xref: /plan9/sys/src/cmd/unix/drawterm/exportfs/exportsrv.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <fcall.h>
48ccd4a63SDavid du Colombier #define Extern	extern
58ccd4a63SDavid du Colombier #include "exportfs.h"
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier char Ebadfid[] = "Bad fid";
88ccd4a63SDavid du Colombier char Enotdir[] = "Not a directory";
98ccd4a63SDavid du Colombier char Edupfid[] = "Fid already in use";
108ccd4a63SDavid du Colombier char Eopen[] = "Fid already opened";
118ccd4a63SDavid du Colombier char Exmnt[] = "Cannot .. past mount point";
128ccd4a63SDavid du Colombier char Emip[] = "Mount in progress";
138ccd4a63SDavid du Colombier char Enopsmt[] = "Out of pseudo mount points";
148ccd4a63SDavid du Colombier char Enomem[] = "No memory";
158ccd4a63SDavid du Colombier char Eversion[] = "Bad 9P2000 version";
168ccd4a63SDavid du Colombier 
iounit(int x)178ccd4a63SDavid du Colombier int iounit(int x)
188ccd4a63SDavid du Colombier {
19*58da3067SDavid du Colombier 	return 8*8192+IOHDRSZ;
208ccd4a63SDavid du Colombier }
218ccd4a63SDavid du Colombier 
228ccd4a63SDavid du Colombier void*
emallocz(ulong n)238ccd4a63SDavid du Colombier emallocz(ulong n)
248ccd4a63SDavid du Colombier {
258ccd4a63SDavid du Colombier 	void *v;
268ccd4a63SDavid du Colombier 
278ccd4a63SDavid du Colombier 	v = mallocz(n, 1);
288ccd4a63SDavid du Colombier 	if(v == nil)
298ccd4a63SDavid du Colombier 		panic("out of memory");
308ccd4a63SDavid du Colombier 	return v;
318ccd4a63SDavid du Colombier }
328ccd4a63SDavid du Colombier 
338ccd4a63SDavid du Colombier 
348ccd4a63SDavid du Colombier void
Xversion(Fsrpc * t)358ccd4a63SDavid du Colombier Xversion(Fsrpc *t)
368ccd4a63SDavid du Colombier {
378ccd4a63SDavid du Colombier 	Fcall rhdr;
388ccd4a63SDavid du Colombier 
398ccd4a63SDavid du Colombier 	if(t->work.msize > messagesize)
408ccd4a63SDavid du Colombier 		t->work.msize = messagesize;
418ccd4a63SDavid du Colombier 	messagesize = t->work.msize;
428ccd4a63SDavid du Colombier 	if(strncmp(t->work.version, "9P2000", 6) != 0){
438ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Eversion);
448ccd4a63SDavid du Colombier 		return;
458ccd4a63SDavid du Colombier 	}
468ccd4a63SDavid du Colombier 	rhdr.version = "9P2000";
478ccd4a63SDavid du Colombier 	rhdr.msize = t->work.msize;
488ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
498ccd4a63SDavid du Colombier 	t->busy = 0;
508ccd4a63SDavid du Colombier }
518ccd4a63SDavid du Colombier 
528ccd4a63SDavid du Colombier void
Xauth(Fsrpc * t)538ccd4a63SDavid du Colombier Xauth(Fsrpc *t)
548ccd4a63SDavid du Colombier {
558ccd4a63SDavid du Colombier 	Fcall rhdr;
568ccd4a63SDavid du Colombier 
578ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, "exportfs: authentication not required");
588ccd4a63SDavid du Colombier 	t->busy = 0;
598ccd4a63SDavid du Colombier }
608ccd4a63SDavid du Colombier 
618ccd4a63SDavid du Colombier void
Xflush(Fsrpc * t)628ccd4a63SDavid du Colombier Xflush(Fsrpc *t)
638ccd4a63SDavid du Colombier {
648ccd4a63SDavid du Colombier 	Fsrpc *w, *e;
658ccd4a63SDavid du Colombier 	Fcall rhdr;
668ccd4a63SDavid du Colombier 
678ccd4a63SDavid du Colombier 	e = &Workq[Nr_workbufs];
688ccd4a63SDavid du Colombier 
698ccd4a63SDavid du Colombier 	for(w = Workq; w < e; w++) {
708ccd4a63SDavid du Colombier 		if(w->work.tag == t->work.oldtag) {
718ccd4a63SDavid du Colombier 			DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint);
728ccd4a63SDavid du Colombier 			if(w->busy && w->pid) {
738ccd4a63SDavid du Colombier 				w->flushtag = t->work.tag;
748ccd4a63SDavid du Colombier 				DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
758ccd4a63SDavid du Colombier 			//	if(w->canint)
768ccd4a63SDavid du Colombier 			//		postnote(PNPROC, w->pid, "flush");
778ccd4a63SDavid du Colombier 				t->busy = 0;
788ccd4a63SDavid du Colombier 				return;
798ccd4a63SDavid du Colombier 			}
808ccd4a63SDavid du Colombier 		}
818ccd4a63SDavid du Colombier 	}
828ccd4a63SDavid du Colombier 
838ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
848ccd4a63SDavid du Colombier 	DEBUG(DFD, "\tflush reply\n");
858ccd4a63SDavid du Colombier 	t->busy = 0;
868ccd4a63SDavid du Colombier }
878ccd4a63SDavid du Colombier 
888ccd4a63SDavid du Colombier void
Xattach(Fsrpc * t)898ccd4a63SDavid du Colombier Xattach(Fsrpc *t)
908ccd4a63SDavid du Colombier {
918ccd4a63SDavid du Colombier 	Fcall rhdr;
928ccd4a63SDavid du Colombier 	Fid *f;
938ccd4a63SDavid du Colombier 
948ccd4a63SDavid du Colombier 	f = newfid(t->work.fid);
958ccd4a63SDavid du Colombier 	if(f == 0) {
968ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
978ccd4a63SDavid du Colombier 		t->busy = 0;
988ccd4a63SDavid du Colombier 		return;
998ccd4a63SDavid du Colombier 	}
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier 	if(srvfd >= 0){
1028ccd4a63SDavid du Colombier /*
1038ccd4a63SDavid du Colombier 		if(psmpt == 0){
1048ccd4a63SDavid du Colombier 		Nomount:
1058ccd4a63SDavid du Colombier 			reply(&t->work, &rhdr, Enopsmt);
1068ccd4a63SDavid du Colombier 			t->busy = 0;
1078ccd4a63SDavid du Colombier 			freefid(t->work.fid);
1088ccd4a63SDavid du Colombier 			return;
1098ccd4a63SDavid du Colombier 		}
1108ccd4a63SDavid du Colombier 		for(i=0; i<Npsmpt; i++)
1118ccd4a63SDavid du Colombier 			if(psmap[i] == 0)
1128ccd4a63SDavid du Colombier 				break;
1138ccd4a63SDavid du Colombier 		if(i >= Npsmpt)
1148ccd4a63SDavid du Colombier 			goto Nomount;
1158ccd4a63SDavid du Colombier 		sprint(buf, "%d", i);
1168ccd4a63SDavid du Colombier 		f->f = file(psmpt, buf);
1178ccd4a63SDavid du Colombier 		if(f->f == nil)
1188ccd4a63SDavid du Colombier 			goto Nomount;
1198ccd4a63SDavid du Colombier 		sprint(buf, "/mnt/exportfs/%d", i);
1208ccd4a63SDavid du Colombier 		nfd = dup(srvfd, -1);
1218ccd4a63SDavid du Colombier 		if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
1228ccd4a63SDavid du Colombier 			errstr(buf, sizeof buf);
1238ccd4a63SDavid du Colombier 			reply(&t->work, &rhdr, buf);
1248ccd4a63SDavid du Colombier 			t->busy = 0;
1258ccd4a63SDavid du Colombier 			freefid(t->work.fid);
1268ccd4a63SDavid du Colombier 			close(nfd);
1278ccd4a63SDavid du Colombier 			return;
1288ccd4a63SDavid du Colombier 		}
1298ccd4a63SDavid du Colombier 		psmap[i] = 1;
1308ccd4a63SDavid du Colombier 		f->mid = i;
1318ccd4a63SDavid du Colombier */
1328ccd4a63SDavid du Colombier 	}else{
1338ccd4a63SDavid du Colombier 		f->f = root;
1348ccd4a63SDavid du Colombier 		f->f->ref++;
1358ccd4a63SDavid du Colombier 	}
1368ccd4a63SDavid du Colombier 
1378ccd4a63SDavid du Colombier 	rhdr.qid = f->f->qid;
1388ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
1398ccd4a63SDavid du Colombier 	t->busy = 0;
1408ccd4a63SDavid du Colombier }
1418ccd4a63SDavid du Colombier 
1428ccd4a63SDavid du Colombier Fid*
clonefid(Fid * f,int new)1438ccd4a63SDavid du Colombier clonefid(Fid *f, int new)
1448ccd4a63SDavid du Colombier {
1458ccd4a63SDavid du Colombier 	Fid *n;
1468ccd4a63SDavid du Colombier 
1478ccd4a63SDavid du Colombier 	n = newfid(new);
1488ccd4a63SDavid du Colombier 	if(n == 0) {
1498ccd4a63SDavid du Colombier 		n = getfid(new);
1508ccd4a63SDavid du Colombier 		if(n == 0)
1518ccd4a63SDavid du Colombier 			fatal("inconsistent fids");
1528ccd4a63SDavid du Colombier 		if(n->fid >= 0)
1538ccd4a63SDavid du Colombier 			close(n->fid);
1548ccd4a63SDavid du Colombier 		freefid(new);
1558ccd4a63SDavid du Colombier 		n = newfid(new);
1568ccd4a63SDavid du Colombier 		if(n == 0)
1578ccd4a63SDavid du Colombier 			fatal("inconsistent fids2");
1588ccd4a63SDavid du Colombier 	}
1598ccd4a63SDavid du Colombier 	n->f = f->f;
1608ccd4a63SDavid du Colombier 	n->f->ref++;
1618ccd4a63SDavid du Colombier 	return n;
1628ccd4a63SDavid du Colombier }
1638ccd4a63SDavid du Colombier 
1648ccd4a63SDavid du Colombier void
Xwalk(Fsrpc * t)1658ccd4a63SDavid du Colombier Xwalk(Fsrpc *t)
1668ccd4a63SDavid du Colombier {
1678ccd4a63SDavid du Colombier 	char err[ERRMAX], *e;
1688ccd4a63SDavid du Colombier 	Fcall rhdr;
1698ccd4a63SDavid du Colombier 	Fid *f, *nf;
1708ccd4a63SDavid du Colombier 	File *wf;
1718ccd4a63SDavid du Colombier 	int i;
1728ccd4a63SDavid du Colombier 
1738ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
1748ccd4a63SDavid du Colombier 	if(f == 0) {
1758ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
1768ccd4a63SDavid du Colombier 		t->busy = 0;
1778ccd4a63SDavid du Colombier 		return;
1788ccd4a63SDavid du Colombier 	}
1798ccd4a63SDavid du Colombier 
1808ccd4a63SDavid du Colombier 	nf = nil;
1818ccd4a63SDavid du Colombier 	if(t->work.newfid != t->work.fid){
1828ccd4a63SDavid du Colombier 		nf = clonefid(f, t->work.newfid);
1838ccd4a63SDavid du Colombier 		f = nf;
1848ccd4a63SDavid du Colombier 	}
1858ccd4a63SDavid du Colombier 
1868ccd4a63SDavid du Colombier 	rhdr.nwqid = 0;
1878ccd4a63SDavid du Colombier 	e = nil;
1888ccd4a63SDavid du Colombier 	for(i=0; i<t->work.nwname; i++){
1898ccd4a63SDavid du Colombier 		if(i == MAXWELEM){
1908ccd4a63SDavid du Colombier 			e = "Too many path elements";
1918ccd4a63SDavid du Colombier 			break;
1928ccd4a63SDavid du Colombier 		}
1938ccd4a63SDavid du Colombier 
1948ccd4a63SDavid du Colombier 		if(strcmp(t->work.wname[i], "..") == 0) {
1958ccd4a63SDavid du Colombier 			if(f->f->parent == nil) {
1968ccd4a63SDavid du Colombier 				e = Exmnt;
1978ccd4a63SDavid du Colombier 				break;
1988ccd4a63SDavid du Colombier 			}
1998ccd4a63SDavid du Colombier 			wf = f->f->parent;
2008ccd4a63SDavid du Colombier 			wf->ref++;
2018ccd4a63SDavid du Colombier 			goto Accept;
2028ccd4a63SDavid du Colombier 		}
2038ccd4a63SDavid du Colombier 
2048ccd4a63SDavid du Colombier 		wf = file(f->f, t->work.wname[i]);
2058ccd4a63SDavid du Colombier 		if(wf == 0){
2068ccd4a63SDavid du Colombier 			errstr(err, sizeof err);
2078ccd4a63SDavid du Colombier 			e = err;
2088ccd4a63SDavid du Colombier 			break;
2098ccd4a63SDavid du Colombier 		}
2108ccd4a63SDavid du Colombier     Accept:
2118ccd4a63SDavid du Colombier 		freefile(f->f);
2128ccd4a63SDavid du Colombier 		rhdr.wqid[rhdr.nwqid++] = wf->qid;
2138ccd4a63SDavid du Colombier 		f->f = wf;
2148ccd4a63SDavid du Colombier 		continue;
2158ccd4a63SDavid du Colombier 	}
2168ccd4a63SDavid du Colombier 
2178ccd4a63SDavid du Colombier 	if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
2188ccd4a63SDavid du Colombier 		freefid(t->work.newfid);
2198ccd4a63SDavid du Colombier 	if(rhdr.nwqid > 0)
2208ccd4a63SDavid du Colombier 		e = nil;
2218ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, e);
2228ccd4a63SDavid du Colombier 	t->busy = 0;
2238ccd4a63SDavid du Colombier }
2248ccd4a63SDavid du Colombier 
2258ccd4a63SDavid du Colombier void
Xclunk(Fsrpc * t)2268ccd4a63SDavid du Colombier Xclunk(Fsrpc *t)
2278ccd4a63SDavid du Colombier {
2288ccd4a63SDavid du Colombier 	Fcall rhdr;
2298ccd4a63SDavid du Colombier 	Fid *f;
2308ccd4a63SDavid du Colombier 
2318ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
2328ccd4a63SDavid du Colombier 	if(f == 0) {
2338ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
2348ccd4a63SDavid du Colombier 		t->busy = 0;
2358ccd4a63SDavid du Colombier 		return;
2368ccd4a63SDavid du Colombier 	}
2378ccd4a63SDavid du Colombier 
2388ccd4a63SDavid du Colombier 	if(f->fid >= 0)
2398ccd4a63SDavid du Colombier 		close(f->fid);
2408ccd4a63SDavid du Colombier 
2418ccd4a63SDavid du Colombier 	freefid(t->work.fid);
2428ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
2438ccd4a63SDavid du Colombier 	t->busy = 0;
2448ccd4a63SDavid du Colombier }
2458ccd4a63SDavid du Colombier 
2468ccd4a63SDavid du Colombier void
Xstat(Fsrpc * t)2478ccd4a63SDavid du Colombier Xstat(Fsrpc *t)
2488ccd4a63SDavid du Colombier {
2498ccd4a63SDavid du Colombier 	char err[ERRMAX], *path;
2508ccd4a63SDavid du Colombier 	Fcall rhdr;
2518ccd4a63SDavid du Colombier 	Fid *f;
2528ccd4a63SDavid du Colombier 	Dir *d;
2538ccd4a63SDavid du Colombier 	int s;
2548ccd4a63SDavid du Colombier 	uchar *statbuf;
2558ccd4a63SDavid du Colombier 
2568ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
2578ccd4a63SDavid du Colombier 	if(f == 0) {
2588ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
2598ccd4a63SDavid du Colombier 		t->busy = 0;
2608ccd4a63SDavid du Colombier 		return;
2618ccd4a63SDavid du Colombier 	}
2628ccd4a63SDavid du Colombier 	if(f->fid >= 0)
2638ccd4a63SDavid du Colombier 		d = dirfstat(f->fid);
2648ccd4a63SDavid du Colombier 	else {
2658ccd4a63SDavid du Colombier 		path = makepath(f->f, "");
2668ccd4a63SDavid du Colombier 		d = dirstat(path);
2678ccd4a63SDavid du Colombier 		free(path);
2688ccd4a63SDavid du Colombier 	}
2698ccd4a63SDavid du Colombier 
2708ccd4a63SDavid du Colombier 	if(d == nil) {
2718ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
2728ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
2738ccd4a63SDavid du Colombier 		t->busy = 0;
2748ccd4a63SDavid du Colombier 		return;
2758ccd4a63SDavid du Colombier 	}
2768ccd4a63SDavid du Colombier 
2778ccd4a63SDavid du Colombier 	d->qid.path = f->f->qidt->uniqpath;
2788ccd4a63SDavid du Colombier 	s = sizeD2M(d);
2798ccd4a63SDavid du Colombier 	statbuf = emallocz(s);
2808ccd4a63SDavid du Colombier 	s = convD2M(d, statbuf, s);
2818ccd4a63SDavid du Colombier 	free(d);
2828ccd4a63SDavid du Colombier 	rhdr.nstat = s;
2838ccd4a63SDavid du Colombier 	rhdr.stat = statbuf;
2848ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
2858ccd4a63SDavid du Colombier 	free(statbuf);
2868ccd4a63SDavid du Colombier 	t->busy = 0;
2878ccd4a63SDavid du Colombier }
2888ccd4a63SDavid du Colombier 
2898ccd4a63SDavid du Colombier static int
getiounit(int fd)2908ccd4a63SDavid du Colombier getiounit(int fd)
2918ccd4a63SDavid du Colombier {
2928ccd4a63SDavid du Colombier 	int n;
2938ccd4a63SDavid du Colombier 
2948ccd4a63SDavid du Colombier 	n = iounit(fd);
2958ccd4a63SDavid du Colombier 	if(n > messagesize-IOHDRSZ)
2968ccd4a63SDavid du Colombier 		n = messagesize-IOHDRSZ;
2978ccd4a63SDavid du Colombier 	return n;
2988ccd4a63SDavid du Colombier }
2998ccd4a63SDavid du Colombier 
3008ccd4a63SDavid du Colombier void
Xcreate(Fsrpc * t)3018ccd4a63SDavid du Colombier Xcreate(Fsrpc *t)
3028ccd4a63SDavid du Colombier {
3038ccd4a63SDavid du Colombier 	char err[ERRMAX], *path;
3048ccd4a63SDavid du Colombier 	Fcall rhdr;
3058ccd4a63SDavid du Colombier 	Fid *f;
3068ccd4a63SDavid du Colombier 	File *nf;
3078ccd4a63SDavid du Colombier 
3088ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
3098ccd4a63SDavid du Colombier 	if(f == 0) {
3108ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
3118ccd4a63SDavid du Colombier 		t->busy = 0;
3128ccd4a63SDavid du Colombier 		return;
3138ccd4a63SDavid du Colombier 	}
3148ccd4a63SDavid du Colombier 
3158ccd4a63SDavid du Colombier 
3168ccd4a63SDavid du Colombier 	path = makepath(f->f, t->work.name);
3178ccd4a63SDavid du Colombier 	f->fid = create(path, t->work.mode, t->work.perm);
3188ccd4a63SDavid du Colombier 	free(path);
3198ccd4a63SDavid du Colombier 	if(f->fid < 0) {
3208ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
3218ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
3228ccd4a63SDavid du Colombier 		t->busy = 0;
3238ccd4a63SDavid du Colombier 		return;
3248ccd4a63SDavid du Colombier 	}
3258ccd4a63SDavid du Colombier 
3268ccd4a63SDavid du Colombier 	nf = file(f->f, t->work.name);
3278ccd4a63SDavid du Colombier 	if(nf == 0) {
3288ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
3298ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
3308ccd4a63SDavid du Colombier 		t->busy = 0;
3318ccd4a63SDavid du Colombier 		return;
3328ccd4a63SDavid du Colombier 	}
3338ccd4a63SDavid du Colombier 
3348ccd4a63SDavid du Colombier 	f->mode = t->work.mode;
3358ccd4a63SDavid du Colombier 	freefile(f->f);
3368ccd4a63SDavid du Colombier 	f->f = nf;
3378ccd4a63SDavid du Colombier 	rhdr.qid = f->f->qid;
3388ccd4a63SDavid du Colombier 	rhdr.iounit = getiounit(f->fid);
3398ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
3408ccd4a63SDavid du Colombier 	t->busy = 0;
3418ccd4a63SDavid du Colombier }
3428ccd4a63SDavid du Colombier 
3438ccd4a63SDavid du Colombier void
Xremove(Fsrpc * t)3448ccd4a63SDavid du Colombier Xremove(Fsrpc *t)
3458ccd4a63SDavid du Colombier {
3468ccd4a63SDavid du Colombier 	char err[ERRMAX], *path;
3478ccd4a63SDavid du Colombier 	Fcall rhdr;
3488ccd4a63SDavid du Colombier 	Fid *f;
3498ccd4a63SDavid du Colombier 
3508ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
3518ccd4a63SDavid du Colombier 	if(f == 0) {
3528ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
3538ccd4a63SDavid du Colombier 		t->busy = 0;
3548ccd4a63SDavid du Colombier 		return;
3558ccd4a63SDavid du Colombier 	}
3568ccd4a63SDavid du Colombier 
3578ccd4a63SDavid du Colombier 	path = makepath(f->f, "");
3588ccd4a63SDavid du Colombier 	DEBUG(DFD, "\tremove: %s\n", path);
3598ccd4a63SDavid du Colombier 	if(remove(path) < 0) {
3608ccd4a63SDavid du Colombier 		free(path);
3618ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
3628ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
3638ccd4a63SDavid du Colombier 		t->busy = 0;
3648ccd4a63SDavid du Colombier 		return;
3658ccd4a63SDavid du Colombier 	}
3668ccd4a63SDavid du Colombier 	free(path);
3678ccd4a63SDavid du Colombier 
3688ccd4a63SDavid du Colombier 	f->f->inval = 1;
3698ccd4a63SDavid du Colombier 	if(f->fid >= 0)
3708ccd4a63SDavid du Colombier 		close(f->fid);
3718ccd4a63SDavid du Colombier 	freefid(t->work.fid);
3728ccd4a63SDavid du Colombier 
3738ccd4a63SDavid du Colombier 	reply(&t->work, &rhdr, 0);
3748ccd4a63SDavid du Colombier 	t->busy = 0;
3758ccd4a63SDavid du Colombier }
3768ccd4a63SDavid du Colombier 
3778ccd4a63SDavid du Colombier void
Xwstat(Fsrpc * t)3788ccd4a63SDavid du Colombier Xwstat(Fsrpc *t)
3798ccd4a63SDavid du Colombier {
3808ccd4a63SDavid du Colombier 	char err[ERRMAX], *path;
3818ccd4a63SDavid du Colombier 	Fcall rhdr;
3828ccd4a63SDavid du Colombier 	Fid *f;
3838ccd4a63SDavid du Colombier 	int s;
3848ccd4a63SDavid du Colombier 	char *strings;
3858ccd4a63SDavid du Colombier 	Dir d;
3868ccd4a63SDavid du Colombier 
3878ccd4a63SDavid du Colombier 	f = getfid(t->work.fid);
3888ccd4a63SDavid du Colombier 	if(f == 0) {
3898ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
3908ccd4a63SDavid du Colombier 		t->busy = 0;
3918ccd4a63SDavid du Colombier 		return;
3928ccd4a63SDavid du Colombier 	}
3938ccd4a63SDavid du Colombier 	strings = emallocz(t->work.nstat);	/* ample */
3948ccd4a63SDavid du Colombier 	if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
3958ccd4a63SDavid du Colombier 		rerrstr(err, sizeof err);
3968ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
3978ccd4a63SDavid du Colombier 		t->busy = 0;
3988ccd4a63SDavid du Colombier 		free(strings);
3998ccd4a63SDavid du Colombier 		return;
4008ccd4a63SDavid du Colombier 	}
4018ccd4a63SDavid du Colombier 
4028ccd4a63SDavid du Colombier 	if(f->fid >= 0)
4038ccd4a63SDavid du Colombier 		s = dirfwstat(f->fid, &d);
4048ccd4a63SDavid du Colombier 	else {
4058ccd4a63SDavid du Colombier 		path = makepath(f->f, "");
4068ccd4a63SDavid du Colombier 		s = dirwstat(path, &d);
4078ccd4a63SDavid du Colombier 		free(path);
4088ccd4a63SDavid du Colombier 	}
4098ccd4a63SDavid du Colombier 	if(s < 0) {
4108ccd4a63SDavid du Colombier 		rerrstr(err, sizeof err);
4118ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, err);
4128ccd4a63SDavid du Colombier 	}
4138ccd4a63SDavid du Colombier 	else {
4148ccd4a63SDavid du Colombier 		/* wstat may really be rename */
4158ccd4a63SDavid du Colombier 		if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
4168ccd4a63SDavid du Colombier 			free(f->f->name);
4178ccd4a63SDavid du Colombier 			f->f->name = estrdup(d.name);
4188ccd4a63SDavid du Colombier 		}
4198ccd4a63SDavid du Colombier 		reply(&t->work, &rhdr, 0);
4208ccd4a63SDavid du Colombier 	}
4218ccd4a63SDavid du Colombier 	free(strings);
4228ccd4a63SDavid du Colombier 	t->busy = 0;
4238ccd4a63SDavid du Colombier }
4248ccd4a63SDavid du Colombier 
4258ccd4a63SDavid du Colombier void
slave(Fsrpc * f)4268ccd4a63SDavid du Colombier slave(Fsrpc *f)
4278ccd4a63SDavid du Colombier {
4288ccd4a63SDavid du Colombier 	Proc *p;
4298ccd4a63SDavid du Colombier 	int pid;
4308ccd4a63SDavid du Colombier 	static int nproc;
4318ccd4a63SDavid du Colombier 
4328ccd4a63SDavid du Colombier 	for(;;) {
4338ccd4a63SDavid du Colombier 		for(p = Proclist; p; p = p->next) {
4348ccd4a63SDavid du Colombier 			if(p->busy == 0) {
4358ccd4a63SDavid du Colombier 				f->pid = p->pid;
4368ccd4a63SDavid du Colombier 				p->busy = 1;
437ec59a3ddSDavid du Colombier 				pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f);
4388ccd4a63SDavid du Colombier 				if(pid != p->pid)
4398ccd4a63SDavid du Colombier 					fatal("rendezvous sync fail");
4408ccd4a63SDavid du Colombier 				return;
4418ccd4a63SDavid du Colombier 			}
4428ccd4a63SDavid du Colombier 		}
4438ccd4a63SDavid du Colombier 
4448ccd4a63SDavid du Colombier 		if(++nproc > MAXPROC)
4458ccd4a63SDavid du Colombier 			fatal("too many procs");
4468ccd4a63SDavid du Colombier 
4478ccd4a63SDavid du Colombier 		pid = kproc("slave", blockingslave, nil);
4488ccd4a63SDavid du Colombier 		DEBUG(DFD, "slave pid %d\n", pid);
4498ccd4a63SDavid du Colombier 		if(pid == -1)
4508ccd4a63SDavid du Colombier 			fatal("kproc");
4518ccd4a63SDavid du Colombier 
4528ccd4a63SDavid du Colombier 		p = malloc(sizeof(Proc));
4538ccd4a63SDavid du Colombier 		if(p == 0)
4548ccd4a63SDavid du Colombier 			fatal("out of memory");
4558ccd4a63SDavid du Colombier 
4568ccd4a63SDavid du Colombier 		p->busy = 0;
4578ccd4a63SDavid du Colombier 		p->pid = pid;
4588ccd4a63SDavid du Colombier 		p->next = Proclist;
4598ccd4a63SDavid du Colombier 		Proclist = p;
4608ccd4a63SDavid du Colombier 
4618ccd4a63SDavid du Colombier DEBUG(DFD, "parent %d rendez\n", pid);
462ec59a3ddSDavid du Colombier 		rendezvous((void*)(uintptr)pid, p);
4638ccd4a63SDavid du Colombier DEBUG(DFD, "parent %d went\n", pid);
4648ccd4a63SDavid du Colombier 	}
4658ccd4a63SDavid du Colombier }
4668ccd4a63SDavid du Colombier 
4678ccd4a63SDavid du Colombier void
blockingslave(void * x)4688ccd4a63SDavid du Colombier blockingslave(void *x)
4698ccd4a63SDavid du Colombier {
4708ccd4a63SDavid du Colombier 	Fsrpc *p;
4718ccd4a63SDavid du Colombier 	Fcall rhdr;
4728ccd4a63SDavid du Colombier 	Proc *m;
4738ccd4a63SDavid du Colombier 	int pid;
4748ccd4a63SDavid du Colombier 
4758ccd4a63SDavid du Colombier 	USED(x);
4768ccd4a63SDavid du Colombier 
4778ccd4a63SDavid du Colombier 	notify(flushaction);
4788ccd4a63SDavid du Colombier 
4798ccd4a63SDavid du Colombier 	pid = getpid();
4808ccd4a63SDavid du Colombier 
4818ccd4a63SDavid du Colombier DEBUG(DFD, "blockingslave %d rendez\n", pid);
482ec59a3ddSDavid du Colombier 	m = (Proc*)rendezvous((void*)(uintptr)pid, 0);
4838ccd4a63SDavid du Colombier DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m);
4848ccd4a63SDavid du Colombier 
4858ccd4a63SDavid du Colombier 	for(;;) {
486ec59a3ddSDavid du Colombier 		p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid);
487ec59a3ddSDavid du Colombier 		if((uintptr)p == ~(uintptr)0)			/* Interrupted */
4888ccd4a63SDavid du Colombier 			continue;
4898ccd4a63SDavid du Colombier 
4908ccd4a63SDavid du Colombier 		DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
4918ccd4a63SDavid du Colombier 		if(p->flushtag != NOTAG)
4928ccd4a63SDavid du Colombier 			goto flushme;
4938ccd4a63SDavid du Colombier 
4948ccd4a63SDavid du Colombier 		switch(p->work.type) {
4958ccd4a63SDavid du Colombier 		case Tread:
4968ccd4a63SDavid du Colombier 			slaveread(p);
4978ccd4a63SDavid du Colombier 			break;
4988ccd4a63SDavid du Colombier 
4998ccd4a63SDavid du Colombier 		case Twrite:
5008ccd4a63SDavid du Colombier 			slavewrite(p);
5018ccd4a63SDavid du Colombier 			break;
5028ccd4a63SDavid du Colombier 
5038ccd4a63SDavid du Colombier 		case Topen:
5048ccd4a63SDavid du Colombier 			slaveopen(p);
5058ccd4a63SDavid du Colombier 			break;
5068ccd4a63SDavid du Colombier 
5078ccd4a63SDavid du Colombier 		default:
5088ccd4a63SDavid du Colombier 			reply(&p->work, &rhdr, "exportfs: slave type error");
5098ccd4a63SDavid du Colombier 		}
5108ccd4a63SDavid du Colombier 		if(p->flushtag != NOTAG) {
5118ccd4a63SDavid du Colombier flushme:
5128ccd4a63SDavid du Colombier 			p->work.type = Tflush;
5138ccd4a63SDavid du Colombier 			p->work.tag = p->flushtag;
5148ccd4a63SDavid du Colombier 			reply(&p->work, &rhdr, 0);
5158ccd4a63SDavid du Colombier 		}
5168ccd4a63SDavid du Colombier 		p->busy = 0;
5178ccd4a63SDavid du Colombier 		m->busy = 0;
5188ccd4a63SDavid du Colombier 	}
5198ccd4a63SDavid du Colombier }
5208ccd4a63SDavid du Colombier 
5218ccd4a63SDavid du Colombier int
openmount(int sfd)5228ccd4a63SDavid du Colombier openmount(int sfd)
5238ccd4a63SDavid du Colombier {
5248ccd4a63SDavid du Colombier 	werrstr("openmount not implemented");
5258ccd4a63SDavid du Colombier 	return -1;
5268ccd4a63SDavid du Colombier }
5278ccd4a63SDavid du Colombier 
5288ccd4a63SDavid du Colombier void
slaveopen(Fsrpc * p)5298ccd4a63SDavid du Colombier slaveopen(Fsrpc *p)
5308ccd4a63SDavid du Colombier {
5318ccd4a63SDavid du Colombier 	char err[ERRMAX], *path;
5328ccd4a63SDavid du Colombier 	Fcall *work, rhdr;
5338ccd4a63SDavid du Colombier 	Fid *f;
5348ccd4a63SDavid du Colombier 	Dir *d;
5358ccd4a63SDavid du Colombier 
5368ccd4a63SDavid du Colombier 	work = &p->work;
5378ccd4a63SDavid du Colombier 
5388ccd4a63SDavid du Colombier 	f = getfid(work->fid);
5398ccd4a63SDavid du Colombier 	if(f == 0) {
5408ccd4a63SDavid du Colombier 		reply(work, &rhdr, Ebadfid);
5418ccd4a63SDavid du Colombier 		return;
5428ccd4a63SDavid du Colombier 	}
5438ccd4a63SDavid du Colombier 	if(f->fid >= 0) {
5448ccd4a63SDavid du Colombier 		close(f->fid);
5458ccd4a63SDavid du Colombier 		f->fid = -1;
5468ccd4a63SDavid du Colombier 	}
5478ccd4a63SDavid du Colombier 
5488ccd4a63SDavid du Colombier 	path = makepath(f->f, "");
5498ccd4a63SDavid du Colombier 	DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
5508ccd4a63SDavid du Colombier 
5518ccd4a63SDavid du Colombier 	p->canint = 1;
5528ccd4a63SDavid du Colombier 	if(p->flushtag != NOTAG){
5538ccd4a63SDavid du Colombier 		free(path);
5548ccd4a63SDavid du Colombier 		return;
5558ccd4a63SDavid du Colombier 	}
5568ccd4a63SDavid du Colombier 	/* There is a race here I ignore because there are no locks */
5578ccd4a63SDavid du Colombier 	f->fid = open(path, work->mode);
5588ccd4a63SDavid du Colombier 	free(path);
5598ccd4a63SDavid du Colombier 	p->canint = 0;
5608ccd4a63SDavid du Colombier 	if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
5618ccd4a63SDavid du Colombier 	Error:
5628ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
5638ccd4a63SDavid du Colombier 		reply(work, &rhdr, err);
5648ccd4a63SDavid du Colombier 		return;
5658ccd4a63SDavid du Colombier 	}
5668ccd4a63SDavid du Colombier 	f->f->qid = d->qid;
5678ccd4a63SDavid du Colombier 	free(d);
5688ccd4a63SDavid du Colombier 	if(f->f->qid.type & QTMOUNT){	/* fork new exportfs for this */
5698ccd4a63SDavid du Colombier 		f->fid = openmount(f->fid);
5708ccd4a63SDavid du Colombier 		if(f->fid < 0)
5718ccd4a63SDavid du Colombier 			goto Error;
5728ccd4a63SDavid du Colombier 	}
5738ccd4a63SDavid du Colombier 
5748ccd4a63SDavid du Colombier 	DEBUG(DFD, "\topen: fd %d\n", f->fid);
5758ccd4a63SDavid du Colombier 	f->mode = work->mode;
5768ccd4a63SDavid du Colombier 	rhdr.iounit = getiounit(f->fid);
5778ccd4a63SDavid du Colombier 	rhdr.qid = f->f->qid;
5788ccd4a63SDavid du Colombier 	reply(work, &rhdr, 0);
5798ccd4a63SDavid du Colombier }
5808ccd4a63SDavid du Colombier 
5818ccd4a63SDavid du Colombier void
slaveread(Fsrpc * p)5828ccd4a63SDavid du Colombier slaveread(Fsrpc *p)
5838ccd4a63SDavid du Colombier {
5848ccd4a63SDavid du Colombier 	Fid *f;
5858ccd4a63SDavid du Colombier 	int n, r;
5868ccd4a63SDavid du Colombier 	Fcall *work, rhdr;
5878ccd4a63SDavid du Colombier 	char *data, err[ERRMAX];
5888ccd4a63SDavid du Colombier 
5898ccd4a63SDavid du Colombier 	work = &p->work;
5908ccd4a63SDavid du Colombier 
5918ccd4a63SDavid du Colombier 	f = getfid(work->fid);
5928ccd4a63SDavid du Colombier 	if(f == 0) {
5938ccd4a63SDavid du Colombier 		reply(work, &rhdr, Ebadfid);
5948ccd4a63SDavid du Colombier 		return;
5958ccd4a63SDavid du Colombier 	}
5968ccd4a63SDavid du Colombier 
5978ccd4a63SDavid du Colombier 	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
5988ccd4a63SDavid du Colombier 	p->canint = 1;
5998ccd4a63SDavid du Colombier 	if(p->flushtag != NOTAG)
6008ccd4a63SDavid du Colombier 		return;
6018ccd4a63SDavid du Colombier 	data = malloc(n);
6028ccd4a63SDavid du Colombier 	if(data == nil)
6038ccd4a63SDavid du Colombier 		fatal(Enomem);
6048ccd4a63SDavid du Colombier 
6058ccd4a63SDavid du Colombier 	/* can't just call pread, since directories must update the offset */
6068ccd4a63SDavid du Colombier 	r = pread(f->fid, data, n, work->offset);
6078ccd4a63SDavid du Colombier 	p->canint = 0;
6088ccd4a63SDavid du Colombier 	if(r < 0) {
6098ccd4a63SDavid du Colombier 		free(data);
6108ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
6118ccd4a63SDavid du Colombier 		reply(work, &rhdr, err);
6128ccd4a63SDavid du Colombier 		return;
6138ccd4a63SDavid du Colombier 	}
6148ccd4a63SDavid du Colombier 
6158ccd4a63SDavid du Colombier 	DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
6168ccd4a63SDavid du Colombier 
6178ccd4a63SDavid du Colombier 	rhdr.data = data;
6188ccd4a63SDavid du Colombier 	rhdr.count = r;
6198ccd4a63SDavid du Colombier 	reply(work, &rhdr, 0);
6208ccd4a63SDavid du Colombier 	free(data);
6218ccd4a63SDavid du Colombier }
6228ccd4a63SDavid du Colombier 
6238ccd4a63SDavid du Colombier void
slavewrite(Fsrpc * p)6248ccd4a63SDavid du Colombier slavewrite(Fsrpc *p)
6258ccd4a63SDavid du Colombier {
6268ccd4a63SDavid du Colombier 	char err[ERRMAX];
6278ccd4a63SDavid du Colombier 	Fcall *work, rhdr;
6288ccd4a63SDavid du Colombier 	Fid *f;
6298ccd4a63SDavid du Colombier 	int n;
6308ccd4a63SDavid du Colombier 
6318ccd4a63SDavid du Colombier 	work = &p->work;
6328ccd4a63SDavid du Colombier 
6338ccd4a63SDavid du Colombier 	f = getfid(work->fid);
6348ccd4a63SDavid du Colombier 	if(f == 0) {
6358ccd4a63SDavid du Colombier 		reply(work, &rhdr, Ebadfid);
6368ccd4a63SDavid du Colombier 		return;
6378ccd4a63SDavid du Colombier 	}
6388ccd4a63SDavid du Colombier 
6398ccd4a63SDavid du Colombier 	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
6408ccd4a63SDavid du Colombier 	p->canint = 1;
6418ccd4a63SDavid du Colombier 	if(p->flushtag != NOTAG)
6428ccd4a63SDavid du Colombier 		return;
6438ccd4a63SDavid du Colombier 	n = pwrite(f->fid, work->data, n, work->offset);
6448ccd4a63SDavid du Colombier 	p->canint = 0;
6458ccd4a63SDavid du Colombier 	if(n < 0) {
6468ccd4a63SDavid du Colombier 		errstr(err, sizeof err);
6478ccd4a63SDavid du Colombier 		reply(work, &rhdr, err);
6488ccd4a63SDavid du Colombier 		return;
6498ccd4a63SDavid du Colombier 	}
6508ccd4a63SDavid du Colombier 
6518ccd4a63SDavid du Colombier 	DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
6528ccd4a63SDavid du Colombier 
6538ccd4a63SDavid du Colombier 	rhdr.count = n;
6548ccd4a63SDavid du Colombier 	reply(work, &rhdr, 0);
6558ccd4a63SDavid du Colombier }
6568ccd4a63SDavid du Colombier 
6578ccd4a63SDavid du Colombier void
reopen(Fid * f)6588ccd4a63SDavid du Colombier reopen(Fid *f)
6598ccd4a63SDavid du Colombier {
6608ccd4a63SDavid du Colombier 	USED(f);
6618ccd4a63SDavid du Colombier 	fatal("reopen");
6628ccd4a63SDavid du Colombier }
6638ccd4a63SDavid du Colombier 
6648ccd4a63SDavid du Colombier void
flushaction(void * a,char * cause)6658ccd4a63SDavid du Colombier flushaction(void *a, char *cause)
6668ccd4a63SDavid du Colombier {
6678ccd4a63SDavid du Colombier 	USED(a);
6688ccd4a63SDavid du Colombier 	if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
6698ccd4a63SDavid du Colombier 		fprint(2, "exportsrv: note: %s\n", cause);
6708ccd4a63SDavid du Colombier 		exits("noted");
6718ccd4a63SDavid du Colombier 	}
6728ccd4a63SDavid du Colombier 	if(strncmp(cause, "kill", 4) == 0)
6738ccd4a63SDavid du Colombier 		noted(NDFLT);
6748ccd4a63SDavid du Colombier 
6758ccd4a63SDavid du Colombier 	noted(NCONT);
6768ccd4a63SDavid du Colombier }
677