[ostree] util: Add an API to atomic-replace a file, dirfd relative, optional fsync
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] util: Add an API to atomic-replace a file, dirfd relative, optional fsync
- Date: Thu, 12 Feb 2015 16:43:45 +0000 (UTC)
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]