[libglnx] Add glnx_mkdtempat



commit 03138641298fd6799f46b16423871f959332bacf
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Dec 11 15:56:29 2015 +0100

    Add glnx_mkdtempat
    
    Create a temporary directory using mkdirat.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=757611

 glnx-dirfd.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 glnx-dirfd.h |    5 ++++
 2 files changed, 82 insertions(+), 0 deletions(-)
---
diff --git a/glnx-dirfd.c b/glnx-dirfd.c
index a51eb3d..d126f15 100644
--- a/glnx-dirfd.c
+++ b/glnx-dirfd.c
@@ -226,3 +226,80 @@ glnx_fdrel_abspath (int         dfd,
     return g_strdup (path);
   return g_strdup_printf ("/proc/self/fd/%d/%s", dfd, path);
 }
+
+/**
+ * glnx_mkdtempat:
+ * @dfd: Directory fd
+ * @tmpl: (type filename): template directory name
+ * @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)
+{
+  char *XXXXXX;
+  int count;
+  static const char letters[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static const int NLETTERS = sizeof (letters) - 1;
+  glong value;
+  GTimeVal tv;
+  static int counter = 0;
+
+  g_return_val_if_fail (tmpl != NULL, -1);
+
+  /* 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;
+    }
+
+  /* Get some more or less random data.  */
+  g_get_current_time (&tv);
+  value = (tv.tv_usec ^ tv.tv_sec) + counter++;
+
+  for (count = 0; count < 100; value += 7777, ++count)
+    {
+      glong v = value;
+
+      /* Fill in the random bits.  */
+      XXXXXX[0] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[1] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[2] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[3] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[4] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[5] = letters[v % NLETTERS];
+
+      if (mkdirat (dfd, tmpl, mode) == -1)
+        {
+          if (errno == EEXIST)
+            continue;
+
+          /* Any other error will apply also to other names we might
+           *  try, and there are 2^32 or so of them, so give up now.
+           */
+          glnx_set_prefix_error_from_errno (error, "%s", "mkdirat");
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+
+  g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
+               "mkstempat ran out of combinations to try.");
+  return FALSE;
+}
diff --git a/glnx-dirfd.h b/glnx-dirfd.h
index bcf7f1e..5b7b77a 100644
--- a/glnx-dirfd.h
+++ b/glnx-dirfd.h
@@ -77,4 +77,9 @@ gboolean glnx_opendirat (int             dfd,
 char *glnx_fdrel_abspath (int         dfd,
                           const char *path);
 
+gboolean glnx_mkdtempat (int dfd,
+                         gchar *tmpl,
+                         int mode,
+                         GError **error);
+
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]