|
|
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.