1 /* mkdir - Make directories Author: V. Archer */
3 /* Copyright 1991 by Vincent Archer
4 * You may freely redistribute this software, in source or binary
5 * form, provided that you do not alter this copyright mention in any
11 #include <minix/minlib.h>
19 extern int optind
, opterr
;
22 #define USR_MODES (S_ISUID|S_IRWXU)
23 #define GRP_MODES (S_ISGID|S_IRWXG)
24 #define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
26 #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
28 #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
30 #define DEFAULT_MODE (S_IRWXU|S_IRWXG|S_IRWXO)
31 #define USER_WX (S_IWUSR|S_IXUSR)
34 /* Global variables */
40 _PROTOTYPE(int main
, (int argc
, char **argv
));
41 _PROTOTYPE(mode_t parsemode
, (char *symbolic
, mode_t oldmode
));
42 _PROTOTYPE(int makepath
, (char *fordir
));
43 _PROTOTYPE(int makedir
, (char *dirname
));
44 _PROTOTYPE(void usage
, (void));
46 /* Parse a P1003.2 4.7.7-conformant symbolic mode. */
47 mode_t
parsemode(char *symbolic
, mode_t oldmode
)
49 mode_t who
, mask
, newmode
, tmpmask
;
52 unsigned long octalmode
;
54 octalmode
= strtoul(symbolic
, &end
, 010);
55 if (octalmode
< ALL_MODES
&& *end
== 0 && end
!= symbolic
) return octalmode
;
57 newmode
= oldmode
& ALL_MODES
;
60 for (; *symbolic
; symbolic
++) {
61 if (*symbolic
== 'a') {
65 if (*symbolic
== 'u') {
69 if (*symbolic
== 'g') {
73 if (*symbolic
== 'o') {
79 if (!*symbolic
|| *symbolic
== ',') usage();
81 if (*symbolic
== ',') break;
87 case '=': action
= *symbolic
++;
90 for (; *symbolic
; symbolic
++) {
91 if (*symbolic
== 'u') {
92 tmpmask
= newmode
& S_IRWXU
;
93 mask
|= tmpmask
| (tmpmask
<< 3) | (tmpmask
<< 6);
97 if (*symbolic
== 'g') {
98 tmpmask
= newmode
& S_IRWXG
;
99 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
<< 3);
103 if (*symbolic
== 'o') {
104 tmpmask
= newmode
& S_IRWXO
;
105 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
>> 6);
109 if (*symbolic
== 'r') {
110 mask
|= S_IRUSR
| S_IRGRP
| S_IROTH
;
113 if (*symbolic
== 'w') {
114 mask
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
117 if (*symbolic
== 'x') {
121 if (*symbolic
== 's') {
122 mask
|= S_ISUID
| S_ISGID
;
125 if (*symbolic
== 'X') {
126 if (S_ISDIR(oldmode
) || (oldmode
& EXE_MODES
))
131 if (*symbolic
== 't') {
147 newmode
|= who
& mask
;
149 newmode
|= mask
& (~u_mask
);
153 newmode
&= ~(who
& mask
);
155 newmode
&= ~mask
| u_mask
;
158 if (*symbolic
) symbolic
++;
173 symbolic
= (char *) 0;
176 while ((c
= getopt(argc
, argv
, "m:p")) != EOF
) switch (c
) {
177 case 'm': symbolic
= optarg
; break;
178 case 'p': pflag
= 1; break;
181 if (optind
>= argc
) usage();
184 while (optind
< argc
) error
|= makedir(argv
[optind
++]);
189 /* P1003.2 requires that missing intermediate pathname components should be
190 * created if the -p option is specified (4.40.3).
195 char parent
[PATH_MAX
+ 1], *end
, *last
;
197 strcpy(parent
, fordir
);
199 if (!(end
= strrchr(parent
, '/'))) return(0);
201 if (!parent
[0] || !strcmp(parent
, ".")) return(0);
202 } while((last
= strrchr(parent
, '/')) && !strcmp(last
+1, "."));
204 if (!stat(parent
, &st
)) {
205 if (S_ISDIR(st
.st_mode
)) return(0);
210 if (mkdir(parent
, DEFAULT_MODE
)) {
211 if (makepath(parent
)) return(1);
212 if (mkdir(parent
, DEFAULT_MODE
)) {
218 /* P1003.2 states that, regardless of umask() value, intermediate paths
219 * should have at least write and search (x) permissions (4.40.10).
221 if ((u_mask
& USER_WX
) &&
222 chmod(parent
, ((~u_mask
) | USER_WX
)) & DEFAULT_MODE
) {
230 /* Actual directory creation, using a mkdir() system call. */
234 if (mkdir(dirname
, DEFAULT_MODE
)) {
239 if (!stat(dirname
, &st
)) {
240 if (S_ISDIR(st
.st_mode
)) return(0);
245 if (makepath(dirname
)) return(1);
246 if (mkdir(dirname
, DEFAULT_MODE
)) {
251 if (symbolic
&& (stat(dirname
, &st
) ||
252 chmod(dirname
, parsemode(symbolic
, st
.st_mode
)))) {
260 /* Posix command prototype. */
263 std_err("Usage: mkdir [-p] [-m mode] dir...\n");