]> granicus.if.org Git - neomutt/commitdiff
lib: add mutt_mkdir
authorRichard Russon <rich@flatcap.org>
Sat, 7 Jan 2017 15:32:55 +0000 (15:32 +0000)
committerRichard Russon <rich@flatcap.org>
Mon, 23 Jan 2017 15:11:23 +0000 (15:11 +0000)
Make directories recursively

lib.c
lib.h

diff --git a/lib.c b/lib.c
index 85374e486a173ff00258c0ec10a09d85379f0951..1519b2f63875ef68a6a1616070d9f5c34a83fad1 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -1157,3 +1157,59 @@ char * strfcpy (char *dest, const char *src, size_t dlen)
   return dest0;
 }
 
+/**
+ * mutt_mkdir - Recursively create directories
+ * @path: Directories to create
+ * @mode: Permissions for final directory
+ * @return:
+ * *    0  Success
+ * *   -1  Error (errno set)
+ *
+ * Create a directory, creating the parents if necessary. (like mkdir -p)
+ *
+ * Note: The permissions are only set on the final directory.
+ *       The permissions of any parent directoies are determined by the umask.
+ *       (This is how "mkdir -p" behaves)
+ */
+int mutt_mkdir(const char *path, mode_t mode)
+{
+  if (!path || !*path)
+  {
+    errno = EINVAL;
+    return -1;
+  }
+
+  char *p;
+  char _path[PATH_MAX];
+  const size_t len = strlen(path);
+
+  if (len >= sizeof(_path))
+  {
+    errno = ENAMETOOLONG;
+    return -1;
+  }
+
+  /* Create a mutable copy */
+  strfcpy(_path, path, sizeof(_path));
+
+  for (p = _path + 1; *p; p++)
+  {
+    if (*p != '/')
+      continue;
+
+    /* Temporarily truncate the path */
+    *p = '\0';
+
+    if ((mkdir(_path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) && (errno != EEXIST))
+      return -1;
+
+    *p = '/';
+  }
+
+  if ((mkdir(_path, mode) != 0) && (errno != EEXIST))
+    return -1;
+
+  errno = 0;
+  return 0;
+}
+
diff --git a/lib.h b/lib.h
index cc824003afdeb6b19afaa2128e979f3719176f66..97e873a3ec60ca8ff3379784b4bf73f69b109756 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -210,6 +210,7 @@ int safe_symlink (const char *, const char *);
 int safe_fclose (FILE **);
 int safe_fsync_close (FILE **);
 int mutt_rmtree (const char *);
+int mutt_mkdir(const char *path, mode_t mode);
 
 size_t mutt_quote_filename (char *, size_t, const char *);
 size_t mutt_strlen (const char *);