|
|
1.1 ! root 1: static char *sccsid = "@(#)rm.c 4.22 (Berkeley) 4/21/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(), *malloc(); ! 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; ! 77: ! 78: if (isdot(arg)) { ! 79: fprintf(stderr, "rm: cannot remove `.' or `..'\n"); ! 80: return (0); ! 81: } ! 82: if (lstat(arg, &buf)) { ! 83: if (!fflg) { ! 84: fprintf(stderr, "rm: %s nonexistent\n", arg); ! 85: errcode++; ! 86: } ! 87: return (0); /* error */ ! 88: } ! 89: if ((buf.st_mode&S_IFMT) == S_IFDIR) { ! 90: if (!rflg) { ! 91: if (!fflg) { ! 92: fprintf(stderr, "rm: %s directory\n", arg); ! 93: errcode++; ! 94: } ! 95: return (0); ! 96: } ! 97: if (iflg && level != 0) { ! 98: printf("rm: remove directory %s? ", arg); ! 99: if (!yes()) ! 100: return (0); /* didn't remove everything */ ! 101: } ! 102: if (access(arg, R_OK|W_OK|X_OK) != 0) { ! 103: if (rmdir(arg) == 0) ! 104: return (1); /* salvaged: removed empty dir */ ! 105: if (!fflg) { ! 106: fprintf(stderr, "rm: %s not changed\n", arg); ! 107: errcode++; ! 108: } ! 109: return (0); /* error */ ! 110: } ! 111: if ((dirp = opendir(arg)) == NULL) { ! 112: if (!fflg) { ! 113: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 114: errcode++; ! 115: } ! 116: return (0); ! 117: } ! 118: if (level == 0) ! 119: append(arg); ! 120: prevname[0] = '\0'; ! 121: while ((dp = readdir(dirp)) != NULL) { ! 122: if (isdot(dp->d_name)) { ! 123: strcpy(prevname, dp->d_name); ! 124: continue; ! 125: } ! 126: append(dp->d_name); ! 127: closedir(dirp); ! 128: ok = rm(path, level + 1); ! 129: for (cp = pathp; *--cp != '/' && cp > path; ) ! 130: ; ! 131: pathp = cp; ! 132: *cp++ = '\0'; ! 133: if ((dirp = opendir(arg)) == NULL) { ! 134: if (!fflg) { ! 135: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 136: errcode++; ! 137: } ! 138: break; ! 139: } ! 140: /* pick up where we left off */ ! 141: if (prevname[0] != '\0') { ! 142: while ((dp = readdir(dirp)) != NULL && ! 143: strcmp(prevname, dp->d_name) != 0) ! 144: ; ! 145: } ! 146: /* skip the one we just failed to delete */ ! 147: if (!ok) { ! 148: dp = readdir(dirp); ! 149: if (dp != NULL && strcmp(cp, dp->d_name)) { ! 150: fprintf(stderr, ! 151: "rm: internal synchronization error: %s, %s, %s\n", ! 152: arg, cp, dp->d_name); ! 153: } ! 154: strcpy(prevname, dp->d_name); ! 155: } ! 156: } ! 157: closedir(dirp); ! 158: if (level == 0) { ! 159: pathp = path; ! 160: *pathp = '\0'; ! 161: } ! 162: if (iflg) { ! 163: printf("rm: remove %s? ", arg); ! 164: if (!yes()) ! 165: return (0); ! 166: } ! 167: if (rmdir(arg) < 0) { ! 168: if (!fflg || iflg) { ! 169: fprintf(stderr, "rm: %s not removed\n", arg); ! 170: errcode++; ! 171: } ! 172: return (0); ! 173: } ! 174: return (1); ! 175: } ! 176: ! 177: if (!fflg) { ! 178: if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) { ! 179: printf("rm: override protection %o for %s? ", ! 180: buf.st_mode&0777, arg); ! 181: if (!yes()) ! 182: return (0); ! 183: goto rm; ! 184: } ! 185: } ! 186: if (iflg) { ! 187: printf("rm: remove %s? ", arg); ! 188: if (!yes()) ! 189: return (0); ! 190: } ! 191: rm: if (unlink(arg) < 0) { ! 192: if (!fflg || iflg) { ! 193: fprintf(stderr, "rm: %s: ", arg); ! 194: perror((char *)NULL); ! 195: errcode++; ! 196: } ! 197: return (0); ! 198: } ! 199: return (1); ! 200: } ! 201: ! 202: /* ! 203: * Get a yes/no answer from the user. ! 204: */ ! 205: yes() ! 206: { ! 207: int i, b; ! 208: ! 209: i = b = getchar(); ! 210: while (b != '\n' && b != EOF) ! 211: b = getchar(); ! 212: return (i == 'y'); ! 213: } ! 214: ! 215: /* ! 216: * Append 'name' to 'path'. ! 217: */ ! 218: append(name) ! 219: char *name; ! 220: { ! 221: register int n; ! 222: ! 223: n = strlen(name); ! 224: if (path == NULL) { ! 225: pathsz = MAXNAMLEN + MAXPATHLEN + 2; ! 226: if ((path = malloc((u_int)pathsz)) == NULL) { ! 227: fprintf(stderr, "rm: ran out of memory\n"); ! 228: exit(1); ! 229: } ! 230: pathp = path; ! 231: } else if (pathp + n + 2 > path + pathsz) { ! 232: fprintf(stderr, "rm: path name too long: %s\n", path); ! 233: exit(1); ! 234: } else if (pathp != path && pathp[-1] != '/') ! 235: *pathp++ = '/'; ! 236: strcpy(pathp, name); ! 237: pathp += n; ! 238: } ! 239: ! 240: usage() ! 241: { ! 242: fputs("usage: rm [-rif] file ...\n", stderr); ! 243: exit(1); ! 244: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.