URI:
       tvftp.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tvftp.c (8483B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <thread.h>
            5 #include <venti.h>
            6 #include <sunrpc.h>
            7 #include <nfs3.h>
            8 #include <diskfs.h>
            9 
           10 uchar *buf;
           11 uint bufsize;
           12 Nfs3Handle cwd, root;
           13 Biobuf bin, bout;
           14 char pwd[1000];
           15 Fsys *fsys;
           16 SunAuthUnix *auth;
           17 VtConn *z;
           18 VtCache *c;
           19 Disk *disk;
           20 
           21 char *cmdhelp(int, char**);
           22 char *cmdcd(int, char**);
           23 char *cmdpwd(int, char**);
           24 char *cmdls(int, char**);
           25 char *cmdget(int, char**);
           26 char *cmdblock(int, char**);
           27 char *cmddisk(int, char**);
           28 
           29 typedef struct Cmd Cmd;
           30 struct Cmd
           31 {
           32         char *s;
           33         char *(*fn)(int, char**);
           34         char *help;
           35 };
           36 
           37 Cmd cmdtab[] =
           38 {
           39         "cd", cmdcd, "cd dir - change directory",
           40         "ls", cmdls, "ls [-d] path... - list file",
           41         "get", cmdget, "get path [lpath] - copy file to local directory",
           42         "pwd", cmdpwd, "pwd - print working directory",
           43         "help", cmdhelp, "help - print usage summaries",
           44         "block", cmdblock, "block path offset - print disk offset of path's byte offset",
           45         "disk", cmddisk, "disk offset count - dump disk contents"
           46 };
           47 
           48 char*
           49 ebuf(void)
           50 {
           51         static char buf[ERRMAX];
           52 
           53         rerrstr(buf, sizeof buf);
           54         return buf;
           55 }
           56 
           57 static char*
           58 estrdup(char *s)
           59 {
           60         char *t;
           61 
           62         t = emalloc(strlen(s)+1);
           63         strcpy(t, s);
           64         return t;
           65 }
           66 
           67 char*
           68 walk(char *path, Nfs3Handle *ph)
           69 {
           70         char *p, *q;
           71         Nfs3Handle h;
           72         Nfs3Status ok;
           73 
           74         path = estrdup(path); /* writable */
           75         if(path[0] == '/')
           76                 h = root;
           77         else
           78                 h = cwd;
           79         for(p=path; *p; p=q){
           80                 q = strchr(p, '/');
           81                 if(q == nil)
           82                         q = p+strlen(p);
           83                 else
           84                         *q++ = 0;
           85                 if(*p == 0)
           86                         continue;
           87                 if((ok = fsyslookup(fsys, auth, &h, p, &h)) != Nfs3Ok){
           88                         nfs3errstr(ok);
           89                         free(path);
           90                         return ebuf();
           91                 }
           92         }
           93         *ph = h;
           94         free(path);
           95         return nil;
           96 }
           97 
           98 char*
           99 cmdhelp(int argc, char **argv)
          100 {
          101         int i;
          102 
          103         for(i=0; i<nelem(cmdtab); i++)
          104                 print("%s\n", cmdtab[i].help);
          105         return nil;
          106 }
          107 
          108 char*
          109 cmdcd(int argc, char **argv)
          110 {
          111         char *err;
          112         Nfs3Attr attr;
          113         Nfs3Status ok;
          114         Nfs3Handle h;
          115 
          116         if(argc != 2)
          117                 return "usage: cd dir";
          118 
          119         if((err = walk(argv[1], &h)) != nil)
          120                 return err;
          121         if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){
          122                 nfs3errstr(ok);
          123                 fprint(2, "%s: %r\n", argv[1]);
          124                 return nil;
          125         }
          126         if(attr.type != Nfs3FileDir)
          127                 return "not a directory";
          128         if(argv[1][0] == '/')
          129                 pwd[0] = 0;
          130         strcat(pwd, "/");
          131         strcat(pwd, argv[1]);
          132         cleanname(pwd);
          133         cwd = h;
          134         print("%s\n", pwd);
          135         return nil;
          136 }
          137 
          138 char*
          139 cmdpwd(int argc, char **argv)
          140 {
          141         if(argc != 1)
          142                 return "usage: pwd";
          143 
          144         print("%s\n", pwd);
          145         return nil;
          146 }
          147 
          148 /*
          149  * XXX maybe make a list of these in memory and then print them nicer
          150  */
          151 void
          152 ls(char *dir, char *elem, Nfs3Attr *attr)
          153 {
          154         char c;
          155 
          156         c = ' ';        /* use attr->type */
          157         Bprint(&bout, "%s%s%s", dir ? dir : "", dir && elem ? "/" : "", elem ? elem : "");
          158         Bprint(&bout, " %c%luo %1d %4d %4d", c, attr->mode, attr->nlink, attr->uid, attr->gid);
          159         Bprint(&bout, " %11,lld %11,lld %4d.%4d %#11,llux %#11,llux",
          160                 attr->size, attr->used, attr->major, attr->minor, attr->fsid, attr->fileid);
          161         Bprint(&bout, "\n");
          162 }
          163 
          164 void
          165 lsdir(char *dir, Nfs3Handle *h)
          166 {
          167         uchar *data, *p, *ep;
          168         Nfs3Attr attr;
          169         Nfs3Entry e;
          170         Nfs3Handle eh;
          171         u32int count;
          172         u1int eof;
          173         Nfs3Status ok;
          174         u64int cookie;
          175 
          176         cookie = 0;
          177         for(;;){
          178                 ok = fsysreaddir(fsys, auth, h, 8192, cookie, &data, &count, &eof);
          179                 if(ok != Nfs3Ok){
          180                         nfs3errstr(ok);
          181                         fprint(2, "ls %s: %r\n", dir);
          182                         return;
          183                 }
          184 fprint(2, "got %d\n", count);
          185                 p = data;
          186                 ep = data+count;
          187                 while(p<ep){
          188                         if(nfs3entryunpack(p, ep, &p, &e) < 0){
          189                                 fprint(2, "%s: unpacking directory: %r\n", dir);
          190                                 break;
          191                         }
          192                         cookie = e.cookie;
          193                         if((ok = fsyslookup(fsys, auth, h, e.name, &eh)) != Nfs3Ok){
          194                                 nfs3errstr(ok);
          195                                 fprint(2, "%s/%s: %r\n", dir, e.name);
          196                                 continue;
          197                         }
          198                         if((ok = fsysgetattr(fsys, auth, &eh, &attr)) != Nfs3Ok){
          199                                 nfs3errstr(ok);
          200                                 fprint(2, "%s/%s: %r\n", dir, e.name);
          201                                 continue;
          202                         }
          203                         ls(dir, e.name, &attr);
          204                 }
          205                 free(data);
          206                 if(eof)
          207                         break;
          208         }
          209 }
          210 
          211 char*
          212 cmdls(int argc, char **argv)
          213 {
          214         int i;
          215         int dflag;
          216         char *e;
          217         Nfs3Handle h;
          218         Nfs3Attr attr;
          219         Nfs3Status ok;
          220 
          221         dflag = 0;
          222         ARGBEGIN{
          223         case 'd':
          224                 dflag = 1;
          225                 break;
          226         default:
          227                 return "usage: ls [-d] [path...]";
          228         }ARGEND
          229 
          230         if(argc == 0){
          231                 lsdir(nil, &cwd);
          232                 Bflush(&bout);
          233                 return nil;
          234         }
          235 
          236         for(i=0; i<argc; i++){
          237                 if((e = walk(argv[i], &h)) != nil){
          238                         fprint(2, "%s: %s\n", argv[i], e);
          239                         continue;
          240                 }
          241                 if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){
          242                         nfs3errstr(ok);
          243                         fprint(2, "%s: %r\n", argv[i]);
          244                         continue;
          245                 }
          246                 if(attr.type != Nfs3FileDir || dflag)
          247                         ls(argv[i], nil, &attr);
          248                 else
          249                         lsdir(argv[i], &h);
          250                 Bflush(&bout);
          251         }
          252         return nil;
          253 }
          254 
          255 char*
          256 cmdget(int argc, char **argv)
          257 {
          258         uchar eof;
          259         u32int n;
          260         int dflag, fd;
          261         char *e, *local;
          262         uchar *buf;
          263         Nfs3Handle h;
          264         Nfs3Attr attr;
          265         Nfs3Status ok;
          266         vlong o;
          267 
          268         dflag = 0;
          269         ARGBEGIN{
          270         default:
          271         usage:
          272                 return "usage: get path [lpath]]";
          273         }ARGEND
          274 
          275         if(argc != 1 && argc != 2)
          276                 goto usage;
          277 
          278         if((e = walk(argv[0], &h)) != nil){
          279                 fprint(2, "%s: %s\n", argv[0], e);
          280                 return nil;
          281         }
          282         if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){
          283                 nfs3errstr(ok);
          284                 fprint(2, "%s: %r\n", argv[0]);
          285                 return nil;
          286         }
          287         local = argv[0];
          288         if(argc == 2)
          289                 local = argv[1];
          290         if((fd = create(local, OWRITE, 0666)) < 0){
          291                 fprint(2, "create %s: %r\n", local);
          292                 return nil;
          293         }
          294         eof = 0;
          295         for(o=0; o<attr.size && !eof; o+=n){
          296                 if((ok = fsysreadfile(fsys, nil, &h, fsys->blocksize, o, &buf, &n, &eof)) != Nfs3Ok){
          297                         nfs3errstr(ok);
          298                         fprint(2, "reading %s: %r\n", argv[0]);
          299                         close(fd);
          300                         return nil;
          301                 }
          302                 if(write(fd, buf, n) != n){
          303                         fprint(2, "writing %s: %r\n", local);
          304                         close(fd);
          305                         free(buf);
          306                         return nil;
          307                 }
          308                 free(buf);
          309         }
          310         close(fd);
          311         fprint(2, "copied %,lld bytes\n", o);
          312         return nil;
          313 }
          314 
          315 
          316 char*
          317 cmdblock(int argc, char **argv)
          318 {
          319         char *e;
          320         Nfs3Handle h;
          321         u64int bno;
          322 
          323         ARGBEGIN{
          324         default:
          325                 return "usage: block path offset";
          326         }ARGEND
          327 
          328         if(argc != 2)
          329                 return "usage: block path offset";
          330 
          331         if((e = walk(argv[0], &h)) != nil){
          332                 fprint(2, "%s: %s\n", argv[0], e);
          333                 return nil;
          334         }
          335         if((bno = fsys->fileblock(fsys, &h, strtoll(argv[1], 0, 0))) == 0){
          336                 fprint(2, "%s: %r\n", argv[0]);
          337                 return nil;
          338         }
          339         print("%#llux\n", bno);
          340         return nil;
          341 }
          342 
          343 char*
          344 cmddisk(int argc, char **argv)
          345 {
          346         Block *b;
          347         int delta, count, i;
          348         u64int offset;
          349         uchar *p;
          350 
          351         ARGBEGIN{
          352         default:
          353                 return "usage: disk offset count";
          354         }ARGEND
          355 
          356         if(argc != 2)
          357                 return "usage: disk offset count";
          358 
          359         offset = strtoull(argv[0], 0, 0);
          360         count = atoi(argv[1]);
          361         delta = offset%fsys->blocksize;
          362 
          363         b = diskread(disk, fsys->blocksize, offset-delta);
          364         if(b == nil){
          365                 fprint(2, "diskread: %r\n");
          366                 return nil;
          367         }
          368         p = b->data + delta;
          369         for(i=0; i<count; i++){
          370                 Bprint(&bout, "%2.2ux ", p[i]);
          371                 if(i%16 == 15)
          372                         Bprint(&bout, "\n");
          373                 else if(i%8 == 7)
          374                         Bprint(&bout, " - ");
          375         }
          376         if(i%16 != 0)
          377                 Bprint(&bout, "\n");
          378         Bflush(&bout);
          379         blockput(b);
          380         return nil;
          381 }
          382 
          383 void
          384 usage(void)
          385 {
          386         fprint(2, "usage: vftp score\n");
          387         threadexitsall("usage");
          388 }
          389 
          390 extern int allowall;
          391 
          392 void
          393 threadmain(int argc, char **argv)
          394 {
          395         char *err, *f[10], *p;
          396         int i, nf;
          397         uchar score[VtScoreSize];
          398         Nfs3Status ok;
          399 
          400         allowall = 1;
          401         ARGBEGIN{
          402         case 'V':
          403                 chattyventi++;
          404                 break;
          405         default:
          406                 usage();
          407         }ARGEND
          408 
          409         if(argc != 1)
          410                 usage();
          411 
          412         fmtinstall('F', vtfcallfmt);
          413         fmtinstall('H', encodefmt);
          414         fmtinstall('V', vtscorefmt);
          415 
          416         if(access(argv[0], AEXIST) >= 0 || strchr(argv[0], '/')){
          417                 if((disk = diskopenfile(argv[0])) == nil)
          418                         sysfatal("diskopen: %r");
          419                 if((disk = diskcache(disk, 32768, 16)) == nil)
          420                         sysfatal("diskcache: %r");
          421         }else{
          422                 if(vtparsescore(argv[0], nil, score) < 0)
          423                         sysfatal("bad score '%s'", argv[0]);
          424                 if((z = vtdial(nil)) == nil)
          425                         sysfatal("vtdial: %r");
          426                 if(vtconnect(z) < 0)
          427                         sysfatal("vtconnect: %r");
          428                 if((c = vtcachealloc(z, 32768, 32)) == nil)
          429                         sysfatal("vtcache: %r");
          430                 if((disk = diskopenventi(c, score)) == nil)
          431                         sysfatal("diskopenventi: %r");
          432         }
          433         if((fsys = fsysopen(disk)) == nil)
          434                 sysfatal("fsysopen: %r");
          435 
          436         fprint(2, "block size %d\n", fsys->blocksize);
          437         buf = emalloc(fsys->blocksize);
          438         if((ok = fsysroot(fsys, &root)) != Nfs3Ok){
          439                 nfs3errstr(ok);
          440                 sysfatal("accessing root: %r");
          441         }
          442         cwd = root;
          443         Binit(&bin, 0, OREAD);
          444         Binit(&bout, 1, OWRITE);
          445 
          446         while(fprint(2, "vftp> "), (p = Brdstr(&bin, '\n', 1)) != nil){
          447                 if(p[0] == '#')
          448                         continue;
          449                 nf = tokenize(p, f, nelem(f));
          450                 if(nf == 0)
          451                         continue;
          452                 for(i=0; i<nelem(cmdtab); i++){
          453                         if(strcmp(f[0], cmdtab[i].s) == 0){
          454                                 if((err = cmdtab[i].fn(nf, f)) != nil)
          455                                         fprint(2, "%s\n", err);
          456                                 break;
          457                         }
          458                 }
          459                 if(i == nelem(cmdtab))
          460                         fprint(2, "unknown command '%s'\n", f[0]);
          461         }
          462         threadexitsall(nil);
          463 }