/src/clib/deps/mkdirp/mkdirp.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | // |
3 | | // mkdirp.c |
4 | | // |
5 | | // Copyright (c) 2013 Stephen Mathieson |
6 | | // MIT licensed |
7 | | // |
8 | | |
9 | | #include <unistd.h> |
10 | | #include <errno.h> |
11 | | #include <stdlib.h> |
12 | | #include <string.h> |
13 | | #include "strdup/strdup.h" |
14 | | #include "path-normalize/path-normalize.h" |
15 | | #include "mkdirp.h" |
16 | | |
17 | | #ifdef _WIN32 |
18 | | #define PATH_SEPARATOR '\\' |
19 | | #else |
20 | 0 | #define PATH_SEPARATOR '/' |
21 | | #endif |
22 | | |
23 | | /* |
24 | | * Recursively `mkdir(path, mode)` |
25 | | */ |
26 | | |
27 | | int |
28 | 0 | mkdirp(const char *path, mode_t mode) { |
29 | 0 | char *pathname = NULL; |
30 | 0 | char *parent = NULL; |
31 | |
|
32 | 0 | if (NULL == path) return -1; |
33 | | |
34 | 0 | pathname = path_normalize(path); |
35 | 0 | if (NULL == pathname) goto fail; |
36 | | |
37 | 0 | parent = strdup(pathname); |
38 | 0 | if (NULL == parent) goto fail; |
39 | | |
40 | 0 | char *p = parent + strlen(parent); |
41 | 0 | while (PATH_SEPARATOR != *p && p != parent) { |
42 | 0 | p--; |
43 | 0 | } |
44 | 0 | *p = '\0'; |
45 | | |
46 | | // make parent dir |
47 | 0 | if (p != parent && 0 != mkdirp(parent, mode)) goto fail; |
48 | 0 | free(parent); |
49 | | |
50 | | // make this one if parent has been made |
51 | | #ifdef _WIN32 |
52 | | // http://msdn.microsoft.com/en-us/library/2fkk4dzw.aspx |
53 | | int rc = mkdir(pathname); |
54 | | #else |
55 | 0 | int rc = mkdir(pathname, mode); |
56 | 0 | #endif |
57 | |
|
58 | 0 | free(pathname); |
59 | |
|
60 | 0 | return 0 == rc || EEXIST == errno |
61 | 0 | ? 0 |
62 | 0 | : -1; |
63 | | |
64 | 0 | fail: |
65 | 0 | free(pathname); |
66 | 0 | free(parent); |
67 | 0 | return -1; |
68 | 0 | } |