Blob


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>
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;
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**);
29 typedef struct Cmd Cmd;
30 struct Cmd
31 {
32 char *s;
33 char *(*fn)(int, char**);
34 char *help;
35 };
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 };
48 char*
49 ebuf(void)
50 {
51 static char buf[ERRMAX];
53 rerrstr(buf, sizeof buf);
54 return buf;
55 }
57 static char*
58 estrdup(char *s)
59 {
60 char *t;
62 t = emalloc(strlen(s)+1);
63 strcpy(t, s);
64 return t;
65 }
67 char*
68 walk(char *path, Nfs3Handle *ph)
69 {
70 char *p, *q;
71 Nfs3Handle h;
72 Nfs3Status ok;
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 }
98 char*
99 cmdhelp(int argc, char **argv)
101 int i;
103 for(i=0; i<nelem(cmdtab); i++)
104 print("%s\n", cmdtab[i].help);
105 return nil;
108 char*
109 cmdcd(int argc, char **argv)
111 char *err;
112 Nfs3Attr attr;
113 Nfs3Status ok;
114 Nfs3Handle h;
116 if(argc != 2)
117 return "usage: cd dir";
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;
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;
138 char*
139 cmdpwd(int argc, char **argv)
141 if(argc != 1)
142 return "usage: pwd";
144 print("%s\n", pwd);
145 return nil;
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)
154 char c;
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");
164 void
165 lsdir(char *dir, Nfs3Handle *h)
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;
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;
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;
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;
198 if((ok = fsysgetattr(fsys, auth, &eh, &attr)) != Nfs3Ok){
199 nfs3errstr(ok);
200 fprint(2, "%s/%s: %r\n", dir, e.name);
201 continue;
203 ls(dir, e.name, &attr);
205 free(data);
206 if(eof)
207 break;
211 char*
212 cmdls(int argc, char **argv)
214 int i;
215 int dflag;
216 char *e;
217 Nfs3Handle h;
218 Nfs3Attr attr;
219 Nfs3Status ok;
221 dflag = 0;
222 ARGBEGIN{
223 case 'd':
224 dflag = 1;
225 break;
226 default:
227 return "usage: ls [-d] [path...]";
228 }ARGEND
230 if(argc == 0){
231 lsdir(nil, &cwd);
232 Bflush(&bout);
233 return nil;
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;
241 if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){
242 nfs3errstr(ok);
243 fprint(2, "%s: %r\n", argv[i]);
244 continue;
246 if(attr.type != Nfs3FileDir || dflag)
247 ls(argv[i], nil, &attr);
248 else
249 lsdir(argv[i], &h);
250 Bflush(&bout);
252 return nil;
255 char*
256 cmdget(int argc, char **argv)
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;
268 dflag = 0;
269 ARGBEGIN{
270 default:
271 usage:
272 return "usage: get path [lpath]]";
273 }ARGEND
275 if(argc != 1 && argc != 2)
276 goto usage;
278 if((e = walk(argv[0], &h)) != nil){
279 fprint(2, "%s: %s\n", argv[0], e);
280 return nil;
282 if((ok = fsysgetattr(fsys, auth, &h, &attr)) != Nfs3Ok){
283 nfs3errstr(ok);
284 fprint(2, "%s: %r\n", argv[0]);
285 return nil;
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;
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;
302 if(write(fd, buf, n) != n){
303 fprint(2, "writing %s: %r\n", local);
304 close(fd);
305 free(buf);
306 return nil;
308 free(buf);
310 close(fd);
311 fprint(2, "copied %,lld bytes\n", o);
312 return nil;
316 char*
317 cmdblock(int argc, char **argv)
319 char *e;
320 Nfs3Handle h;
321 u64int bno;
323 ARGBEGIN{
324 default:
325 return "usage: block path offset";
326 }ARGEND
328 if(argc != 2)
329 return "usage: block path offset";
331 if((e = walk(argv[0], &h)) != nil){
332 fprint(2, "%s: %s\n", argv[0], e);
333 return nil;
335 if((bno = fsys->fileblock(fsys, &h, strtoll(argv[1], 0, 0))) == 0){
336 fprint(2, "%s: %r\n", argv[0]);
337 return nil;
339 print("%#llux\n", bno);
340 return nil;
343 char*
344 cmddisk(int argc, char **argv)
346 Block *b;
347 int delta, count, i;
348 u64int offset;
349 uchar *p;
351 ARGBEGIN{
352 default:
353 return "usage: disk offset count";
354 }ARGEND
356 if(argc != 2)
357 return "usage: disk offset count";
359 offset = strtoull(argv[0], 0, 0);
360 count = atoi(argv[1]);
361 delta = offset%fsys->blocksize;
363 b = diskread(disk, fsys->blocksize, offset-delta);
364 if(b == nil){
365 fprint(2, "diskread: %r\n");
366 return nil;
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, " - ");
376 if(i%16 != 0)
377 Bprint(&bout, "\n");
378 Bflush(&bout);
379 blockput(b);
380 return nil;
383 void
384 usage(void)
386 fprint(2, "usage: vftp score\n");
387 threadexitsall("usage");
390 extern int allowall;
392 void
393 threadmain(int argc, char **argv)
395 char *err, *f[10], *p;
396 int i, nf;
397 uchar score[VtScoreSize];
398 Nfs3Status ok;
400 allowall = 1;
401 ARGBEGIN{
402 case 'V':
403 chattyventi++;
404 break;
405 default:
406 usage();
407 }ARGEND
409 if(argc != 1)
410 usage();
412 fmtinstall('F', vtfcallfmt);
413 fmtinstall('H', encodefmt);
414 fmtinstall('V', vtscorefmt);
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");
433 if((fsys = fsysopen(disk)) == nil)
434 sysfatal("fsysopen: %r");
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");
442 cwd = root;
443 Binit(&bin, 0, OREAD);
444 Binit(&bout, 1, OWRITE);
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;
459 if(i == nelem(cmdtab))
460 fprint(2, "unknown command '%s'\n", f[0]);
462 threadexitsall(nil);