From 9307f51893702e9bdd2292e46de64e9e5aecb50f Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 20 Apr 2017 17:03:24 +0100 Subject: glnx-shutil: Add glnx_shutil_mkdir_p_at_open() This is a variant of glnx_shutil_mkdir_p_at() which opens the given directory and returns a dirfd to it. Currently, the implementation cannot be race-free (due to a kernel bug), but it could eventually be made race-free. Signed-off-by: Philip Withnall --- glnx-shutil.c | 37 +++++++++++++++++++++++++++++++++++++ glnx-shutil.h | 8 ++++++++ 2 files changed, 45 insertions(+) diff --git a/glnx-shutil.c b/glnx-shutil.c index 6ff9fa6..4c62ba2 100644 --- a/glnx-shutil.c +++ b/glnx-shutil.c @@ -246,3 +246,40 @@ glnx_shutil_mkdir_p_at (int dfd, out: return ret; } + +/** + * glnx_shutil_mkdir_p_at_open: + * @dfd: Directory fd + * @path: Directory path to be created + * @mode: Mode for newly created directories + * @out_dfd: (out caller-allocates): Return location for an FD to @dfd/@path, + * or `-1` on error + * @cancellable: (nullable): Cancellable, or %NULL + * @error: Return location for a #GError, or %NULL + * + * Similar to glnx_shutil_mkdir_p_at(), except it opens the resulting directory + * and returns a directory FD to it. Currently, this is not guaranteed to be + * race-free. + * + * Returns: %TRUE on success, %FALSE otherwise + * Since: UNRELEASED + */ +gboolean +glnx_shutil_mkdir_p_at_open (int dfd, + const char *path, + int mode, + int *out_dfd, + GCancellable *cancellable, + GError **error) +{ + /* FIXME: It’s not possible to eliminate the race here until + * openat(O_DIRECTORY | O_CREAT) works (and returns a directory rather than a + * file). It appears to be not supported in current kernels. (Tested with + * 4.10.10-200.fc25.x86_64.) */ + *out_dfd = -1; + + if (!glnx_shutil_mkdir_p_at (dfd, path, mode, cancellable, error)) + return FALSE; + + return glnx_opendirat (dfd, path, TRUE, out_dfd, error); +} diff --git a/glnx-shutil.h b/glnx-shutil.h index 8cc732c..56a99fa 100644 --- a/glnx-shutil.h +++ b/glnx-shutil.h @@ -37,4 +37,12 @@ glnx_shutil_mkdir_p_at (int dfd, GCancellable *cancellable, GError **error); +gboolean +glnx_shutil_mkdir_p_at_open (int dfd, + const char *path, + int mode, + int *out_dfd, + GCancellable *cancellable, + GError **error); + G_END_DECLS -- cgit v1.2.1