Annotation of researchv9/cmd/mv.c, revision 1.1

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

unix.superglobalmegacorp.com

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