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: }