Merge branch 'speed-up-query-exists' into 'main'

gio: Add a query_exists vfunc to GFile

See merge request GNOME/glib!4272
This commit is contained in:
Philip Withnall 2024-10-01 15:45:04 +00:00
commit f6d7878a54
5 changed files with 41 additions and 3 deletions

View File

@ -1192,8 +1192,11 @@ g_file_enumerate_children_finish (GFile *file,
* @cancellable: (nullable): optional #GCancellable object, * @cancellable: (nullable): optional #GCancellable object,
* %NULL to ignore * %NULL to ignore
* *
* Utility function to check if a particular file exists. This is * Utility function to check if a particular file exists.
* implemented using g_file_query_info() and as such does blocking I/O. *
* 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) * 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 * and then execute something based on the outcome of that, because the
@ -1222,9 +1225,15 @@ gboolean
g_file_query_exists (GFile *file, g_file_query_exists (GFile *file,
GCancellable *cancellable) GCancellable *cancellable)
{ {
GFileIface *iface;
GFileInfo *info; 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, info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NONE, cancellable, NULL); G_FILE_QUERY_INFO_NONE, cancellable, NULL);

View File

@ -148,6 +148,7 @@ typedef struct _GFileIface GFileIface;
* @measure_disk_usage: Recursively measures the disk usage of @file. Since 2.38 * @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_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 * @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. * An interface for writing VFS file handles.
**/ **/
@ -598,6 +599,9 @@ struct _GFileIface
guint64 *num_dirs, guint64 *num_dirs,
guint64 *num_files, guint64 *num_files,
GError **error); GError **error);
gboolean (* query_exists) (GFile *file,
GCancellable *cancellable);
}; };
GIO_AVAILABLE_IN_ALL GIO_AVAILABLE_IN_ALL

View File

@ -1259,6 +1259,17 @@ g_local_file_query_info (GFile *file,
return info; 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 * static GFileAttributeInfoList *
g_local_file_query_settable_attributes (GFile *file, g_local_file_query_settable_attributes (GFile *file,
GCancellable *cancellable, GCancellable *cancellable,
@ -3142,6 +3153,9 @@ g_local_file_file_iface_init (GFileIface *iface)
iface->monitor_dir = g_local_file_monitor_dir; iface->monitor_dir = g_local_file_monitor_dir;
iface->monitor_file = g_local_file_monitor_file; iface->monitor_file = g_local_file_monitor_file;
iface->measure_disk_usage = g_local_file_measure_disk_usage; 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; iface->supports_thread_contexts = TRUE;
} }

View File

@ -657,6 +657,15 @@ g_resource_file_set_display_name (GFile *file,
return NULL; 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 static void
g_resource_file_file_iface_init (GFileIface *iface) 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->query_writable_namespaces = g_resource_file_query_writable_namespaces;
iface->read_fn = g_resource_file_read; iface->read_fn = g_resource_file_read;
iface->monitor_file = g_resource_file_monitor_file; iface->monitor_file = g_resource_file_monitor_file;
iface->query_exists = g_resource_file_query_exists;
iface->supports_thread_contexts = TRUE; iface->supports_thread_contexts = TRUE;
} }

View File

@ -683,6 +683,7 @@ functions = [
'endmntent', 'endmntent',
'endservent', 'endservent',
'epoll_create1', 'epoll_create1',
'faccessat',
'fallocate', 'fallocate',
'fchmod', 'fchmod',
'fchown', 'fchown',