|
|
1.1 root 1: /*
2: * /usr/src/cmd/cp.c
3: * Usage: cp [ -d ] file1 file2
4: * cp [ -d ] file ... directory
5: * Copy one file to another or
6: * copy several files into a directory.
7: * define SLOW for 'block at a time copying' .... (not recommended)
8: */
9:
10: #include <stdio.h>
11: #include <sys/stat.h>
12: #include <sys/types.h>
13: #include <errno.h>
14:
15: #define MAX(a, b) ((a) < (b) ? (b) : (a))
16: #define or ||
17: #define and &&
18: #define not !
19: #define TRUE (0==0)
20: #define FALSE (not TRUE)
21:
22: extern int errno;
23: struct stat sb;
24:
25: #ifndef SLOW
26: char buf[50*BUFSIZ];
27: #else
28: char buf[BUFSIZ];
29: #endif
30: int dflag;
31: char *namebuf;
32: char *suffix;
33: char *target;
34:
35: main(argc, argv)
36: int argc;
37: char *argv[];
38: {
39: register int i;
40: register int n;
41: register int status = 0;
42:
43: if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {
44: ++dflag;
45: --argc;
46: ++argv;
47: }
48: n = init(argc, argv);
49: if (namebuf == NULL)
50: return (cp(argv[1], target) ? 0 : 1);
51: for (i = 1; i <= n; ++i)
52: status |= cpdir(argv[i]);
53: return (status ? 0 : 1);
54: }
55:
56: /*
57: * Copy inf to outf.
58: */
59: cp(inf, outf)
60: char *inf, *outf;
61: {
62: #ifndef SLOW
63: register char *ip;
64: #endif
65: register int n;
66: register int i;
67: register short infd;
68: register short outfd;
69: register short mode;
70: register ino_t ino;
71: register dev_t dev;
72: register fsize_t size;
73: time_t times[2];
74: #ifndef SLOW
75: register char *wp;
76: register int wflag;
77: #endif
78:
79: if (stat(inf, &sb) < 0) {
80: cperr("%s: cannot find", inf);
81: return (FALSE);
82: }
83: if ((sb.st_mode & S_IFMT) == S_IFDIR) {
84: cperr("%s: directory", inf);
85: return (FALSE);
86: }
87: mode = sb.st_mode;
88: size = sb.st_size;
89: ino = sb.st_ino;
90: dev = sb.st_dev;
91: if (dflag)
92: times[1] = sb.st_mtime;
93:
94: if (stat(outf, &sb) >= 0)
95: if (sb.st_ino==ino && sb.st_dev==dev) {
96: cperr("%s: cannot copy file to itself", inf);
97: return (FALSE);
98: }
99: if ((infd = open(inf, 0)) < 0) {
100: cperr("%s: cannot open", inf);
101: return (FALSE);
102: }
103: if ((outfd = creat(outf, mode & 06777)) < 0) {
104: if (errno == ETXTBSY)
105: cperr("%s: cannot copy over busy shared text file", outf);
106: else
107: cperr("%s: cannot create", outf);
108: close(infd);
109: return (FALSE);
110: }
111:
112: #ifndef SLOW
113: while ((n = read(infd, buf, sizeof(buf))) > 0) {
114: #else
115: while ((n = read(infd, buf, BUFSIZ)) > 0) {
116: #endif
117: /*
118: * Check for blocks of zeroes (holes in a sparse file).
119: * However, a block of zeroes at the end of a file must be
120: * written so the file has correct length.
121: */
122: #ifndef SLOW
123: wp = ip = buf;
124: size -= n;
125: while ((n-BUFSIZ) > 0 || ((n-BUFSIZ) == 0 && size != 0)) {
126: n -= BUFSIZ;
127: wflag = FALSE;
128: ip = wp;
129: for (i = 0; i < BUFSIZ; ++i)
130: if (*ip++ != '\0') {
131: wflag = TRUE;
132: break;
133: }
134: if (wflag) {
135: if (write(outfd, wp, BUFSIZ) < BUFSIZ) {
136: cperr("%s: write error", outf);
137: close(infd);
138: close(outfd);
139: return (FALSE);
140: }
141: } else {
142: lseek(outfd, (long)BUFSIZ, 1);
143: }
144: wp += BUFSIZ;
145: }
146: if (write(outfd, wp, n) < n) {
147: cperr("%s: write error", outf);
148: close(infd);
149: close(outfd);
150: return (FALSE);
151: }
152: #else
153: if ((size -= n) == (fsize_t)0)
154: goto WRITE;
155: for (i = 0; i < n; ++i)
156: if (buf[i] != '\0')
157: goto WRITE;
158: lseek(outfd, (long)BUFSIZ, 1);
159: continue;
160:
161: WRITE:
162: if (write(outfd, buf, n) < n) {
163: cperr("%s: write error", outf);
164: close(infd);
165: close(outfd);
166: return (FALSE);
167: }
168: #endif
169: }
170:
171: close(infd);
172: if (dflag && fstat(outfd, &sb) != -1) {
173: times[0] = sb.st_atime;
174: if (utime(outf, times) == -1)
175: cperr("%s: cannot preserve mtime", outf);
176: }
177: close(outfd);
178: if (n < 0) {
179: cperr("%s: read error", inf);
180: return (FALSE);
181: }
182: return (TRUE);
183: }
184:
185: /*
186: * The second form of cp, copy a file into a directory. This builds the name
187: * of the target file in namebuf and then just calls `cp'.
188: */
189: cpdir(file)
190: char *file;
191: {
192: register char *a, *b;
193:
194: for (a = b = file; *b != '\0'; )
195: if (*b++ == '/')
196: a = b;
197: strcpy(suffix, a);
198: return (cp(file, namebuf));
199: }
200:
201: usage()
202: {
203: fprintf(stderr,
204: "Usage:\tcp [ -d ] file1 file2\n"
205: "\tcp [ -d ] file ... directory\n"
206: );
207: exit (2);
208: }
209:
210: cperr(arg0)
211: {
212: fprintf(stderr, "cp: %r\n", &arg0);
213: }
214:
215: /*
216: * Check whether target is a directory, regular file, non-extant or in error.
217: * If a directory, malloc namebuf big enough for all names.
218: * Also, set flags used by cperr.
219: */
220: init(ac, av)
221: register int ac;
222: register char *av[];
223: {
224: register int n;
225:
226: if (ac < 3)
227: usage();
228: target = av[ac-1];
229: if (stat(target, &sb) == 0 and (sb.st_mode & S_IFMT) == S_IFDIR) {
230: av[ac-1] = NULL;
231: n = 0;
232: while (*++av != NULL)
233: if (n < strlen(*av))
234: n = strlen(*av);
235: namebuf = malloc(n + strlen(target) + 2);
236: if (namebuf == NULL) {
237: cperr("out of memory");
238: exit(1);
239: }
240: strcpy(namebuf, target);
241: suffix = namebuf + strlen(target);
242: *suffix++ = '/';
243: return (ac - 2);
244: }
245: if (ac != 3)
246: usage();
247: return (1);
248: }
249:
250: /* end of cp.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.