xref: /plan9/sys/src/cmd/dossrv/xfssrv.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include "iotrack.h"
63e12c5d1SDavid du Colombier #include "dat.h"
7*9a747e4fSDavid du Colombier #include "dosfs.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier #include "errstr.h"
113e12c5d1SDavid du Colombier 
12*9a747e4fSDavid du Colombier #define	Reqsize	(sizeof(Fcall)+Maxfdata)
13*9a747e4fSDavid du Colombier Fcall	*req;
14*9a747e4fSDavid du Colombier Fcall	*rep;
15*9a747e4fSDavid du Colombier 
16*9a747e4fSDavid du Colombier uchar	mdata[Maxiosize];
17*9a747e4fSDavid du Colombier char	repdata[Maxfdata];
18*9a747e4fSDavid du Colombier uchar	statbuf[STATMAX];
193e12c5d1SDavid du Colombier int	errno;
20*9a747e4fSDavid du Colombier char	errbuf[ERRMAX];
213e12c5d1SDavid du Colombier void	rmservice(void);
223e12c5d1SDavid du Colombier char	srvfile[64];
233e12c5d1SDavid du Colombier char	*deffile;
247dd7cddfSDavid du Colombier int	doabort;
25*9a747e4fSDavid du Colombier int	trspaces;
26*9a747e4fSDavid du Colombier 
27*9a747e4fSDavid du Colombier void	(*fcalls[])(void) = {
28*9a747e4fSDavid du Colombier 	[Tversion]	rversion,
29*9a747e4fSDavid du Colombier 	[Tflush]	rflush,
30*9a747e4fSDavid du Colombier 	[Tauth]	rauth,
31*9a747e4fSDavid du Colombier 	[Tattach]	rattach,
32*9a747e4fSDavid du Colombier 	[Twalk]		rwalk,
33*9a747e4fSDavid du Colombier 	[Topen]		ropen,
34*9a747e4fSDavid du Colombier 	[Tcreate]	rcreate,
35*9a747e4fSDavid du Colombier 	[Tread]		rread,
36*9a747e4fSDavid du Colombier 	[Twrite]	rwrite,
37*9a747e4fSDavid du Colombier 	[Tclunk]	rclunk,
38*9a747e4fSDavid du Colombier 	[Tremove]	rremove,
39*9a747e4fSDavid du Colombier 	[Tstat]		rstat,
40*9a747e4fSDavid du Colombier 	[Twstat]	rwstat,
41*9a747e4fSDavid du Colombier };
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier void
usage(void)443e12c5d1SDavid du Colombier usage(void)
453e12c5d1SDavid du Colombier {
463e12c5d1SDavid du Colombier 	fprint(2, "usage: %s [-v] [-s] [-f devicefile] [srvname]\n", argv0);
473e12c5d1SDavid du Colombier 	exits("usage");
483e12c5d1SDavid du Colombier }
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier void
main(int argc,char ** argv)513e12c5d1SDavid du Colombier main(int argc, char **argv)
523e12c5d1SDavid du Colombier {
53*9a747e4fSDavid du Colombier 	int stdio, srvfd, pipefd[2];
543e12c5d1SDavid du Colombier 
55*9a747e4fSDavid du Colombier 	rep = malloc(sizeof(Fcall));
56*9a747e4fSDavid du Colombier 	req = malloc(Reqsize);
57*9a747e4fSDavid du Colombier 	if(rep == nil || req == nil)
58*9a747e4fSDavid du Colombier 		panic("out of memory");
593e12c5d1SDavid du Colombier 	stdio = 0;
603e12c5d1SDavid du Colombier 	ARGBEGIN{
61*9a747e4fSDavid du Colombier 	case ':':
62*9a747e4fSDavid du Colombier 		trspaces = 1;
63*9a747e4fSDavid du Colombier 		break;
647dd7cddfSDavid du Colombier 	case 'r':
657dd7cddfSDavid du Colombier 		readonly = 1;
667dd7cddfSDavid du Colombier 		break;
673e12c5d1SDavid du Colombier 	case 'v':
683e12c5d1SDavid du Colombier 		++chatty;
693e12c5d1SDavid du Colombier 		break;
703e12c5d1SDavid du Colombier 	case 'f':
713e12c5d1SDavid du Colombier 		deffile = ARGF();
723e12c5d1SDavid du Colombier 		break;
733e12c5d1SDavid du Colombier 	case 's':
743e12c5d1SDavid du Colombier 		stdio = 1;
753e12c5d1SDavid du Colombier 		break;
767dd7cddfSDavid du Colombier 	case 'p':
777dd7cddfSDavid du Colombier 		doabort = 1;
787dd7cddfSDavid du Colombier 		break;
793e12c5d1SDavid du Colombier 	default:
803e12c5d1SDavid du Colombier 		usage();
813e12c5d1SDavid du Colombier 	}ARGEND
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier 	if(argc == 0)
843e12c5d1SDavid du Colombier 		strcpy(srvfile, "#s/dos");
853e12c5d1SDavid du Colombier 	else if(argc == 1)
86*9a747e4fSDavid du Colombier 		snprint(srvfile, sizeof srvfile, "#s/%s", argv[0]);
873e12c5d1SDavid du Colombier 	else
883e12c5d1SDavid du Colombier 		usage();
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier 	if(stdio){
913e12c5d1SDavid du Colombier 		pipefd[0] = 0;
923e12c5d1SDavid du Colombier 		pipefd[1] = 1;
933e12c5d1SDavid du Colombier 	}else{
943e12c5d1SDavid du Colombier 		close(0);
953e12c5d1SDavid du Colombier 		close(1);
963e12c5d1SDavid du Colombier 		open("/dev/null", OREAD);
973e12c5d1SDavid du Colombier 		open("/dev/null", OWRITE);
983e12c5d1SDavid du Colombier 		if(pipe(pipefd) < 0)
993e12c5d1SDavid du Colombier 			panic("pipe");
100*9a747e4fSDavid du Colombier 		srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
1013e12c5d1SDavid du Colombier 		if(srvfd < 0)
1023e12c5d1SDavid du Colombier 			panic(srvfile);
1033e12c5d1SDavid du Colombier 		fprint(srvfd, "%d", pipefd[0]);
1043e12c5d1SDavid du Colombier 		close(pipefd[0]);
1053e12c5d1SDavid du Colombier 		atexit(rmservice);
1067dd7cddfSDavid du Colombier 		fprint(2, "%s: serving %s\n", argv0, srvfile);
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 	srvfd = pipefd[1];
1093e12c5d1SDavid du Colombier 
1107dd7cddfSDavid du Colombier 	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){
1113e12c5d1SDavid du Colombier 	case -1:
1123e12c5d1SDavid du Colombier 		panic("fork");
1133e12c5d1SDavid du Colombier 	default:
1143e12c5d1SDavid du Colombier 		_exits(0);
1153e12c5d1SDavid du Colombier 	case 0:
1163e12c5d1SDavid du Colombier 		break;
1173e12c5d1SDavid du Colombier 	}
1183e12c5d1SDavid du Colombier 
1193e12c5d1SDavid du Colombier 	iotrack_init();
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier 	if(!chatty){
1223e12c5d1SDavid du Colombier 		close(2);
1233e12c5d1SDavid du Colombier 		open("#c/cons", OWRITE);
1243e12c5d1SDavid du Colombier 	}
125*9a747e4fSDavid du Colombier 
126*9a747e4fSDavid du Colombier 	io(srvfd);
1273e12c5d1SDavid du Colombier 	exits(0);
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier void
io(int srvfd)131*9a747e4fSDavid du Colombier io(int srvfd)
132*9a747e4fSDavid du Colombier {
133*9a747e4fSDavid du Colombier 	int n, pid;
134*9a747e4fSDavid du Colombier 
135*9a747e4fSDavid du Colombier 	pid = getpid();
136*9a747e4fSDavid du Colombier 
137*9a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
138*9a747e4fSDavid du Colombier 	for(;;){
139*9a747e4fSDavid du Colombier 		/*
140*9a747e4fSDavid du Colombier 		 * reading from a pipe or a network device
141*9a747e4fSDavid du Colombier 		 * will give an error after a few eof reads.
142*9a747e4fSDavid du Colombier 		 * however, we cannot tell the difference
143*9a747e4fSDavid du Colombier 		 * between a zero-length read and an interrupt
144*9a747e4fSDavid du Colombier 		 * on the processes writing to us,
145*9a747e4fSDavid du Colombier 		 * so we wait for the error.
146*9a747e4fSDavid du Colombier 		 */
147*9a747e4fSDavid du Colombier 		n = read9pmsg(srvfd, mdata, sizeof mdata);
148*9a747e4fSDavid du Colombier 		if(n < 0)
149*9a747e4fSDavid du Colombier 			break;
150*9a747e4fSDavid du Colombier 		if(n == 0)
151*9a747e4fSDavid du Colombier 			continue;
152*9a747e4fSDavid du Colombier 		if(convM2S(mdata, n, req) == 0)
153*9a747e4fSDavid du Colombier 			continue;
154*9a747e4fSDavid du Colombier 
155*9a747e4fSDavid du Colombier 		if(chatty)
156*9a747e4fSDavid du Colombier 			fprint(2, "dossrv %d:<-%F\n", pid, req);
157*9a747e4fSDavid du Colombier 
158*9a747e4fSDavid du Colombier 		errno = 0;
159*9a747e4fSDavid du Colombier 		if(!fcalls[req->type])
160*9a747e4fSDavid du Colombier 			errno = Ebadfcall;
161*9a747e4fSDavid du Colombier 		else
162*9a747e4fSDavid du Colombier 			(*fcalls[req->type])();
163*9a747e4fSDavid du Colombier 		if(errno){
164*9a747e4fSDavid du Colombier 			rep->type = Rerror;
165*9a747e4fSDavid du Colombier 			rep->ename = xerrstr(errno);
166*9a747e4fSDavid du Colombier 		}else{
167*9a747e4fSDavid du Colombier 			rep->type = req->type + 1;
168*9a747e4fSDavid du Colombier 			rep->fid = req->fid;
169*9a747e4fSDavid du Colombier 		}
170*9a747e4fSDavid du Colombier 		rep->tag = req->tag;
171*9a747e4fSDavid du Colombier 		if(chatty)
172*9a747e4fSDavid du Colombier 			fprint(2, "dossrv %d:->%F\n", pid, rep);
173*9a747e4fSDavid du Colombier 		n = convS2M(rep, mdata, sizeof mdata);
174*9a747e4fSDavid du Colombier 		if(n == 0)
175*9a747e4fSDavid du Colombier 			panic("convS2M error on write");
176*9a747e4fSDavid du Colombier 		if(write(srvfd, mdata, n) != n)
177*9a747e4fSDavid du Colombier 			panic("mount write");
178*9a747e4fSDavid du Colombier 	}
179*9a747e4fSDavid du Colombier 	chat("server shut down");
180*9a747e4fSDavid du Colombier }
181*9a747e4fSDavid du Colombier 
182*9a747e4fSDavid du Colombier void
rmservice(void)1833e12c5d1SDavid du Colombier rmservice(void)
1843e12c5d1SDavid du Colombier {
1853e12c5d1SDavid du Colombier 	remove(srvfile);
1863e12c5d1SDavid du Colombier }
1873e12c5d1SDavid du Colombier 
1883e12c5d1SDavid du Colombier char *
xerrstr(int e)1893e12c5d1SDavid du Colombier xerrstr(int e)
1903e12c5d1SDavid du Colombier {
1913e12c5d1SDavid du Colombier 	if (e < 0 || e >= sizeof errmsg/sizeof errmsg[0])
1923e12c5d1SDavid du Colombier 		return "no such error";
193*9a747e4fSDavid du Colombier 	if(e == Eerrstr){
194*9a747e4fSDavid du Colombier 		errstr(errbuf, sizeof errbuf);
195*9a747e4fSDavid du Colombier 		return errbuf;
196*9a747e4fSDavid du Colombier 	}
1973e12c5d1SDavid du Colombier 	return errmsg[e];
1983e12c5d1SDavid du Colombier }
199*9a747e4fSDavid du Colombier 
200*9a747e4fSDavid du Colombier int
eqqid(Qid q1,Qid q2)201*9a747e4fSDavid du Colombier eqqid(Qid q1, Qid q2)
202*9a747e4fSDavid du Colombier {
203*9a747e4fSDavid du Colombier 	return q1.path == q2.path && q1.type == q2.type && q1.vers == q2.vers;
204*9a747e4fSDavid du Colombier }
205