#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 *cmdget(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", "get", cmdget, "get path [lpath] - copy file to local directory", "pwd", cmdpwd, "pwd - print working directory", "help", cmdhelp, "help - print usage summaries", "block", cmdblock, "block path offset - print disk offset of path's byte offset", "disk", cmddisk, "disk offset count - dump disk contents" }; char* ebuf(void) { static char buf[ERRMAX]; rerrstr(buf, sizeof buf); return buf; } static char* estrdup(char *s) { char *t; t = emalloc(strlen(s)+1); strcpy(t, s); return t; } char* walk(char *path, Nfs3Handle *ph) { char *p, *q; Nfs3Handle h; Nfs3Status ok; path = estrdup(path); /* writable */ 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); free(path); return ebuf(); } } *ph = h; free(path); 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", argv[1]); 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 ? elem : ""); Bprint(&bout, " %c%luo %1d %4d %4d", c, attr->mode, attr->nlink, attr->uid, attr->gid); Bprint(&bout, " %11,lld %11,lld %4d.%4d %#11,llux %#11,llux", attr->size, attr->used, attr->major, attr->minor, attr->fsid, attr->fileid); 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, &eof); if(ok != Nfs3Ok){ nfs3errstr(ok); fprint(2, "ls %s: %r\n", dir); return; } fprint(2, "got %d\n", count); 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)) != Nfs3Ok){ nfs3errstr(ok); fprint(2, "%s/%s: %r\n", dir, e.name); continue; } if((ok = fsysgetattr(fsys, auth, &eh, &attr)) != Nfs3Ok){ 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* cmdget(int argc, char **argv) { uchar eof; u32int n; int dflag, fd; char *e, *local; uchar *buf; Nfs3Handle h; Nfs3Attr attr; Nfs3Status ok; vlong o; dflag = 0; ARGBEGIN{ default: usage: return "usage: get path [lpath]]"; }ARGEND if(argc != 1 && argc != 2) goto usage; if((e = walk(argv[0], &h)) != nil){ fprint(2, "%s: %s\n", argv[0], e); return nil; } if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){ nfs3errstr(ok); fprint(2, "%s: %r\n", argv[0]); return nil; } local = argv[0]; if(argc == 2) local = argv[1]; if((fd = create(local, OWRITE, 0666)) < 0){ fprint(2, "create %s: %r\n", local); return nil; } eof = 0; for(o=0; o<attr.size && !eof; o+=n){ if((ok = fsysreadfile(fsys, nil, &h, fsys->blocksize, o, &buf, &n, &eof)) != Nfs3Ok){ nfs3errstr(ok); fprint(2, "reading %s: %r\n", argv[0]); close(fd); return nil; } if(write(fd, buf, n) != n){ fprint(2, "writing %s: %r\n", local); close(fd); free(buf); return nil; } free(buf); } close(fd); fprint(2, "copied %,lld bytes\n", o); 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"); } extern int allowall; void threadmain(int argc, char **argv) { char *err, *f[10], *p; int i, nf; uchar score[VtScoreSize]; Nfs3Status ok; allowall = 1; ARGBEGIN{ case 'V': chattyventi++; break; default: usage(); }ARGEND if(argc != 1) usage(); fmtinstall('F', vtfcallfmt); fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); if(access(argv[0], AEXIST) >= 0 || strchr(argv[0], '/')){ if((disk = diskopenfile(argv[0])) == nil) sysfatal("diskopen: %r"); if((disk = diskcache(disk, 32768, 16)) == nil) sysfatal("diskcache: %r"); }else{ 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, 32768, 32)) == nil) sysfatal("vtcache: %r"); if((disk = diskopenventi(c, score)) == nil) sysfatal("diskopenventi: %r"); } if((fsys = fsysopen(disk)) == nil) sysfatal("fsysopen: %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); }