Annotation of 40BSD/cmd/mv.c, revision 1.1.1.1

1.1       root        1: static char *sccsid = "@(#)mv.c        4.1 (Berkeley) 10/6/80";
                      2: /*
                      3:  * mv file1 file2
                      4:  */
                      5: 
                      6: #include <stdio.h>
                      7: #include <sys/types.h>
                      8: #include <sys/stat.h>
                      9: #include <sys/dir.h>
                     10: #include <signal.h>
                     11: 
                     12: #define        DOT     "."
                     13: #define        DOTDOT  ".."
                     14: #define        DELIM   '/'
                     15: #define SDELIM "/"
                     16: #define        MAXN    100
                     17: #define MODEBITS 07777
                     18: #define ROOTINO 2
                     19: 
                     20: char   *pname();
                     21: char   *sprintf();
                     22: char   *dname();
                     23: struct stat s1, s2;
                     24: int    iflag = 0;      /* interactive flag. If this flag is set,
                     25:                         * the user is queried before files are
                     26:                         * destroyed by cp.
                     27:                         */
                     28: int    fflag = 0;      /* force flag. supercedes all restrictions */
                     29: 
                     30: main(argc, argv)
                     31: register char *argv[];
                     32: {
                     33:        register i, r;
                     34: 
                     35:        /* get the flag(s) */
                     36: 
                     37:        if (argc < 2)
                     38:                goto usage;
                     39:        if (*argv[1] == '-') {
                     40:                argc--;
                     41:                while (*++argv[1] != '\0')
                     42:                        switch (*argv[1]) {
                     43: 
                     44:                        /* interactive mode */
                     45:                        case 'i':
                     46:                                iflag++;
                     47:                                break;
                     48: 
                     49:                        /* force moves */
                     50:                        case 'f':
                     51:                                fflag++;
                     52:                                break;
                     53: 
                     54:                        /* don't live with bad options */
                     55:                        default:
                     56:                                goto usage;
                     57:                        }
                     58:                argv++;
                     59:        }
                     60:        if (argc < 3)
                     61:                goto usage;
                     62:        if (stat(argv[1], &s1) < 0) {
                     63:                fprintf(stderr, "mv: cannot access %s\n", argv[1]);
                     64:                return(1);
                     65:        }
                     66:        if ((s1.st_mode & S_IFMT) == S_IFDIR) {
                     67:                if (argc != 3)
                     68:                        goto usage;
                     69:                return mvdir(argv[1], argv[2]);
                     70:        }
                     71:        setuid(getuid());
                     72:        if (argc > 3)
                     73:                if (stat(argv[argc-1], &s2) < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
                     74:                        goto usage;
                     75:        r = 0;
                     76:        for (i=1; i<argc-1; i++)
                     77:                r |= move(argv[i], argv[argc-1]);
                     78:        return(r);
                     79: usage:
                     80:        fprintf(stderr, "usage: mv f1 f2; or mv d1 d2; or mv f1 ... fn d1\n");
                     81:        return(1);
                     82: }
                     83: 
                     84: move(source, target)
                     85: char *source, *target;
                     86: {
                     87:        register c, i;
                     88:        int     status;
                     89:        char    buf[MAXN];
                     90: 
                     91:        if (stat(source, &s1) < 0) {
                     92:                fprintf(stderr, "mv: cannot access %s\n", source);
                     93:                return(1);
                     94:        }
                     95:        if ((s1.st_mode & S_IFMT) == S_IFDIR) {
                     96:                fprintf(stderr, "mv: directory rename only\n");
                     97:                return(1);
                     98:        }
                     99:        if (stat(target, &s2) >= 0) {
                    100:                if ((s2.st_mode & S_IFMT) == S_IFDIR) {
                    101:                        sprintf(buf, "%s/%s", target, dname(source));
                    102:                        target = buf;
                    103:                }
                    104:                if (stat(target, &s2) >= 0) {
                    105:                        if ((s2.st_mode & S_IFMT) == S_IFDIR) {
                    106:                                fprintf(stderr, "mv: %s is a directory\n", target);
                    107:                                return(1);
                    108:                        } else if (iflag && !fflag) {
                    109:                                fprintf(stderr, "remove %s? ", target);
                    110:                                i = c = getchar();
                    111:                                while (c != '\n' && c != EOF)
                    112:                                        c = getchar();
                    113:                                if (i != 'y')
                    114:                                        return(1);
                    115:                        }
                    116:                        if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) {
                    117:                                fprintf(stderr, "mv: %s and %s are identical\n",
                    118:                                                source, target);
                    119:                                return(1);
                    120:                        }
                    121:                        if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
                    122:                                fprintf(stderr, "override protection %o for %s? ", 
                    123:                                        s2.st_mode & MODEBITS, target);
                    124:                                i = c = getchar();
                    125:                                while (c != '\n' && c != EOF)
                    126:                                        c = getchar();
                    127:                                if (i != 'y')
                    128:                                        return(1);
                    129:                        }
                    130:                        if (unlink(target) < 0) {
                    131:                                fprintf(stderr, "mv: cannot unlink %s\n", target);
                    132:                                return(1);
                    133:                        }
                    134:                }
                    135:        }
                    136:        if (link(source, target) < 0) {
                    137:                i = fork();
                    138:                if (i == -1) {
                    139:                        fprintf(stderr, "mv: try again\n");
                    140:                        return(1);
                    141:                }
                    142:                if (i == 0) {
                    143:                        execl("/bin/cp", "cp", source, target, 0);
                    144:                        fprintf(stderr, "mv: cannot exec cp\n");
                    145:                        exit(1);
                    146:                }
                    147:                while ((c = wait(&status)) != i && c != -1)
                    148:                        ;
                    149:                if (status != 0)
                    150:                        return(1);
                    151:                utime(target, &s1.st_atime);
                    152:        }
                    153:        if (unlink(source) < 0) {
                    154:                fprintf(stderr, "mv: cannot unlink %s\n", source);
                    155:                return(1);
                    156:        }
                    157:        return(0);
                    158: }
                    159: 
                    160: mvdir(source, target)
                    161: char *source, *target;
                    162: {
                    163:        register char *p;
                    164:        register i;
                    165:        char buf[MAXN];
                    166:        char c,cc;
                    167: 
                    168:        if (stat(target, &s2) >= 0) {
                    169:                if ((s2.st_mode&S_IFMT) != S_IFDIR) {
                    170:                        fprintf(stderr, "mv: %s exists\n", target);
                    171:                        return(1);
                    172:                } else if (iflag && !fflag) {
                    173:                        fprintf(stderr, "remove %s? ", target);
                    174:                        cc = c = getchar();
                    175:                        while (c != '\n' && c != EOF)
                    176:                                c = getchar();
                    177:                        if (cc != 'y')
                    178:                                return(1);
                    179:                }
                    180:                if (strlen(target) > MAXN-DIRSIZ-2) {
                    181:                        fprintf(stderr, "mv :target name too long\n");
                    182:                        return(1);
                    183:                }
                    184:                strcpy(buf, target);
                    185:                target = buf;
                    186:                strcat(buf, SDELIM);
                    187:                strcat(buf, dname(source));
                    188:                if (stat(target, &s2) >= 0) {
                    189:                        fprintf(stderr, "mv: %s exists\n", buf);
                    190:                        return(1);
                    191:                }
                    192:        }
                    193:        if (strcmp(source, target) == 0) {
                    194:                fprintf(stderr, "mv: ?? source == target, source exists and target doesnt\n");
                    195:                return(1);
                    196:        }
                    197:        p = dname(source);
                    198:        if (!strcmp(p, DOT) || !strcmp(p, DOTDOT) || !strcmp(p, "") || p[strlen(p)-1]=='/') {
                    199:                fprintf(stderr, "mv: cannot rename %s\n", p);
                    200:                return(1);
                    201:        }
                    202:        if (stat(pname(source), &s1) < 0 || stat(pname(target), &s2) < 0) {
                    203:                fprintf(stderr, "mv: cannot locate parent\n");
                    204:                return(1);
                    205:        }
                    206:        if (access(pname(target), 2) < 0) {
                    207:                fprintf(stderr, "mv: no write access to %s\n", pname(target));
                    208:                return(1);
                    209:        }
                    210:        if (access(pname(source), 2) < 0) {
                    211:                fprintf(stderr, "mv: no write access to %s\n", pname(source));
                    212:                return(1);
                    213:        }
                    214:        if (access(source, 2) < 0) {
                    215:                fprintf(stderr, "mv: no write access to %s\n", source);
                    216:                return(1);
                    217:        }
                    218:        if (s1.st_dev != s2.st_dev) {
                    219:                fprintf(stderr, "mv: cannot move directories across devices\n");
                    220:                return(1);
                    221:        }
                    222:        if (s1.st_ino != s2.st_ino) {
                    223:                char dst[MAXN+5];
                    224: 
                    225:                if (chkdot(source) || chkdot(target)) {
                    226:                        fprintf(stderr, "mv: Sorry, path names including %s aren't allowed\n", DOTDOT);
                    227:                        return(1);
                    228:                }
                    229:                stat(source, &s1);
                    230:                if (check(pname(target), s1.st_ino))
                    231:                        return(1);
                    232:                for (i = 1; i <= NSIG; i++)
                    233:                        signal(i, SIG_IGN);
                    234:                if (link(source, target) < 0) {
                    235:                        fprintf(stderr, "mv: cannot link %s to %s\n", target, source);
                    236:                        return(1);
                    237:                }
                    238:                if (unlink(source) < 0) {
                    239:                        fprintf(stderr, "mv: %s: cannot unlink\n", source);
                    240:                        unlink(target);
                    241:                        return(1);
                    242:                }
                    243:                strcat(dst, target);
                    244:                strcat(dst, "/");
                    245:                strcat(dst, DOTDOT);
                    246:                if (unlink(dst) < 0) {
                    247:                        fprintf(stderr, "mv: %s: cannot unlink\n", dst);
                    248:                        if (link(target, source) >= 0)
                    249:                                unlink(target);
                    250:                        return(1);
                    251:                }
                    252:                if (link(pname(target), dst) < 0) {
                    253:                        fprintf(stderr, "mv: cannot link %s to %s\n",
                    254:                                dst, pname(target));
                    255:                        if (link(pname(source), dst) >= 0)
                    256:                                if (link(target, source) >= 0)
                    257:                                        unlink(target);
                    258:                        return(1);
                    259:                }
                    260:                return(0);
                    261:        }
                    262:        if (link(source, target) < 0) {
                    263:                fprintf(stderr, "mv: cannot link %s and %s\n",
                    264:                        source, target);
                    265:                return(1);
                    266:        }
                    267:        if (unlink(source) < 0) {
                    268:                fprintf(stderr, "mv: ?? cannot unlink %s\n", source);
                    269:                return(1);
                    270:        }
                    271:        return(0);
                    272: }
                    273: 
                    274: char *
                    275: pname(name)
                    276: register char *name;
                    277: {
                    278:        register c;
                    279:        register char *p, *q;
                    280:        static  char buf[MAXN];
                    281: 
                    282:        p = q = buf;
                    283:        while (c = *p++ = *name++)
                    284:                if (c == DELIM)
                    285:                        q = p-1;
                    286:        if (q == buf && *q == DELIM)
                    287:                q++;
                    288:        *q = 0;
                    289:        return buf[0]? buf : DOT;
                    290: }
                    291: 
                    292: char *
                    293: dname(name)
                    294: register char *name;
                    295: {
                    296:        register char *p;
                    297: 
                    298:        p = name;
                    299:        while (*p)
                    300:                if (*p++ == DELIM && *p)
                    301:                        name = p;
                    302:        return name;
                    303: }
                    304: 
                    305: check(spth, dinode)
                    306: char *spth;
                    307: ino_t dinode;
                    308: {
                    309:        char nspth[MAXN];
                    310:        struct stat sbuf;
                    311: 
                    312:        sbuf.st_ino = 0;
                    313: 
                    314:        strcpy(nspth, spth);
                    315:        while (sbuf.st_ino != ROOTINO) {
                    316:                if (stat(nspth, &sbuf) < 0) {
                    317:                        fprintf(stderr, "mv: cannot access %s\n", nspth);
                    318:                        return(1);
                    319:                }
                    320:                if (sbuf.st_ino == dinode) {
                    321:                        fprintf(stderr, "mv: cannot move a directory into itself\n");
                    322:                        return(1);
                    323:                }
                    324:                if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) {
                    325:                        fprintf(stderr, "mv: name too long\n");
                    326:                        return(1);
                    327:                }
                    328:                strcat(nspth, SDELIM);
                    329:                strcat(nspth, DOTDOT);
                    330:        }
                    331:        return(0);
                    332: }
                    333: 
                    334: chkdot(s)
                    335: register char *s;
                    336: {
                    337:        do {
                    338:                if (strcmp(dname(s), DOTDOT) == 0)
                    339:                        return(1);
                    340:                s = pname(s);
                    341:        } while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0);
                    342:        return(0);
                    343: }

unix.superglobalmegacorp.com

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