From b266bcd4502bb6ecee52a34ccaf4b39869d4b6ca Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sat, 7 Jan 2017 15:32:55 +0000 Subject: [PATCH] lib: add mutt_mkdir Make directories recursively --- lib.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib.h | 1 + 2 files changed, 57 insertions(+) diff --git a/lib.c b/lib.c index 85374e486..1519b2f63 100644 --- 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 cc824003a..97e873a3e 100644 --- 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 *); -- 2.40.0