1*74a4d8c2SCharles.Forsyth #include <lib9.h>
2*74a4d8c2SCharles.Forsyth
3*74a4d8c2SCharles.Forsyth #define DEFB (8*1024)
4*74a4d8c2SCharles.Forsyth
5*74a4d8c2SCharles.Forsyth void copy(char *from, char *to, int todir);
6*74a4d8c2SCharles.Forsyth void copy1(int fdf, int fdt, char *from, char *to);
7*74a4d8c2SCharles.Forsyth void fixbackslash(char *file);
8*74a4d8c2SCharles.Forsyth
9*74a4d8c2SCharles.Forsyth void
main(int argc,char * argv[])10*74a4d8c2SCharles.Forsyth main(int argc, char *argv[])
11*74a4d8c2SCharles.Forsyth {
12*74a4d8c2SCharles.Forsyth Dir *dirb;
13*74a4d8c2SCharles.Forsyth int todir, i;
14*74a4d8c2SCharles.Forsyth
15*74a4d8c2SCharles.Forsyth if(argc<3){
16*74a4d8c2SCharles.Forsyth fprint(2, "usage:\tcp fromfile tofile\n");
17*74a4d8c2SCharles.Forsyth fprint(2, "\tcp fromfile ... todir\n");
18*74a4d8c2SCharles.Forsyth exits("usage");
19*74a4d8c2SCharles.Forsyth }
20*74a4d8c2SCharles.Forsyth
21*74a4d8c2SCharles.Forsyth for(i=0; i<argc; i++)
22*74a4d8c2SCharles.Forsyth fixbackslash(argv[i]);
23*74a4d8c2SCharles.Forsyth
24*74a4d8c2SCharles.Forsyth
25*74a4d8c2SCharles.Forsyth todir=0;
26*74a4d8c2SCharles.Forsyth if((dirb = dirstat(argv[argc-1]))!=nil && (dirb->mode&DMDIR))
27*74a4d8c2SCharles.Forsyth todir=1;
28*74a4d8c2SCharles.Forsyth if(argc>3 && !todir){
29*74a4d8c2SCharles.Forsyth fprint(2, "cp: %s not a directory\n", argv[argc-1]);
30*74a4d8c2SCharles.Forsyth exits("bad usage");
31*74a4d8c2SCharles.Forsyth }
32*74a4d8c2SCharles.Forsyth for(i=1; i<argc-1; i++)
33*74a4d8c2SCharles.Forsyth copy(argv[i], argv[argc-1], todir);
34*74a4d8c2SCharles.Forsyth exits(0);
35*74a4d8c2SCharles.Forsyth }
36*74a4d8c2SCharles.Forsyth
37*74a4d8c2SCharles.Forsyth void
copy(char * from,char * to,int todir)38*74a4d8c2SCharles.Forsyth copy(char *from, char *to, int todir)
39*74a4d8c2SCharles.Forsyth {
40*74a4d8c2SCharles.Forsyth Dir *dirb, *dirt;
41*74a4d8c2SCharles.Forsyth char name[256];
42*74a4d8c2SCharles.Forsyth int fdf, fdt;
43*74a4d8c2SCharles.Forsyth
44*74a4d8c2SCharles.Forsyth if(todir){
45*74a4d8c2SCharles.Forsyth char *s, *elem;
46*74a4d8c2SCharles.Forsyth elem=s=from;
47*74a4d8c2SCharles.Forsyth while(*s++)
48*74a4d8c2SCharles.Forsyth if(s[-1]=='/')
49*74a4d8c2SCharles.Forsyth elem=s;
50*74a4d8c2SCharles.Forsyth sprint(name, "%s/%s", to, elem);
51*74a4d8c2SCharles.Forsyth to=name;
52*74a4d8c2SCharles.Forsyth }
53*74a4d8c2SCharles.Forsyth if((dirb = dirstat(from))==nil){
54*74a4d8c2SCharles.Forsyth fprint(2,"cp: can't stat %s: %r\n", from);
55*74a4d8c2SCharles.Forsyth return;
56*74a4d8c2SCharles.Forsyth }
57*74a4d8c2SCharles.Forsyth if(dirb->mode&DMDIR){
58*74a4d8c2SCharles.Forsyth fprint(2, "cp: %s is a directory\n", from);
59*74a4d8c2SCharles.Forsyth return;
60*74a4d8c2SCharles.Forsyth }
61*74a4d8c2SCharles.Forsyth dirb->mode &= 0777;
62*74a4d8c2SCharles.Forsyth if((dirt = dirstat(to))!=nil)
63*74a4d8c2SCharles.Forsyth if(dirb->qid.path==dirt->qid.path && dirb->qid.vers==dirt->qid.vers)
64*74a4d8c2SCharles.Forsyth if(dirb->dev==dirt->dev && dirb->type==dirt->type){
65*74a4d8c2SCharles.Forsyth fprint(2, "cp: %s and %s are the same file\n", from, to);
66*74a4d8c2SCharles.Forsyth return;
67*74a4d8c2SCharles.Forsyth }
68*74a4d8c2SCharles.Forsyth fdf=open(from, OREAD);
69*74a4d8c2SCharles.Forsyth if(fdf<0){
70*74a4d8c2SCharles.Forsyth fprint(2, "cp: can't open %s: %r\n", from);
71*74a4d8c2SCharles.Forsyth return;
72*74a4d8c2SCharles.Forsyth }
73*74a4d8c2SCharles.Forsyth fdt=create(to, OWRITE, dirb->mode);
74*74a4d8c2SCharles.Forsyth if(fdt<0){
75*74a4d8c2SCharles.Forsyth fprint(2, "cp: can't create %s: %r\n", to);
76*74a4d8c2SCharles.Forsyth close(fdf);
77*74a4d8c2SCharles.Forsyth return;
78*74a4d8c2SCharles.Forsyth }
79*74a4d8c2SCharles.Forsyth copy1(fdf, fdt, from, to);
80*74a4d8c2SCharles.Forsyth close(fdf);
81*74a4d8c2SCharles.Forsyth close(fdt);
82*74a4d8c2SCharles.Forsyth }
83*74a4d8c2SCharles.Forsyth
84*74a4d8c2SCharles.Forsyth void
copy1(int fdf,int fdt,char * from,char * to)85*74a4d8c2SCharles.Forsyth copy1(int fdf, int fdt, char *from, char *to)
86*74a4d8c2SCharles.Forsyth {
87*74a4d8c2SCharles.Forsyth char *buf;
88*74a4d8c2SCharles.Forsyth long n, n1, rcount;
89*74a4d8c2SCharles.Forsyth char err[ERRMAX];
90*74a4d8c2SCharles.Forsyth
91*74a4d8c2SCharles.Forsyth buf = malloc(DEFB);
92*74a4d8c2SCharles.Forsyth /* clear any residual error */
93*74a4d8c2SCharles.Forsyth err[0] = '\0';
94*74a4d8c2SCharles.Forsyth errstr(err, ERRMAX);
95*74a4d8c2SCharles.Forsyth for(rcount=0;; rcount++) {
96*74a4d8c2SCharles.Forsyth n = read(fdf, buf, DEFB);
97*74a4d8c2SCharles.Forsyth if(n <= 0)
98*74a4d8c2SCharles.Forsyth break;
99*74a4d8c2SCharles.Forsyth n1 = write(fdt, buf, n);
100*74a4d8c2SCharles.Forsyth if(n1 != n) {
101*74a4d8c2SCharles.Forsyth fprint(2, "cp: error writing %s: %r\n", to);
102*74a4d8c2SCharles.Forsyth break;
103*74a4d8c2SCharles.Forsyth }
104*74a4d8c2SCharles.Forsyth }
105*74a4d8c2SCharles.Forsyth if(n < 0)
106*74a4d8c2SCharles.Forsyth fprint(2, "cp: error reading %s: %r\n", from);
107*74a4d8c2SCharles.Forsyth free(buf);
108*74a4d8c2SCharles.Forsyth }
109*74a4d8c2SCharles.Forsyth
110*74a4d8c2SCharles.Forsyth void
fixbackslash(char * file)111*74a4d8c2SCharles.Forsyth fixbackslash(char *file)
112*74a4d8c2SCharles.Forsyth {
113*74a4d8c2SCharles.Forsyth char *p;
114*74a4d8c2SCharles.Forsyth
115*74a4d8c2SCharles.Forsyth for(p=file; *p; p++)
116*74a4d8c2SCharles.Forsyth if(*p == '\\')
117*74a4d8c2SCharles.Forsyth *p = '/';
118*74a4d8c2SCharles.Forsyth }
119