]> git.sur5r.net Git - i3/i3/blob - libi3/mkdirp.c
mkdirp: do not throw an error if directory exists
[i3/i3] / libi3 / mkdirp.c
1 #include "libi3.h"
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/stat.h>
6
7 /*
8  * Emulates mkdir -p (creates any missing folders)
9  *
10  */
11 bool mkdirp(const char *path) {
12     if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
13         return true;
14     if (errno == EEXIST) {
15         struct stat st;
16         /* Check that the named file actually is a directory. */
17         if (stat(path, &st)) {
18             ELOG("stat(%s) failed: %s\n", path, strerror(errno));
19             return false;
20         }
21         if (!S_ISDIR(st.st_mode)) {
22             ELOG("mkdir(%s) failed: %s\n", path, strerror(ENOTDIR));
23             return false;
24         }
25         return true;
26     } else if (errno != ENOENT) {
27         ELOG("mkdir(%s) failed: %s\n", path, strerror(errno));
28         return false;
29     }
30     char *copy = sstrdup(path);
31     /* strip trailing slashes, if any */
32     while (copy[strlen(copy) - 1] == '/')
33         copy[strlen(copy) - 1] = '\0';
34
35     char *sep = strrchr(copy, '/');
36     if (sep == NULL) {
37         if (copy != NULL) {
38             free(copy);
39             copy = NULL;
40         }
41         return false;
42     }
43     *sep = '\0';
44     bool result = false;
45     if (mkdirp(copy))
46         result = mkdirp(path);
47     free(copy);
48
49     return result;
50 }