plan9port

[fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port # fast
git clone https://src.adamsgaard.dk/plan9port.git # slow
Log | Files | Refs | README | LICENSE Back to index

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 }