|
|
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.