|
|
1.1 root 1: /*
2: * mkdir.c
3: * 5/10/90
4: * Usage: mkdir [ -rp ] dir ...
5: * Make directories.
6: *
7: * Changes by michael 5/10/93
8: * implemented -p option
9: *
10: * Changes by steve 5/10/90:
11: * in getchild(), bumped strncpy count by 1 to return NUL-terminated result
12: * in getparent(), hacked bogus "ending slash" code so that e.g.
13: * getparent("/foo") returns "/" rather than ""
14: *
15: * Changes by steve 4/12/90:
16: * corrected fatal() call
17: * added success return status to mkdir()
18: * improved return status of getchild()
19: * implemented -r option
20: */
21:
22: #include <sys/dir.h>
23: #include <sys/ino.h>
24: #include <signal.h>
25: #include <stdio.h>
26: #include <errno.h>
27:
28:
29: #define equal(s1, s2) (strcmp(s1, s2) == 0)
30:
31: int interrupted;
32: int rflag;
33:
34: char *getparent(),
35: *getchild(),
36: *concat(),
37: *malloc(),
38: *strcat(),
39: *strcpy(),
40: *strncpy();
41:
42: /*
43: * main
44: * Interrupts are handled to prevent the formation of mangled directories.
45: */
46: main(argc, argv)
47: register char **argv;
48: {
49: register int status = 0;
50:
51: catch(SIGINT);
52: catch(SIGHUP);
53: signal(SIGQUIT, SIG_IGN);
54:
55: if (argc > 1 && argv[1][0] == '-' &&
56: (argv[1][1] == 'r' || argv[1][1] == 'p')) {
57: ++rflag;
58: --argc;
59: ++argv;
60: }
61: if (*++argv == NULL) {
62: fprintf(stderr, "Usage: mkdir [-rp] dir ...\n");
63: exit(1);
64: } else
65: while (*argv) {
66: if (mkdir(*argv++) < 0)
67: status = 1; /* error */
68: if (interrupted)
69: exit(1);
70: }
71: exit(status);
72: }
73:
74: /*
75: * Make a directory.
76: * If the parent exists and is writeable, the directory and its "." and
77: * ".." links are created.
78: */
79: int
80: mkdir(dir)
81: register char *dir;
82: {
83: register char *parent,
84: *child;
85:
86: if ((child = getchild(dir)) == NULL) {
87: error("cannot get child name %s", dir);
88: return -1;
89: } else if (equal(child, ".") || equal(child, "..")) {
90: error("%s not allowed", dir);
91: return -1;
92: }
93: if ((parent = getparent(dir)) == NULL)
94: return -1;
95: if (access(parent, 03)) {
96: if (rflag && errno == ENOENT) {
97: /* Make parent recursively. */
98: if (mkdir(parent) != 0) {
99: free(parent);
100: return -1;
101: }
102: } else {
103: switch (errno) {
104: case ENOENT:
105: error("parent directory %s does not exist", parent);
106: break;
107: case EACCES:
108: error("no permission to mkdir in %s", parent);
109: break;
110: default:
111: noway(dir);
112: break;
113: }
114: free(parent);
115: return -1;
116: }
117: }
118: if (mknod(dir, IFDIR|0777, 0)) {
119: switch (errno) {
120: case EEXIST:
121: error("%s already exists", dir);
122: break;
123: case EPERM:
124: error("not the super-user");
125: break;
126: default:
127: noway(dir);
128: break;
129: }
130: free(parent);
131: return -1;
132: } else if (link(dir, concat(dir, "/."))) {
133: linkerr(dir, ".");
134: free(parent);
135: return -1;
136: } else if (link(parent, concat(dir, "/.."))) {
137: linkerr(dir, "..");
138: free(parent);
139: return -1;
140: }
141: free(parent);
142: return (chown(dir, getuid(), getgid()) < 0) ? -1 : 0;
143: }
144:
145:
146: /*
147: * Return name of parent in an allocated buffer.
148: */
149: char *
150: getparent(dir)
151: char *dir;
152: {
153: register i;
154: register char *p;
155: char *par;
156: int tmp;
157:
158: i = strlen(dir);
159: par = malloc(i+1);
160: if (par == NULL) {
161: nomemory();
162: return NULL;
163: }
164: strcpy(par, dir);
165:
166: for (p=par+i; p>par; )
167: if (*--p != '/')
168: break;
169: for (++p; *--p!='/'; )
170: if (p == par) {
171: *p = '.';
172: break;
173: }
174: *++p = 0;
175: tmp = strlen(par) - 1;
176: if (tmp > 0 && par[tmp] == '/')
177: par[tmp] = 0; /* kill any ending slash */
178: return par;
179: }
180:
181: /*
182: * Return rightmost component of pathname
183: * in a statically allocated buffer.
184: */
185: char *
186: getchild(dir)
187: register char *dir;
188: {
189: register char *p,
190: *q;
191: int i;
192: static char ch[DIRSIZ+1];
193:
194: p = &dir[strlen(dir)];
195: do {
196: if (p == dir)
197: fatal("illegal directory name");
198: } while (*--p == '/');
199: q = p;
200: while (q > dir)
201: if (*--q == '/') {
202: ++q;
203: break;
204: }
205: i = p+1 - q;
206: if (i > DIRSIZ)
207: i = DIRSIZ;
208: return strncpy(ch, q, i+1);
209: }
210:
211:
212: /*
213: * Return concatenation of 's1' and 's2' in a malloc'ed buffer.
214: * Free the previous buffer.
215: */
216: char *
217: concat(s1, s2)
218: char *s1,
219: *s2;
220: {
221: static char *str;
222:
223: if (str)
224: free(str);
225: str = malloc(strlen(s1)+strlen(s2)+1);
226: if (str == NULL) {
227: nomemory();
228: return -1;
229: }
230: strcpy(str, s1);
231: return strcat(str, s2);
232: }
233:
234:
235: /*
236: * Recover from link failure.
237: * In the event that "." or ".." cannot be created, remove all traces
238: * of the directory.
239: */
240: linkerr(dir, name)
241: char *dir,
242: *name;
243: {
244: unlink(concat(dir, "/."));
245: unlink(concat(dir, "/.."));
246: unlink(dir);
247: error("link to %s failed", name);
248: return -1;
249: }
250:
251:
252: nomemory()
253: {
254: error("out of memory");
255: return -1;
256: }
257:
258:
259: noway(dir)
260: char *dir;
261: {
262: error("cannot make %s", dir);
263: return -1;
264: }
265:
266:
267: onintr()
268: {
269: signal(SIGINT, SIG_IGN);
270: signal(SIGHUP, SIG_IGN);
271: ++interrupted;
272: }
273:
274:
275: catch(sig)
276: {
277: if (signal(sig, SIG_IGN) == SIG_DFL)
278: signal(sig, onintr);
279: }
280:
281: error(arg1)
282: char *arg1;
283: {
284: fprintf(stderr, "mkdir: %r\n", &arg1);
285: }
286:
287: fatal(arg1)
288: char *arg1;
289: {
290: error(arg1);
291: exit(1);
292: }
293:
294: /* end of mkdir.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.