|
|
1.1 ! root 1: ! 2: /* ! 3: * rmdir -- remove directories ! 4: */ ! 5: #include <sys/stat.h> ! 6: #include <sys/dir.h> ! 7: #include <signal.h> ! 8: #include <stdio.h> ! 9: #include <errno.h> ! 10: ! 11: ! 12: #define equal( s1, s2) (strcmp( s1, s2) == 0) ! 13: ! 14: int fflag, /* force flag */ ! 15: interrupted; ! 16: struct stat dot; ! 17: ! 18: char *getparent(), ! 19: *getchild(), ! 20: *strncpy(), ! 21: *strcat(), ! 22: *strcpy(), ! 23: *concat(); ! 24: ! 25: /* ! 26: * main ! 27: * Interrupts are handled to prevent the formation of mangled directories. ! 28: */ ! 29: main( argc, argv) ! 30: register char **argv; ! 31: { ! 32: register int status = 0; ! 33: ! 34: if (*++argv!= NULL && equal( *argv, "-f")) { ! 35: if (getuid()) ! 36: fatal("only superuser can force"); ! 37: ++fflag; ! 38: ++argv; ! 39: } ! 40: if (stat( ".", &dot)) ! 41: fatal("can't find ."); ! 42: catch(SIGINT); ! 43: catch(SIGHUP); ! 44: signal(SIGQUIT, SIG_IGN); ! 45: ! 46: if (*argv == NULL) { ! 47: fprintf(stderr, "Usage: rmdir [ -f ] dir ...\n"); ! 48: exit(1); ! 49: } ! 50: else ! 51: while (*argv) { ! 52: if (rmdir(*argv++) < 0) ! 53: status = 1; /* error */ ! 54: if (interrupted) ! 55: exit(1); ! 56: } ! 57: exit(status); ! 58: } ! 59: ! 60: ! 61: /* ! 62: * remove a directory ! 63: * The directory and its "." and ".." entries are unlinked if everything ! 64: * looks kosher. The force option causes most checking to be suppressed ! 65: * and unlinks only what is specifically named. `rmdir' takes a dim view ! 66: * to non-hierarchical directories. ! 67: */ ! 68: rmdir(dir) ! 69: register char *dir; ! 70: { ! 71: register char *child; ! 72: register FILE *f; ! 73: struct stat s; ! 74: struct direct d; ! 75: ! 76: ! 77: if ((int) (child = getchild( dir)) < 0) { ! 78: error("can't get child dir name %s", dir); ! 79: return(-1); ! 80: } ! 81: if (access( dir, 0) || stat( dir, &s)) { ! 82: error("can't find %s", dir); ! 83: return(-1); ! 84: } ! 85: if ((s.st_mode&S_IFMT) != S_IFDIR) { ! 86: error("%s not a directory", dir); ! 87: return(-1); ! 88: } ! 89: if (access( getparent( dir), 3)) { ! 90: error("no permission to remove %s", dir); ! 91: return(-1); ! 92: } ! 93: if (fflag == 0) { ! 94: if (equal( child, ".") || equal( child, "..")) { ! 95: error("%s not allowed", dir); ! 96: return(-1); ! 97: } ! 98: if (s.st_ino==dot.st_ino && s.st_dev==dot.st_dev) { ! 99: error("but %s is your working directory", dir); ! 100: return(-1); ! 101: } ! 102: f = fopen( dir, "r"); ! 103: if (f==NULL || access( dir, 4)) { ! 104: error("can't read %s", dir); ! 105: return(-1); ! 106: } ! 107: while (fread( &d, sizeof d, 1, f) == 1) { ! 108: if (d.d_ino == 0) ! 109: continue; ! 110: if (equal( d.d_name, ".") || equal( d.d_name, "..")) ! 111: continue; ! 112: error("%s not empty", dir); ! 113: return(-1); ! 114: } ! 115: fclose(f); ! 116: ! 117: if (s.st_nlink <= 2) { ! 118: unlink( concat( dir, "/.")); ! 119: unlink( concat( dir, "/..")); ! 120: } ! 121: } ! 122: ! 123: if (unlink( dir)) { ! 124: error("unlink %s failed", dir); ! 125: return(-1); ! 126: } ! 127: return(0); ! 128: } ! 129: ! 130: ! 131: /* ! 132: * return name of parent ! 133: */ ! 134: char * ! 135: getparent( dir) ! 136: char *dir; ! 137: { ! 138: register i; ! 139: register char *p; ! 140: static char *par; ! 141: int tmp; ! 142: ! 143: if (par) ! 144: free( par); ! 145: i = strlen( dir); ! 146: par = malloc( i+1); ! 147: if (par == NULL) ! 148: nomemory( ); ! 149: strcpy( par, dir); ! 150: ! 151: for (p=par+i; p>par; ) ! 152: if (*--p != '/') ! 153: break; ! 154: for (++p; *--p!='/'; ) ! 155: if (p == par) { ! 156: *p = '.'; ! 157: break; ! 158: } ! 159: *++p = '\0'; ! 160: if (par[tmp = strlen(par)-1] == '/') ! 161: par[tmp] = 0; /* kill any ending slash */ ! 162: return (par); ! 163: } ! 164: ! 165: ! 166: /* ! 167: * return rightmost component of pathname ! 168: */ ! 169: char * ! 170: getchild( dir) ! 171: register char *dir; ! 172: { ! 173: register char *p, ! 174: *q; ! 175: int i; ! 176: static char ch[DIRSIZ+1]; ! 177: ! 178: p = &dir[strlen( dir)]; ! 179: do { ! 180: if (p == dir) { ! 181: error("not permitted"); ! 182: return(-1); ! 183: } ! 184: } while (*--p == '/'); ! 185: q = p; ! 186: while (q > dir) ! 187: if (*--q == '/') { ! 188: ++q; ! 189: break; ! 190: } ! 191: i = p+1 - q; ! 192: if (i > DIRSIZ) ! 193: i = DIRSIZ; ! 194: return (strncpy( ch, q, i)); ! 195: } ! 196: ! 197: ! 198: /* ! 199: * return concatenation of `s1' and `s2' ! 200: */ ! 201: char * ! 202: concat( s1, s2) ! 203: char *s1, ! 204: *s2; ! 205: { ! 206: static char *str; ! 207: ! 208: if (str) ! 209: free( str); ! 210: str = malloc( strlen( s1)+strlen( s2)+1); ! 211: if (str == NULL) ! 212: nomemory( ); ! 213: strcpy( str, s1); ! 214: return (strcat( str, s2)); ! 215: } ! 216: ! 217: ! 218: nomemory( ) ! 219: { ! 220: fatal("out of memory"); ! 221: } ! 222: ! 223: ! 224: onintr( ) ! 225: { ! 226: ! 227: signal( SIGINT, SIG_IGN); ! 228: signal( SIGHUP, SIG_IGN); ! 229: ++interrupted; ! 230: } ! 231: ! 232: ! 233: catch( sig) ! 234: { ! 235: ! 236: if( signal( sig, SIG_IGN) == SIG_DFL) ! 237: signal( sig, onintr); ! 238: } ! 239: ! 240: ! 241: error(arg1) ! 242: char *arg1; ! 243: { ! 244: fprintf( stderr, "rmdir: %r\n", &arg1); ! 245: } ! 246: ! 247: fatal(arg1) ! 248: char *arg1; ! 249: { ! 250: error(arg1); ! 251: exit(1); ! 252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.