tnew - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit d0cda8c42368dd1208469c7bd81749667df39a03 | |
parent f19d56825d36b224a376b4012c7656871d9b1535 | |
Author: rsc <devnull@localhost> | |
Date: Thu, 28 Jul 2005 12:46:10 +0000 | |
new | |
Diffstat: | |
A src/cmd/vbackup/vftp.c | 379 +++++++++++++++++++++++++++++… | |
1 file changed, 379 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/src/cmd/vbackup/vftp.c b/src/cmd/vbackup/vftp.c | |
t@@ -0,0 +1,379 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <thread.h> | |
+#include <venti.h> | |
+#include <sunrpc.h> | |
+#include <nfs3.h> | |
+#include <diskfs.h> | |
+ | |
+uchar *buf; | |
+uint bufsize; | |
+Nfs3Handle cwd, root; | |
+Biobuf bin, bout; | |
+char pwd[1000]; | |
+Fsys *fsys; | |
+SunAuthUnix *auth; | |
+VtConn *z; | |
+VtCache *c; | |
+Disk *disk; | |
+ | |
+char *cmdhelp(int, char**); | |
+char *cmdcd(int, char**); | |
+char *cmdpwd(int, char**); | |
+char *cmdls(int, char**); | |
+char *cmdcp(int, char**); | |
+char *cmdblock(int, char**); | |
+char *cmddisk(int, char**); | |
+ | |
+typedef struct Cmd Cmd; | |
+struct Cmd | |
+{ | |
+ char *s; | |
+ char *(*fn)(int, char**); | |
+ char *help; | |
+}; | |
+ | |
+Cmd cmdtab[] = | |
+{ | |
+ "cd", cmdcd, "cd dir - change directory", | |
+ "ls", cmdls, "ls [-d] path... - list file", | |
+ "pwd", cmdpwd, "pwd - print working directory", | |
+ "help", cmdhelp, "help - print usage summaries", | |
+ "block", cmdblock, "block path offset - print disk offset of path's by… | |
+ "disk", cmddisk, "disk offset count - dump disk contents", | |
+}; | |
+ | |
+char* | |
+ebuf(void) | |
+{ | |
+ static char buf[ERRMAX]; | |
+ | |
+ rerrstr(buf, sizeof buf); | |
+ return buf; | |
+} | |
+ | |
+char* | |
+walk(char *path, Nfs3Handle *ph) | |
+{ | |
+ char *p, *q; | |
+ Nfs3Handle h; | |
+ Nfs3Status ok; | |
+ | |
+ if(path[0] == '/') | |
+ h = root; | |
+ else | |
+ h = cwd; | |
+ for(p=path; *p; p=q){ | |
+ q = strchr(p, '/'); | |
+ if(q == nil) | |
+ q = p+strlen(p); | |
+ else | |
+ *q++ = 0; | |
+ if(*p == 0) | |
+ continue; | |
+ if((ok = fsyslookup(fsys, auth, &h, p, &h)) != Nfs3Ok){ | |
+ nfs3errstr(ok); | |
+ return ebuf(); | |
+ } | |
+ } | |
+ *ph = h; | |
+ return nil; | |
+} | |
+ | |
+char* | |
+cmdhelp(int argc, char **argv) | |
+{ | |
+ int i; | |
+ | |
+ for(i=0; i<nelem(cmdtab); i++) | |
+ print("%s\n", cmdtab[i].help); | |
+ return nil; | |
+} | |
+ | |
+char* | |
+cmdcd(int argc, char **argv) | |
+{ | |
+ char *err; | |
+ Nfs3Attr attr; | |
+ Nfs3Status ok; | |
+ Nfs3Handle h; | |
+ | |
+ if(argc != 2) | |
+ return "usage: cd dir"; | |
+ | |
+ if((err = walk(argv[1], &h)) != nil) | |
+ return err; | |
+ if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){ | |
+ nfs3errstr(ok); | |
+ fprint(2, "%s: %r\n"); | |
+ return nil; | |
+ } | |
+ if(attr.type != Nfs3FileDir) | |
+ return "not a directory"; | |
+ if(argv[1][0] == '/') | |
+ pwd[0] = 0; | |
+ strcat(pwd, "/"); | |
+ strcat(pwd, argv[1]); | |
+ cleanname(pwd); | |
+ cwd = h; | |
+ print("%s\n", pwd); | |
+ return nil; | |
+} | |
+ | |
+char* | |
+cmdpwd(int argc, char **argv) | |
+{ | |
+ if(argc != 1) | |
+ return "usage: pwd"; | |
+ | |
+ print("%s\n", pwd); | |
+ return nil; | |
+} | |
+ | |
+/* | |
+ * XXX maybe make a list of these in memory and then print them nicer | |
+ */ | |
+void | |
+ls(char *dir, char *elem, Nfs3Attr *attr) | |
+{ | |
+ char c; | |
+ | |
+ c = ' '; /* use attr->type */ | |
+ Bprint(&bout, "%s%s%s", dir ? dir : "", dir && elem ? "/" : "", elem ?… | |
+ Bprint(&bout, " %c%luo %1d %4d %4d", c, attr->mode, attr->nlink, attr-… | |
+ Bprint(&bout, " %11,lld %11,lld %4d.%4d %#11,llux %#11,llux", | |
+ attr->size, attr->used, attr->major, attr->minor, attr->fsid, … | |
+ Bprint(&bout, "\n"); | |
+} | |
+ | |
+void | |
+lsdir(char *dir, Nfs3Handle *h) | |
+{ | |
+ uchar *data, *p, *ep; | |
+ Nfs3Attr attr; | |
+ Nfs3Entry e; | |
+ Nfs3Handle eh; | |
+ u32int count; | |
+ u1int eof; | |
+ Nfs3Status ok; | |
+ u64int cookie; | |
+ | |
+ cookie = 0; | |
+ for(;;){ | |
+ ok = fsysreaddir(fsys, auth, h, 8192, cookie, &data, &count, &… | |
+fprint(2, "got %d\n", count); | |
+ if(ok != Nfs3Ok){ | |
+ nfs3errstr(ok); | |
+ fprint(2, "ls %s: %r\n", dir); | |
+ return; | |
+ } | |
+ p = data; | |
+ ep = data+count; | |
+ while(p<ep){ | |
+ if(nfs3entryunpack(p, ep, &p, &e) < 0){ | |
+ fprint(2, "%s: unpacking directory: %r\n", dir… | |
+ break; | |
+ } | |
+ cookie = e.cookie; | |
+ if((ok = fsyslookup(fsys, auth, h, e.name, &eh)) != Nf… | |
+ nfs3errstr(ok); | |
+ fprint(2, "%s/%s: %r\n", dir, e.name); | |
+ continue; | |
+ } | |
+ if((ok = fsysgetattr(fsys, auth, &eh, &attr)) != Nfs3O… | |
+ nfs3errstr(ok); | |
+ fprint(2, "%s/%s: %r\n", dir, e.name); | |
+ continue; | |
+ } | |
+ ls(dir, e.name, &attr); | |
+ } | |
+ free(data); | |
+ if(eof) | |
+ break; | |
+ } | |
+} | |
+ | |
+char* | |
+cmdls(int argc, char **argv) | |
+{ | |
+ int i; | |
+ int dflag; | |
+ char *e; | |
+ Nfs3Handle h; | |
+ Nfs3Attr attr; | |
+ Nfs3Status ok; | |
+ | |
+ dflag = 0; | |
+ ARGBEGIN{ | |
+ case 'd': | |
+ dflag = 1; | |
+ break; | |
+ default: | |
+ return "usage: ls [-d] [path...]"; | |
+ }ARGEND | |
+ | |
+ if(argc == 0){ | |
+ lsdir(nil, &cwd); | |
+ Bflush(&bout); | |
+ return nil; | |
+ } | |
+ | |
+ for(i=0; i<argc; i++){ | |
+ if((e = walk(argv[i], &h)) != nil){ | |
+ fprint(2, "%s: %s\n", argv[i], e); | |
+ continue; | |
+ } | |
+ if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){ | |
+ nfs3errstr(ok); | |
+ fprint(2, "%s: %r\n", argv[i]); | |
+ continue; | |
+ } | |
+ if(attr.type != Nfs3FileDir || dflag) | |
+ ls(argv[i], nil, &attr); | |
+ else | |
+ lsdir(argv[i], &h); | |
+ Bflush(&bout); | |
+ } | |
+ return nil; | |
+} | |
+ | |
+char* | |
+cmdblock(int argc, char **argv) | |
+{ | |
+ char *e; | |
+ Nfs3Handle h; | |
+ u64int bno; | |
+ | |
+ ARGBEGIN{ | |
+ default: | |
+ return "usage: block path offset"; | |
+ }ARGEND | |
+ | |
+ if(argc != 2) | |
+ return "usage: block path offset"; | |
+ | |
+ if((e = walk(argv[0], &h)) != nil){ | |
+ fprint(2, "%s: %s\n", argv[0], e); | |
+ return nil; | |
+ } | |
+ if((bno = fsys->fileblock(fsys, &h, strtoll(argv[1], 0, 0))) == 0){ | |
+ fprint(2, "%s: %r\n", argv[0]); | |
+ return nil; | |
+ } | |
+ print("%#llux\n", bno); | |
+ return nil; | |
+} | |
+ | |
+char* | |
+cmddisk(int argc, char **argv) | |
+{ | |
+ Block *b; | |
+ int delta, count, i; | |
+ u64int offset; | |
+ uchar *p; | |
+ | |
+ ARGBEGIN{ | |
+ default: | |
+ return "usage: disk offset count"; | |
+ }ARGEND | |
+ | |
+ if(argc != 2) | |
+ return "usage: disk offset count"; | |
+ | |
+ offset = strtoull(argv[0], 0, 0); | |
+ count = atoi(argv[1]); | |
+ delta = offset%fsys->blocksize; | |
+ | |
+ b = diskread(disk, fsys->blocksize, offset-delta); | |
+ if(b == nil){ | |
+ fprint(2, "diskread: %r\n"); | |
+ return nil; | |
+ } | |
+ p = b->data + delta; | |
+ for(i=0; i<count; i++){ | |
+ Bprint(&bout, "%2.2ux ", p[i]); | |
+ if(i%16 == 15) | |
+ Bprint(&bout, "\n"); | |
+ else if(i%8 == 7) | |
+ Bprint(&bout, " - "); | |
+ } | |
+ if(i%16 != 0) | |
+ Bprint(&bout, "\n"); | |
+ Bflush(&bout); | |
+ blockput(b); | |
+ return nil; | |
+} | |
+ | |
+void | |
+usage(void) | |
+{ | |
+ fprint(2, "usage: vftp score\n"); | |
+ threadexitsall("usage"); | |
+} | |
+ | |
+void | |
+threadmain(int argc, char **argv) | |
+{ | |
+ char *err, *f[10], *p; | |
+ int i, nf; | |
+ uchar score[VtScoreSize]; | |
+ Nfs3Status ok; | |
+ | |
+ ARGBEGIN{ | |
+ case 'V': | |
+ chattyventi++; | |
+ break; | |
+ default: | |
+ usage(); | |
+ }ARGEND | |
+ | |
+ if(argc != 1) | |
+ usage(); | |
+ | |
+ fmtinstall('F', vtfcallfmt); | |
+ fmtinstall('H', encodefmt); | |
+ fmtinstall('V', vtscorefmt); | |
+ | |
+ if(vtparsescore(argv[0], nil, score) < 0) | |
+ sysfatal("bad score '%s'", argv[0]); | |
+ if((z = vtdial(nil)) == nil) | |
+ sysfatal("vtdial: %r"); | |
+ if(vtconnect(z) < 0) | |
+ sysfatal("vtconnect: %r"); | |
+ if((c = vtcachealloc(z, 16384, 32)) == nil) | |
+ sysfatal("vtcache: %r"); | |
+ if((disk = diskopenventi(c, score)) == nil) | |
+ sysfatal("diskopenventi: %r"); | |
+ if((fsys = fsysopen(disk)) == nil) | |
+ sysfatal("ffsopen: %r"); | |
+ | |
+ fprint(2, "block size %d\n", fsys->blocksize); | |
+ buf = emalloc(fsys->blocksize); | |
+ if((ok = fsysroot(fsys, &root)) != Nfs3Ok){ | |
+ nfs3errstr(ok); | |
+ sysfatal("accessing root: %r"); | |
+ } | |
+ cwd = root; | |
+ Binit(&bin, 0, OREAD); | |
+ Binit(&bout, 1, OWRITE); | |
+ | |
+ while(fprint(2, "vftp> "), (p = Brdstr(&bin, '\n', 1)) != nil){ | |
+ if(p[0] == '#') | |
+ continue; | |
+ nf = tokenize(p, f, nelem(f)); | |
+ if(nf == 0) | |
+ continue; | |
+ for(i=0; i<nelem(cmdtab); i++){ | |
+ if(strcmp(f[0], cmdtab[i].s) == 0){ | |
+ if((err = cmdtab[i].fn(nf, f)) != nil) | |
+ fprint(2, "%s\n", err); | |
+ break; | |
+ } | |
+ } | |
+ if(i == nelem(cmdtab)) | |
+ fprint(2, "unknown command '%s'\n", f[0]); | |
+ } | |
+ threadexitsall(nil); | |
+} | |
+ |