Annotation of 43BSD/bin/rm.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.