|
|
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.13 (Berkeley) 10/11/85"; ! 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: copy(from, to) ! 79: char *from, *to; ! 80: { ! 81: int fold, fnew, n, exists; ! 82: char *last, destname[MAXPATHLEN + 1], buf[MAXBSIZE]; ! 83: struct stat stfrom, stto; ! 84: ! 85: fold = open(from, 0); ! 86: if (fold < 0) { ! 87: Perror(from); ! 88: return (1); ! 89: } ! 90: if (fstat(fold, &stfrom) < 0) { ! 91: Perror(from); ! 92: (void) close(fold); ! 93: return (1); ! 94: } ! 95: if (stat(to, &stto) >= 0 && ! 96: (stto.st_mode&S_IFMT) == S_IFDIR) { ! 97: last = rindex(from, '/'); ! 98: if (last) last++; else last = from; ! 99: if (strlen(to) + strlen(last) >= sizeof destname - 1) { ! 100: fprintf(stderr, "cp: %s/%s: Name too long", to, last); ! 101: (void) close(fold); ! 102: return(1); ! 103: } ! 104: (void) sprintf(destname, "%s/%s", to, last); ! 105: to = destname; ! 106: } ! 107: if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) { ! 108: int fixmode = 0; /* cleanup mode after rcopy */ ! 109: ! 110: (void) close(fold); ! 111: if (stat(to, &stto) < 0) { ! 112: if (mkdir(to, (stfrom.st_mode & 07777) | 0700) < 0) { ! 113: Perror(to); ! 114: return (1); ! 115: } ! 116: fixmode = 1; ! 117: } else if ((stto.st_mode&S_IFMT) != S_IFDIR) { ! 118: fprintf(stderr, "cp: %s: Not a directory.\n", to); ! 119: return (1); ! 120: } else if (pflag) ! 121: fixmode = 1; ! 122: n = rcopy(from, to); ! 123: if (fixmode) ! 124: (void) chmod(to, stfrom.st_mode & 07777); ! 125: return (n); ! 126: } ! 127: ! 128: if ((stfrom.st_mode&S_IFMT) == S_IFDIR) ! 129: fprintf(stderr, ! 130: "cp: %s: Is a directory (copying as plain file).\n", ! 131: from); ! 132: ! 133: exists = stat(to, &stto) == 0; ! 134: if (exists) { ! 135: if (stfrom.st_dev == stto.st_dev && ! 136: stfrom.st_ino == stto.st_ino) { ! 137: fprintf(stderr, ! 138: "cp: %s and %s are identical (not copied).\n", ! 139: from, to); ! 140: (void) close(fold); ! 141: return (1); ! 142: } ! 143: if (iflag && isatty(fileno(stdin))) { ! 144: int i, c; ! 145: ! 146: fprintf (stderr, "overwrite %s? ", to); ! 147: i = c = getchar(); ! 148: while (c != '\n' && c != EOF) ! 149: c = getchar(); ! 150: if (i != 'y') { ! 151: (void) close(fold); ! 152: return(1); ! 153: } ! 154: } ! 155: } ! 156: fnew = creat(to, stfrom.st_mode & 07777); ! 157: if (fnew < 0) { ! 158: Perror(to); ! 159: (void) close(fold); return(1); ! 160: } ! 161: if (exists && pflag) ! 162: (void) fchmod(fnew, stfrom.st_mode & 07777); ! 163: ! 164: for (;;) { ! 165: n = read(fold, buf, sizeof buf); ! 166: if (n == 0) ! 167: break; ! 168: if (n < 0) { ! 169: Perror(from); ! 170: (void) close(fold); (void) close(fnew); return (1); ! 171: } ! 172: if (write(fnew, buf, n) != n) { ! 173: Perror(to); ! 174: (void) close(fold); (void) close(fnew); return (1); ! 175: } ! 176: } ! 177: (void) close(fold); (void) close(fnew); ! 178: if (pflag) ! 179: return (setimes(to, &stfrom)); ! 180: return (0); ! 181: } ! 182: ! 183: rcopy(from, to) ! 184: char *from, *to; ! 185: { ! 186: DIR *fold = opendir(from); ! 187: struct direct *dp; ! 188: struct stat statb; ! 189: int errs = 0; ! 190: char fromname[MAXPATHLEN + 1]; ! 191: ! 192: if (fold == 0 || (pflag && fstat(fold->dd_fd, &statb) < 0)) { ! 193: Perror(from); ! 194: return (1); ! 195: } ! 196: for (;;) { ! 197: dp = readdir(fold); ! 198: if (dp == 0) { ! 199: closedir(fold); ! 200: if (pflag) ! 201: return (setimes(to, &statb) + errs); ! 202: return (errs); ! 203: } ! 204: if (dp->d_ino == 0) ! 205: continue; ! 206: if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) ! 207: continue; ! 208: if (strlen(from)+1+strlen(dp->d_name) >= sizeof fromname - 1) { ! 209: fprintf(stderr, "cp: %s/%s: Name too long.\n", ! 210: from, dp->d_name); ! 211: errs++; ! 212: continue; ! 213: } ! 214: (void) sprintf(fromname, "%s/%s", from, dp->d_name); ! 215: errs += copy(fromname, to); ! 216: } ! 217: } ! 218: ! 219: int ! 220: setimes(path, statp) ! 221: char *path; ! 222: struct stat *statp; ! 223: { ! 224: struct timeval tv[2]; ! 225: ! 226: tv[0].tv_sec = statp->st_atime; ! 227: tv[1].tv_sec = statp->st_mtime; ! 228: tv[0].tv_usec = tv[1].tv_usec = 0; ! 229: if (utimes(path, tv) < 0) { ! 230: Perror(path); ! 231: return (1); ! 232: } ! 233: return (0); ! 234: } ! 235: ! 236: Perror(s) ! 237: char *s; ! 238: { ! 239: ! 240: fprintf(stderr, "cp: "); ! 241: perror(s); ! 242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.