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