Annotation of 43BSDTahoe/bin/mv.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif /* not lint */
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)mv.c       5.7 (Berkeley) 4/21/88";
                     15: #endif /* not lint */
                     16: 
                     17: /*
                     18:  * mv file1 file2
                     19:  */
                     20: #include <sys/param.h>
                     21: #include <sys/stat.h>
                     22: #include <sys/time.h>
                     23: #include <sys/file.h>
                     24: #include <stdio.h>
                     25: #include <errno.h>
                     26: 
                     27: #define        DELIM   '/'
                     28: #define MODEBITS 07777
                     29: 
                     30: #define        ISDIR(st)       (((st).st_mode&S_IFMT) == S_IFDIR)
                     31: #define        ISLNK(st)       (((st).st_mode&S_IFMT) == S_IFLNK)
                     32: #define        ISREG(st)       (((st).st_mode&S_IFMT) == S_IFREG)
                     33: #define        ISDEV(st) \
                     34:        (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
                     35: 
                     36: char   *dname();
                     37: int    iflag = 0;      /* interactive mode */
                     38: int    fflag = 0;      /* force overwriting */
                     39: extern unsigned errno;
                     40: 
                     41: main(argc, argv)
                     42:        register int argc;
                     43:        register char **argv;
                     44: {
                     45:        extern int optind;
                     46:        struct stat st;
                     47:        int ch, r;
                     48:        char *dest;
                     49: 
                     50:        while ((ch = getopt(argc, argv, "-fi")) != EOF)
                     51:                switch((char)ch) {
                     52:                case '-':
                     53:                        goto endarg;
                     54:                case 'f':
                     55:                        fflag++;
                     56:                        break;
                     57:                case 'i':
                     58:                        iflag++;
                     59:                        break;
                     60:                case '?':
                     61:                default:
                     62:                        usage();
                     63:                }
                     64: endarg:        argv += optind;
                     65:        argc -= optind;
                     66: 
                     67:        if (argc < 2)
                     68:                usage();
                     69:        dest = argv[argc - 1];
                     70:        if (stat(dest, &st) >= 0 && ISDIR(st)) {
                     71:                for (r = 0; --argc; ++argv)
                     72:                        r |= movewithshortname(*argv, dest);
                     73:                exit(r);
                     74:        }
                     75:        if (argc != 2)
                     76:                usage();
                     77:        r = move(argv[0], argv[1]);
                     78:        exit(r);
                     79: }
                     80: 
                     81: movewithshortname(src, dest)
                     82:        char *src, *dest;
                     83: {
                     84:        register char *shortname;
                     85:        char target[MAXPATHLEN + 1];
                     86: 
                     87:        shortname = dname(src);
                     88:        if (strlen(dest) + strlen(shortname) > MAXPATHLEN - 1) {
                     89:                error("%s/%s: pathname too long", dest,
                     90:                        shortname);
                     91:                return (1);
                     92:        }
                     93:        (void)sprintf(target, "%s/%s", dest, shortname);
                     94:        return (move(src, target));
                     95: }
                     96: 
                     97: move(source, target)
                     98:        char *source, *target;
                     99: {
                    100:        int targetexists;
                    101:        struct stat s1, s2;
                    102: 
                    103:        if (lstat(source, &s1) < 0) {
                    104:                Perror2(source, "Cannot access");
                    105:                return (1);
                    106:        }
                    107:        /*
                    108:         * First, try to rename source to destination.
                    109:         * The only reason we continue on failure is if
                    110:         * the move is on a nondirectory and not across
                    111:         * file systems.
                    112:         */
                    113:        targetexists = lstat(target, &s2) >= 0;
                    114:        if (targetexists) {
                    115:                if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
                    116:                        error("%s and %s are identical", source, target);
                    117:                        return (1);
                    118:                }
                    119:                if (!fflag && isatty(fileno(stdin)))
                    120:                        if (iflag) {
                    121:                                if (!query("remove %s? ", target))
                    122:                                        return (1);
                    123:                        }
                    124:                        else if (access(target, W_OK) < 0 &&
                    125:                            !query("override protection %o for %s? ",
                    126:                            s2.st_mode & MODEBITS, target))
                    127:                                return (1);
                    128:        }
                    129:        if (rename(source, target) >= 0)
                    130:                return (0);
                    131:        if (errno != EXDEV) {
                    132:                Perror2(errno == ENOENT && targetexists == 0 ? target : source,
                    133:                    "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:                Perror2(target, "Cannot unlink");
                    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 + 1];
                    152: 
                    153:                m = readlink(source, symln, sizeof (symln) - 1);
                    154:                if (m < 0) {
                    155:                        Perror(source);
                    156:                        return (1);
                    157:                }
                    158:                symln[m] = '\0';
                    159: 
                    160:                (void) umask(~(s1.st_mode & MODEBITS));
                    161:                if (symlink(symln, target) < 0) {
                    162:                        Perror(target);
                    163:                        return (1);
                    164:                }
                    165:                goto cleanup;
                    166:        }
                    167:        (void) umask(0);
                    168:        if (ISDEV(s1)) {
                    169:                struct timeval tv[2];
                    170: 
                    171:                if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
                    172:                        Perror(target);
                    173:                        return (1);
                    174:                }
                    175: 
                    176:                tv[0].tv_sec = s1.st_atime;
                    177:                tv[0].tv_usec = 0;
                    178:                tv[1].tv_sec = s1.st_mtime;
                    179:                tv[1].tv_usec = 0;
                    180:                (void) utimes(target, tv);
                    181:                goto cleanup;
                    182:        }
                    183:        if (ISREG(s1)) {
                    184:                register int fi, fo, n;
                    185:                struct timeval tv[2];
                    186:                char buf[MAXBSIZE];
                    187: 
                    188:                fi = open(source, 0);
                    189:                if (fi < 0) {
                    190:                        Perror(source);
                    191:                        return (1);
                    192:                }
                    193: 
                    194:                fo = creat(target, s1.st_mode & MODEBITS);
                    195:                if (fo < 0) {
                    196:                        Perror(target);
                    197:                        close(fi);
                    198:                        return (1);
                    199:                }
                    200: 
                    201:                for (;;) {
                    202:                        n = read(fi, buf, sizeof buf);
                    203:                        if (n == 0) {
                    204:                                break;
                    205:                        } else if (n < 0) {
                    206:                                Perror2(source, "read");
                    207:                                close(fi);
                    208:                                close(fo);
                    209:                                return (1);
                    210:                        } else if (write(fo, buf, n) != n) {
                    211:                                Perror2(target, "write");
                    212:                                close(fi);
                    213:                                close(fo);
                    214:                                return (1);
                    215:                        }
                    216:                }
                    217: 
                    218:                close(fi);
                    219:                close(fo);
                    220: 
                    221:                tv[0].tv_sec = s1.st_atime;
                    222:                tv[0].tv_usec = 0;
                    223:                tv[1].tv_sec = s1.st_mtime;
                    224:                tv[1].tv_usec = 0;
                    225:                (void) utimes(target, tv);
                    226:                goto cleanup;
                    227:        }
                    228:        error("%s: unknown file type %o", source, s1.st_mode);
                    229:        return (1);
                    230: 
                    231: cleanup:
                    232:        if (unlink(source) < 0) {
                    233:                Perror2(source, "Cannot unlink");
                    234:                return (1);
                    235:        }
                    236:        return (0);
                    237: }
                    238: 
                    239: /*VARARGS*/
                    240: query(prompt, a1, a2)
                    241:        char *a1;
                    242: {
                    243:        register int i, c;
                    244: 
                    245:        fprintf(stderr, prompt, a1, a2);
                    246:        i = c = getchar();
                    247:        while (c != '\n' && c != EOF)
                    248:                c = getchar();
                    249:        return (i == 'y');
                    250: }
                    251: 
                    252: char *
                    253: dname(name)
                    254:        register char *name;
                    255: {
                    256:        register char *p;
                    257: 
                    258:        p = name;
                    259:        while (*p)
                    260:                if (*p++ == DELIM && *p)
                    261:                        name = p;
                    262:        return name;
                    263: }
                    264: 
                    265: /*VARARGS*/
                    266: error(fmt, a1, a2)
                    267:        char *fmt;
                    268: {
                    269: 
                    270:        fprintf(stderr, "mv: ");
                    271:        fprintf(stderr, fmt, a1, a2);
                    272:        fprintf(stderr, "\n");
                    273: }
                    274: 
                    275: Perror(s)
                    276:        char *s;
                    277: {
                    278:        char buf[MAXPATHLEN + 10];
                    279: 
                    280:        (void)sprintf(buf, "mv: %s", s);
                    281:        perror(buf);
                    282: }
                    283: 
                    284: Perror2(s1, s2)
                    285:        char *s1, *s2;
                    286: {
                    287:        char buf[MAXPATHLEN + 20];
                    288: 
                    289:        (void)sprintf(buf, "mv: %s: %s", s1, s2);
                    290:        perror(buf);
                    291: }
                    292: 
                    293: usage()
                    294: {
                    295:        fputs("usage: mv [-if] file1 file2 or mv [-if] file/directory ... directory\n", stderr);
                    296:        exit(1);
                    297: }

unix.superglobalmegacorp.com

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