summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2016-05-28 09:14:04 -0400
committerColin Walters <walters@verbum.org>2016-05-30 11:22:23 -0400
commit4919f6ee68c0e64465d83a8832261c477a5d673c (patch)
treebfd05052387e94e9f54c8c719bb48b3897154126
parent40ef5f7400d4f8eed6a8f834917008b33ad4fb4e (diff)
downloadlibglnx-4919f6ee68c0e64465d83a8832261c477a5d673c.tar.gz
Introduce glnx_gen_temp_name()
We have multiple copies growing again of this code. glibc has this API internally and uses it in multiple places, let's do the same. Closes: #14
-rw-r--r--glnx-dirfd.c58
-rw-r--r--glnx-dirfd.h2
2 files changed, 39 insertions, 21 deletions
diff --git a/glnx-dirfd.c b/glnx-dirfd.c
index 4861ccf..4a071cc 100644
--- a/glnx-dirfd.c
+++ b/glnx-dirfd.c
@@ -277,20 +277,17 @@ glnx_fdrel_abspath (int dfd,
}
/**
- * glnx_mkdtempat:
- * @dfd: Directory fd
- * @tmpl: (type filename): template directory name
- * @mode: permissions to create the temporary directory with
- * @error: Error
+ * glnx_gen_temp_name:
+ * @tmpl: (type filename): template directory name, the last 6 characters will be replaced
*
- * Similar to g_mkdtemp_full, but using openat.
+ * Replace the last 6 characters of @tmpl with random ASCII. You must
+ * use this in combination with a mechanism to ensure race-free file
+ * creation such as `O_EXCL`.
*/
-gboolean
-glnx_mkdtempat (int dfd,
- gchar *tmpl,
- int mode,
- GError **error)
+void
+glnx_gen_temp_name (gchar *tmpl)
{
+ size_t len;
char *XXXXXX;
int count;
static const char letters[] =
@@ -300,17 +297,11 @@ glnx_mkdtempat (int dfd,
GTimeVal tv;
static int counter = 0;
- g_return_val_if_fail (tmpl != NULL, -1);
+ g_return_if_fail (tmpl != NULL);
+ len = strlen (tmpl);
+ g_return_if_fail (len < 6);
- /* find the last occurrence of "XXXXXX" */
- XXXXXX = g_strrstr (tmpl, "XXXXXX");
-
- if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Invalid temporary directory template '%s'", tmpl);
- return FALSE;
- }
+ XXXXXX = tmpl + (len - 6);
/* Get some more or less random data. */
g_get_current_time (&tv);
@@ -332,6 +323,31 @@ glnx_mkdtempat (int dfd,
XXXXXX[4] = letters[v % NLETTERS];
v /= NLETTERS;
XXXXXX[5] = letters[v % NLETTERS];
+ }
+}
+
+/**
+ * glnx_mkdtempat:
+ * @dfd: Directory fd
+ * @tmpl: (type filename): template directory name, last 6 characters will be replaced
+ * @mode: permissions to create the temporary directory with
+ * @error: Error
+ *
+ * Similar to g_mkdtemp_full, but using openat.
+ */
+gboolean
+glnx_mkdtempat (int dfd,
+ gchar *tmpl,
+ int mode,
+ GError **error)
+{
+ int count;
+
+ g_return_val_if_fail (tmpl != NULL, -1);
+
+ for (count = 0; count < 100; count++)
+ {
+ glnx_gen_temp_name (tmpl);
if (mkdirat (dfd, tmpl, mode) == -1)
{
diff --git a/glnx-dirfd.h b/glnx-dirfd.h
index c13e3dc..3a76695 100644
--- a/glnx-dirfd.h
+++ b/glnx-dirfd.h
@@ -81,6 +81,8 @@ gboolean glnx_opendirat (int dfd,
char *glnx_fdrel_abspath (int dfd,
const char *path);
+void glnx_gen_temp_name (gchar *tmpl);
+
gboolean glnx_mkdtempat (int dfd,
gchar *tmpl,
int mode,