diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2024-10-01 15:45:04 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2024-10-01 15:45:04 +0000 |
commit | f6d7878a544f7de234713f20ec66fb32442b889b (patch) | |
tree | 95b826e990ed314a0fd368a28f50f1c3f6811cd7 | |
parent | 2b5d3b5831fb027ca041130bf91779ed7e5c9bf0 (diff) | |
parent | ab51ed0521d16227a0496c972ddc0bbcd5c9cd74 (diff) |
Merge branch 'speed-up-query-exists' into 'main'
gio: Add a query_exists vfunc to GFile
See merge request GNOME/glib!4272
-rw-r--r-- | gio/gfile.c | 15 | ||||
-rw-r--r-- | gio/gfile.h | 4 | ||||
-rw-r--r-- | gio/glocalfile.c | 14 | ||||
-rw-r--r-- | gio/gresourcefile.c | 10 | ||||
-rw-r--r-- | meson.build | 1 |
5 files changed, 41 insertions, 3 deletions
diff --git a/gio/gfile.c b/gio/gfile.c index 5ac73c03e..6f104459f 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -1192,8 +1192,11 @@ g_file_enumerate_children_finish (GFile *file, * @cancellable: (nullable): optional #GCancellable object, * %NULL to ignore * - * Utility function to check if a particular file exists. This is - * implemented using g_file_query_info() and as such does blocking I/O. + * Utility function to check if a particular file exists. + * + * The fallback implementation of this API is using [method@Gio.File.query_info] + * and therefore may do blocking I/O. To asynchronously query the existence + * of a file, use [method@Gio.File.query_info_async]. * * Note that in many cases it is [racy to first check for file existence](https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use) * and then execute something based on the outcome of that, because the @@ -1222,9 +1225,15 @@ gboolean g_file_query_exists (GFile *file, GCancellable *cancellable) { + GFileIface *iface; GFileInfo *info; - g_return_val_if_fail (G_IS_FILE(file), FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); + + iface = G_FILE_GET_IFACE (file); + + if (iface->query_exists) + return iface->query_exists (file, cancellable); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, cancellable, NULL); diff --git a/gio/gfile.h b/gio/gfile.h index d49c3b36c..74e50db83 100644 --- a/gio/gfile.h +++ b/gio/gfile.h @@ -148,6 +148,7 @@ typedef struct _GFileIface GFileIface; * @measure_disk_usage: Recursively measures the disk usage of @file. Since 2.38 * @measure_disk_usage_async: Asynchronously recursively measures the disk usage of @file. Since 2.38 * @measure_disk_usage_finish: Finishes an asynchronous recursive measurement of the disk usage of @file. Since 2.38 + * @query_exists: Queries whether a file exists. Since 2.84 * * An interface for writing VFS file handles. **/ @@ -598,6 +599,9 @@ struct _GFileIface guint64 *num_dirs, guint64 *num_files, GError **error); + + gboolean (* query_exists) (GFile *file, + GCancellable *cancellable); }; GIO_AVAILABLE_IN_ALL diff --git a/gio/glocalfile.c b/gio/glocalfile.c index ac918d25e..7c02cc36e 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -1259,6 +1259,17 @@ g_local_file_query_info (GFile *file, return info; } +#ifdef HAVE_FACCESSAT +static gboolean +g_local_file_query_exists (GFile *file, + GCancellable *cancellable) +{ + GLocalFile *local = G_LOCAL_FILE (file); + + return faccessat (0, local->filename, F_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) == 0; +} +#endif + static GFileAttributeInfoList * g_local_file_query_settable_attributes (GFile *file, GCancellable *cancellable, @@ -3142,6 +3153,9 @@ g_local_file_file_iface_init (GFileIface *iface) iface->monitor_dir = g_local_file_monitor_dir; iface->monitor_file = g_local_file_monitor_file; iface->measure_disk_usage = g_local_file_measure_disk_usage; +#ifdef HAVE_FACCESSAT + iface->query_exists = g_local_file_query_exists; +#endif iface->supports_thread_contexts = TRUE; } diff --git a/gio/gresourcefile.c b/gio/gresourcefile.c index 5b772d94b..da1f368e5 100644 --- a/gio/gresourcefile.c +++ b/gio/gresourcefile.c @@ -657,6 +657,15 @@ g_resource_file_set_display_name (GFile *file, return NULL; } +static gboolean +g_resource_file_query_exists (GFile *file, + GCancellable *cancellable) +{ + GResourceFile *resource = G_RESOURCE_FILE (file); + + return g_resources_get_info (resource->path, 0, NULL, NULL, NULL); +} + static void g_resource_file_file_iface_init (GFileIface *iface) { @@ -683,6 +692,7 @@ g_resource_file_file_iface_init (GFileIface *iface) iface->query_writable_namespaces = g_resource_file_query_writable_namespaces; iface->read_fn = g_resource_file_read; iface->monitor_file = g_resource_file_monitor_file; + iface->query_exists = g_resource_file_query_exists; iface->supports_thread_contexts = TRUE; } diff --git a/meson.build b/meson.build index 5f7870d1f..748831ac5 100644 --- a/meson.build +++ b/meson.build @@ -683,6 +683,7 @@ functions = [ 'endmntent', 'endservent', 'epoll_create1', + 'faccessat', 'fallocate', 'fchmod', 'fchown', |