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