xref: /inferno-os/utils/cp/cp.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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