Commit | Line | Data |
---|---|---|
bcf1365c | 1 | /* |
59d11f9a KB |
2 | * Copyright (c) 1983, 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
0f38f750 | 4 | * |
27c71911 | 5 | * %sccs.include.redist.c% |
bcf1365c DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
59d11f9a KB |
9 | static char copyright[] = |
10 | "@(#) Copyright (c) 1983, 1992, 1993\n\ | |
11 | The Regents of the University of California. All rights reserved.\n"; | |
0f38f750 | 12 | #endif /* not lint */ |
bcf1365c DF |
13 | |
14 | #ifndef lint | |
4af6b121 | 15 | static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) %G%"; |
0f38f750 | 16 | #endif /* not lint */ |
bcf1365c | 17 | |
937fdd8f KB |
18 | #include <sys/types.h> |
19 | #include <sys/stat.h> | |
779eba17 | 20 | |
2de05b7b | 21 | #include <err.h> |
937fdd8f | 22 | #include <errno.h> |
a645d56b | 23 | #include <stdio.h> |
779eba17 | 24 | #include <stdlib.h> |
6ebcb998 | 25 | #include <string.h> |
4af6b121 | 26 | #include <unistd.h> |
fe19c180 | 27 | |
2de05b7b KB |
28 | int build __P((char *)); |
29 | void usage __P((void)); | |
ea857b71 | 30 | |
779eba17 | 31 | int |
fe19c180 | 32 | main(argc, argv) |
0f38f750 | 33 | int argc; |
779eba17 | 34 | char *argv[]; |
fe19c180 | 35 | { |
4af6b121 KB |
36 | int ch, exitval, oct, omode, pflag; |
37 | mode_t *set; | |
38 | char *ep, *mode; | |
fe19c180 | 39 | |
937fdd8f | 40 | pflag = 0; |
4af6b121 KB |
41 | mode = NULL; |
42 | while ((ch = getopt(argc, argv, "m:p")) != EOF) | |
937fdd8f KB |
43 | switch(ch) { |
44 | case 'p': | |
45 | pflag = 1; | |
46 | break; | |
4af6b121 KB |
47 | case 'm': |
48 | mode = optarg; | |
49 | break; | |
937fdd8f KB |
50 | case '?': |
51 | default: | |
52 | usage(); | |
53 | } | |
54 | ||
4af6b121 KB |
55 | argc -= optind; |
56 | argv += optind; | |
57 | if (argv[0] == NULL) | |
937fdd8f KB |
58 | usage(); |
59 | ||
4af6b121 KB |
60 | if (mode == NULL) { |
61 | omode = S_IRWXU | S_IRWXG | S_IRWXO; | |
62 | oct = 1; | |
63 | } else if (*mode >= '0' && *mode <= '7') { | |
64 | omode = (int)strtol(mode, &ep, 8); | |
65 | if (omode < 0 || *ep) | |
66 | errx(1, "invalid file mode: %s", mode); | |
67 | oct = 1; | |
68 | } else { | |
69 | if ((set = setmode(mode)) == NULL) | |
70 | errx(1, "invalid file mode: %s", mode); | |
71 | oct = 0; | |
72 | } | |
73 | ||
74 | for (exitval = 0; *argv != NULL; ++argv) { | |
75 | if (pflag && build(*argv)) { | |
76 | exitval = 1; | |
77 | continue; | |
78 | } | |
79 | if (mkdir(*argv, oct ? | |
80 | omode : getmode(set, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { | |
2de05b7b KB |
81 | warn("%s", *argv); |
82 | exitval = 1; | |
83 | } | |
4af6b121 | 84 | } |
937fdd8f KB |
85 | exit(exitval); |
86 | } | |
87 | ||
2de05b7b | 88 | int |
937fdd8f KB |
89 | build(path) |
90 | char *path; | |
91 | { | |
937fdd8f | 92 | struct stat sb; |
4af6b121 KB |
93 | mode_t numask, oumask; |
94 | int first; | |
95 | char *p; | |
937fdd8f | 96 | |
779eba17 | 97 | p = path; |
4af6b121 | 98 | if (p[0] == '/') /* Skip leading '/'. */ |
779eba17 | 99 | ++p; |
4af6b121 KB |
100 | for (first = 1;; ++p) { |
101 | if (p[0] == '\0' || p[0] == '/' && p[1] == '\0') | |
102 | break; | |
103 | if (p[0] != '/') | |
104 | continue; | |
105 | *p = '\0'; | |
106 | if (first) { | |
107 | /* | |
108 | * POSIX 1003.2: | |
109 | * For each dir operand that does not name an existing | |
110 | * directory, effects equivalent to those cased by the | |
111 | * following command shall occcur: | |
112 | * | |
113 | * mkdir -p -m $(umask -S),u+wx $(dirname dir) && | |
114 | * mkdir [-m mode] dir | |
115 | * | |
116 | * We change the user's umask and then restore it, | |
117 | * instead of doing chmod's. | |
118 | */ | |
119 | oumask = umask(0); | |
120 | numask = oumask & ~(S_IWUSR | S_IXUSR); | |
121 | (void)umask(numask); | |
122 | first = 0; | |
123 | } | |
124 | if (stat(path, &sb)) { | |
125 | if (errno != ENOENT || | |
126 | mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0) { | |
127 | warn("%s", path); | |
128 | return (1); | |
937fdd8f | 129 | } |
937fdd8f | 130 | } |
4af6b121 | 131 | *p = '/'; |
2de05b7b | 132 | } |
4af6b121 KB |
133 | if (!first) |
134 | (void)umask(oumask); | |
2de05b7b | 135 | return (0); |
937fdd8f KB |
136 | } |
137 | ||
779eba17 | 138 | void |
937fdd8f KB |
139 | usage() |
140 | { | |
4af6b121 | 141 | (void)fprintf(stderr, "usage: mkdir [-p] [-m mode] directory ...\n"); |
2de05b7b | 142 | exit (1); |
779eba17 | 143 | } |