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 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 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 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 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