vftp.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 }