BSD 4_2 release
[unix-history] / usr / src / bin / cp.c
CommitLineData
5f89032b 1#ifndef lint
7afd0a98 2static char *sccsid = "@(#)cp.c 4.8 83/07/01";
5f89032b
BJ
3#endif
4
84592a94 5/*
5f89032b 6 * cp
84592a94 7 */
84592a94 8#include <stdio.h>
f4d092e2 9#include <sys/param.h>
84592a94 10#include <sys/stat.h>
7afd0a98 11#include <sys/dir.h>
5f89032b 12
f4d092e2 13#define BSIZE 8192
5f89032b
BJ
14
15int iflag;
16int rflag;
17char *rindex(), *sprintf();
84592a94
BJ
18
19main(argc, argv)
5f89032b
BJ
20 int argc;
21 char **argv;
84592a94 22{
5f89032b
BJ
23 struct stat stb;
24 int rc, i;
84592a94 25
5f89032b
BJ
26 argc--, argv++;
27 while (argc > 0 && **argv == '-') {
28 (*argv)++;
29 while (**argv) switch (*(*argv)++) {
84592a94 30
5f89032b
BJ
31 case 'i':
32 iflag++; break;
84592a94 33
5f89032b
BJ
34 case 'r':
35 rflag++; break;
84592a94 36
5f89032b
BJ
37 default:
38 goto usage;
39 }
40 argc--; argv++;
84592a94 41 }
5f89032b 42 if (argc < 2)
84592a94 43 goto usage;
5f89032b 44 if (argc > 2 || rflag) {
3e9da018 45 if (stat(argv[argc-1], &stb) < 0)
84592a94 46 goto usage;
5f89032b 47 if ((stb.st_mode&S_IFMT) != S_IFDIR)
84592a94
BJ
48 goto usage;
49 }
5f89032b
BJ
50 rc = 0;
51 for (i = 0; i < argc-1; i++)
52 rc |= copy(argv[i], argv[argc-1]);
53 exit(rc);
84592a94 54usage:
5f89032b
BJ
55 fprintf(stderr,
56 "Usage: cp f1 f2; or cp [ -r ] f1 ... fn d2\n");
84592a94
BJ
57 exit(1);
58}
59
60copy(from, to)
5f89032b 61 char *from, *to;
84592a94
BJ
62{
63 int fold, fnew, n;
5f89032b
BJ
64 char *last, destname[BSIZE], buf[BSIZE];
65 struct stat stfrom, stto;
66
67 fold = open(from, 0);
68 if (fold < 0) {
1a4b831f 69 Perror(from);
5f89032b 70 return (1);
84592a94 71 }
5f89032b 72 if (fstat(fold, &stfrom) < 0) {
1a4b831f
SL
73 Perror(from);
74 (void) close(fold);
5f89032b 75 return (1);
84592a94 76 }
3e9da018 77 if (stat(to, &stto) >= 0 &&
5f89032b
BJ
78 (stto.st_mode&S_IFMT) == S_IFDIR) {
79 last = rindex(from, '/');
80 if (last) last++; else last = from;
81 if (strlen(to) + strlen(last) >= BSIZE - 1) {
82 fprintf(stderr, "cp: %s/%s: Name too long", to, last);
1a4b831f 83 (void) close(fold);
84592a94 84 return(1);
5f89032b
BJ
85 }
86 (void) sprintf(destname, "%s/%s", to, last);
87 to = destname;
88 }
89 if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) {
90 (void) close(fold);
3e9da018 91 if (stat(to, &stto) < 0) {
e01c32c9 92 if (mkdir(to, (int)stfrom.st_mode) < 0) {
1a4b831f 93 Perror(to);
5f89032b 94 return (1);
e01c32c9 95 }
5f89032b
BJ
96 } else if ((stto.st_mode&S_IFMT) != S_IFDIR) {
97 fprintf(stderr, "cp: %s: Not a directory.\n", to);
98 return (1);
99 }
100 return (rcopy(from, to));
101 }
3e9da018 102 if (stat(to, &stto) >= 0) {
5f89032b
BJ
103 if (stfrom.st_dev == stto.st_dev &&
104 stfrom.st_ino == stto.st_ino) {
105 fprintf(stderr, "cp: Cannot copy file to itself.\n");
1a4b831f 106 (void) close(fold);
5f89032b
BJ
107 return (1);
108 }
109 if (iflag) {
110 int i, c;
111
84592a94
BJ
112 fprintf (stderr, "overwrite %s? ", to);
113 i = c = getchar();
114 while (c != '\n' && c != EOF)
115 c = getchar();
1a4b831f
SL
116 if (i != 'y') {
117 (void) close(fold);
84592a94 118 return(1);
1a4b831f 119 }
84592a94
BJ
120 }
121 }
5f89032b
BJ
122 fnew = creat(to, (int)stfrom.st_mode);
123 if (fnew < 0) {
1a4b831f 124 Perror(to);
5f89032b 125 (void) close(fold); return(1);
84592a94 126 }
5f89032b
BJ
127 for (;;) {
128 n = read(fold, buf, BSIZE);
129 if (n == 0)
130 break;
84592a94 131 if (n < 0) {
1a4b831f 132 Perror(from);
5f89032b
BJ
133 (void) close(fold); (void) close(fnew); return (1);
134 }
135 if (write(fnew, buf, n) != n) {
1a4b831f 136 Perror(to);
5f89032b
BJ
137 (void) close(fold); (void) close(fnew); return (1);
138 }
139 }
140 (void) close(fold); (void) close(fnew); return (0);
141}
142
143rcopy(from, to)
144 char *from, *to;
145{
146 DIR *fold = opendir(from);
147 struct direct *dp;
148 int errs = 0;
149 char fromname[BUFSIZ];
150
151 if (fold == 0) {
1a4b831f 152 Perror(from);
5f89032b
BJ
153 return (1);
154 }
155 for (;;) {
156 dp = readdir(fold);
c4ac082c
KM
157 if (dp == 0) {
158 closedir(fold);
5f89032b 159 return (errs);
c4ac082c 160 }
5f89032b
BJ
161 if (dp->d_ino == 0)
162 continue;
163 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
164 continue;
165 if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
166 fprintf(stderr, "cp: %s/%s: Name too long.\n",
167 from, dp->d_name);
168 errs++;
169 continue;
170 }
171 (void) sprintf(fromname, "%s/%s", from, dp->d_name);
172 errs += copy(fromname, to);
173 }
174}
1a4b831f
SL
175
176Perror(s)
177 char *s;
178{
179
180 fprintf(stderr, "cp: ");
181 perror(s);
182}