tnew - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit d0cda8c42368dd1208469c7bd81749667df39a03
 (DIR) parent f19d56825d36b224a376b4012c7656871d9b1535
 (HTM) 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(-)
       ---
 (DIR) 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 byte offset",
       +        "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 ? 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);
       +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)) != 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*
       +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);
       +}
       +