28 |
|
|
29 |
int FAST_FUNC bb_make_directory(char *path, long mode, int flags) |
int FAST_FUNC bb_make_directory(char *path, long mode, int flags) |
30 |
{ |
{ |
31 |
mode_t mask; |
mode_t cur_mask; |
32 |
|
mode_t org_mask; |
33 |
const char *fail_msg; |
const char *fail_msg; |
34 |
char *s = path; |
char *s; |
35 |
char c; |
char c; |
36 |
struct stat st; |
struct stat st; |
37 |
|
|
38 |
mask = umask(0); |
/* Happens on bb_make_directory(dirname("no_slashes"),...) */ |
39 |
umask(mask & ~0300); /* Ensure intermediate dirs are wx */ |
if (LONE_CHAR(path, '.')) |
40 |
|
return 0; |
41 |
|
|
42 |
|
org_mask = cur_mask = (mode_t)-1L; |
43 |
|
s = path; |
44 |
while (1) { |
while (1) { |
45 |
c = '\0'; |
c = '\0'; |
46 |
|
|
47 |
if (flags & FILEUTILS_RECUR) { /* Get the parent. */ |
if (flags & FILEUTILS_RECUR) { /* Get the parent */ |
48 |
/* Bypass leading non-'/'s and then subsequent '/'s. */ |
/* Bypass leading non-'/'s and then subsequent '/'s */ |
49 |
while (*s) { |
while (*s) { |
50 |
if (*s == '/') { |
if (*s == '/') { |
51 |
do { |
do { |
52 |
++s; |
++s; |
53 |
} while (*s == '/'); |
} while (*s == '/'); |
54 |
c = *s; /* Save the current char */ |
c = *s; /* Save the current char */ |
55 |
*s = '\0'; /* and replace it with nul. */ |
*s = '\0'; /* and replace it with nul */ |
56 |
break; |
break; |
57 |
} |
} |
58 |
++s; |
++s; |
59 |
} |
} |
60 |
} |
} |
61 |
|
|
62 |
if (!c) /* Last component uses orig umask */ |
if (c != '\0') { |
63 |
umask(mask); |
/* Intermediate dirs: must have wx for user */ |
64 |
|
if (cur_mask == (mode_t)-1L) { /* wasn't done yet? */ |
65 |
|
mode_t new_mask; |
66 |
|
org_mask = umask(0); |
67 |
|
cur_mask = 0; |
68 |
|
/* Clear u=wx in umask - this ensures |
69 |
|
* they won't be cleared on mkdir */ |
70 |
|
new_mask = (org_mask & ~(mode_t)0300); |
71 |
|
//bb_error_msg("org_mask:%o cur_mask:%o", org_mask, new_mask); |
72 |
|
if (new_mask != cur_mask) { |
73 |
|
cur_mask = new_mask; |
74 |
|
umask(new_mask); |
75 |
|
} |
76 |
|
} |
77 |
|
} else { |
78 |
|
/* Last component: uses original umask */ |
79 |
|
//bb_error_msg("1 org_mask:%o", org_mask); |
80 |
|
if (org_mask != cur_mask) { |
81 |
|
cur_mask = org_mask; |
82 |
|
umask(org_mask); |
83 |
|
} |
84 |
|
} |
85 |
|
|
86 |
if (mkdir(path, 0777) < 0) { |
if (mkdir(path, 0777) < 0) { |
87 |
/* If we failed for any other reason than the directory |
/* If we failed for any other reason than the directory |
88 |
* already exists, output a diagnostic and return -1. */ |
* already exists, output a diagnostic and return -1 */ |
89 |
if (errno != EEXIST |
if (errno != EEXIST |
90 |
|| !(flags & FILEUTILS_RECUR) |
|| !(flags & FILEUTILS_RECUR) |
91 |
|| ((stat(path, &st) < 0) || !S_ISDIR(st.st_mode)) |
|| ((stat(path, &st) < 0) || !S_ISDIR(st.st_mode)) |
92 |
) { |
) { |
93 |
fail_msg = "create"; |
fail_msg = "create"; |
|
umask(mask); |
|
94 |
break; |
break; |
95 |
} |
} |
96 |
/* Since the directory exists, don't attempt to change |
/* Since the directory exists, don't attempt to change |
97 |
* permissions if it was the full target. Note that |
* permissions if it was the full target. Note that |
98 |
* this is not an error condition. */ |
* this is not an error condition. */ |
99 |
if (!c) { |
if (!c) { |
100 |
umask(mask); |
goto ret0; |
|
return 0; |
|
101 |
} |
} |
102 |
} |
} |
103 |
|
|
109 |
fail_msg = "set permissions of"; |
fail_msg = "set permissions of"; |
110 |
break; |
break; |
111 |
} |
} |
112 |
return 0; |
goto ret0; |
113 |
} |
} |
114 |
|
|
115 |
/* Remove any inserted nul from the path (recursive mode). */ |
/* Remove any inserted nul from the path (recursive mode) */ |
116 |
*s = c; |
*s = c; |
117 |
} /* while (1) */ |
} /* while (1) */ |
118 |
|
|
119 |
bb_perror_msg("cannot %s directory '%s'", fail_msg, path); |
bb_perror_msg("can't %s directory '%s'", fail_msg, path); |
120 |
return -1; |
flags = -1; |
121 |
|
goto ret; |
122 |
|
ret0: |
123 |
|
flags = 0; |
124 |
|
ret: |
125 |
|
//bb_error_msg("2 org_mask:%o", org_mask); |
126 |
|
if (org_mask != cur_mask) |
127 |
|
umask(org_mask); |
128 |
|
return flags; |
129 |
} |
} |