13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
4219b2ee8SDavid du Colombier #define DEFB (8*1024)
53e12c5d1SDavid du Colombier
6*5d459b5aSDavid du Colombier int failed;
79a747e4fSDavid du Colombier int gflag;
89a747e4fSDavid du Colombier int uflag;
97dd7cddfSDavid du Colombier int xflag;
103e12c5d1SDavid du Colombier void copy(char *from, char *to, int todir);
119a747e4fSDavid du Colombier int copy1(int fdf, int fdt, char *from, char *to);
123e12c5d1SDavid du Colombier
133e12c5d1SDavid du Colombier void
main(int argc,char * argv[])143e12c5d1SDavid du Colombier main(int argc, char *argv[])
153e12c5d1SDavid du Colombier {
169a747e4fSDavid du Colombier Dir *dirb;
173e12c5d1SDavid du Colombier int todir, i;
183e12c5d1SDavid du Colombier
197dd7cddfSDavid du Colombier ARGBEGIN {
209a747e4fSDavid du Colombier case 'g':
219a747e4fSDavid du Colombier gflag++;
229a747e4fSDavid du Colombier break;
239a747e4fSDavid du Colombier case 'u':
249a747e4fSDavid du Colombier uflag++;
259a747e4fSDavid du Colombier gflag++;
269a747e4fSDavid du Colombier break;
277dd7cddfSDavid du Colombier case 'x':
287dd7cddfSDavid du Colombier xflag++;
297dd7cddfSDavid du Colombier break;
307dd7cddfSDavid du Colombier default:
317dd7cddfSDavid du Colombier goto usage;
327dd7cddfSDavid du Colombier } ARGEND
337dd7cddfSDavid du Colombier
343e12c5d1SDavid du Colombier todir=0;
357dd7cddfSDavid du Colombier if(argc < 2)
367dd7cddfSDavid du Colombier goto usage;
379a747e4fSDavid du Colombier dirb = dirstat(argv[argc-1]);
389a747e4fSDavid du Colombier if(dirb!=nil && (dirb->mode&DMDIR))
393e12c5d1SDavid du Colombier todir=1;
407dd7cddfSDavid du Colombier if(argc>2 && !todir){
413e12c5d1SDavid du Colombier fprint(2, "cp: %s not a directory\n", argv[argc-1]);
423e12c5d1SDavid du Colombier exits("bad usage");
433e12c5d1SDavid du Colombier }
447dd7cddfSDavid du Colombier for(i=0; i<argc-1; i++)
453e12c5d1SDavid du Colombier copy(argv[i], argv[argc-1], todir);
46*5d459b5aSDavid du Colombier if(failed)
47*5d459b5aSDavid du Colombier exits("errors");
483e12c5d1SDavid du Colombier exits(0);
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier usage:
519a747e4fSDavid du Colombier fprint(2, "usage:\tcp [-gux] fromfile tofile\n");
527dd7cddfSDavid du Colombier fprint(2, "\tcp [-x] fromfile ... todir\n");
537dd7cddfSDavid du Colombier exits("usage");
543e12c5d1SDavid du Colombier }
553e12c5d1SDavid du Colombier
569a747e4fSDavid du Colombier int
samefile(Dir * a,char * an,char * bn)579a747e4fSDavid du Colombier samefile(Dir *a, char *an, char *bn)
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier Dir *b;
609a747e4fSDavid du Colombier int ret;
619a747e4fSDavid du Colombier
629a747e4fSDavid du Colombier ret = 0;
639a747e4fSDavid du Colombier b=dirstat(bn);
649a747e4fSDavid du Colombier if(b != nil)
659a747e4fSDavid du Colombier if(b->qid.type==a->qid.type)
669a747e4fSDavid du Colombier if(b->qid.path==a->qid.path)
679a747e4fSDavid du Colombier if(b->qid.vers==a->qid.vers)
689a747e4fSDavid du Colombier if(b->dev==a->dev)
699a747e4fSDavid du Colombier if(b->type==a->type){
709a747e4fSDavid du Colombier fprint(2, "cp: %s and %s are the same file\n", an, bn);
719a747e4fSDavid du Colombier ret = 1;
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier free(b);
749a747e4fSDavid du Colombier return ret;
759a747e4fSDavid du Colombier }
769a747e4fSDavid du Colombier
773e12c5d1SDavid du Colombier void
copy(char * from,char * to,int todir)783e12c5d1SDavid du Colombier copy(char *from, char *to, int todir)
793e12c5d1SDavid du Colombier {
809a747e4fSDavid du Colombier Dir *dirb, dirt;
813e12c5d1SDavid du Colombier char name[256];
829a747e4fSDavid du Colombier int fdf, fdt, mode;
833e12c5d1SDavid du Colombier
843e12c5d1SDavid du Colombier if(todir){
853e12c5d1SDavid du Colombier char *s, *elem;
863e12c5d1SDavid du Colombier elem=s=from;
873e12c5d1SDavid du Colombier while(*s++)
883e12c5d1SDavid du Colombier if(s[-1]=='/')
893e12c5d1SDavid du Colombier elem=s;
903e12c5d1SDavid du Colombier sprint(name, "%s/%s", to, elem);
913e12c5d1SDavid du Colombier to=name;
923e12c5d1SDavid du Colombier }
939a747e4fSDavid du Colombier
949a747e4fSDavid du Colombier if((dirb=dirstat(from))==nil){
95219b2ee8SDavid du Colombier fprint(2,"cp: can't stat %s: %r\n", from);
96*5d459b5aSDavid du Colombier failed = 1;
973e12c5d1SDavid du Colombier return;
983e12c5d1SDavid du Colombier }
999a747e4fSDavid du Colombier mode = dirb->mode;
1009a747e4fSDavid du Colombier if(mode&DMDIR){
1013e12c5d1SDavid du Colombier fprint(2, "cp: %s is a directory\n", from);
1029a747e4fSDavid du Colombier free(dirb);
103*5d459b5aSDavid du Colombier failed = 1;
1043e12c5d1SDavid du Colombier return;
1053e12c5d1SDavid du Colombier }
1069a747e4fSDavid du Colombier if(samefile(dirb, from, to)){
1079a747e4fSDavid du Colombier free(dirb);
108*5d459b5aSDavid du Colombier failed = 1;
1093e12c5d1SDavid du Colombier return;
1103e12c5d1SDavid du Colombier }
1119a747e4fSDavid du Colombier mode &= 0777;
1123e12c5d1SDavid du Colombier fdf=open(from, OREAD);
1133e12c5d1SDavid du Colombier if(fdf<0){
114219b2ee8SDavid du Colombier fprint(2, "cp: can't open %s: %r\n", from);
1159a747e4fSDavid du Colombier free(dirb);
116*5d459b5aSDavid du Colombier failed = 1;
1173e12c5d1SDavid du Colombier return;
1183e12c5d1SDavid du Colombier }
1199a747e4fSDavid du Colombier fdt=create(to, OWRITE, mode);
1203e12c5d1SDavid du Colombier if(fdt<0){
121219b2ee8SDavid du Colombier fprint(2, "cp: can't create %s: %r\n", to);
1223e12c5d1SDavid du Colombier close(fdf);
1239a747e4fSDavid du Colombier free(dirb);
124*5d459b5aSDavid du Colombier failed = 1;
1253e12c5d1SDavid du Colombier return;
1263e12c5d1SDavid du Colombier }
1279a747e4fSDavid du Colombier if(copy1(fdf, fdt, from, to)==0 && (xflag || gflag || uflag)){
1289a747e4fSDavid du Colombier nulldir(&dirt);
1299a747e4fSDavid du Colombier if(xflag){
1309a747e4fSDavid du Colombier dirt.mtime = dirb->mtime;
1319a747e4fSDavid du Colombier dirt.mode = dirb->mode;
1329a747e4fSDavid du Colombier }
1339a747e4fSDavid du Colombier if(uflag)
1349a747e4fSDavid du Colombier dirt.uid = dirb->uid;
1359a747e4fSDavid du Colombier if(gflag)
1369a747e4fSDavid du Colombier dirt.gid = dirb->gid;
1379a747e4fSDavid du Colombier if(dirfwstat(fdt, &dirt) < 0)
1389a747e4fSDavid du Colombier fprint(2, "cp: warning: can't wstat %s: %r\n", to);
1399a747e4fSDavid du Colombier }
1409a747e4fSDavid du Colombier free(dirb);
1413e12c5d1SDavid du Colombier close(fdf);
1423e12c5d1SDavid du Colombier close(fdt);
1433e12c5d1SDavid du Colombier }
1443e12c5d1SDavid du Colombier
1459a747e4fSDavid du Colombier int
copy1(int fdf,int fdt,char * from,char * to)1463e12c5d1SDavid du Colombier copy1(int fdf, int fdt, char *from, char *to)
1473e12c5d1SDavid du Colombier {
148219b2ee8SDavid du Colombier char *buf;
149219b2ee8SDavid du Colombier long n, n1, rcount;
1509a747e4fSDavid du Colombier int rv;
1519a747e4fSDavid du Colombier char err[ERRMAX];
1523e12c5d1SDavid du Colombier
153219b2ee8SDavid du Colombier buf = malloc(DEFB);
154219b2ee8SDavid du Colombier /* clear any residual error */
1559a747e4fSDavid du Colombier err[0] = '\0';
1569a747e4fSDavid du Colombier errstr(err, ERRMAX);
1579a747e4fSDavid du Colombier rv = 0;
1583e12c5d1SDavid du Colombier for(rcount=0;; rcount++) {
159219b2ee8SDavid du Colombier n = read(fdf, buf, DEFB);
1603e12c5d1SDavid du Colombier if(n <= 0)
1613e12c5d1SDavid du Colombier break;
1623e12c5d1SDavid du Colombier n1 = write(fdt, buf, n);
1633e12c5d1SDavid du Colombier if(n1 != n) {
164219b2ee8SDavid du Colombier fprint(2, "cp: error writing %s: %r\n", to);
165*5d459b5aSDavid du Colombier failed = 1;
1669a747e4fSDavid du Colombier rv = -1;
1673e12c5d1SDavid du Colombier break;
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier }
1709a747e4fSDavid du Colombier if(n < 0) {
171219b2ee8SDavid du Colombier fprint(2, "cp: error reading %s: %r\n", from);
172*5d459b5aSDavid du Colombier failed = 1;
1739a747e4fSDavid du Colombier rv = -1;
1749a747e4fSDavid du Colombier }
175219b2ee8SDavid du Colombier free(buf);
1769a747e4fSDavid du Colombier return rv;
1773e12c5d1SDavid du Colombier }
178