Annotation of 42BSD/bin/mv.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *sccsid = "@(#)mv.c        4.13 (Berkeley) 83/06/30";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * mv file1 file2
        !             7:  */
        !             8: #include <sys/param.h>
        !             9: #include <sys/stat.h>
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include <sys/dir.h>
        !            13: #include <errno.h>
        !            14: #include <signal.h>
        !            15: 
        !            16: #define        DELIM   '/'
        !            17: #define MODEBITS 07777
        !            18: 
        !            19: #define        ISDIR(st)       (((st).st_mode&S_IFMT) == S_IFDIR)
        !            20: #define        ISLNK(st)       (((st).st_mode&S_IFMT) == S_IFLNK)
        !            21: #define        ISREG(st)       (((st).st_mode&S_IFMT) == S_IFREG)
        !            22: #define        ISDEV(st) \
        !            23:        (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
        !            24: 
        !            25: char   *sprintf();
        !            26: char   *dname();
        !            27: struct stat s1, s2;
        !            28: int    iflag = 0;      /* interactive mode */
        !            29: int    fflag = 0;      /* force overwriting */
        !            30: extern unsigned errno;
        !            31: 
        !            32: main(argc, argv)
        !            33:        register char *argv[];
        !            34: {
        !            35:        register i, r;
        !            36:        register char *arg;
        !            37:        char *dest;
        !            38: 
        !            39:        if (argc < 2)
        !            40:                goto usage;
        !            41:        while (argc > 1 && *argv[1] == '-') {
        !            42:                argc--;
        !            43:                arg = *++argv;
        !            44: 
        !            45:                /*
        !            46:                 * all files following a null option
        !            47:                 * are considered file names
        !            48:                 */
        !            49:                if (*(arg+1) == '\0')
        !            50:                        break;
        !            51:                while (*++arg != '\0') switch (*arg) {
        !            52: 
        !            53:                case 'i':
        !            54:                        iflag++;
        !            55:                        break;
        !            56: 
        !            57:                case 'f':
        !            58:                        fflag++;
        !            59:                        break;
        !            60: 
        !            61:                default:
        !            62:                        goto usage;
        !            63:                }
        !            64:        }
        !            65:        if (argc < 3)
        !            66:                goto usage;
        !            67:        dest = argv[argc-1];
        !            68:        if (stat(dest, &s2) >= 0 && ISDIR(s2)) {
        !            69:                r = 0;
        !            70:                for (i = 1; i < argc-1; i++)
        !            71:                        r |= movewithshortname(argv[i], dest);
        !            72:                exit(r);
        !            73:        }
        !            74:        if (argc > 3)
        !            75:                goto usage;
        !            76:        r = move(argv[1], argv[2]);
        !            77:        exit(r);
        !            78:        /*NOTREACHED*/
        !            79: usage:
        !            80:        fprintf(stderr,
        !            81: "usage: mv [-if] f1 f2 or mv [-if] f1 ... fn d1 (`fn' is a file or directory)\n");
        !            82:        return (1);
        !            83: }
        !            84: 
        !            85: movewithshortname(src, dest)
        !            86:        char *src, *dest;
        !            87: {
        !            88:        register char *shortname;
        !            89:        char target[MAXPATHLEN + 1];
        !            90: 
        !            91:        shortname = dname(src);
        !            92:        if (strlen(dest) + strlen(shortname) > MAXPATHLEN - 1) {
        !            93:                error("%s/%s: pathname too long", dest,
        !            94:                        shortname);
        !            95:                return (1);
        !            96:        }
        !            97:        sprintf(target, "%s/%s", dest, shortname);
        !            98:        return (move(src, target));
        !            99: }
        !           100: 
        !           101: move(source, target)
        !           102:        char *source, *target;
        !           103: {
        !           104:        int targetexists;
        !           105: 
        !           106:        if (lstat(source, &s1) < 0) {
        !           107:                error("cannot access %s", source);
        !           108:                return (1);
        !           109:        }
        !           110:        /*
        !           111:         * First, try to rename source to destination.
        !           112:         * The only reason we continue on failure is if
        !           113:         * the move is on a nondirectory and not across
        !           114:         * file systems.
        !           115:         */
        !           116:        targetexists = lstat(target, &s2) >= 0;
        !           117:        if (targetexists) {
        !           118:                if (iflag && !fflag && query("remove %s? ", target) == 0)
        !           119:                        return (1);
        !           120:                if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
        !           121:                        error("%s and %s are identical", source, target);
        !           122:                        return (1);
        !           123:                }
        !           124:                if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
        !           125:                        if (query("override protection %o for %s? ",
        !           126:                          s2.st_mode & MODEBITS, target) == 0)
        !           127:                                return (1);
        !           128:                }
        !           129:        }
        !           130:        if (rename(source, target) >= 0)
        !           131:                return (0);
        !           132:        if (errno != EXDEV) {
        !           133:                Perror2(source, "rename");
        !           134:                return (1);
        !           135:        }
        !           136:        if (ISDIR(s1)) {
        !           137:                error("can't mv directories across file systems");
        !           138:                return (1);
        !           139:        }
        !           140:        if (targetexists && unlink(target) < 0) {
        !           141:                error("cannot unlink %s", target);
        !           142:                return (1);
        !           143:        }
        !           144:        /*
        !           145:         * File can't be renamed, try to recreate the symbolic
        !           146:         * link or special device, or copy the file wholesale
        !           147:         * between file systems.
        !           148:         */
        !           149:        if (ISLNK(s1)) {
        !           150:                register m;
        !           151:                char symln[MAXPATHLEN];
        !           152: 
        !           153:                if (readlink(source, symln, sizeof (symln)) < 0) {
        !           154:                        Perror(source);
        !           155:                        return (1);
        !           156:                }
        !           157:                m = umask(~(s1.st_mode & MODEBITS));
        !           158:                if (symlink(symln, target) < 0) {
        !           159:                        Perror(target);
        !           160:                        return (1);
        !           161:                }
        !           162:                (void) umask(m);
        !           163:                goto cleanup;
        !           164:        }
        !           165:        if (ISDEV(s1)) {
        !           166:                time_t tv[2];
        !           167: 
        !           168:                if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
        !           169:                        Perror(target);
        !           170:                        return (1);
        !           171:                }
        !           172:                /* kludge prior to utimes */
        !           173:                tv[0] = s1.st_atime;
        !           174:                tv[1] = s1.st_mtime;
        !           175:                (void) utime(target, tv);
        !           176:                goto cleanup;
        !           177:        }
        !           178:        if (ISREG(s1)) {
        !           179:                int i, c, status;
        !           180:                time_t tv[2];
        !           181: 
        !           182:                i = fork();
        !           183:                if (i == -1) {
        !           184:                        error("try again");
        !           185:                        return (1);
        !           186:                }
        !           187:                if (i == 0) {
        !           188:                        execl("/bin/cp", "cp", source, target, 0);
        !           189:                        error("cannot exec /bin/cp");
        !           190:                        exit(1);
        !           191:                }
        !           192:                while ((c = wait(&status)) != i && c != -1)
        !           193:                        ;
        !           194:                if (status != 0)
        !           195:                        return (1);
        !           196:                /* kludge prior to utimes */
        !           197:                tv[0] = s1.st_atime;
        !           198:                tv[1] = s1.st_mtime;
        !           199:                (void) utime(target, tv);
        !           200:                goto cleanup;
        !           201:        }
        !           202:        error("%s: unknown file type %o", source, s1.st_mode);
        !           203:        return (1);
        !           204: 
        !           205: cleanup:
        !           206:        if (unlink(source) < 0) {
        !           207:                error("cannot unlink %s", source);
        !           208:                return (1);
        !           209:        }
        !           210:        return (0);
        !           211: }
        !           212: 
        !           213: /*VARARGS*/
        !           214: query(prompt, a1, a2)
        !           215:        char *a1;
        !           216: {
        !           217:        register char i, c;
        !           218: 
        !           219:        fprintf(stderr, prompt, a1, a2);
        !           220:        i = c = getchar();
        !           221:        while (c != '\n' && c != EOF)
        !           222:                c = getchar();
        !           223:        return (i == 'y');
        !           224: }
        !           225: 
        !           226: char *
        !           227: dname(name)
        !           228:        register char *name;
        !           229: {
        !           230:        register char *p;
        !           231: 
        !           232:        p = name;
        !           233:        while (*p)
        !           234:                if (*p++ == DELIM && *p)
        !           235:                        name = p;
        !           236:        return name;
        !           237: }
        !           238: 
        !           239: /*VARARGS*/
        !           240: error(fmt, a1, a2)
        !           241:        char *fmt;
        !           242: {
        !           243: 
        !           244:        fprintf(stderr, "mv: ");
        !           245:        fprintf(stderr, fmt, a1, a2);
        !           246:        fprintf(stderr, "\n");
        !           247: }
        !           248: 
        !           249: Perror(s)
        !           250:        char *s;
        !           251: {
        !           252:        char buf[MAXPATHLEN + 10];
        !           253:        
        !           254:        sprintf(buf, "mv: %s", s);
        !           255:        perror(buf);
        !           256: }
        !           257: 
        !           258: Perror2(s1, s2)
        !           259:        char *s1, *s2;
        !           260: {
        !           261:        char buf[MAXPATHLEN + 20];
        !           262: 
        !           263:        sprintf(buf, "mv: %s: %s", s1, s2);
        !           264:        perror(buf);
        !           265: }

unix.superglobalmegacorp.com

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