plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

main.c (9655B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <auth.h>
      4 #include <fcall.h>
      5 #include <errno.h>
      6 #include "dat.h"
      7 #include "fns.h"
      8 
      9 enum
     10 {
     11 	Maxfdata	= 8192,
     12 	Maxiosize	= IOHDRSZ+Maxfdata,
     13 };
     14 
     15 void io(int);
     16 void rversion(void);
     17 void	rattach(void);
     18 void	rauth(void);
     19 void	rclunk(void);
     20 void	rcreate(void);
     21 void	rflush(void);
     22 void	ropen(void);
     23 void	rread(void);
     24 void	rremove(void);
     25 void	rsession(void);
     26 void	rstat(void);
     27 void	rwalk(void);
     28 void	rwrite(void);
     29 void	rwstat(void);
     30 
     31 static int	openflags(int);
     32 static void	usage(void);
     33 
     34 #define Reqsize (sizeof(Fcall)+Maxfdata)
     35 
     36 Fcall *req;
     37 Fcall *rep;
     38 
     39 uchar mdata[Maxiosize];
     40 char fdata[Maxfdata];
     41 uchar statbuf[STATMAX];
     42 
     43 
     44 extern Xfsub	*xsublist[];
     45 extern int	nclust;
     46 
     47 jmp_buf	err_lab[16];
     48 int	nerr_lab;
     49 char	err_msg[ERRMAX];
     50 
     51 int	chatty;
     52 int	nojoliet;
     53 int	noplan9;
     54 int norock;
     55 
     56 void    (*fcalls[Tmax])(void);
     57 
     58 static void
     59 initfcalls(void)
     60 {
     61 	fcalls[Tversion]=	rversion;
     62 	fcalls[Tflush]=	rflush;
     63 	fcalls[Tauth]=	rauth;
     64 	fcalls[Tattach]=	rattach;
     65 	fcalls[Twalk]=		rwalk;
     66 	fcalls[Topen]=		ropen;
     67 	fcalls[Tcreate]=	rcreate;
     68 	fcalls[Tread]=		rread;
     69 	fcalls[Twrite]=	rwrite;
     70 	fcalls[Tclunk]=	rclunk;
     71 	fcalls[Tremove]=	rremove;
     72 	fcalls[Tstat]=		rstat;
     73 	fcalls[Twstat]=	rwstat;
     74 }
     75 
     76 void
     77 main(int argc, char **argv)
     78 {
     79 	int srvfd, pipefd[2], stdio;
     80 	Xfsub **xs;
     81 	char *mtpt;
     82 
     83 	initfcalls();
     84 	stdio = 0;
     85 	mtpt = nil;
     86 	ARGBEGIN {
     87 	case '9':
     88 		noplan9 = 1;
     89 		break;
     90 	case 'c':
     91 		nclust = atoi(EARGF(usage()));
     92 		if (nclust <= 0)
     93 			sysfatal("nclust %d non-positive", nclust);
     94 		break;
     95 	case 'f':
     96 		deffile = EARGF(usage());
     97 		break;
     98 	case 'r':
     99 		norock = 1;
    100 		break;
    101 	case 's':
    102 		stdio = 1;
    103 		break;
    104 	case 'v':
    105 		chatty = 1;
    106 		break;
    107 	case 'J':
    108 		nojoliet = 1;
    109 		break;
    110 	case 'm':
    111 		mtpt = EARGF(usage());
    112 		break;
    113 	default:
    114 		usage();
    115 	} ARGEND
    116 
    117 	switch(argc) {
    118 	case 0:
    119 		break;
    120 	case 1:
    121 		srvname = argv[0];
    122 		break;
    123 	default:
    124 		usage();
    125 	}
    126 
    127 	iobuf_init();
    128 	for(xs=xsublist; *xs; xs++)
    129 		(*(*xs)->reset)();
    130 
    131 	if(stdio) {
    132 		pipefd[0] = 0;
    133 		pipefd[1] = 1;
    134 	} else {
    135 		close(0);
    136 		close(1);
    137 		open("/dev/null", OREAD);
    138 		open("/dev/null", OWRITE);
    139 		if(pipe(pipefd) < 0)
    140 			panic(1, "pipe");
    141 
    142 		if(post9pservice(pipefd[0], srvname, mtpt) < 0)
    143 			sysfatal("post9pservice: %r");
    144 		close(pipefd[0]);
    145 	}
    146 	srvfd = pipefd[1];
    147 
    148 	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
    149 	case -1:
    150 		panic(1, "fork");
    151 	default:
    152 		_exits(0);
    153 	case 0:
    154 		break;
    155 	}
    156 
    157 	io(srvfd);
    158 	exits(0);
    159 }
    160 
    161 void
    162 io(int srvfd)
    163 {
    164 	int n, pid;
    165 	Fcall xreq, xrep;
    166 
    167 	req = &xreq;
    168 	rep = &xrep;
    169 	pid = getpid();
    170 	fmtinstall('F', fcallfmt);
    171 
    172 	for(;;){
    173 		/*
    174 		 * reading from a pipe or a network device
    175 		 * will give an error after a few eof reads.
    176 		 * however, we cannot tell the difference
    177 		 * between a zero-length read and an interrupt
    178 		 * on the processes writing to us,
    179 		 * so we wait for the error.
    180 		 */
    181 		n = read9pmsg(srvfd, mdata, sizeof mdata);
    182 		if(n < 0)
    183 			break;
    184 		if(n == 0)
    185 			continue;
    186 		if(convM2S(mdata, n, req) == 0)
    187 			continue;
    188 
    189 		if(chatty)
    190 			fprint(2, "9660srv %d:<-%F\n", pid, req);
    191 
    192 		errno = 0;
    193 		if(!waserror()){
    194 			err_msg[0] = 0;
    195 			if(req->type >= nelem(fcalls) || !fcalls[req->type])
    196 				error("bad fcall type");
    197 			(*fcalls[req->type])();
    198 			poperror();
    199 		}
    200 
    201 		if(err_msg[0]){
    202 			rep->type = Rerror;
    203 			rep->ename = err_msg;
    204 		}else{
    205 			rep->type = req->type + 1;
    206 			rep->fid = req->fid;
    207 		}
    208 		rep->tag = req->tag;
    209 
    210 		if(chatty)
    211 			fprint(2, "9660srv %d:->%F\n", pid, rep);
    212 		n = convS2M(rep, mdata, sizeof mdata);
    213 		if(n == 0)
    214 			panic(1, "convS2M error on write");
    215 		if(write(srvfd, mdata, n) != n)
    216 			panic(1, "mount write");
    217 		if(nerr_lab != 0)
    218 			panic(0, "err stack %d");
    219 	}
    220 	chat("server shut down");
    221 }
    222 
    223 static void
    224 usage(void)
    225 {
    226 	fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
    227 	exits("usage");
    228 }
    229 
    230 void
    231 error(char *p)
    232 {
    233 	strecpy(err_msg, err_msg+sizeof err_msg, p);
    234 	nexterror();
    235 }
    236 
    237 void
    238 nexterror(void)
    239 {
    240 	longjmp(err_lab[--nerr_lab], 1);
    241 }
    242 
    243 void*
    244 ealloc(long n)
    245 {
    246 	void *p;
    247 
    248 	p = malloc(n);
    249 	if(p == 0)
    250 		error("no memory");
    251 	return p;
    252 }
    253 
    254 void
    255 setnames(Dir *d, char *n)
    256 {
    257 	d->name = n;
    258 	d->uid = n+Maxname;
    259 	d->gid = n+Maxname*2;
    260 	d->muid = n+Maxname*3;
    261 
    262 	d->name[0] = '\0';
    263 	d->uid[0] = '\0';
    264 	d->gid[0] = '\0';
    265 	d->muid[0] = '\0';
    266 }
    267 
    268 void
    269 rversion(void)
    270 {
    271 	if(req->msize > Maxiosize)
    272 		rep->msize = Maxiosize;
    273 	else
    274 		rep->msize = req->msize;
    275 	rep->version = "9P2000";
    276 }
    277 
    278 void
    279 rauth(void)
    280 {
    281 	error("9660srv: authentication not required");
    282 }
    283 
    284 void
    285 rflush(void)
    286 {
    287 }
    288 
    289 void
    290 rattach(void)
    291 {
    292 	Xfs *xf;
    293 	Xfile *root;
    294 	Xfsub **xs;
    295 
    296 	chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
    297 		req->fid, req->uname, req->aname);
    298 
    299 	if(waserror()){
    300 		xfile(req->fid, Clunk);
    301 		nexterror();
    302 	}
    303 	root = xfile(req->fid, Clean);
    304 	root->qid = (Qid){0, 0, QTDIR};
    305 	root->xf = xf = ealloc(sizeof(Xfs));
    306 	memset(xf, 0, sizeof(Xfs));
    307 	xf->ref = 1;
    308 	xf->d = getxdata(req->aname);
    309 
    310 	for(xs=xsublist; *xs; xs++)
    311 		if((*(*xs)->attach)(root) >= 0){
    312 			poperror();
    313 			xf->s = *xs;
    314 			xf->rootqid = root->qid;
    315 			rep->qid = root->qid;
    316 			return;
    317 		}
    318 	error("unknown format");
    319 }
    320 
    321 Xfile*
    322 doclone(Xfile *of, int newfid)
    323 {
    324 	Xfile *nf, *next;
    325 
    326 	nf = xfile(newfid, Clean);
    327 	if(waserror()){
    328 		xfile(newfid, Clunk);
    329 		nexterror();
    330 	}
    331 	next = nf->next;
    332 	*nf = *of;
    333 	nf->next = next;
    334 	nf->fid = newfid;
    335 	refxfs(nf->xf, 1);
    336 	if(nf->len){
    337 		nf->ptr = ealloc(nf->len);
    338 		memmove(nf->ptr, of->ptr, nf->len);
    339 	}else
    340 		nf->ptr = of->ptr;
    341 	(*of->xf->s->clone)(of, nf);
    342 	poperror();
    343 	return nf;
    344 }
    345 
    346 void
    347 rwalk(void)
    348 {
    349 	Xfile *f, *nf;
    350 	Isofile *oldptr;
    351 	int oldlen;
    352 	Qid oldqid;
    353 
    354 	rep->nwqid = 0;
    355 	nf = nil;
    356 	f = xfile(req->fid, Asis);
    357 	if(req->fid != req->newfid)
    358 		f = nf = doclone(f, req->newfid);
    359 
    360 	/* save old state in case of error */
    361 	oldqid = f->qid;
    362 	oldlen = f->len;
    363 	oldptr = f->ptr;
    364 	if(oldlen){
    365 		oldptr = ealloc(oldlen);
    366 		memmove(oldptr, f->ptr, oldlen);
    367 	}
    368 
    369 	if(waserror()){
    370 		if(nf != nil)
    371 			xfile(req->newfid, Clunk);
    372 		if(rep->nwqid == req->nwname){
    373 			if(oldlen)
    374 				free(oldptr);
    375 		}else{
    376 			/* restore previous state */
    377 			f->qid = oldqid;
    378 			if(f->len)
    379 				free(f->ptr);
    380 			f->ptr = oldptr;
    381 			f->len = oldlen;
    382 		}
    383 		if(rep->nwqid==req->nwname || rep->nwqid > 0){
    384 			err_msg[0] = '\0';
    385 			return;
    386 		}
    387 		nexterror();
    388 	}
    389 
    390 	for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
    391 		chat("\twalking %s\n", req->wname[rep->nwqid]);
    392 		if(!(f->qid.type & QTDIR)){
    393 			chat("\tnot dir: type=%#x\n", f->qid.type);
    394 			error("walk in non-directory");
    395 		}
    396 
    397 		if(strcmp(req->wname[rep->nwqid], "..")==0){
    398 			if(f->qid.path != f->xf->rootqid.path)
    399 				(*f->xf->s->walkup)(f);
    400 		}else
    401 			(*f->xf->s->walk)(f, req->wname[rep->nwqid]);
    402 		rep->wqid[rep->nwqid] = f->qid;
    403 	}
    404 	poperror();
    405 	if(oldlen)
    406 		free(oldptr);
    407 }
    408 
    409 void
    410 ropen(void)
    411 {
    412 	Xfile *f;
    413 
    414 	f = xfile(req->fid, Asis);
    415 	if(f->flags&Omodes)
    416 		error("open on open file");
    417 	if(req->mode&ORCLOSE)
    418 		error("no removes");
    419 	(*f->xf->s->open)(f, req->mode);
    420 	f->flags = openflags(req->mode);
    421 	rep->qid = f->qid;
    422 	rep->iounit = 0;
    423 }
    424 
    425 void
    426 rcreate(void)
    427 {
    428 	error("no creates");
    429 /*
    430 	Xfile *f;
    431 
    432 	if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
    433 		error("create . or ..");
    434 	f = xfile(req->fid, Asis);
    435 	if(f->flags&Omodes)
    436 		error("create on open file");
    437 	if(!(f->qid.path&CHDIR))
    438 		error("create in non-directory");
    439 	(*f->xf->s->create)(f, req->name, req->perm, req->mode);
    440 	chat("f->qid=0x%8.8lux...", f->qid.path);
    441 	f->flags = openflags(req->mode);
    442 	rep->qid = f->qid;
    443 */
    444 }
    445 
    446 void
    447 rread(void)
    448 {
    449 	Xfile *f;
    450 
    451 	f=xfile(req->fid, Asis);
    452 	if (!(f->flags&Oread))
    453 		error("file not opened for reading");
    454 	if(f->qid.type & QTDIR)
    455 		rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
    456 	else
    457 		rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
    458 	rep->data = fdata;
    459 }
    460 
    461 void
    462 rwrite(void)
    463 {
    464 	Xfile *f;
    465 
    466 	f=xfile(req->fid, Asis);
    467 	if(!(f->flags&Owrite))
    468 		error("file not opened for writing");
    469 	rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
    470 }
    471 
    472 void
    473 rclunk(void)
    474 {
    475 	Xfile *f;
    476 
    477 	if(!waserror()){
    478 		f = xfile(req->fid, Asis);
    479 		(*f->xf->s->clunk)(f);
    480 		poperror();
    481 	}
    482 	xfile(req->fid, Clunk);
    483 }
    484 
    485 void
    486 rremove(void)
    487 {
    488 	error("no removes");
    489 }
    490 
    491 void
    492 rstat(void)
    493 {
    494 	Xfile *f;
    495 	Dir dir;
    496 
    497 	chat("stat(fid=%d)...", req->fid);
    498 	f=xfile(req->fid, Asis);
    499 	setnames(&dir, fdata);
    500 	(*f->xf->s->stat)(f, &dir);
    501 	if(chatty)
    502 		showdir(2, &dir);
    503 	rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
    504 	rep->stat = statbuf;
    505 }
    506 
    507 void
    508 rwstat(void)
    509 {
    510 	error("no wstat");
    511 }
    512 
    513 static int
    514 openflags(int mode)
    515 {
    516 	int flags = 0;
    517 
    518 	switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
    519 	case OREAD:
    520 	case OEXEC:
    521 		flags = Oread; break;
    522 	case OWRITE:
    523 		flags = Owrite; break;
    524 	case ORDWR:
    525 		flags = Oread|Owrite; break;
    526 	}
    527 	if(mode & ORCLOSE)
    528 		flags |= Orclose;
    529 	return flags;
    530 }
    531 
    532 void
    533 showdir(int fd, Dir *s)
    534 {
    535 	char a_time[32], m_time[32];
    536 	char *p;
    537 
    538 	strcpy(a_time, ctime(s->atime));
    539 	if(p=strchr(a_time, '\n'))	/* assign = */
    540 		*p = 0;
    541 	strcpy(m_time, ctime(s->mtime));
    542 	if(p=strchr(m_time, '\n'))	/* assign = */
    543 		*p = 0;
    544 	fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
    545 mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
    546 		s->name, s->qid.path, s->qid.vers, s->type, s->dev,
    547 		s->mode, s->mode,
    548 		a_time, m_time, s->length, s->uid, s->gid);
    549 }
    550 
    551 #define	SIZE	1024
    552 
    553 void
    554 chat(char *fmt, ...)
    555 {
    556 	va_list arg;
    557 
    558 	if(chatty){
    559 		va_start(arg, fmt);
    560 		vfprint(2, fmt, arg);
    561 		va_end(arg);
    562 	}
    563 }
    564 
    565 void
    566 panic(int rflag, char *fmt, ...)
    567 {
    568 	va_list arg;
    569 	char buf[SIZE]; int n;
    570 
    571 	n = sprint(buf, "%s %d: ", argv0, getpid());
    572 	va_start(arg, fmt);
    573 	vseprint(buf+n, buf+SIZE, fmt, arg);
    574 	va_end(arg);
    575 	fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
    576 	if(chatty){
    577 		fprint(2, "abort\n");
    578 		abort();
    579 	}
    580 	exits("panic");
    581 }