xref: /plan9-contrib/sys/src/cmd/exportfs/exportsrv.c (revision 61b17cc6b921f626d2c0a0d5982f2e19948a8fce)
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 #define Extern	extern
63e12c5d1SDavid du Colombier #include "exportfs.h"
73e12c5d1SDavid du Colombier 
87ec5746aSDavid du Colombier extern char *netdir, *local, *remote;
97ec5746aSDavid du Colombier 
10*61b17cc6SDavid du Colombier char Ebadfid[] = "bad fid";
11*61b17cc6SDavid du Colombier char Enotdir[] = "not a directory";
12*61b17cc6SDavid du Colombier char Edupfid[] = "fid already in use";
13*61b17cc6SDavid du Colombier char Eopen[] = "fid already opened";
14*61b17cc6SDavid du Colombier char Emip[] = "mount in progress";
15*61b17cc6SDavid du Colombier char Enopsmt[] = "out of pseudo mount points";
16*61b17cc6SDavid du Colombier char Enomem[] = "no memory";
17*61b17cc6SDavid du Colombier char Eversion[] = "bad 9P2000 version";
18*61b17cc6SDavid du Colombier char Ereadonly[] = "file system read only";
19*61b17cc6SDavid du Colombier char Enoprocs[] = "out of processes";
209a747e4fSDavid du Colombier 
219a747e4fSDavid du Colombier ulong messagesize;
2224b9ac62SDavid du Colombier int readonly;
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier void
Xversion(Fsrpc * t)259a747e4fSDavid du Colombier Xversion(Fsrpc *t)
263e12c5d1SDavid du Colombier {
279a747e4fSDavid du Colombier 	Fcall rhdr;
283e12c5d1SDavid du Colombier 
29*61b17cc6SDavid du Colombier 	if(t->work.msize < 256){
30*61b17cc6SDavid du Colombier 		reply(&t->work, &rhdr, "version: message size too small");
31*61b17cc6SDavid du Colombier 		putsbuf(t);
32*61b17cc6SDavid du Colombier 		return;
33*61b17cc6SDavid du Colombier 	}
349a747e4fSDavid du Colombier 	if(t->work.msize > messagesize)
359a747e4fSDavid du Colombier 		t->work.msize = messagesize;
369a747e4fSDavid du Colombier 	messagesize = t->work.msize;
379a747e4fSDavid du Colombier 	if(strncmp(t->work.version, "9P2000", 6) != 0){
389a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Eversion);
39*61b17cc6SDavid du Colombier 		putsbuf(t);
409a747e4fSDavid du Colombier 		return;
419a747e4fSDavid du Colombier 	}
429a747e4fSDavid du Colombier 	rhdr.version = "9P2000";
439a747e4fSDavid du Colombier 	rhdr.msize = t->work.msize;
449a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
45*61b17cc6SDavid du Colombier 	putsbuf(t);
463e12c5d1SDavid du Colombier }
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier void
Xauth(Fsrpc * t)499a747e4fSDavid du Colombier Xauth(Fsrpc *t)
503e12c5d1SDavid du Colombier {
519a747e4fSDavid du Colombier 	Fcall rhdr;
523e12c5d1SDavid du Colombier 
533ff48bf5SDavid du Colombier 	reply(&t->work, &rhdr, "exportfs: authentication not required");
54*61b17cc6SDavid du Colombier 	putsbuf(t);
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier void
Xflush(Fsrpc * t)589a747e4fSDavid du Colombier Xflush(Fsrpc *t)
593e12c5d1SDavid du Colombier {
609a747e4fSDavid du Colombier 	Fcall rhdr;
61*61b17cc6SDavid du Colombier 	Fsrpc *w;
62*61b17cc6SDavid du Colombier 	Proc *m;
633e12c5d1SDavid du Colombier 
64*61b17cc6SDavid du Colombier 	for(m = Proclist; m != nil; m = m->next){
65*61b17cc6SDavid du Colombier 		w = m->busy;
66*61b17cc6SDavid du Colombier 		if(w == nil || w->work.tag != t->work.oldtag)
67*61b17cc6SDavid du Colombier 			continue;
683e12c5d1SDavid du Colombier 
69*61b17cc6SDavid du Colombier 		lock(m);
70*61b17cc6SDavid du Colombier 		w = m->busy;
71*61b17cc6SDavid du Colombier 		if(w != nil && w->work.tag == t->work.oldtag) {
729a747e4fSDavid du Colombier 			w->flushtag = t->work.tag;
739a747e4fSDavid du Colombier 			DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
74*61b17cc6SDavid du Colombier 			postnote(PNPROC, m->pid, "flush");
75*61b17cc6SDavid du Colombier 			unlock(m);
76*61b17cc6SDavid du Colombier 			putsbuf(t);
773e12c5d1SDavid du Colombier 			return;
783e12c5d1SDavid du Colombier 		}
79*61b17cc6SDavid du Colombier 		unlock(m);
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 
829a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
837dd7cddfSDavid du Colombier 	DEBUG(DFD, "\tflush reply\n");
84*61b17cc6SDavid du Colombier 	putsbuf(t);
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier void
Xattach(Fsrpc * t)889a747e4fSDavid du Colombier Xattach(Fsrpc *t)
893e12c5d1SDavid du Colombier {
909a747e4fSDavid du Colombier 	int i, nfd;
919a747e4fSDavid du Colombier 	Fcall rhdr;
923e12c5d1SDavid du Colombier 	Fid *f;
939a747e4fSDavid du Colombier 	char buf[128];
943e12c5d1SDavid du Colombier 
959a747e4fSDavid du Colombier 	f = newfid(t->work.fid);
96*61b17cc6SDavid du Colombier 	if(f == nil) {
979a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
98*61b17cc6SDavid du Colombier 		putsbuf(t);
993e12c5d1SDavid du Colombier 		return;
1003e12c5d1SDavid du Colombier 	}
1013e12c5d1SDavid du Colombier 
1029a747e4fSDavid du Colombier 	if(srvfd >= 0){
103*61b17cc6SDavid du Colombier 		if(psmpt == nil)
104*61b17cc6SDavid du Colombier 			goto Nomount;
1059a747e4fSDavid du Colombier 		for(i=0; i<Npsmpt; i++)
1069a747e4fSDavid du Colombier 			if(psmap[i] == 0)
1079a747e4fSDavid du Colombier 				break;
1089a747e4fSDavid du Colombier 		if(i >= Npsmpt)
1099a747e4fSDavid du Colombier 			goto Nomount;
110*61b17cc6SDavid du Colombier 		snprint(buf, sizeof(buf), "%d", i);
1119a747e4fSDavid du Colombier 		f->f = file(psmpt, buf);
1129a747e4fSDavid du Colombier 		if(f->f == nil)
1139a747e4fSDavid du Colombier 			goto Nomount;
114*61b17cc6SDavid du Colombier 		snprint(buf, sizeof(buf), "/mnt/exportfs/%d", i);
1159a747e4fSDavid du Colombier 		nfd = dup(srvfd, -1);
1169a747e4fSDavid du Colombier 		if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
1179a747e4fSDavid du Colombier 			errstr(buf, sizeof buf);
1189a747e4fSDavid du Colombier 			reply(&t->work, &rhdr, buf);
1199a747e4fSDavid du Colombier 			freefid(t->work.fid);
120*61b17cc6SDavid du Colombier 			putsbuf(t);
1219a747e4fSDavid du Colombier 			close(nfd);
1229a747e4fSDavid du Colombier 			return;
1239a747e4fSDavid du Colombier 		}
1249a747e4fSDavid du Colombier 		psmap[i] = 1;
1259a747e4fSDavid du Colombier 		f->mid = i;
1269a747e4fSDavid du Colombier 	}else{
1273e12c5d1SDavid du Colombier 		f->f = root;
1287dd7cddfSDavid du Colombier 		f->f->ref++;
1293e12c5d1SDavid du Colombier 	}
1303e12c5d1SDavid du Colombier 
1319a747e4fSDavid du Colombier 	rhdr.qid = f->f->qid;
1329a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
133*61b17cc6SDavid du Colombier 	putsbuf(t);
134*61b17cc6SDavid du Colombier 	return;
135*61b17cc6SDavid du Colombier 
136*61b17cc6SDavid du Colombier Nomount:
137*61b17cc6SDavid du Colombier 	reply(&t->work, &rhdr, Enopsmt);
138*61b17cc6SDavid du Colombier 	freefid(t->work.fid);
139*61b17cc6SDavid du Colombier 	putsbuf(t);
1409a747e4fSDavid du Colombier }
1419a747e4fSDavid du Colombier 
1429a747e4fSDavid du Colombier Fid*
clonefid(Fid * f,int new)1439a747e4fSDavid du Colombier clonefid(Fid *f, int new)
1443e12c5d1SDavid du Colombier {
1459a747e4fSDavid du Colombier 	Fid *n;
1463e12c5d1SDavid du Colombier 
1479a747e4fSDavid du Colombier 	n = newfid(new);
148*61b17cc6SDavid du Colombier 	if(n == nil) {
1499a747e4fSDavid du Colombier 		n = getfid(new);
150*61b17cc6SDavid du Colombier 		if(n == nil)
151219b2ee8SDavid du Colombier 			fatal("inconsistent fids");
152219b2ee8SDavid du Colombier 		if(n->fid >= 0)
153219b2ee8SDavid du Colombier 			close(n->fid);
1549a747e4fSDavid du Colombier 		freefid(new);
1559a747e4fSDavid du Colombier 		n = newfid(new);
156*61b17cc6SDavid du Colombier 		if(n == nil)
157219b2ee8SDavid du Colombier 			fatal("inconsistent fids2");
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 	n->f = f->f;
1607dd7cddfSDavid du Colombier 	n->f->ref++;
1619a747e4fSDavid du Colombier 	return n;
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier 
1649a747e4fSDavid du Colombier void
Xwalk(Fsrpc * t)1659a747e4fSDavid du Colombier Xwalk(Fsrpc *t)
1663e12c5d1SDavid du Colombier {
1679a747e4fSDavid du Colombier 	char err[ERRMAX], *e;
1689a747e4fSDavid du Colombier 	Fcall rhdr;
1699a747e4fSDavid du Colombier 	Fid *f, *nf;
1709a747e4fSDavid du Colombier 	File *wf;
1719a747e4fSDavid du Colombier 	int i;
1723e12c5d1SDavid du Colombier 
1739a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
174*61b17cc6SDavid du Colombier 	if(f == nil) {
1759a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
176*61b17cc6SDavid du Colombier 		putsbuf(t);
1779a747e4fSDavid du Colombier 		return;
1783e12c5d1SDavid du Colombier 	}
1793e12c5d1SDavid du Colombier 
1809a747e4fSDavid du Colombier 	nf = nil;
1819a747e4fSDavid du Colombier 	if(t->work.newfid != t->work.fid){
1829a747e4fSDavid du Colombier 		nf = clonefid(f, t->work.newfid);
1839a747e4fSDavid du Colombier 		f = nf;
1849a747e4fSDavid du Colombier 	}
1859a747e4fSDavid du Colombier 
1869a747e4fSDavid du Colombier 	rhdr.nwqid = 0;
1879a747e4fSDavid du Colombier 	e = nil;
1889a747e4fSDavid du Colombier 	for(i=0; i<t->work.nwname; i++){
1899a747e4fSDavid du Colombier 
1909a747e4fSDavid du Colombier 		if(strcmp(t->work.wname[i], "..") == 0) {
191*61b17cc6SDavid du Colombier 			if(f->f->parent != nil)
1929a747e4fSDavid du Colombier 				wf = f->f->parent;
193*61b17cc6SDavid du Colombier 			else
194*61b17cc6SDavid du Colombier 				wf = f->f;
1959a747e4fSDavid du Colombier 			wf->ref++;
196*61b17cc6SDavid du Colombier 		}else{
1979a747e4fSDavid du Colombier 			wf = file(f->f, t->work.wname[i]);
198*61b17cc6SDavid du Colombier 			if(wf == nil){
1999a747e4fSDavid du Colombier 				errstr(err, sizeof err);
2009a747e4fSDavid du Colombier 				e = err;
2019a747e4fSDavid du Colombier 				break;
2029a747e4fSDavid du Colombier 			}
203*61b17cc6SDavid du Colombier 		}
204*61b17cc6SDavid du Colombier 
2059a747e4fSDavid du Colombier 		freefile(f->f);
2069a747e4fSDavid du Colombier 		rhdr.wqid[rhdr.nwqid++] = wf->qid;
2079a747e4fSDavid du Colombier 		f->f = wf;
2089a747e4fSDavid du Colombier 		continue;
2093e12c5d1SDavid du Colombier 	}
2103e12c5d1SDavid du Colombier 
2119a747e4fSDavid du Colombier 	if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
2129a747e4fSDavid du Colombier 		freefid(t->work.newfid);
2139a747e4fSDavid du Colombier 	if(rhdr.nwqid > 0)
2149a747e4fSDavid du Colombier 		e = nil;
2159a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, e);
216*61b17cc6SDavid du Colombier 	putsbuf(t);
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier void
Xclunk(Fsrpc * t)2209a747e4fSDavid du Colombier Xclunk(Fsrpc *t)
2217dd7cddfSDavid du Colombier {
2229a747e4fSDavid du Colombier 	Fcall rhdr;
2233e12c5d1SDavid du Colombier 	Fid *f;
2243e12c5d1SDavid du Colombier 
2259a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
226*61b17cc6SDavid du Colombier 	if(f == nil) {
2279a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
228*61b17cc6SDavid du Colombier 		putsbuf(t);
2293e12c5d1SDavid du Colombier 		return;
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2333e12c5d1SDavid du Colombier 		close(f->fid);
2343e12c5d1SDavid du Colombier 
2359a747e4fSDavid du Colombier 	freefid(t->work.fid);
2369a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
237*61b17cc6SDavid du Colombier 	putsbuf(t);
2383e12c5d1SDavid du Colombier }
2393e12c5d1SDavid du Colombier 
2403e12c5d1SDavid du Colombier void
Xstat(Fsrpc * t)2419a747e4fSDavid du Colombier Xstat(Fsrpc *t)
2423e12c5d1SDavid du Colombier {
2439a747e4fSDavid du Colombier 	char err[ERRMAX], *path;
2449a747e4fSDavid du Colombier 	Fcall rhdr;
2453e12c5d1SDavid du Colombier 	Fid *f;
2469a747e4fSDavid du Colombier 	Dir *d;
2473e12c5d1SDavid du Colombier 	int s;
2489a747e4fSDavid du Colombier 	uchar *statbuf;
2493e12c5d1SDavid du Colombier 
2509a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
251*61b17cc6SDavid du Colombier 	if(f == nil) {
2529a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
253*61b17cc6SDavid du Colombier 		putsbuf(t);
2543e12c5d1SDavid du Colombier 		return;
2553e12c5d1SDavid du Colombier 	}
2563e12c5d1SDavid du Colombier 	if(f->fid >= 0)
2579a747e4fSDavid du Colombier 		d = dirfstat(f->fid);
2583e12c5d1SDavid du Colombier 	else {
2599a747e4fSDavid du Colombier 		path = makepath(f->f, "");
2609a747e4fSDavid du Colombier 		d = dirstat(path);
2619a747e4fSDavid du Colombier 		free(path);
2623e12c5d1SDavid du Colombier 	}
2633e12c5d1SDavid du Colombier 
2649a747e4fSDavid du Colombier 	if(d == nil) {
2659a747e4fSDavid du Colombier 		errstr(err, sizeof err);
2669a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
267*61b17cc6SDavid du Colombier 		putsbuf(t);
2683e12c5d1SDavid du Colombier 		return;
2693e12c5d1SDavid du Colombier 	}
2709a747e4fSDavid du Colombier 
2719a747e4fSDavid du Colombier 	d->qid.path = f->f->qidt->uniqpath;
2729a747e4fSDavid du Colombier 	s = sizeD2M(d);
2739a747e4fSDavid du Colombier 	statbuf = emallocz(s);
2749a747e4fSDavid du Colombier 	s = convD2M(d, statbuf, s);
2759a747e4fSDavid du Colombier 	free(d);
2769a747e4fSDavid du Colombier 	rhdr.nstat = s;
2779a747e4fSDavid du Colombier 	rhdr.stat = statbuf;
2789a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
2799a747e4fSDavid du Colombier 	free(statbuf);
280*61b17cc6SDavid du Colombier 	putsbuf(t);
2819a747e4fSDavid du Colombier }
2829a747e4fSDavid du Colombier 
2839a747e4fSDavid du Colombier static int
getiounit(int fd)2849a747e4fSDavid du Colombier getiounit(int fd)
2859a747e4fSDavid du Colombier {
2869a747e4fSDavid du Colombier 	int n;
2879a747e4fSDavid du Colombier 
2889a747e4fSDavid du Colombier 	n = iounit(fd);
2899a747e4fSDavid du Colombier 	if(n > messagesize-IOHDRSZ)
2909a747e4fSDavid du Colombier 		n = messagesize-IOHDRSZ;
2919a747e4fSDavid du Colombier 	return n;
2923e12c5d1SDavid du Colombier }
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier void
Xcreate(Fsrpc * t)2959a747e4fSDavid du Colombier Xcreate(Fsrpc *t)
2963e12c5d1SDavid du Colombier {
2979a747e4fSDavid du Colombier 	char err[ERRMAX], *path;
2989a747e4fSDavid du Colombier 	Fcall rhdr;
2993e12c5d1SDavid du Colombier 	Fid *f;
3003e12c5d1SDavid du Colombier 	File *nf;
3013e12c5d1SDavid du Colombier 
30224b9ac62SDavid du Colombier 	if(readonly) {
30324b9ac62SDavid du Colombier 		reply(&t->work, &rhdr, Ereadonly);
304*61b17cc6SDavid du Colombier 		putsbuf(t);
30524b9ac62SDavid du Colombier 		return;
30624b9ac62SDavid du Colombier 	}
3079a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
308*61b17cc6SDavid du Colombier 	if(f == nil) {
3099a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
310*61b17cc6SDavid du Colombier 		putsbuf(t);
3113e12c5d1SDavid du Colombier 		return;
3123e12c5d1SDavid du Colombier 	}
3133e12c5d1SDavid du Colombier 
3143e12c5d1SDavid du Colombier 
3159a747e4fSDavid du Colombier 	path = makepath(f->f, t->work.name);
3169a747e4fSDavid du Colombier 	f->fid = create(path, t->work.mode, t->work.perm);
3179a747e4fSDavid du Colombier 	free(path);
3183e12c5d1SDavid du Colombier 	if(f->fid < 0) {
3199a747e4fSDavid du Colombier 		errstr(err, sizeof err);
3209a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
321*61b17cc6SDavid du Colombier 		putsbuf(t);
3223e12c5d1SDavid du Colombier 		return;
3233e12c5d1SDavid du Colombier 	}
3243e12c5d1SDavid du Colombier 
3259a747e4fSDavid du Colombier 	nf = file(f->f, t->work.name);
326*61b17cc6SDavid du Colombier 	if(nf == nil) {
3279a747e4fSDavid du Colombier 		errstr(err, sizeof err);
3289a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
329*61b17cc6SDavid du Colombier 		putsbuf(t);
3303e12c5d1SDavid du Colombier 		return;
3313e12c5d1SDavid du Colombier 	}
3323e12c5d1SDavid du Colombier 
3339a747e4fSDavid du Colombier 	f->mode = t->work.mode;
3347dd7cddfSDavid du Colombier 	freefile(f->f);
3353e12c5d1SDavid du Colombier 	f->f = nf;
3369a747e4fSDavid du Colombier 	rhdr.qid = f->f->qid;
3379a747e4fSDavid du Colombier 	rhdr.iounit = getiounit(f->fid);
3389a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
339*61b17cc6SDavid du Colombier 	putsbuf(t);
3403e12c5d1SDavid du Colombier }
3413e12c5d1SDavid du Colombier 
3423e12c5d1SDavid du Colombier void
Xremove(Fsrpc * t)3439a747e4fSDavid du Colombier Xremove(Fsrpc *t)
3443e12c5d1SDavid du Colombier {
3459a747e4fSDavid du Colombier 	char err[ERRMAX], *path;
3469a747e4fSDavid du Colombier 	Fcall rhdr;
3473e12c5d1SDavid du Colombier 	Fid *f;
3483e12c5d1SDavid du Colombier 
34924b9ac62SDavid du Colombier 	if(readonly) {
35024b9ac62SDavid du Colombier 		reply(&t->work, &rhdr, Ereadonly);
351*61b17cc6SDavid du Colombier 		putsbuf(t);
35224b9ac62SDavid du Colombier 		return;
35324b9ac62SDavid du Colombier 	}
3549a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
355*61b17cc6SDavid du Colombier 	if(f == nil) {
3569a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
357*61b17cc6SDavid du Colombier 		putsbuf(t);
3583e12c5d1SDavid du Colombier 		return;
3593e12c5d1SDavid du Colombier 	}
3603e12c5d1SDavid du Colombier 
3619a747e4fSDavid du Colombier 	path = makepath(f->f, "");
3627dd7cddfSDavid du Colombier 	DEBUG(DFD, "\tremove: %s\n", path);
3633e12c5d1SDavid du Colombier 	if(remove(path) < 0) {
3649a747e4fSDavid du Colombier 		free(path);
3659a747e4fSDavid du Colombier 		errstr(err, sizeof err);
3669a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
367*61b17cc6SDavid du Colombier 		putsbuf(t);
3683e12c5d1SDavid du Colombier 		return;
3693e12c5d1SDavid du Colombier 	}
3709a747e4fSDavid du Colombier 	free(path);
3713e12c5d1SDavid du Colombier 
3727dd7cddfSDavid du Colombier 	f->f->inval = 1;
3733e12c5d1SDavid du Colombier 	if(f->fid >= 0)
3743e12c5d1SDavid du Colombier 		close(f->fid);
3759a747e4fSDavid du Colombier 	freefid(t->work.fid);
3763e12c5d1SDavid du Colombier 
3779a747e4fSDavid du Colombier 	reply(&t->work, &rhdr, 0);
378*61b17cc6SDavid du Colombier 	putsbuf(t);
3793e12c5d1SDavid du Colombier }
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier void
Xwstat(Fsrpc * t)3829a747e4fSDavid du Colombier Xwstat(Fsrpc *t)
3833e12c5d1SDavid du Colombier {
3849a747e4fSDavid du Colombier 	char err[ERRMAX], *path;
3859a747e4fSDavid du Colombier 	Fcall rhdr;
3863e12c5d1SDavid du Colombier 	Fid *f;
3873e12c5d1SDavid du Colombier 	int s;
3889a747e4fSDavid du Colombier 	char *strings;
3899a747e4fSDavid du Colombier 	Dir d;
3903e12c5d1SDavid du Colombier 
39124b9ac62SDavid du Colombier 	if(readonly) {
39224b9ac62SDavid du Colombier 		reply(&t->work, &rhdr, Ereadonly);
393*61b17cc6SDavid du Colombier 		putsbuf(t);
39424b9ac62SDavid du Colombier 		return;
39524b9ac62SDavid du Colombier 	}
3969a747e4fSDavid du Colombier 	f = getfid(t->work.fid);
397*61b17cc6SDavid du Colombier 	if(f == nil) {
3989a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, Ebadfid);
399*61b17cc6SDavid du Colombier 		putsbuf(t);
4003e12c5d1SDavid du Colombier 		return;
4013e12c5d1SDavid du Colombier 	}
4029a747e4fSDavid du Colombier 	strings = emallocz(t->work.nstat);	/* ample */
40374f16c81SDavid du Colombier 	if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
4049a747e4fSDavid du Colombier 		rerrstr(err, sizeof err);
4059a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
406*61b17cc6SDavid du Colombier 		putsbuf(t);
4079a747e4fSDavid du Colombier 		free(strings);
4089a747e4fSDavid du Colombier 		return;
4099a747e4fSDavid du Colombier 	}
4109a747e4fSDavid du Colombier 
4113e12c5d1SDavid du Colombier 	if(f->fid >= 0)
4129a747e4fSDavid du Colombier 		s = dirfwstat(f->fid, &d);
4133e12c5d1SDavid du Colombier 	else {
4149a747e4fSDavid du Colombier 		path = makepath(f->f, "");
4159a747e4fSDavid du Colombier 		s = dirwstat(path, &d);
4169a747e4fSDavid du Colombier 		free(path);
4173e12c5d1SDavid du Colombier 	}
4183e12c5d1SDavid du Colombier 	if(s < 0) {
4199a747e4fSDavid du Colombier 		rerrstr(err, sizeof err);
4209a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, err);
4213e12c5d1SDavid du Colombier 	}
422219b2ee8SDavid du Colombier 	else {
423219b2ee8SDavid du Colombier 		/* wstat may really be rename */
424*61b17cc6SDavid du Colombier 		if(strcmp(d.name, f->f->name)!=0 && d.name[0]!=0){
4259a747e4fSDavid du Colombier 			free(f->f->name);
4269a747e4fSDavid du Colombier 			f->f->name = estrdup(d.name);
427219b2ee8SDavid du Colombier 		}
4289a747e4fSDavid du Colombier 		reply(&t->work, &rhdr, 0);
4293e12c5d1SDavid du Colombier 	}
4309a747e4fSDavid du Colombier 	free(strings);
431*61b17cc6SDavid du Colombier 	putsbuf(t);
4323e12c5d1SDavid du Colombier }
4333e12c5d1SDavid du Colombier 
4347ec5746aSDavid du Colombier /*
4357ec5746aSDavid du Colombier  * based on libthread's threadsetname, but drags in less library code.
4367ec5746aSDavid du Colombier  * actually just sets the arguments displayed.
4377ec5746aSDavid du Colombier  */
4387ec5746aSDavid du Colombier void
procsetname(char * fmt,...)4397ec5746aSDavid du Colombier procsetname(char *fmt, ...)
4407ec5746aSDavid du Colombier {
4417ec5746aSDavid du Colombier 	int fd;
4427ec5746aSDavid du Colombier 	char *cmdname;
4437ec5746aSDavid du Colombier 	char buf[128];
4447ec5746aSDavid du Colombier 	va_list arg;
4457ec5746aSDavid du Colombier 
4467ec5746aSDavid du Colombier 	va_start(arg, fmt);
4477ec5746aSDavid du Colombier 	cmdname = vsmprint(fmt, arg);
4487ec5746aSDavid du Colombier 	va_end(arg);
4497ec5746aSDavid du Colombier 	if (cmdname == nil)
4507ec5746aSDavid du Colombier 		return;
4517ec5746aSDavid du Colombier 	snprint(buf, sizeof buf, "#p/%d/args", getpid());
4527ec5746aSDavid du Colombier 	if((fd = open(buf, OWRITE)) >= 0){
4537ec5746aSDavid du Colombier 		write(fd, cmdname, strlen(cmdname)+1);
4547ec5746aSDavid du Colombier 		close(fd);
4557ec5746aSDavid du Colombier 	}
4567ec5746aSDavid du Colombier 	free(cmdname);
4577ec5746aSDavid du Colombier }
4587ec5746aSDavid du Colombier 
4593e12c5d1SDavid du Colombier void
slave(Fsrpc * f)4603e12c5d1SDavid du Colombier slave(Fsrpc *f)
4613e12c5d1SDavid du Colombier {
4623e12c5d1SDavid du Colombier 	static int nproc;
463*61b17cc6SDavid du Colombier 	Proc *m, **l;
464*61b17cc6SDavid du Colombier 	Fcall rhdr;
465*61b17cc6SDavid du Colombier 	int omode;
466*61b17cc6SDavid du Colombier 	int pid;
4673e12c5d1SDavid du Colombier 
46824b9ac62SDavid du Colombier 	if(readonly){
46924b9ac62SDavid du Colombier 		switch(f->work.type){
47024b9ac62SDavid du Colombier 		case Twrite:
47124b9ac62SDavid du Colombier 			reply(&f->work, &rhdr, Ereadonly);
472*61b17cc6SDavid du Colombier 			putsbuf(f);
47324b9ac62SDavid du Colombier 			return;
47424b9ac62SDavid du Colombier 		case Topen:
475*61b17cc6SDavid du Colombier 			omode = f->work.mode & 3;
476*61b17cc6SDavid du Colombier 			if(omode != OREAD && omode != OEXEC || (f->work.mode&(OTRUNC|ORCLOSE)) != 0){
47724b9ac62SDavid du Colombier 				reply(&f->work, &rhdr, Ereadonly);
478*61b17cc6SDavid du Colombier 				putsbuf(f);
47924b9ac62SDavid du Colombier 				return;
48024b9ac62SDavid du Colombier 			}
48124b9ac62SDavid du Colombier 		}
48224b9ac62SDavid du Colombier 	}
4833e12c5d1SDavid du Colombier 	for(;;) {
484*61b17cc6SDavid du Colombier 		for(l = &Proclist; (m = *l) != nil; l = &m->next) {
485*61b17cc6SDavid du Colombier 			if(m->busy != nil)
486*61b17cc6SDavid du Colombier 				continue;
487*61b17cc6SDavid du Colombier 
488*61b17cc6SDavid du Colombier 			m->busy = f;
489*61b17cc6SDavid du Colombier 			while(rendezvous(m, f) == (void*)~0)
490*61b17cc6SDavid du Colombier 				;
491*61b17cc6SDavid du Colombier 
492*61b17cc6SDavid du Colombier 			/* swept a slave proc */
493*61b17cc6SDavid du Colombier 			if(f == nil){
494*61b17cc6SDavid du Colombier 				*l = m->next;
495*61b17cc6SDavid du Colombier 				free(m);
496*61b17cc6SDavid du Colombier 				nproc--;
497*61b17cc6SDavid du Colombier 				break;
498*61b17cc6SDavid du Colombier 			}
499*61b17cc6SDavid du Colombier 			f = nil;
500*61b17cc6SDavid du Colombier 
501*61b17cc6SDavid du Colombier 			/*
502*61b17cc6SDavid du Colombier 			 * as long as the number of slave procs
503*61b17cc6SDavid du Colombier 			 * is small, dont bother sweeping.
504*61b17cc6SDavid du Colombier 			 */
505*61b17cc6SDavid du Colombier 			if(nproc < 16)
506*61b17cc6SDavid du Colombier 				break;
507*61b17cc6SDavid du Colombier 		}
508*61b17cc6SDavid du Colombier 		if(f == nil)
5093e12c5d1SDavid du Colombier 			return;
5103e12c5d1SDavid du Colombier 
511*61b17cc6SDavid du Colombier 		m = emallocz(sizeof(Proc));
512*61b17cc6SDavid du Colombier 		pid = rfork(RFPROC|RFMEM|RFNOWAIT);
5133e12c5d1SDavid du Colombier 		switch(pid) {
5143e12c5d1SDavid du Colombier 		case -1:
515*61b17cc6SDavid du Colombier 			reply(&f->work, &rhdr, Enoprocs);
516*61b17cc6SDavid du Colombier 			putsbuf(f);
517*61b17cc6SDavid du Colombier 			free(m);
518*61b17cc6SDavid du Colombier 			return;
5193e12c5d1SDavid du Colombier 
5203e12c5d1SDavid du Colombier 		case 0:
521*61b17cc6SDavid du Colombier 			if(local[0] != '\0'){
5227ec5746aSDavid du Colombier 				if(netdir[0] != '\0')
523*61b17cc6SDavid du Colombier 					procsetname("%s: %s -> %s", netdir, local, remote);
5247ec5746aSDavid du Colombier 				else
5257ec5746aSDavid du Colombier 					procsetname("%s -> %s", local, remote);
526*61b17cc6SDavid du Colombier 			}
527*61b17cc6SDavid du Colombier 			blockingslave(m);
528*61b17cc6SDavid du Colombier 			_exits(0);
5293e12c5d1SDavid du Colombier 
5303e12c5d1SDavid du Colombier 		default:
531*61b17cc6SDavid du Colombier 			m->pid = pid;
532*61b17cc6SDavid du Colombier 			m->next = Proclist;
533*61b17cc6SDavid du Colombier 			Proclist = m;
534*61b17cc6SDavid du Colombier 			nproc++;
5353e12c5d1SDavid du Colombier 		}
5363e12c5d1SDavid du Colombier 	}
5373e12c5d1SDavid du Colombier }
5383e12c5d1SDavid du Colombier 
5393e12c5d1SDavid du Colombier void
blockingslave(Proc * m)540*61b17cc6SDavid du Colombier blockingslave(Proc *m)
5413e12c5d1SDavid du Colombier {
5423e12c5d1SDavid du Colombier 	Fsrpc *p;
5439a747e4fSDavid du Colombier 	Fcall rhdr;
5443e12c5d1SDavid du Colombier 
5453e12c5d1SDavid du Colombier 	notify(flushaction);
5463e12c5d1SDavid du Colombier 
5473e12c5d1SDavid du Colombier 	for(;;) {
548*61b17cc6SDavid du Colombier 		p = rendezvous(m, nil);
54974f16c81SDavid du Colombier 		if(p == (void*)~0)	/* Interrupted */
5503e12c5d1SDavid du Colombier 			continue;
551*61b17cc6SDavid du Colombier 		if(p == nil)		/* Swept */
552*61b17cc6SDavid du Colombier 			break;
5533e12c5d1SDavid du Colombier 
554*61b17cc6SDavid du Colombier 		DEBUG(DFD, "\tslave: %d %F\n", m->pid, &p->work);
5553e12c5d1SDavid du Colombier 		if(p->flushtag != NOTAG)
5563e12c5d1SDavid du Colombier 			goto flushme;
5573e12c5d1SDavid du Colombier 
5583e12c5d1SDavid du Colombier 		switch(p->work.type) {
5593e12c5d1SDavid du Colombier 		case Tread:
5603e12c5d1SDavid du Colombier 			slaveread(p);
5613e12c5d1SDavid du Colombier 			break;
5623e12c5d1SDavid du Colombier 
5633e12c5d1SDavid du Colombier 		case Twrite:
5643e12c5d1SDavid du Colombier 			slavewrite(p);
5653e12c5d1SDavid du Colombier 			break;
5663e12c5d1SDavid du Colombier 
5673e12c5d1SDavid du Colombier 		case Topen:
5683e12c5d1SDavid du Colombier 			slaveopen(p);
5693e12c5d1SDavid du Colombier 			break;
5703e12c5d1SDavid du Colombier 
5713e12c5d1SDavid du Colombier 		default:
5729a747e4fSDavid du Colombier 			reply(&p->work, &rhdr, "exportfs: slave type error");
5733e12c5d1SDavid du Colombier 		}
5743e12c5d1SDavid du Colombier flushme:
575*61b17cc6SDavid du Colombier 		lock(m);
576*61b17cc6SDavid du Colombier 		m->busy = nil;
577*61b17cc6SDavid du Colombier 		unlock(m);
578*61b17cc6SDavid du Colombier 
579*61b17cc6SDavid du Colombier 		/* no more flushes can come in now */
580*61b17cc6SDavid du Colombier 		if(p->flushtag != NOTAG) {
5813e12c5d1SDavid du Colombier 			p->work.type = Tflush;
5823e12c5d1SDavid du Colombier 			p->work.tag = p->flushtag;
5839a747e4fSDavid du Colombier 			reply(&p->work, &rhdr, 0);
5843e12c5d1SDavid du Colombier 		}
585*61b17cc6SDavid du Colombier 		putsbuf(p);
5863e12c5d1SDavid du Colombier 	}
5873e12c5d1SDavid du Colombier }
5883e12c5d1SDavid du Colombier 
5899a747e4fSDavid du Colombier int
openmount(int sfd)5909a747e4fSDavid du Colombier openmount(int sfd)
591219b2ee8SDavid du Colombier {
592*61b17cc6SDavid du Colombier 	int p[2], fd, i, n;
5939a747e4fSDavid du Colombier 	char *arg[10], fdbuf[20], mbuf[20];
594*61b17cc6SDavid du Colombier 	Dir *dir;
595219b2ee8SDavid du Colombier 
5969a747e4fSDavid du Colombier 	if(pipe(p) < 0)
5979a747e4fSDavid du Colombier 		return -1;
598219b2ee8SDavid du Colombier 
599*61b17cc6SDavid du Colombier 	switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG|RFREND)){
6009a747e4fSDavid du Colombier 	case -1:
601*61b17cc6SDavid du Colombier 		close(p[0]);
602*61b17cc6SDavid du Colombier 		close(p[1]);
6039a747e4fSDavid du Colombier 		return -1;
6049a747e4fSDavid du Colombier 
6059a747e4fSDavid du Colombier 	default:
6069a747e4fSDavid du Colombier 		close(sfd);
6079a747e4fSDavid du Colombier 		close(p[0]);
6089a747e4fSDavid du Colombier 		return p[1];
6099a747e4fSDavid du Colombier 
6109a747e4fSDavid du Colombier 	case 0:
611219b2ee8SDavid du Colombier 		break;
612219b2ee8SDavid du Colombier 	}
613219b2ee8SDavid du Colombier 
614*61b17cc6SDavid du Colombier 	dup(p[0], 0);
615*61b17cc6SDavid du Colombier 	dup(p[0], 1);
616219b2ee8SDavid du Colombier 
617*61b17cc6SDavid du Colombier 	/* close all remaining file descriptors except sfd */
618*61b17cc6SDavid du Colombier 	if((fd = open("/fd", OREAD)) < 0)
619*61b17cc6SDavid du Colombier 		_exits("open /fd failed");
620*61b17cc6SDavid du Colombier 	n = dirreadall(fd, &dir);
621*61b17cc6SDavid du Colombier 	for(i=0; i<n; i++){
622*61b17cc6SDavid du Colombier 		if(strstr(dir[i].name, "ctl"))
623*61b17cc6SDavid du Colombier 			continue;
624*61b17cc6SDavid du Colombier 		fd = atoi(dir[i].name);
625*61b17cc6SDavid du Colombier 		if(fd > 2 && fd != sfd)
626*61b17cc6SDavid du Colombier 			close(fd);
627*61b17cc6SDavid du Colombier 	}
628*61b17cc6SDavid du Colombier 	free(dir);
629*61b17cc6SDavid du Colombier 
630*61b17cc6SDavid du Colombier 	arg[0] = argv0; /* "/bin/exportfs" */
6319a747e4fSDavid du Colombier 	snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);
6329a747e4fSDavid du Colombier 	arg[1] = fdbuf;
6339a747e4fSDavid du Colombier 	snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);
6349a747e4fSDavid du Colombier 	arg[2] = mbuf;
6359a747e4fSDavid du Colombier 	arg[3] = nil;
636219b2ee8SDavid du Colombier 
637*61b17cc6SDavid du Colombier 	exec(arg[0], arg);
6389a747e4fSDavid du Colombier 	_exits("whoops: exec failed");
6399a747e4fSDavid du Colombier 	return -1;
640219b2ee8SDavid du Colombier }
641219b2ee8SDavid du Colombier 
6423e12c5d1SDavid du Colombier void
slaveopen(Fsrpc * p)6433e12c5d1SDavid du Colombier slaveopen(Fsrpc *p)
6443e12c5d1SDavid du Colombier {
6459a747e4fSDavid du Colombier 	char err[ERRMAX], *path;
6469a747e4fSDavid du Colombier 	Fcall *work, rhdr;
6473e12c5d1SDavid du Colombier 	Fid *f;
6489a747e4fSDavid du Colombier 	Dir *d;
6493e12c5d1SDavid du Colombier 
6503e12c5d1SDavid du Colombier 	work = &p->work;
6513e12c5d1SDavid du Colombier 
6523e12c5d1SDavid du Colombier 	f = getfid(work->fid);
653*61b17cc6SDavid du Colombier 	if(f == nil) {
6549a747e4fSDavid du Colombier 		reply(work, &rhdr, Ebadfid);
6553e12c5d1SDavid du Colombier 		return;
6563e12c5d1SDavid du Colombier 	}
6573e12c5d1SDavid du Colombier 	if(f->fid >= 0) {
6583e12c5d1SDavid du Colombier 		close(f->fid);
6593e12c5d1SDavid du Colombier 		f->fid = -1;
6603e12c5d1SDavid du Colombier 	}
6613e12c5d1SDavid du Colombier 
6629a747e4fSDavid du Colombier 	path = makepath(f->f, "");
6637dd7cddfSDavid du Colombier 	DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
6643e12c5d1SDavid du Colombier 	f->fid = open(path, work->mode);
6659a747e4fSDavid du Colombier 	free(path);
6669a747e4fSDavid du Colombier 	if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
6679a747e4fSDavid du Colombier 	Error:
6689a747e4fSDavid du Colombier 		errstr(err, sizeof err);
6699a747e4fSDavid du Colombier 		reply(work, &rhdr, err);
6703e12c5d1SDavid du Colombier 		return;
6713e12c5d1SDavid du Colombier 	}
6729a747e4fSDavid du Colombier 	f->f->qid = d->qid;
6739a747e4fSDavid du Colombier 	free(d);
6749a747e4fSDavid du Colombier 	if(f->f->qid.type & QTMOUNT){	/* fork new exportfs for this */
6759a747e4fSDavid du Colombier 		f->fid = openmount(f->fid);
6769a747e4fSDavid du Colombier 		if(f->fid < 0)
6779a747e4fSDavid du Colombier 			goto Error;
6789a747e4fSDavid du Colombier 	}
6793e12c5d1SDavid du Colombier 
6807dd7cddfSDavid du Colombier 	DEBUG(DFD, "\topen: fd %d\n", f->fid);
6813e12c5d1SDavid du Colombier 	f->mode = work->mode;
682a960ed1cSDavid du Colombier 	f->offset = 0;
6839a747e4fSDavid du Colombier 	rhdr.iounit = getiounit(f->fid);
6849a747e4fSDavid du Colombier 	rhdr.qid = f->f->qid;
6859a747e4fSDavid du Colombier 	reply(work, &rhdr, 0);
6863e12c5d1SDavid du Colombier }
6873e12c5d1SDavid du Colombier 
6883e12c5d1SDavid du Colombier void
slaveread(Fsrpc * p)6893e12c5d1SDavid du Colombier slaveread(Fsrpc *p)
6903e12c5d1SDavid du Colombier {
6913e12c5d1SDavid du Colombier 	Fid *f;
6923e12c5d1SDavid du Colombier 	int n, r;
6939a747e4fSDavid du Colombier 	Fcall *work, rhdr;
6949a747e4fSDavid du Colombier 	char *data, err[ERRMAX];
6953e12c5d1SDavid du Colombier 
6963e12c5d1SDavid du Colombier 	work = &p->work;
6973e12c5d1SDavid du Colombier 
6983e12c5d1SDavid du Colombier 	f = getfid(work->fid);
699*61b17cc6SDavid du Colombier 	if(f == nil) {
7009a747e4fSDavid du Colombier 		reply(work, &rhdr, Ebadfid);
7013e12c5d1SDavid du Colombier 		return;
7023e12c5d1SDavid du Colombier 	}
7033e12c5d1SDavid du Colombier 
7049a747e4fSDavid du Colombier 	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
7059a747e4fSDavid du Colombier 	data = malloc(n);
706*61b17cc6SDavid du Colombier 	if(data == nil) {
707*61b17cc6SDavid du Colombier 		reply(work, &rhdr, Enomem);
708*61b17cc6SDavid du Colombier 		return;
709*61b17cc6SDavid du Colombier 	}
7109a747e4fSDavid du Colombier 
7119a747e4fSDavid du Colombier 	/* can't just call pread, since directories must update the offset */
712a960ed1cSDavid du Colombier 	if(patternfile != nil && (f->f->qid.type&QTDIR))
713a960ed1cSDavid du Colombier 		r = preaddir(f, (uchar*)data, n, work->offset);
714a960ed1cSDavid du Colombier 	else
7159a747e4fSDavid du Colombier 		r = pread(f->fid, data, n, work->offset);
7163e12c5d1SDavid du Colombier 	if(r < 0) {
7179a747e4fSDavid du Colombier 		free(data);
7189a747e4fSDavid du Colombier 		errstr(err, sizeof err);
7199a747e4fSDavid du Colombier 		reply(work, &rhdr, err);
7203e12c5d1SDavid du Colombier 		return;
7213e12c5d1SDavid du Colombier 	}
7227dd7cddfSDavid du Colombier 	DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
7233e12c5d1SDavid du Colombier 
7249a747e4fSDavid du Colombier 	rhdr.data = data;
7259a747e4fSDavid du Colombier 	rhdr.count = r;
7269a747e4fSDavid du Colombier 	reply(work, &rhdr, 0);
7279a747e4fSDavid du Colombier 	free(data);
7283e12c5d1SDavid du Colombier }
7293e12c5d1SDavid du Colombier 
7303e12c5d1SDavid du Colombier void
slavewrite(Fsrpc * p)7313e12c5d1SDavid du Colombier slavewrite(Fsrpc *p)
7323e12c5d1SDavid du Colombier {
7339a747e4fSDavid du Colombier 	char err[ERRMAX];
7349a747e4fSDavid du Colombier 	Fcall *work, rhdr;
7353e12c5d1SDavid du Colombier 	Fid *f;
7363e12c5d1SDavid du Colombier 	int n;
7373e12c5d1SDavid du Colombier 
7383e12c5d1SDavid du Colombier 	work = &p->work;
7393e12c5d1SDavid du Colombier 
7403e12c5d1SDavid du Colombier 	f = getfid(work->fid);
741*61b17cc6SDavid du Colombier 	if(f == nil) {
7429a747e4fSDavid du Colombier 		reply(work, &rhdr, Ebadfid);
7433e12c5d1SDavid du Colombier 		return;
7443e12c5d1SDavid du Colombier 	}
7453e12c5d1SDavid du Colombier 
7469a747e4fSDavid du Colombier 	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
7479a747e4fSDavid du Colombier 	n = pwrite(f->fid, work->data, n, work->offset);
7483e12c5d1SDavid du Colombier 	if(n < 0) {
7499a747e4fSDavid du Colombier 		errstr(err, sizeof err);
7509a747e4fSDavid du Colombier 		reply(work, &rhdr, err);
7513e12c5d1SDavid du Colombier 		return;
7523e12c5d1SDavid du Colombier 	}
7533e12c5d1SDavid du Colombier 
7547dd7cddfSDavid du Colombier 	DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
7553e12c5d1SDavid du Colombier 
7569a747e4fSDavid du Colombier 	rhdr.count = n;
7579a747e4fSDavid du Colombier 	reply(work, &rhdr, 0);
7583e12c5d1SDavid du Colombier }
7593e12c5d1SDavid du Colombier 
7603e12c5d1SDavid du Colombier void
reopen(Fid * f)7613e12c5d1SDavid du Colombier reopen(Fid *f)
7623e12c5d1SDavid du Colombier {
7633e12c5d1SDavid du Colombier 	USED(f);
7643e12c5d1SDavid du Colombier 	fatal("reopen");
7653e12c5d1SDavid du Colombier }
7663e12c5d1SDavid du Colombier 
7673e12c5d1SDavid du Colombier void
flushaction(void * a,char * cause)7683e12c5d1SDavid du Colombier flushaction(void *a, char *cause)
7693e12c5d1SDavid du Colombier {
7703e12c5d1SDavid du Colombier 	USED(a);
7713e12c5d1SDavid du Colombier 	if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
7723e12c5d1SDavid du Colombier 		fprint(2, "exportsrv: note: %s\n", cause);
7733e12c5d1SDavid du Colombier 		exits("noted");
7743e12c5d1SDavid du Colombier 	}
7753e12c5d1SDavid du Colombier 	if(strncmp(cause, "kill", 4) == 0)
7763e12c5d1SDavid du Colombier 		noted(NDFLT);
7773e12c5d1SDavid du Colombier 
7783e12c5d1SDavid du Colombier 	noted(NCONT);
7793e12c5d1SDavid du Colombier }
780