gio: Implement query_exists for local files

We can’t quite use `access()` for this, like `g_file_test()` does, as
`g_file_query_info()` considers a broken symlink to exist, so we need to
match that by passing `AT_SYMLINK_NOFOLLOW`.

We also use the `AT_EACCESS` flag, which makes the `faccessat()` call
cheaper on Hurd.

Systems without `faccessat()` will continue to use the
`g_file_query_info()`-based implementation of `g_file_query_exists()`.

(Commit message rewritten by Philip Withnall.)
This commit is contained in:
Matthias Clasen 2024-09-12 10:27:35 -04:00 committed by Philip Withnall
parent 85ce99f4ad
commit 65ad41d8a4
2 changed files with 15 additions and 0 deletions

View File

@ -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;
}

View File

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