Annotation of 40BSD/cmd/mv.c, revision 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.