[libgsystem] fileutil: Add gs_file_openat_noatime()



commit bd2c1e436b270b39ca262765e775b4556d6bd50b
Author: Colin Walters <walters verbum org>
Date:   Sat Sep 7 04:14:35 2013 -0400

    fileutil: Add gs_file_openat_noatime()
    
    While porting relevant parts of OSTree to use openat()/renameat() and
    friends, it commonly occurs that I wanted to do
    gs_file_read_noatime().  Make a variant of that API, named differently
    because the _noatime implies reading.

 gsystem-file-utils.c |   78 ++++++++++++++++++++++++++++++--------------------
 gsystem-file-utils.h |    7 ++++
 2 files changed, 54 insertions(+), 31 deletions(-)
---
diff --git a/gsystem-file-utils.c b/gsystem-file-utils.c
index 0486bf8..e23f17e 100644
--- a/gsystem-file-utils.c
+++ b/gsystem-file-utils.c
@@ -68,29 +68,56 @@ open_nointr (const char *path, int flags, mode_t mode)
   return res;
 }
 
-static int
-_open_fd_noatime (const char *path)
+static inline void
+_set_error_from_errno (GError **error)
+{
+  int errsv = errno;
+  g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                       g_strerror (errsv));
+}
+
+/**
+ * gs_file_openat_noatime:
+ * @dfd: File descriptor for directory
+ * @name: Pathname, relative to @dfd
+ * @ret_fd: (out): Returned file descriptor
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Wrapper for openat() using %O_RDONLY with %O_NOATIME if available.
+ */
+gboolean
+gs_file_openat_noatime (int            dfd,
+                        const char    *name,
+                        int           *ret_fd,
+                        GCancellable  *cancellable,
+                        GError       **error)
 {
   int fd;
 
 #ifdef O_NOATIME
-  fd = open_nointr (path, O_RDONLY | O_NOATIME, 0);
+  do
+    fd = openat (dfd, name, O_RDONLY | O_NOATIME, 0);
+  while (G_UNLIKELY (fd == -1 && errno == EINTR));
   /* Only the owner or superuser may use O_NOATIME; so we may get
    * EPERM.  EINVAL may happen if the kernel is really old...
    */
   if (fd == -1 && (errno == EPERM || errno == EINVAL))
 #endif
-    fd = open_nointr (path, O_RDONLY, 0);
+    do
+      fd = openat (dfd, name, O_RDONLY, 0);
+    while (G_UNLIKELY (fd == -1 && errno == EINTR));
   
-  return fd;
-}
-
-static inline void
-_set_error_from_errno (GError **error)
-{
-  int errsv = errno;
-  g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                       g_strerror (errsv));
+  if (fd == -1)
+    {
+      _set_error_from_errno (error);
+      return FALSE;
+    }
+  else
+    {
+      *ret_fd = fd;
+      return TRUE;
+    }
 }
 
 /**
@@ -127,12 +154,8 @@ gs_file_read_noatime (GFile         *file,
       return NULL;
     }
 
-  fd = _open_fd_noatime (path);
-  if (fd < 0)
-    {
-      _set_error_from_errno (error);
-      return NULL;
-    }
+  if (!gs_file_openat_noatime (AT_FDCWD, path, &fd, cancellable, error))
+    return NULL;
 
   return g_unix_input_stream_new (fd, TRUE);
 }
@@ -203,12 +226,8 @@ gs_file_map_noatime (GFile         *file,
   if (path == NULL)
     return NULL;
 
-  fd = _open_fd_noatime (path);
-  if (fd < 0)
-    {
-      _set_error_from_errno (error);
-      return NULL;
-    }
+  if (!gs_file_openat_noatime (AT_FDCWD, path, &fd, cancellable, error))
+    return NULL;
   
   ret = g_mapped_file_new_from_fd (fd, FALSE, error);
   close_nointr_noerror (fd); /* Ignore errors - we always want to close */
@@ -267,12 +286,9 @@ gs_file_sync_data (GFile          *file,
   int res;
   int fd = -1; 
 
-  fd = _open_fd_noatime (gs_file_get_path_cached (file));
-  if (fd < 0)
-    {
-      _set_error_from_errno (error);
-      goto out;
-    }
+  if (!gs_file_openat_noatime (AT_FDCWD, gs_file_get_path_cached (file), &fd,
+                               cancellable, error))
+    goto out;
 
   do
     res = fdatasync (fd);
diff --git a/gsystem-file-utils.h b/gsystem-file-utils.h
index 38f4b0a..7473386 100644
--- a/gsystem-file-utils.h
+++ b/gsystem-file-utils.h
@@ -36,6 +36,12 @@ gboolean gs_file_enumerator_iterate (GFileEnumerator  *direnum,
                                      GCancellable     *cancellable,
                                      GError          **error);
 
+gboolean gs_file_openat_noatime (int            dirfd,
+                                 const char    *name,
+                                 int           *out_fd,
+                                 GCancellable  *cancellable,
+                                 GError       **error);
+
 GInputStream *gs_file_read_noatime (GFile         *file,
                                     GCancellable  *cancellable,
                                     GError       **error);
@@ -48,6 +54,7 @@ gboolean gs_stream_fstat (GFileDescriptorBased *stream,
                           struct stat          *out_stbuf,
                           GCancellable         *cancellable,
                           GError              **error);
+
 #endif
 
 #if GLIB_CHECK_VERSION(2,34,0)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]