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

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Ken Smith of The State University of New York at Buffalo.
                      7:  *
                      8:  * Redistribution and use in source and binary forms are permitted provided
                      9:  * that: (1) source distributions retain this entire copyright notice and
                     10:  * comment, and (2) distributions including binaries display the following
                     11:  * acknowledgement:  ``This product includes software developed by the
                     12:  * University of California, Berkeley and its contributors'' in the
                     13:  * documentation or other materials provided with the distribution and in
                     14:  * all advertising materials mentioning features or use of this software.
                     15:  * Neither the name of the University nor the names of its contributors may
                     16:  * be used to endorse or promote products derived from this software without
                     17:  * specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     19:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     20:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  */
                     22: 
                     23: #ifndef lint
                     24: char copyright[] =
                     25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
                     26:  All rights reserved.\n";
                     27: #endif /* not lint */
                     28: 
                     29: #ifndef lint
                     30: static char sccsid[] = "@(#)mv.c       5.9 (Berkeley) 5/31/90";
                     31: #endif /* not lint */
                     32: 
                     33: #include <sys/param.h>
                     34: #include <sys/time.h>
                     35: #include <sys/wait.h>
                     36: #include <sys/stat.h>
                     37: #include <sys/file.h>
                     38: #include <sys/errno.h>
                     39: #include <stdio.h>
                     40: #include <string.h>
                     41: #include "pathnames.h"
                     42: 
                     43: extern int errno;
                     44: int fflg, iflg;
                     45: 
                     46: main(argc, argv)
                     47:        int argc;
                     48:        char **argv;
                     49: {
                     50:        extern char *optarg;
                     51:        extern int optind;
                     52:        register int baselen, exitval, len;
                     53:        register char *p, *endp;
                     54:        struct stat sbuf;
                     55:        int ch;
                     56:        char path[MAXPATHLEN + 1];
                     57: 
                     58:        while (((ch = getopt(argc, argv, "-if")) != EOF))
                     59:                switch((char)ch) {
                     60:                case 'i':
                     61:                        ++iflg;
                     62:                        break;
                     63:                case 'f':
                     64:                        ++fflg;
                     65:                        break;
                     66:                case '-':               /* undocumented; for compatibility */
                     67:                        goto endarg;
                     68:                case '?':
                     69:                default:
                     70:                        usage();
                     71:                }
                     72: endarg:        argc -= optind;
                     73:        argv += optind;
                     74: 
                     75:        if (argc < 2)
                     76:                usage();
                     77: 
                     78:        /*
                     79:         * if stat fails on target, it doesn't exist (or can't be accessed
                     80:         * by the user, doesn't matter which) try the move.  If target exists,
                     81:         * and isn't a directory, try the move.  More than 2 arguments is an
                     82:         * error.
                     83:         */
                     84:        if (stat(argv[argc - 1], &sbuf) || !S_ISDIR(sbuf.st_mode)) {
                     85:                if (argc > 2)
                     86:                        usage();
                     87:                exit(do_move(argv[0], argv[1]));
                     88:        }
                     89: 
                     90:        /* got a directory, move each file into it */
                     91:        (void)strcpy(path, argv[argc - 1]);
                     92:        baselen = strlen(path);
                     93:        endp = &path[baselen];
                     94:        *endp++ = '/';
                     95:        ++baselen;
                     96:        for (exitval = 0; --argc; ++argv) {
                     97:                if ((p = rindex(*argv, '/')) == NULL)
                     98:                        p = *argv;
                     99:                else
                    100:                        ++p;
                    101:                if ((baselen + (len = strlen(p))) >= MAXPATHLEN)
                    102:                        (void)fprintf(stderr,
                    103:                            "mv: %s: destination pathname too long\n", *argv);
                    104:                else {
                    105:                        bcopy(p, endp, len + 1);
                    106:                        exitval |= do_move(*argv, path);
                    107:                }
                    108:        }
                    109:        exit(exitval);
                    110: }
                    111: 
                    112: do_move(from, to)
                    113:        char *from, *to;
                    114: {
                    115:        struct stat sbuf;
                    116:        int ask, ch;
                    117: 
                    118:        /*
                    119:         * Check access.  If interactive and file exists ask user if it
                    120:         * should be replaced.  Otherwise if file exists but isn't writable
                    121:         * make sure the user wants to clobber it.
                    122:         */
                    123:        if (!fflg && !access(to, F_OK)) {
                    124:                ask = 0;
                    125:                if (iflg) {
                    126:                        (void)fprintf(stderr, "overwrite %s? ", to);
                    127:                        ask = 1;
                    128:                }
                    129:                else if (access(to, W_OK) && !stat(to, &sbuf)) {
                    130:                        (void)fprintf(stderr, "override mode %o on %s? ",
                    131:                            sbuf.st_mode & 07777, to);
                    132:                        ask = 1;
                    133:                }
                    134:                if (ask) {
                    135:                        if ((ch = getchar()) != EOF && ch != '\n')
                    136:                                while (getchar() != '\n');
                    137:                        if (ch != 'y')
                    138:                                return(0);
                    139:                }
                    140:        }
                    141:        if (!rename(from, to))
                    142:                return(0);
                    143:        if (errno != EXDEV) {
                    144:                (void)fprintf(stderr,
                    145:                    "mv: rename %s to %s: %s\n", from, to, strerror(errno));
                    146:                return(1);
                    147:        }
                    148:        /*
                    149:         * if rename fails, and it's a regular file, do the copy
                    150:         * internally; otherwise, use cp and rm.
                    151:         */
                    152:        if (stat(from, &sbuf)) {
                    153:                (void)fprintf(stderr,
                    154:                    "mv: %s: %s\n", from, strerror(errno));
                    155:                return(1);
                    156:        }
                    157:        return(S_ISREG(sbuf.st_mode) ?
                    158:            fastcopy(from, to, &sbuf) : copy(from, to));
                    159: }
                    160: 
                    161: fastcopy(from, to, sbp)
                    162:        char *from, *to;
                    163:        struct stat *sbp;
                    164: {
                    165:        struct timeval tval[2];
                    166:        static u_int blen;
                    167:        static char *bp;
                    168:        register int nread, from_fd, to_fd;
                    169:        char *malloc();
                    170: 
                    171:        if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
                    172:                (void)fprintf(stderr,
                    173:                    "mv: %s: %s\n", from, strerror(errno));
                    174:                return(1);
                    175:        }
                    176:        if ((to_fd = open(to, O_WRONLY|O_CREAT|O_TRUNC, sbp->st_mode)) < 0) {
                    177:                (void)fprintf(stderr,
                    178:                    "mv: %s: %s\n", to, strerror(errno));
                    179:                (void)close(from_fd);
                    180:                return(1);
                    181:        }
                    182:        if (!blen && !(bp = malloc(blen = sbp->st_blksize))) {
                    183:                (void)fprintf(stderr, "mv: %s: out of memory.\n", from);
                    184:                return(1);
                    185:        }
                    186:        while ((nread = read(from_fd, bp, blen)) > 0)
                    187:                if (write(to_fd, bp, nread) != nread) {
                    188:                        (void)fprintf(stderr, "mv: %s: %s\n",
                    189:                            to, strerror(errno));
                    190:                        goto err;
                    191:                }
                    192:        if (nread < 0) {
                    193:                (void)fprintf(stderr, "mv: %s: %s\n", from, strerror(errno));
                    194: err:           (void)unlink(to);
                    195:                (void)close(from_fd);
                    196:                (void)close(to_fd);
                    197:                return(1);
                    198:        }
                    199:        (void)fchown(to_fd, sbp->st_uid, sbp->st_gid);
                    200:        (void)fchmod(to_fd, sbp->st_mode);
                    201: 
                    202:        (void)close(from_fd);
                    203:        (void)close(to_fd);
                    204: 
                    205:        tval[0].tv_sec = sbp->st_atime;
                    206:        tval[1].tv_sec = sbp->st_mtime;
                    207:        tval[0].tv_usec = tval[1].tv_usec = 0;
                    208:        (void)utimes(to, tval);
                    209:        (void)unlink(from);
                    210:        return(0);
                    211: }
                    212: 
                    213: copy(from, to)
                    214:        char *from, *to;
                    215: {
                    216:        int pid, status;
                    217: 
                    218:        if (!(pid = vfork())) {
                    219:                execlp(_PATH_CP, "mv", "-pr", from, to);
                    220:                (void)fprintf(stderr, "mv: can't exec %s.\n", _PATH_CP);
                    221:                _exit(1);
                    222:        }
                    223:        (void)waitpid(pid, &status, 0);
                    224:        if (!WIFEXITED(status) || WEXITSTATUS(status))
                    225:                return(1);
                    226:        if (!(pid = vfork())) {
                    227:                execlp(_PATH_RM, "mv", "-rf", from);
                    228:                (void)fprintf(stderr, "mv: can't exec %s.\n", _PATH_RM);
                    229:                _exit(1);
                    230:        }
                    231:        (void)waitpid(pid, &status, 0);
                    232:        return(!WIFEXITED(status) || WEXITSTATUS(status));
                    233: }
                    234: 
                    235: usage()
                    236: {
                    237:        (void)fprintf(stderr,
                    238: "usage: mv [-if] src target;\n   or: mv [-if] src1 ... srcN directory\n");
                    239:        exit(1);
                    240: }

unix.superglobalmegacorp.com

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