|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.