[ostree] util: Add an API to atomic-replace a file, dirfd relative, optional fsync



commit 65afe1110d657e09ac46affa01ccaac6f2dbbf97
Author: Colin Walters <walters verbum org>
Date:   Wed Feb 4 14:45:09 2015 -0500

    util: Add an API to atomic-replace a file, dirfd relative, optional fsync
    
    This can be used in other places too, but I plan to use it to write
    the summary file.

 src/libotutil/ot-gio-utils.c |   64 +++++++++++++++++++++++++++++------------
 src/libotutil/ot-gio-utils.h |    7 ++++
 2 files changed, 52 insertions(+), 19 deletions(-)
---
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index 5b7ad1a..3028a45 100644
--- a/src/libotutil/ot-gio-utils.c
+++ b/src/libotutil/ot-gio-utils.c
@@ -275,32 +275,26 @@ ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
 }
 
 /**
- * ot_gfile_replace_contents_fsync:
+ * ot_file_replace_contents_at:
  * 
- * Like g_file_replace_contents(), except always uses fdatasync().
+ * Like g_file_replace_contents(), except using a fd-relative
+ * directory, and optionally enforces use of fdatasync().
  */
 gboolean
-ot_gfile_replace_contents_fsync (GFile          *path,
-                                 GBytes         *contents,
-                                 GCancellable   *cancellable,
-                                 GError        **error)
+ot_file_replace_contents_at (int             dfd,
+                             const char     *path,
+                             GBytes         *contents,
+                             gboolean        datasync,
+                             GCancellable   *cancellable,
+                             GError        **error)
 {
   gboolean ret = FALSE;
-  int parent_dfd;
   int fd;
-  const char *target_basename = gs_file_get_basename_cached (path);
-  gs_unref_object GFile *parent = NULL;
   gs_free char *tmpname = NULL;
   gs_unref_object GOutputStream *stream = NULL;
   gs_unref_object GInputStream *instream = NULL;
 
-  parent = g_file_get_parent (path);
-
-  if (!gs_file_open_dir_fd (parent, &parent_dfd,
-                            cancellable, error))
-    goto out;
-
-  if (!gs_file_open_in_tmpdir_at (parent_dfd, 0644,
+  if (!gs_file_open_in_tmpdir_at (dfd, 0644,
                                   &tmpname, &stream,
                                   cancellable, error))
     goto out;
@@ -324,7 +318,7 @@ ot_gfile_replace_contents_fsync (GFile          *path,
                               cancellable, error) < 0)
     goto out;
 
-  if (fdatasync (fd) != 0)
+  if (datasync && fdatasync (fd) != 0)
     {
       gs_set_error_from_errno (error, errno);
       goto out;
@@ -333,7 +327,7 @@ ot_gfile_replace_contents_fsync (GFile          *path,
   if (!g_output_stream_close (stream, cancellable, error))
     goto out;
 
-  if (renameat (parent_dfd, tmpname, parent_dfd, target_basename) == -1)
+  if (renameat (dfd, tmpname, dfd, path) == -1)
     {
       gs_set_error_from_errno (error, errno);
       goto out;
@@ -344,7 +338,39 @@ ot_gfile_replace_contents_fsync (GFile          *path,
   ret = TRUE;
  out:
   if (tmpname)
-    (void) unlinkat (parent_dfd, tmpname, 0);
+    (void) unlinkat (dfd, tmpname, 0);
+  return ret;
+}
+
+/**
+ * ot_gfile_replace_contents_fsync:
+ * 
+ * Like g_file_replace_contents(), except always uses fdatasync().
+ */
+gboolean
+ot_gfile_replace_contents_fsync (GFile          *path,
+                                 GBytes         *contents,
+                                 GCancellable   *cancellable,
+                                 GError        **error)
+{
+  gboolean ret = FALSE;
+  int parent_dfd;
+  const char *target_basename = gs_file_get_basename_cached (path);
+  gs_unref_object GFile *parent = NULL;
+
+  parent = g_file_get_parent (path);
+
+  if (!gs_file_open_dir_fd (parent, &parent_dfd,
+                            cancellable, error))
+    goto out;
+
+  if (!ot_file_replace_contents_at (parent_dfd, target_basename,
+                                    contents, TRUE,
+                                    cancellable, error))
+    goto out;
+
+  ret = TRUE;
+ out:
   if (parent_dfd != -1)
     (void) close (parent_dfd);
   return ret;
diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h
index d108a44..bd0ef5c 100644
--- a/src/libotutil/ot-gio-utils.h
+++ b/src/libotutil/ot-gio-utils.h
@@ -69,6 +69,13 @@ gboolean ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
                                                   GCancellable   *cancellable,
                                                   GError        **error);
 
+gboolean ot_file_replace_contents_at (int             dfd,
+                                      const char     *path,
+                                      GBytes         *contents,
+                                      gboolean        datasync,
+                                      GCancellable   *cancellable,
+                                      GError        **error);
+
 gboolean ot_gfile_replace_contents_fsync (GFile          *path,
                                           GBytes         *contents,
                                           GCancellable   *cancellable,


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