summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2013-09-07 04:14:35 -0400
committerColin Walters <walters@verbum.org>2013-09-07 04:14:35 -0400
commitbd2c1e436b270b39ca262765e775b4556d6bd50b (patch)
tree807af79f642629d4d890a193b310dbbe5a2cf1b2
parentd63409a3d44b61e40f30cde79ebae879925c716d (diff)
downloadlibgsystem-bd2c1e436b270b39ca262765e775b4556d6bd50b.tar.gz
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.
-rw-r--r--gsystem-file-utils.c78
-rw-r--r--gsystem-file-utils.h7
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)