From 7dbdec1d5bc1bf325b43e239b66703be38d65c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 30 Jan 2015 00:51:38 +0100 Subject: [PATCH] Initial mkdir -p function --- src/mkdirp.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/mkdirp.c diff --git a/src/mkdirp.c b/src/mkdirp.c new file mode 100644 index 0000000..7deed44 --- /dev/null +++ b/src/mkdirp.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +int uc_mkdir_p(const char *full_path, mode_t mode) +{ + struct stat st; + int rc = 0; + char *path; + char *p; + + if (full_path == NULL || full_path[0] == 0) { + + errno = EINVAL; + return -1; + } + + rc = stat(full_path, &st); + if (rc == 0) { //already exists + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return -1; + } + if (st.st_mode != (mode | S_IFDIR) && chmod(full_path, mode) != 0) { + return -1; + } + } + + path = strdup(full_path); + if (path == NULL) { + return -1; + } + + //skip leading / + for (p = path; *p == '/'; p++) + ; + + for (;;) { + p = strchr(p, '/'); + if (p == NULL) { + break; + } + + *p = 0; + + rc = stat(path, &st); + if (rc != 0) { //doesn't exist + if (mkdir(path, mode) != 0) { + free(path); + return -1; + } + } else if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + free(path); + return -1; + } else { //dir already exist + + if (st.st_mode != (mode | S_IFDIR) && chmod(path, mode) != 0) { + free(path); + return -1; + } + } + + //in case of multiple / , e.g. foo//bar + *p = '/'; + for (; *p == '/'; p++) + ; + } + + //last part, in case full_path does not end with a / + rc = stat(path, &st); + if (rc != 0) { + rc = mkdir(path, mode); + } + + free(path); + + return rc; +} + + +int main(int argc, char *argv[]) +{ + uc_mkdir_p("a/b//c/d", 0777); +}