|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 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) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)cp.c 4.14 (Berkeley) 12/2/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * cp ! 19: */ ! 20: #include <stdio.h> ! 21: #include <sys/param.h> ! 22: #include <sys/stat.h> ! 23: #include <sys/dir.h> ! 24: #include <sys/time.h> ! 25: ! 26: int iflag; ! 27: int rflag; ! 28: int pflag; ! 29: char *rindex(); ! 30: ! 31: main(argc, argv) ! 32: int argc; ! 33: char **argv; ! 34: { ! 35: struct stat stb; ! 36: int rc, i; ! 37: ! 38: argc--, argv++; ! 39: while (argc > 0 && **argv == '-') { ! 40: (*argv)++; ! 41: while (**argv) switch (*(*argv)++) { ! 42: ! 43: case 'i': ! 44: iflag++; break; ! 45: ! 46: case 'R': ! 47: case 'r': ! 48: rflag++; break; ! 49: ! 50: case 'p': /* preserve mtimes, atimes, and modes */ ! 51: pflag++; ! 52: (void) umask(0); ! 53: break; ! 54: ! 55: default: ! 56: goto usage; ! 57: } ! 58: argc--; argv++; ! 59: } ! 60: if (argc < 2) ! 61: goto usage; ! 62: if (argc > 2) { ! 63: if (stat(argv[argc-1], &stb) < 0) ! 64: goto usage; ! 65: if ((stb.st_mode&S_IFMT) != S_IFDIR) ! 66: goto usage; ! 67: } ! 68: rc = 0; ! 69: for (i = 0; i < argc-1; i++) ! 70: rc |= copy(argv[i], argv[argc-1]); ! 71: exit(rc); ! 72: usage: ! 73: fprintf(stderr, ! 74: "Usage: cp [-ip] f1 f2; or: cp [-irp] f1 ... fn d2\n"); ! 75: exit(1); ! 76: } ! 77: ! 78: /* I/O buffer; guarantee long-word alignment */ ! 79: static char buf[MAXBSIZE]; ! 80: ! 81: copy(from, to) ! 82: char *from, *to; ! 83: { ! 84: int fold, fnew, n, exists; ! 85: char *last, destname[MAXPATHLEN + 1]; ! 86: struct stat stfrom, stto; ! 87: ! 88: fold = open(from, 0); ! 89: if (fold < 0) { ! 90: Perror(from); ! 91: return (1); ! 92: } ! 93: if (fstat(fold, &stfrom) < 0) { ! 94: Perror(from); ! 95: (void) close(fold); ! 96: return (1); ! 97: } ! 98: if (stat(to, &stto) >= 0 && ! 99: (stto.st_mode&S_IFMT) == S_IFDIR) { ! 100: last = rindex(from, '/'); ! 101: if (last) last++; else last = from; ! 102: if (strlen(to) + strlen(last) >= sizeof destname - 1) { ! 103: fprintf(stderr, "cp: %s/%s: Name too long", to, last); ! 104: (void) close(fold); ! 105: return(1); ! 106: } ! 107: (void) sprintf(destname, "%s/%s", to, last); ! 108: to = destname; ! 109: } ! 110: if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) { ! 111: int fixmode = 0; /* cleanup mode after rcopy */ ! 112: ! 113: (void) close(fold); ! 114: if (stat(to, &stto) < 0) { ! 115: if (mkdir(to, (stfrom.st_mode & 07777) | 0700) < 0) { ! 116: Perror(to); ! 117: return (1); ! 118: } ! 119: fixmode = 1; ! 120: } else if ((stto.st_mode&S_IFMT) != S_IFDIR) { ! 121: fprintf(stderr, "cp: %s: Not a directory.\n", to); ! 122: return (1); ! 123: } else if (pflag) ! 124: fixmode = 1; ! 125: n = rcopy(from, to); ! 126: if (fixmode) ! 127: (void) chmod(to, stfrom.st_mode & 07777); ! 128: return (n); ! 129: } ! 130: ! 131: if ((stfrom.st_mode&S_IFMT) == S_IFDIR) ! 132: fprintf(stderr, ! 133: "cp: %s: Is a directory (copying as plain file).\n", ! 134: from); ! 135: ! 136: exists = stat(to, &stto) == 0; ! 137: if (exists) { ! 138: if (stfrom.st_dev == stto.st_dev && ! 139: stfrom.st_ino == stto.st_ino) { ! 140: fprintf(stderr, ! 141: "cp: %s and %s are identical (not copied).\n", ! 142: from, to); ! 143: (void) close(fold); ! 144: return (1); ! 145: } ! 146: if (iflag && isatty(fileno(stdin))) { ! 147: int i, c; ! 148: ! 149: fprintf (stderr, "overwrite %s? ", to); ! 150: i = c = getchar(); ! 151: while (c != '\n' && c != EOF) ! 152: c = getchar(); ! 153: if (i != 'y') { ! 154: (void) close(fold); ! 155: return(1); ! 156: } ! 157: } ! 158: } ! 159: fnew = creat(to, stfrom.st_mode & 07777); ! 160: if (fnew < 0) { ! 161: Perror(to); ! 162: (void) close(fold); return(1); ! 163: } ! 164: if (exists && pflag) ! 165: (void) fchmod(fnew, stfrom.st_mode & 07777); ! 166: ! 167: for (;;) { ! 168: n = read(fold, buf, sizeof buf); ! 169: if (n == 0) ! 170: break; ! 171: if (n < 0) { ! 172: Perror(from); ! 173: (void) close(fold); (void) close(fnew); return (1); ! 174: } ! 175: if (write(fnew, buf, n) != n) { ! 176: Perror(to); ! 177: (void) close(fold); (void) close(fnew); return (1); ! 178: } ! 179: } ! 180: (void) close(fold); (void) close(fnew); ! 181: if (pflag) ! 182: return (setimes(to, &stfrom)); ! 183: return (0); ! 184: } ! 185: ! 186: rcopy(from, to) ! 187: char *from, *to; ! 188: { ! 189: DIR *fold = opendir(from); ! 190: struct direct *dp; ! 191: struct stat statb; ! 192: int errs = 0; ! 193: char fromname[MAXPATHLEN + 1]; ! 194: ! 195: if (fold == 0 || (pflag && fstat(fold->dd_fd, &statb) < 0)) { ! 196: Perror(from); ! 197: return (1); ! 198: } ! 199: for (;;) { ! 200: dp = readdir(fold); ! 201: if (dp == 0) { ! 202: closedir(fold); ! 203: if (pflag) ! 204: return (setimes(to, &statb) + errs); ! 205: return (errs); ! 206: } ! 207: if (dp->d_ino == 0) ! 208: continue; ! 209: if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) ! 210: continue; ! 211: if (strlen(from)+1+strlen(dp->d_name) >= sizeof fromname - 1) { ! 212: fprintf(stderr, "cp: %s/%s: Name too long.\n", ! 213: from, dp->d_name); ! 214: errs++; ! 215: continue; ! 216: } ! 217: (void) sprintf(fromname, "%s/%s", from, dp->d_name); ! 218: errs += copy(fromname, to); ! 219: } ! 220: } ! 221: ! 222: int ! 223: setimes(path, statp) ! 224: char *path; ! 225: struct stat *statp; ! 226: { ! 227: struct timeval tv[2]; ! 228: ! 229: tv[0].tv_sec = statp->st_atime; ! 230: tv[1].tv_sec = statp->st_mtime; ! 231: tv[0].tv_usec = tv[1].tv_usec = 0; ! 232: if (utimes(path, tv) < 0) { ! 233: Perror(path); ! 234: return (1); ! 235: } ! 236: return (0); ! 237: } ! 238: ! 239: Perror(s) ! 240: char *s; ! 241: { ! 242: ! 243: fprintf(stderr, "cp: "); ! 244: perror(s); ! 245: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.