diff options
author | Colin Walters <walters@verbum.org> | 2013-01-04 17:02:39 -0500 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2013-01-04 17:02:39 -0500 |
commit | 660aa3e43f53d272508fc8fcd3eef62b426c59ae (patch) | |
tree | 09e069ebb6e4028af60d6ce7671b6b4a79efb52d | |
parent | b11ad335f459e3c61b317308da57de441660efd0 (diff) | |
download | libgsystem-660aa3e43f53d272508fc8fcd3eef62b426c59ae.tar.gz |
fileutils: Add gs_file_sync_data()
It often occurs that I want to ensure file data is on disk so that
updates can be atomic.
-rw-r--r-- | gsystem-file-utils.c | 65 | ||||
-rw-r--r-- | gsystem-file-utils.h | 4 |
2 files changed, 69 insertions, 0 deletions
diff --git a/gsystem-file-utils.c b/gsystem-file-utils.c index 546ff99..5e70c34 100644 --- a/gsystem-file-utils.c +++ b/gsystem-file-utils.c @@ -159,6 +159,71 @@ gs_file_map_readonly (GFile *file, return ret; } +static int +close_nointr (int fd) +{ + int res; + do + res = close (fd); + while (G_UNLIKELY (res != 0 && errno == EINTR)); + return res; +} + +/** + * gs_file_sync_data: + * @file: a #GFile + * @cancellable: + * @error: + * + * Wraps the UNIX fdatasync() function, which ensures that the data in + * @file is on non-volatile storage. + */ +gboolean +gs_file_sync_data (GFile *file, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + int res; + int fd = -1; + + fd = _open_fd_noatime (gs_file_get_path_cached (file)); + if (fd < 0) + { + int errsv = errno; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + g_strerror (errsv)); + goto out; + } + + do + res = fdatasync (fd); + while (G_UNLIKELY (res != 0 && errno == EINTR)); + if (res != 0) + { + int errsv = errno; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + g_strerror (errsv)); + goto out; + } + + res = close_nointr (fd); + if (res != 0) + { + int errsv = errno; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + g_strerror (errsv)); + goto out; + } + fd = -1; + + ret = TRUE; + out: + if (fd != -1) + (void) close_nointr (fd); + return ret; +} + /** * gs_file_get_path_cached: * diff --git a/gsystem-file-utils.h b/gsystem-file-utils.h index bf07b3a..768cc0c 100644 --- a/gsystem-file-utils.h +++ b/gsystem-file-utils.h @@ -40,6 +40,10 @@ GBytes *gs_file_map_readonly (GFile *file, GCancellable *cancellable, GError **error); +gboolean gs_file_sync_data (GFile *file, + GCancellable *cancellable, + GError **error); + gboolean gs_file_rename (GFile *from, GFile *to, GCancellable *cancellable, |