|
|
1.1 ! root 1: static char *sccsid = "@(#)rm.c 4.23 (Berkeley) 12/5/88"; ! 2: ! 3: /* ! 4: * rm - for ReMoving files, directories & trees. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <sys/param.h> ! 9: #include <sys/stat.h> ! 10: #include <sys/dir.h> ! 11: #include <sys/file.h> ! 12: ! 13: int fflg; /* -f force - supress error messages */ ! 14: int iflg; /* -i interrogate user on each file */ ! 15: int rflg; /* -r recurse */ ! 16: ! 17: int errcode; /* true if errors occured */ ! 18: ! 19: char *strcpy(); ! 20: ! 21: main(argc, argv) ! 22: int argc; ! 23: char **argv; ! 24: { ! 25: extern int optind; ! 26: int ch; ! 27: ! 28: fflg = !isatty(0); ! 29: while ((ch = getopt(argc, argv, "-Rfir")) != EOF) ! 30: switch((char)ch) { ! 31: case '-': ! 32: goto endarg; ! 33: case 'f': ! 34: fflg++; ! 35: break; ! 36: case 'i': ! 37: iflg++; ! 38: break; ! 39: case 'R': ! 40: case 'r': ! 41: rflg++; ! 42: break; ! 43: case '?': ! 44: default: ! 45: usage(); ! 46: } ! 47: endarg: argv += optind; ! 48: ! 49: if (!*argv) { ! 50: if (fflg) ! 51: exit(0); ! 52: usage(); ! 53: } ! 54: do { ! 55: (void)rm(*argv, 0); ! 56: } while (*++argv); ! 57: exit(errcode != 0); ! 58: } ! 59: ! 60: char *path; /* pointer to malloc'ed buffer for path */ ! 61: char *pathp; /* current pointer to end of path */ ! 62: int pathsz; /* size of path */ ! 63: ! 64: #define isdot(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2])) ! 65: /* ! 66: * Return TRUE if sucessful. Recursive with -r (rflg) ! 67: */ ! 68: rm(arg, level) ! 69: char arg[]; ! 70: { ! 71: int ok; /* true if recursive rm succeeded */ ! 72: struct stat buf; /* for finding out what a file is */ ! 73: struct direct *dp; /* for reading a directory */ ! 74: DIR *dirp; /* for reading a directory */ ! 75: char prevname[MAXNAMLEN + 1]; /* previous name for -r */ ! 76: char *cp, *rindex(); ! 77: ! 78: cp = rindex(arg, '/'); ! 79: if (cp == NULL) ! 80: cp = arg; ! 81: else ! 82: ++cp; ! 83: if (isdot(cp)) { ! 84: fprintf(stderr, "rm: cannot remove `.' or `..'\n"); ! 85: return (0); ! 86: } ! 87: if (lstat(arg, &buf)) { ! 88: if (!fflg) { ! 89: fprintf(stderr, "rm: %s nonexistent\n", arg); ! 90: errcode++; ! 91: } ! 92: return (0); /* error */ ! 93: } ! 94: if ((buf.st_mode&S_IFMT) == S_IFDIR) { ! 95: if (!rflg) { ! 96: if (!fflg) { ! 97: fprintf(stderr, "rm: %s directory\n", arg); ! 98: errcode++; ! 99: } ! 100: return (0); ! 101: } ! 102: if (iflg && level != 0) { ! 103: printf("rm: remove directory %s? ", arg); ! 104: if (!yes()) ! 105: return (0); /* didn't remove everything */ ! 106: } ! 107: if (access(arg, R_OK|W_OK|X_OK) != 0) { ! 108: if (rmdir(arg) == 0) ! 109: return (1); /* salvaged: removed empty dir */ ! 110: if (!fflg) { ! 111: fprintf(stderr, "rm: %s not changed\n", arg); ! 112: errcode++; ! 113: } ! 114: return (0); /* error */ ! 115: } ! 116: if ((dirp = opendir(arg)) == NULL) { ! 117: if (!fflg) { ! 118: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 119: errcode++; ! 120: } ! 121: return (0); ! 122: } ! 123: if (level == 0) ! 124: append(arg); ! 125: prevname[0] = '\0'; ! 126: while ((dp = readdir(dirp)) != NULL) { ! 127: if (isdot(dp->d_name)) { ! 128: strcpy(prevname, dp->d_name); ! 129: continue; ! 130: } ! 131: append(dp->d_name); ! 132: closedir(dirp); ! 133: ok = rm(path, level + 1); ! 134: for (cp = pathp; *--cp != '/' && cp > path; ) ! 135: ; ! 136: pathp = cp; ! 137: *cp++ = '\0'; ! 138: if ((dirp = opendir(arg)) == NULL) { ! 139: if (!fflg) { ! 140: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 141: errcode++; ! 142: } ! 143: break; ! 144: } ! 145: /* pick up where we left off */ ! 146: if (prevname[0] != '\0') { ! 147: while ((dp = readdir(dirp)) != NULL && ! 148: strcmp(prevname, dp->d_name) != 0) ! 149: ; ! 150: } ! 151: /* skip the one we just failed to delete */ ! 152: if (!ok) { ! 153: dp = readdir(dirp); ! 154: if (dp != NULL && strcmp(cp, dp->d_name)) { ! 155: fprintf(stderr, ! 156: "rm: internal synchronization error: %s, %s, %s\n", ! 157: arg, cp, dp->d_name); ! 158: } ! 159: strcpy(prevname, dp->d_name); ! 160: } ! 161: } ! 162: closedir(dirp); ! 163: if (level == 0) { ! 164: pathp = path; ! 165: *pathp = '\0'; ! 166: } ! 167: if (iflg) { ! 168: printf("rm: remove %s? ", arg); ! 169: if (!yes()) ! 170: return (0); ! 171: } ! 172: if (rmdir(arg) < 0) { ! 173: if (!fflg || iflg) { ! 174: fprintf(stderr, "rm: %s not removed\n", arg); ! 175: errcode++; ! 176: } ! 177: return (0); ! 178: } ! 179: return (1); ! 180: } ! 181: ! 182: if (!fflg) { ! 183: if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) { ! 184: printf("rm: override protection %o for %s? ", ! 185: buf.st_mode&0777, arg); ! 186: if (!yes()) ! 187: return (0); ! 188: goto rm; ! 189: } ! 190: } ! 191: if (iflg) { ! 192: printf("rm: remove %s? ", arg); ! 193: if (!yes()) ! 194: return (0); ! 195: } ! 196: rm: if (unlink(arg) < 0) { ! 197: if (!fflg || iflg) { ! 198: fprintf(stderr, "rm: %s: ", arg); ! 199: perror((char *)NULL); ! 200: errcode++; ! 201: } ! 202: return (0); ! 203: } ! 204: return (1); ! 205: } ! 206: ! 207: /* ! 208: * Get a yes/no answer from the user. ! 209: */ ! 210: yes() ! 211: { ! 212: int i, b; ! 213: ! 214: i = b = getchar(); ! 215: while (b != '\n' && b != EOF) ! 216: b = getchar(); ! 217: return (i == 'y'); ! 218: } ! 219: ! 220: /* ! 221: * Append 'name' to 'path'. ! 222: */ ! 223: append(name) ! 224: char *name; ! 225: { ! 226: register int n; ! 227: char *malloc(); ! 228: ! 229: n = strlen(name); ! 230: if (path == NULL) { ! 231: pathsz = MAXNAMLEN + MAXPATHLEN + 2; ! 232: if ((path = malloc((u_int)pathsz)) == NULL) { ! 233: fprintf(stderr, "rm: ran out of memory\n"); ! 234: exit(1); ! 235: } ! 236: pathp = path; ! 237: } else if (pathp + n + 2 > path + pathsz) { ! 238: fprintf(stderr, "rm: path name too long: %s\n", path); ! 239: exit(1); ! 240: } else if (pathp != path && pathp[-1] != '/') ! 241: *pathp++ = '/'; ! 242: strcpy(pathp, name); ! 243: pathp += n; ! 244: } ! 245: ! 246: usage() ! 247: { ! 248: fputs("usage: rm [-rif] file ...\n", stderr); ! 249: exit(1); ! 250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.