From 87cd883e8d851eb3b844be9a74f2a444f2e2f190 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 16 Jan 2008 10:11:26 +0000 Subject: [PATCH] Add g_file_query_exists (#508771) 2008-01-16 Alexander Larsson * gfile.[ch]: * gio.symbols: Add g_file_query_exists (#508771) svn path=/trunk/; revision=6319 --- gio/ChangeLog | 6 ++++++ gio/gfile.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ gio/gfile.h | 2 ++ gio/gio.symbols | 1 + 4 files changed, 56 insertions(+) diff --git a/gio/ChangeLog b/gio/ChangeLog index 99abddd7..0d0da767 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,9 @@ +2008-01-16 Alexander Larsson + + * gfile.[ch]: + * gio.symbols: + Add g_file_query_exists (#508771) + 2008-01-15 Murray Cumming * gdrive.c: diff --git a/gio/gfile.c b/gio/gfile.c index 84611ce7..3cc7579a 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -812,6 +812,53 @@ g_file_enumerate_children_finish (GFile *file, return (* iface->enumerate_children_finish) (file, res, error); } +/** + * g_file_query_exists: + * @file: input #GFile. + * @cancellable: 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. + * + * Note that in many cases it is racy to first check for file existance + * and then execute something based on the outcome of that, because the + * file might have been created or removed inbetween the operations. The + * general approach to handling that is to not check, but just do the + * operation and handle the errors as they come. + * + * As an example of race-free checking. Take the case of reading a file, and + * if it doesn't exist, create it. There are two racy versions: read it, and + * on error create it; and: check if it exists, if not create it. These + * can both result in two processes creating the file (with perhaps a partially + * written file as the result). The correct approach is to always try to create + * the file with g_file_create() which will either atomically create the file + * or fail with an G_IO_ERROR_EXISTS error. + * + * However, in many cases an existance check is useful in a user + * interface, for instance to make a menu item sensitive/insensitive, so that + * you don't have to fool users that something is possible and then just show + * and error dialog. If you do this, you should make sure to also handle the + * errors that can happen due to races when you execute the operation. + * + * Returns: %TRUE if the file exists (and can be detected without error), %FALSE otherwise (or if cancelled). + */ +gboolean +g_file_query_exists (GFile *file, + GCancellable *cancellable) +{ + GFileInfo *info; + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NONE, + cancellable, NULL); + if (info != NULL) + { + g_object_unref (info); + return TRUE; + } + + return FALSE; +} /** * g_file_query_info: diff --git a/gio/gfile.h b/gio/gfile.h index 0fd57188..8d8ee6b8 100644 --- a/gio/gfile.h +++ b/gio/gfile.h @@ -612,6 +612,8 @@ void g_file_replace_async (GFile GFileOutputStream * g_file_replace_finish (GFile *file, GAsyncResult *res, GError **error); +gboolean g_file_query_exists (GFile *file, + GCancellable *cancellable); GFileInfo * g_file_query_info (GFile *file, const char *attributes, GFileQueryInfoFlags flags, diff --git a/gio/gio.symbols b/gio/gio.symbols index e679f789..d15e53d3 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -243,6 +243,7 @@ g_file_create_async g_file_create_finish g_file_replace_async g_file_replace_finish +g_file_query_exists g_file_query_info g_file_query_info_async g_file_query_info_finish -- 2.34.1