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