xref: /plan9/sys/src/cmd/disk/kfs/9p12.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include "all.h"
2*9a747e4fSDavid du Colombier #include	"/sys/include/fcall.h"
3*9a747e4fSDavid du Colombier 
4*9a747e4fSDavid du Colombier static int
5*9a747e4fSDavid du Colombier readmsg(Chan *c, void *abuf, int n, int *ninep)
6*9a747e4fSDavid du Colombier {
7*9a747e4fSDavid du Colombier 	int fd, len;
8*9a747e4fSDavid du Colombier 	uchar *buf;
9*9a747e4fSDavid du Colombier 
10*9a747e4fSDavid du Colombier 	buf = abuf;
11*9a747e4fSDavid du Colombier 	fd = c->chan;
12*9a747e4fSDavid du Colombier 	qlock(&c->rlock);
13*9a747e4fSDavid du Colombier 	if(readn(fd, buf, 3) != 3){
14*9a747e4fSDavid du Colombier 		qunlock(&c->rlock);
15*9a747e4fSDavid du Colombier 		print("readn(3) fails: %r\n");
16*9a747e4fSDavid du Colombier 		return -1;
17*9a747e4fSDavid du Colombier 	}
18*9a747e4fSDavid du Colombier 	if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF)
19*9a747e4fSDavid du Colombier 	|| buf[0] == 86	/* Tattach */){
20*9a747e4fSDavid du Colombier 		*ninep = 1;
21*9a747e4fSDavid du Colombier 		/* assume message boundaries */
22*9a747e4fSDavid du Colombier 		n = read(fd, buf+3, n-3);
23*9a747e4fSDavid du Colombier 		if(n < 0){
24*9a747e4fSDavid du Colombier 			qunlock(&c->rlock);
25*9a747e4fSDavid du Colombier 			return -1;
26*9a747e4fSDavid du Colombier 		}
27*9a747e4fSDavid du Colombier 		return n+3;
28*9a747e4fSDavid du Colombier 	}
29*9a747e4fSDavid du Colombier 
30*9a747e4fSDavid du Colombier 	*ninep = 2;
31*9a747e4fSDavid du Colombier 	if(read(fd, buf+3, 1) != 1){
32*9a747e4fSDavid du Colombier 		qunlock(&c->rlock);
33*9a747e4fSDavid du Colombier 		print("read(1) fails: %r\n");
34*9a747e4fSDavid du Colombier 		return -1;
35*9a747e4fSDavid du Colombier 	}
36*9a747e4fSDavid du Colombier 	len = GBIT32(buf);
37*9a747e4fSDavid du Colombier 	if(len > n){
38*9a747e4fSDavid du Colombier 		print("msg too large\n");
39*9a747e4fSDavid du Colombier 		qunlock(&c->rlock);
40*9a747e4fSDavid du Colombier 		return -1;
41*9a747e4fSDavid du Colombier 	}
42*9a747e4fSDavid du Colombier 	if(readn(fd, buf+4, len-4) != len-4){
43*9a747e4fSDavid du Colombier 		print("readn(%d) fails: %r\n", len-4);
44*9a747e4fSDavid du Colombier 		qunlock(&c->rlock);
45*9a747e4fSDavid du Colombier 		return -1;
46*9a747e4fSDavid du Colombier 	}
47*9a747e4fSDavid du Colombier 	qunlock(&c->rlock);
48*9a747e4fSDavid du Colombier 	return len;
49*9a747e4fSDavid du Colombier }
50*9a747e4fSDavid du Colombier 
51*9a747e4fSDavid du Colombier void
52*9a747e4fSDavid du Colombier startserveproc(void (*f)(Chan*, uchar*, int), char *name, Chan *c, uchar *b, int nb)
53*9a747e4fSDavid du Colombier {
54*9a747e4fSDavid du Colombier 	switch(rfork(RFMEM|RFFDG|RFPROC)){
55*9a747e4fSDavid du Colombier 	case -1:
56*9a747e4fSDavid du Colombier 		panic("can't fork");
57*9a747e4fSDavid du Colombier 	case 0:
58*9a747e4fSDavid du Colombier 		break;
59*9a747e4fSDavid du Colombier 	default:
60*9a747e4fSDavid du Colombier 		return;
61*9a747e4fSDavid du Colombier 	}
62*9a747e4fSDavid du Colombier 	procname = name;
63*9a747e4fSDavid du Colombier 	f(c, b, nb);
64*9a747e4fSDavid du Colombier 	_exits(nil);
65*9a747e4fSDavid du Colombier }
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier void
68*9a747e4fSDavid du Colombier serve(Chan *chan)
69*9a747e4fSDavid du Colombier {
70*9a747e4fSDavid du Colombier 	int i, nin, p9;
71*9a747e4fSDavid du Colombier 	uchar inbuf[1024];
72*9a747e4fSDavid du Colombier 	void (*s)(Chan*, uchar*, int);
73*9a747e4fSDavid du Colombier 
74*9a747e4fSDavid du Colombier 	p9 = 0;
75*9a747e4fSDavid du Colombier 	if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0)
76*9a747e4fSDavid du Colombier 		return;
77*9a747e4fSDavid du Colombier 
78*9a747e4fSDavid du Colombier 	switch(p9){
79*9a747e4fSDavid du Colombier 	default:
80*9a747e4fSDavid du Colombier 		print("unknown 9P type\n");
81*9a747e4fSDavid du Colombier 		return;
82*9a747e4fSDavid du Colombier 	case 1:
83*9a747e4fSDavid du Colombier 		s = serve9p1;
84*9a747e4fSDavid du Colombier 		break;
85*9a747e4fSDavid du Colombier 	case 2:
86*9a747e4fSDavid du Colombier 		s = serve9p2;
87*9a747e4fSDavid du Colombier 		break;
88*9a747e4fSDavid du Colombier 	}
89*9a747e4fSDavid du Colombier 
90*9a747e4fSDavid du Colombier 	for(i=1; i<conf.nserve; i++)
91*9a747e4fSDavid du Colombier 		startserveproc(s, "srv", chan, nil, 0);
92*9a747e4fSDavid du Colombier 	(*s)(chan, inbuf, nin);
93*9a747e4fSDavid du Colombier }
94*9a747e4fSDavid du Colombier 
95