diff options
Diffstat (limited to 'utils/cp/cp.c')
| -rw-r--r-- | utils/cp/cp.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/utils/cp/cp.c b/utils/cp/cp.c new file mode 100644 index 00000000..7395e16c --- /dev/null +++ b/utils/cp/cp.c @@ -0,0 +1,118 @@ +#include <lib9.h> + +#define DEFB (8*1024) + +void copy(char *from, char *to, int todir); +void copy1(int fdf, int fdt, char *from, char *to); +void fixbackslash(char *file); + +void +main(int argc, char *argv[]) +{ + Dir *dirb; + int todir, i; + + if(argc<3){ + fprint(2, "usage:\tcp fromfile tofile\n"); + fprint(2, "\tcp fromfile ... todir\n"); + exits("usage"); + } + + for(i=0; i<argc; i++) + fixbackslash(argv[i]); + + + todir=0; + if((dirb = dirstat(argv[argc-1]))!=nil && (dirb->mode&DMDIR)) + todir=1; + if(argc>3 && !todir){ + fprint(2, "cp: %s not a directory\n", argv[argc-1]); + exits("bad usage"); + } + for(i=1; i<argc-1; i++) + copy(argv[i], argv[argc-1], todir); + exits(0); +} + +void +copy(char *from, char *to, int todir) +{ + Dir *dirb, *dirt; + char name[256]; + int fdf, fdt; + + if(todir){ + char *s, *elem; + elem=s=from; + while(*s++) + if(s[-1]=='/') + elem=s; + sprint(name, "%s/%s", to, elem); + to=name; + } + if((dirb = dirstat(from))==nil){ + fprint(2,"cp: can't stat %s: %r\n", from); + return; + } + if(dirb->mode&DMDIR){ + fprint(2, "cp: %s is a directory\n", from); + return; + } + dirb->mode &= 0777; + if((dirt = dirstat(to))!=nil) + if(dirb->qid.path==dirt->qid.path && dirb->qid.vers==dirt->qid.vers) + if(dirb->dev==dirt->dev && dirb->type==dirt->type){ + fprint(2, "cp: %s and %s are the same file\n", from, to); + return; + } + fdf=open(from, OREAD); + if(fdf<0){ + fprint(2, "cp: can't open %s: %r\n", from); + return; + } + fdt=create(to, OWRITE, dirb->mode); + if(fdt<0){ + fprint(2, "cp: can't create %s: %r\n", to); + close(fdf); + return; + } + copy1(fdf, fdt, from, to); + close(fdf); + close(fdt); +} + +void +copy1(int fdf, int fdt, char *from, char *to) +{ + char *buf; + long n, n1, rcount; + char err[ERRMAX]; + + buf = malloc(DEFB); + /* clear any residual error */ + err[0] = '\0'; + errstr(err, ERRMAX); + for(rcount=0;; rcount++) { + n = read(fdf, buf, DEFB); + if(n <= 0) + break; + n1 = write(fdt, buf, n); + if(n1 != n) { + fprint(2, "cp: error writing %s: %r\n", to); + break; + } + } + if(n < 0) + fprint(2, "cp: error reading %s: %r\n", from); + free(buf); +} + +void +fixbackslash(char *file) +{ + char *p; + + for(p=file; *p; p++) + if(*p == '\\') + *p = '/'; +} |
