|
|
1.1 ! root 1: /* ! 2: * /usr/src/cmd/cp.c ! 3: * Usage: cp [ -d ] file1 file2 ! 4: * cp [ -d ] file ... directory ! 5: * Copy one file to another or ! 6: * copy several files into a directory. ! 7: * define SLOW for 'block at a time copying' .... (not recommended) ! 8: */ ! 9: ! 10: #include <stdio.h> ! 11: #include <sys/stat.h> ! 12: #include <sys/types.h> ! 13: #include <errno.h> ! 14: ! 15: #define MAX(a, b) ((a) < (b) ? (b) : (a)) ! 16: #define or || ! 17: #define and && ! 18: #define not ! ! 19: #define TRUE (0==0) ! 20: #define FALSE (not TRUE) ! 21: ! 22: extern int errno; ! 23: struct stat sb; ! 24: ! 25: #ifndef SLOW ! 26: char buf[50*BUFSIZ]; ! 27: #else ! 28: char buf[BUFSIZ]; ! 29: #endif ! 30: int dflag; ! 31: char *namebuf; ! 32: char *suffix; ! 33: char *target; ! 34: ! 35: main(argc, argv) ! 36: int argc; ! 37: char *argv[]; ! 38: { ! 39: register int i; ! 40: register int n; ! 41: register int status = 0; ! 42: ! 43: if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') { ! 44: ++dflag; ! 45: --argc; ! 46: ++argv; ! 47: } ! 48: n = init(argc, argv); ! 49: if (namebuf == NULL) ! 50: return (cp(argv[1], target) ? 0 : 1); ! 51: for (i = 1; i <= n; ++i) ! 52: status |= cpdir(argv[i]); ! 53: return (status ? 0 : 1); ! 54: } ! 55: ! 56: /* ! 57: * Copy inf to outf. ! 58: */ ! 59: cp(inf, outf) ! 60: char *inf, *outf; ! 61: { ! 62: #ifndef SLOW ! 63: register char *ip; ! 64: #endif ! 65: register int n; ! 66: register int i; ! 67: register short infd; ! 68: register short outfd; ! 69: register short mode; ! 70: register ino_t ino; ! 71: register dev_t dev; ! 72: register fsize_t size; ! 73: time_t times[2]; ! 74: #ifndef SLOW ! 75: register char *wp; ! 76: register int wflag; ! 77: #endif ! 78: ! 79: if (stat(inf, &sb) < 0) { ! 80: cperr("%s: cannot find", inf); ! 81: return (FALSE); ! 82: } ! 83: if ((sb.st_mode & S_IFMT) == S_IFDIR) { ! 84: cperr("%s: directory", inf); ! 85: return (FALSE); ! 86: } ! 87: mode = sb.st_mode; ! 88: size = sb.st_size; ! 89: ino = sb.st_ino; ! 90: dev = sb.st_dev; ! 91: if (dflag) ! 92: times[1] = sb.st_mtime; ! 93: ! 94: if (stat(outf, &sb) >= 0) ! 95: if (sb.st_ino==ino && sb.st_dev==dev) { ! 96: cperr("%s: cannot copy file to itself", inf); ! 97: return (FALSE); ! 98: } ! 99: if ((infd = open(inf, 0)) < 0) { ! 100: cperr("%s: cannot open", inf); ! 101: return (FALSE); ! 102: } ! 103: if ((outfd = creat(outf, mode & 06777)) < 0) { ! 104: if (errno == ETXTBSY) ! 105: cperr("%s: cannot copy over busy shared text file", outf); ! 106: else ! 107: cperr("%s: cannot create", outf); ! 108: close(infd); ! 109: return (FALSE); ! 110: } ! 111: ! 112: #ifndef SLOW ! 113: while ((n = read(infd, buf, sizeof(buf))) > 0) { ! 114: #else ! 115: while ((n = read(infd, buf, BUFSIZ)) > 0) { ! 116: #endif ! 117: /* ! 118: * Check for blocks of zeroes (holes in a sparse file). ! 119: * However, a block of zeroes at the end of a file must be ! 120: * written so the file has correct length. ! 121: */ ! 122: #ifndef SLOW ! 123: wp = ip = buf; ! 124: size -= n; ! 125: while ((n-BUFSIZ) > 0 || ((n-BUFSIZ) == 0 && size != 0)) { ! 126: n -= BUFSIZ; ! 127: wflag = FALSE; ! 128: ip = wp; ! 129: for (i = 0; i < BUFSIZ; ++i) ! 130: if (*ip++ != '\0') { ! 131: wflag = TRUE; ! 132: break; ! 133: } ! 134: if (wflag) { ! 135: if (write(outfd, wp, BUFSIZ) < BUFSIZ) { ! 136: cperr("%s: write error", outf); ! 137: close(infd); ! 138: close(outfd); ! 139: return (FALSE); ! 140: } ! 141: } else { ! 142: lseek(outfd, (long)BUFSIZ, 1); ! 143: } ! 144: wp += BUFSIZ; ! 145: } ! 146: if (write(outfd, wp, n) < n) { ! 147: cperr("%s: write error", outf); ! 148: close(infd); ! 149: close(outfd); ! 150: return (FALSE); ! 151: } ! 152: #else ! 153: if ((size -= n) == (fsize_t)0) ! 154: goto WRITE; ! 155: for (i = 0; i < n; ++i) ! 156: if (buf[i] != '\0') ! 157: goto WRITE; ! 158: lseek(outfd, (long)BUFSIZ, 1); ! 159: continue; ! 160: ! 161: WRITE: ! 162: if (write(outfd, buf, n) < n) { ! 163: cperr("%s: write error", outf); ! 164: close(infd); ! 165: close(outfd); ! 166: return (FALSE); ! 167: } ! 168: #endif ! 169: } ! 170: ! 171: close(infd); ! 172: if (dflag && fstat(outfd, &sb) != -1) { ! 173: times[0] = sb.st_atime; ! 174: if (utime(outf, times) == -1) ! 175: cperr("%s: cannot preserve mtime", outf); ! 176: } ! 177: close(outfd); ! 178: if (n < 0) { ! 179: cperr("%s: read error", inf); ! 180: return (FALSE); ! 181: } ! 182: return (TRUE); ! 183: } ! 184: ! 185: /* ! 186: * The second form of cp, copy a file into a directory. This builds the name ! 187: * of the target file in namebuf and then just calls `cp'. ! 188: */ ! 189: cpdir(file) ! 190: char *file; ! 191: { ! 192: register char *a, *b; ! 193: ! 194: for (a = b = file; *b != '\0'; ) ! 195: if (*b++ == '/') ! 196: a = b; ! 197: strcpy(suffix, a); ! 198: return (cp(file, namebuf)); ! 199: } ! 200: ! 201: usage() ! 202: { ! 203: fprintf(stderr, ! 204: "Usage:\tcp [ -d ] file1 file2\n" ! 205: "\tcp [ -d ] file ... directory\n" ! 206: ); ! 207: exit (2); ! 208: } ! 209: ! 210: cperr(arg0) ! 211: { ! 212: fprintf(stderr, "cp: %r\n", &arg0); ! 213: } ! 214: ! 215: /* ! 216: * Check whether target is a directory, regular file, non-extant or in error. ! 217: * If a directory, malloc namebuf big enough for all names. ! 218: * Also, set flags used by cperr. ! 219: */ ! 220: init(ac, av) ! 221: register int ac; ! 222: register char *av[]; ! 223: { ! 224: register int n; ! 225: ! 226: if (ac < 3) ! 227: usage(); ! 228: target = av[ac-1]; ! 229: if (stat(target, &sb) == 0 and (sb.st_mode & S_IFMT) == S_IFDIR) { ! 230: av[ac-1] = NULL; ! 231: n = 0; ! 232: while (*++av != NULL) ! 233: if (n < strlen(*av)) ! 234: n = strlen(*av); ! 235: namebuf = malloc(n + strlen(target) + 2); ! 236: if (namebuf == NULL) { ! 237: cperr("out of memory"); ! 238: exit(1); ! 239: } ! 240: strcpy(namebuf, target); ! 241: suffix = namebuf + strlen(target); ! 242: *suffix++ = '/'; ! 243: return (ac - 2); ! 244: } ! 245: if (ac != 3) ! 246: usage(); ! 247: return (1); ! 248: } ! 249: ! 250: /* end of cp.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.