1 #include <u.h>
2 #include <libc.h>
3
4 #define DEFB (8*1024)
5
6 int failed;
7 int gflag;
8 int uflag;
9 int xflag;
10 void copy(char *from, char *to, int todir);
11 int copy1(int fdf, int fdt, char *from, char *to);
12
13 void
main(int argc,char * argv[])14 main(int argc, char *argv[])
15 {
16 Dir *dirb;
17 int todir, i;
18
19 ARGBEGIN {
20 case 'g':
21 gflag++;
22 break;
23 case 'u':
24 uflag++;
25 gflag++;
26 break;
27 case 'x':
28 xflag++;
29 break;
30 default:
31 goto usage;
32 } ARGEND
33
34 todir=0;
35 if(argc < 2)
36 goto usage;
37 dirb = dirstat(argv[argc-1]);
38 if(dirb!=nil && (dirb->mode&DMDIR))
39 todir=1;
40 if(argc>2 && !todir){
41 fprint(2, "cp: %s not a directory\n", argv[argc-1]);
42 exits("bad usage");
43 }
44 for(i=0; i<argc-1; i++)
45 copy(argv[i], argv[argc-1], todir);
46 if(failed)
47 exits("errors");
48 exits(0);
49
50 usage:
51 fprint(2, "usage:\tcp [-gux] fromfile tofile\n");
52 fprint(2, "\tcp [-x] fromfile ... todir\n");
53 exits("usage");
54 }
55
56 int
samefile(Dir * a,char * an,char * bn)57 samefile(Dir *a, char *an, char *bn)
58 {
59 Dir *b;
60 int ret;
61
62 ret = 0;
63 b=dirstat(bn);
64 if(b != nil)
65 if(b->qid.type==a->qid.type)
66 if(b->qid.path==a->qid.path)
67 if(b->qid.vers==a->qid.vers)
68 if(b->dev==a->dev)
69 if(b->type==a->type){
70 fprint(2, "cp: %s and %s are the same file\n", an, bn);
71 ret = 1;
72 }
73 free(b);
74 return ret;
75 }
76
77 void
copy(char * from,char * to,int todir)78 copy(char *from, char *to, int todir)
79 {
80 Dir *dirb, dirt;
81 char name[256];
82 int fdf, fdt, mode;
83
84 if(todir){
85 char *s, *elem;
86 elem=s=from;
87 while(*s++)
88 if(s[-1]=='/')
89 elem=s;
90 sprint(name, "%s/%s", to, elem);
91 to=name;
92 }
93
94 if((dirb=dirstat(from))==nil){
95 fprint(2,"cp: can't stat %s: %r\n", from);
96 failed = 1;
97 return;
98 }
99 mode = dirb->mode;
100 if(mode&DMDIR){
101 fprint(2, "cp: %s is a directory\n", from);
102 free(dirb);
103 failed = 1;
104 return;
105 }
106 if(samefile(dirb, from, to)){
107 free(dirb);
108 failed = 1;
109 return;
110 }
111 mode &= 0777;
112 fdf=open(from, OREAD);
113 if(fdf<0){
114 fprint(2, "cp: can't open %s: %r\n", from);
115 free(dirb);
116 failed = 1;
117 return;
118 }
119 fdt=create(to, OWRITE, mode);
120 if(fdt<0){
121 fprint(2, "cp: can't create %s: %r\n", to);
122 close(fdf);
123 free(dirb);
124 failed = 1;
125 return;
126 }
127 if(copy1(fdf, fdt, from, to)==0 && (xflag || gflag || uflag)){
128 nulldir(&dirt);
129 if(xflag){
130 dirt.mtime = dirb->mtime;
131 dirt.mode = dirb->mode;
132 }
133 if(uflag)
134 dirt.uid = dirb->uid;
135 if(gflag)
136 dirt.gid = dirb->gid;
137 if(dirfwstat(fdt, &dirt) < 0)
138 fprint(2, "cp: warning: can't wstat %s: %r\n", to);
139 }
140 free(dirb);
141 close(fdf);
142 close(fdt);
143 }
144
145 int
copy1(int fdf,int fdt,char * from,char * to)146 copy1(int fdf, int fdt, char *from, char *to)
147 {
148 char *buf;
149 long n, n1, rcount;
150 int rv;
151 char err[ERRMAX];
152
153 buf = malloc(DEFB);
154 /* clear any residual error */
155 err[0] = '\0';
156 errstr(err, ERRMAX);
157 rv = 0;
158 for(rcount=0;; rcount++) {
159 n = read(fdf, buf, DEFB);
160 if(n <= 0)
161 break;
162 n1 = write(fdt, buf, n);
163 if(n1 != n) {
164 fprint(2, "cp: error writing %s: %r\n", to);
165 failed = 1;
166 rv = -1;
167 break;
168 }
169 }
170 if(n < 0) {
171 fprint(2, "cp: error reading %s: %r\n", from);
172 failed = 1;
173 rv = -1;
174 }
175 free(buf);
176 return rv;
177 }
178