diff --git a/glnx-shutil.c b/glnx-shutil.c index 6ff9fa6825bd796a083e0cab82cab56110e3f7cb..4c62ba21e52cadc501e5e319b5acad2977a5d557 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 8cc732c3fc94d4d0ba0dd30b3cdb7f2509e39e49..56a99fa2c4873fd2ddcc225c520344a527a6b921 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