summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2017-04-20 18:01:56 +0100
committerPhilip Withnall <withnall@endlessm.com>2017-04-21 14:06:19 +0100
commit6746e6f54d6d29066011bace3b7820e9ca240ac6 (patch)
tree3847e29c41817df274d0b7b6ccfdf5c8b9042026
parent9307f51893702e9bdd2292e46de64e9e5aecb50f (diff)
downloadlibglnx-6746e6f54d6d29066011bace3b7820e9ca240ac6.tar.gz
glnx-dirfd: Add variants of glnx_mkdtempat() which open the directory
At the moment, it’s not possible for them to do this race-free (since openat(O_DIRECTORY | O_CREAT | O_EXCL) doesn’t work), but in future this could be possible. In any case, it’s a useful thing to want to do. Signed-off-by: Philip Withnall <withnall@endlessm.com>
-rw-r--r--glnx-dirfd.c67
-rw-r--r--glnx-dirfd.h11
2 files changed, 78 insertions, 0 deletions
diff --git a/glnx-dirfd.c b/glnx-dirfd.c
index 08d9007..8c43720 100644
--- a/glnx-dirfd.c
+++ b/glnx-dirfd.c
@@ -348,3 +348,70 @@ glnx_mkdtempat (int dfd,
"mkstempat ran out of combinations to try.");
return FALSE;
}
+
+/**
+ * glnx_mkdtempat_open:
+ * @dfd: Directory FD
+ * @tmpl: (type filename): template directory name, last 6 characters will be replaced
+ * @mode: permissions to create the temporary directory with
+ * @out_dfd: (out caller-allocates): Return location for an FD for the new
+ * temporary directory, or `-1` on error
+ * @error: Return location for a #GError, or %NULL
+ *
+ * Similar to glnx_mkdtempat(), except it will open the resulting temporary
+ * directory and return a directory FD to it.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ * Since: UNRELEASED
+ */
+gboolean
+glnx_mkdtempat_open (int dfd,
+ gchar *tmpl,
+ int mode,
+ int *out_dfd,
+ GError **error)
+{
+ /* FIXME: Ideally we could use openat(O_DIRECTORY | O_CREAT | O_EXCL) here
+ * to create and open the directory atomically, but that’s not supported by
+ * current kernel versions: http://www.openwall.com/lists/oss-security/2014/11/26/14
+ * (Tested on kernel 4.10.10-200.fc25.x86_64). For the moment, accept a
+ * TOCTTOU race here. */
+ *out_dfd = -1;
+
+ if (!glnx_mkdtempat (dfd, tmpl, mode, error))
+ return FALSE;
+
+ return glnx_opendirat (dfd, tmpl, FALSE, out_dfd, error);
+}
+
+/**
+ * glnx_mkdtempat_open_in_system:
+ * @tmpl: (type filename): template directory name, last 6 characters will be replaced
+ * @mode: permissions to create the temporary directory with
+ * @out_dfd: (out caller-allocates): Return location for an FD for the new
+ * temporary directory, or `-1` on error
+ * @error: Return location for a #GError, or %NULL
+ *
+ * Similar to glnx_mkdtempat_open(), except it will use the system temporary
+ * directory (from g_get_tmp_dir()) as the parent directory to @tmpl.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ * Since: UNRELEASED
+ */
+gboolean
+glnx_mkdtempat_open_in_system (gchar *tmpl,
+ int mode,
+ int *out_dfd,
+ GError **error)
+{
+ glnx_fd_close int tmp_dfd = -1;
+
+ *out_dfd = -1;
+
+ if (!glnx_opendirat (-1, g_get_tmp_dir (), TRUE, &tmp_dfd, error))
+ return FALSE;
+
+ return glnx_mkdtempat_open (tmp_dfd, tmpl, mode, out_dfd, error);
+}
+
+
diff --git a/glnx-dirfd.h b/glnx-dirfd.h
index 3a76695..0cb79e6 100644
--- a/glnx-dirfd.h
+++ b/glnx-dirfd.h
@@ -88,4 +88,15 @@ gboolean glnx_mkdtempat (int dfd,
int mode,
GError **error);
+gboolean glnx_mkdtempat_open (int dfd,
+ gchar *tmpl,
+ int mode,
+ int *out_dfd,
+ GError **error);
+
+gboolean glnx_mkdtempat_open_in_system (gchar *tmpl,
+ int mode,
+ int *out_dfd,
+ GError **error);
+
G_END_DECLS