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
8*7ec5746aSDavid du Colombier extern char *netdir, *local, *remote;
9*7ec5746aSDavid du Colombier
109a747e4fSDavid du Colombier char Ebadfid[] = "Bad fid";
119a747e4fSDavid du Colombier char Enotdir[] = "Not a directory";
129a747e4fSDavid du Colombier char Edupfid[] = "Fid already in use";
139a747e4fSDavid du Colombier char Eopen[] = "Fid already opened";
149a747e4fSDavid du Colombier char Exmnt[] = "Cannot .. past mount point";
159a747e4fSDavid du Colombier char Emip[] = "Mount in progress";
169a747e4fSDavid du Colombier char Enopsmt[] = "Out of pseudo mount points";
179a747e4fSDavid du Colombier char Enomem[] = "No memory";
189a747e4fSDavid du Colombier char Eversion[] = "Bad 9P2000 version";
1924b9ac62SDavid du Colombier char Ereadonly[] = "File system read only";
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
299a747e4fSDavid du Colombier if(t->work.msize > messagesize)
309a747e4fSDavid du Colombier t->work.msize = messagesize;
319a747e4fSDavid du Colombier messagesize = t->work.msize;
329a747e4fSDavid du Colombier if(strncmp(t->work.version, "9P2000", 6) != 0){
339a747e4fSDavid du Colombier reply(&t->work, &rhdr, Eversion);
349a747e4fSDavid du Colombier return;
359a747e4fSDavid du Colombier }
369a747e4fSDavid du Colombier rhdr.version = "9P2000";
379a747e4fSDavid du Colombier rhdr.msize = t->work.msize;
389a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
399a747e4fSDavid du Colombier t->busy = 0;
403e12c5d1SDavid du Colombier }
413e12c5d1SDavid du Colombier
423e12c5d1SDavid du Colombier void
Xauth(Fsrpc * t)439a747e4fSDavid du Colombier Xauth(Fsrpc *t)
443e12c5d1SDavid du Colombier {
459a747e4fSDavid du Colombier Fcall rhdr;
463e12c5d1SDavid du Colombier
473ff48bf5SDavid du Colombier reply(&t->work, &rhdr, "exportfs: authentication not required");
489a747e4fSDavid du Colombier t->busy = 0;
493e12c5d1SDavid du Colombier }
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier void
Xflush(Fsrpc * t)529a747e4fSDavid du Colombier Xflush(Fsrpc *t)
533e12c5d1SDavid du Colombier {
549a747e4fSDavid du Colombier Fsrpc *w, *e;
559a747e4fSDavid du Colombier Fcall rhdr;
563e12c5d1SDavid du Colombier
573e12c5d1SDavid du Colombier e = &Workq[Nr_workbufs];
583e12c5d1SDavid du Colombier
599a747e4fSDavid du Colombier for(w = Workq; w < e; w++) {
609a747e4fSDavid du Colombier if(w->work.tag == t->work.oldtag) {
6174f16c81SDavid du Colombier DEBUG(DFD, "\tQ busy %d pid %p can %d\n", w->busy, w->pid, w->canint);
629a747e4fSDavid du Colombier if(w->busy && w->pid) {
639a747e4fSDavid du Colombier w->flushtag = t->work.tag;
649a747e4fSDavid du Colombier DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
659a747e4fSDavid du Colombier if(w->canint)
669a747e4fSDavid du Colombier postnote(PNPROC, w->pid, "flush");
679a747e4fSDavid du Colombier t->busy = 0;
683e12c5d1SDavid du Colombier return;
693e12c5d1SDavid du Colombier }
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier }
723e12c5d1SDavid du Colombier
739a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
747dd7cddfSDavid du Colombier DEBUG(DFD, "\tflush reply\n");
759a747e4fSDavid du Colombier t->busy = 0;
763e12c5d1SDavid du Colombier }
773e12c5d1SDavid du Colombier
783e12c5d1SDavid du Colombier void
Xattach(Fsrpc * t)799a747e4fSDavid du Colombier Xattach(Fsrpc *t)
803e12c5d1SDavid du Colombier {
819a747e4fSDavid du Colombier int i, nfd;
829a747e4fSDavid du Colombier Fcall rhdr;
833e12c5d1SDavid du Colombier Fid *f;
849a747e4fSDavid du Colombier char buf[128];
853e12c5d1SDavid du Colombier
869a747e4fSDavid du Colombier f = newfid(t->work.fid);
873e12c5d1SDavid du Colombier if(f == 0) {
889a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
899a747e4fSDavid du Colombier t->busy = 0;
903e12c5d1SDavid du Colombier return;
913e12c5d1SDavid du Colombier }
923e12c5d1SDavid du Colombier
939a747e4fSDavid du Colombier if(srvfd >= 0){
949a747e4fSDavid du Colombier if(psmpt == 0){
959a747e4fSDavid du Colombier Nomount:
969a747e4fSDavid du Colombier reply(&t->work, &rhdr, Enopsmt);
979a747e4fSDavid du Colombier t->busy = 0;
989a747e4fSDavid du Colombier freefid(t->work.fid);
999a747e4fSDavid du Colombier return;
1009a747e4fSDavid du Colombier }
1019a747e4fSDavid du Colombier for(i=0; i<Npsmpt; i++)
1029a747e4fSDavid du Colombier if(psmap[i] == 0)
1039a747e4fSDavid du Colombier break;
1049a747e4fSDavid du Colombier if(i >= Npsmpt)
1059a747e4fSDavid du Colombier goto Nomount;
1069a747e4fSDavid du Colombier sprint(buf, "%d", i);
1079a747e4fSDavid du Colombier f->f = file(psmpt, buf);
1089a747e4fSDavid du Colombier if(f->f == nil)
1099a747e4fSDavid du Colombier goto Nomount;
1109a747e4fSDavid du Colombier sprint(buf, "/mnt/exportfs/%d", i);
1119a747e4fSDavid du Colombier nfd = dup(srvfd, -1);
1129a747e4fSDavid du Colombier if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
1139a747e4fSDavid du Colombier errstr(buf, sizeof buf);
1149a747e4fSDavid du Colombier reply(&t->work, &rhdr, buf);
1159a747e4fSDavid du Colombier t->busy = 0;
1169a747e4fSDavid du Colombier freefid(t->work.fid);
1179a747e4fSDavid du Colombier close(nfd);
1189a747e4fSDavid du Colombier return;
1199a747e4fSDavid du Colombier }
1209a747e4fSDavid du Colombier psmap[i] = 1;
1219a747e4fSDavid du Colombier f->mid = i;
1229a747e4fSDavid du Colombier }else{
1233e12c5d1SDavid du Colombier f->f = root;
1247dd7cddfSDavid du Colombier f->f->ref++;
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier
1279a747e4fSDavid du Colombier rhdr.qid = f->f->qid;
1289a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
1299a747e4fSDavid du Colombier t->busy = 0;
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier Fid*
clonefid(Fid * f,int new)1339a747e4fSDavid du Colombier clonefid(Fid *f, int new)
1343e12c5d1SDavid du Colombier {
1359a747e4fSDavid du Colombier Fid *n;
1363e12c5d1SDavid du Colombier
1379a747e4fSDavid du Colombier n = newfid(new);
1383e12c5d1SDavid du Colombier if(n == 0) {
1399a747e4fSDavid du Colombier n = getfid(new);
140219b2ee8SDavid du Colombier if(n == 0)
141219b2ee8SDavid du Colombier fatal("inconsistent fids");
142219b2ee8SDavid du Colombier if(n->fid >= 0)
143219b2ee8SDavid du Colombier close(n->fid);
1449a747e4fSDavid du Colombier freefid(new);
1459a747e4fSDavid du Colombier n = newfid(new);
146219b2ee8SDavid du Colombier if(n == 0)
147219b2ee8SDavid du Colombier fatal("inconsistent fids2");
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier n->f = f->f;
1507dd7cddfSDavid du Colombier n->f->ref++;
1519a747e4fSDavid du Colombier return n;
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier
1549a747e4fSDavid du Colombier void
Xwalk(Fsrpc * t)1559a747e4fSDavid du Colombier Xwalk(Fsrpc *t)
1563e12c5d1SDavid du Colombier {
1579a747e4fSDavid du Colombier char err[ERRMAX], *e;
1589a747e4fSDavid du Colombier Fcall rhdr;
1599a747e4fSDavid du Colombier Fid *f, *nf;
1609a747e4fSDavid du Colombier File *wf;
1619a747e4fSDavid du Colombier int i;
1623e12c5d1SDavid du Colombier
1639a747e4fSDavid du Colombier f = getfid(t->work.fid);
1643e12c5d1SDavid du Colombier if(f == 0) {
1659a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
1669a747e4fSDavid du Colombier t->busy = 0;
1679a747e4fSDavid du Colombier return;
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier
1709a747e4fSDavid du Colombier nf = nil;
1719a747e4fSDavid du Colombier if(t->work.newfid != t->work.fid){
1729a747e4fSDavid du Colombier nf = clonefid(f, t->work.newfid);
1739a747e4fSDavid du Colombier f = nf;
1749a747e4fSDavid du Colombier }
1759a747e4fSDavid du Colombier
1769a747e4fSDavid du Colombier rhdr.nwqid = 0;
1779a747e4fSDavid du Colombier e = nil;
1789a747e4fSDavid du Colombier for(i=0; i<t->work.nwname; i++){
1799a747e4fSDavid du Colombier if(i == MAXWELEM){
1809a747e4fSDavid du Colombier e = "Too many path elements";
1819a747e4fSDavid du Colombier break;
1829a747e4fSDavid du Colombier }
1839a747e4fSDavid du Colombier
1849a747e4fSDavid du Colombier if(strcmp(t->work.wname[i], "..") == 0) {
1857dd7cddfSDavid du Colombier if(f->f->parent == nil) {
1869a747e4fSDavid du Colombier e = Exmnt;
1879a747e4fSDavid du Colombier break;
1883e12c5d1SDavid du Colombier }
1899a747e4fSDavid du Colombier wf = f->f->parent;
1909a747e4fSDavid du Colombier wf->ref++;
1919a747e4fSDavid du Colombier goto Accept;
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier
1949a747e4fSDavid du Colombier wf = file(f->f, t->work.wname[i]);
1959a747e4fSDavid du Colombier if(wf == 0){
1969a747e4fSDavid du Colombier errstr(err, sizeof err);
1979a747e4fSDavid du Colombier e = err;
1989a747e4fSDavid du Colombier break;
1999a747e4fSDavid du Colombier }
2009a747e4fSDavid du Colombier Accept:
2019a747e4fSDavid du Colombier freefile(f->f);
2029a747e4fSDavid du Colombier rhdr.wqid[rhdr.nwqid++] = wf->qid;
2039a747e4fSDavid du Colombier f->f = wf;
2049a747e4fSDavid du Colombier continue;
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier
2079a747e4fSDavid du Colombier if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
2089a747e4fSDavid du Colombier freefid(t->work.newfid);
2099a747e4fSDavid du Colombier if(rhdr.nwqid > 0)
2109a747e4fSDavid du Colombier e = nil;
2119a747e4fSDavid du Colombier reply(&t->work, &rhdr, e);
2129a747e4fSDavid du Colombier t->busy = 0;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier void
Xclunk(Fsrpc * t)2169a747e4fSDavid du Colombier Xclunk(Fsrpc *t)
2177dd7cddfSDavid du Colombier {
2189a747e4fSDavid du Colombier Fcall rhdr;
2193e12c5d1SDavid du Colombier Fid *f;
2203e12c5d1SDavid du Colombier
2219a747e4fSDavid du Colombier f = getfid(t->work.fid);
2223e12c5d1SDavid du Colombier if(f == 0) {
2239a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
2249a747e4fSDavid du Colombier t->busy = 0;
2253e12c5d1SDavid du Colombier return;
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier
2283e12c5d1SDavid du Colombier if(f->fid >= 0)
2293e12c5d1SDavid du Colombier close(f->fid);
2303e12c5d1SDavid du Colombier
2319a747e4fSDavid du Colombier freefid(t->work.fid);
2329a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
2339a747e4fSDavid du Colombier t->busy = 0;
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier
2363e12c5d1SDavid du Colombier void
Xstat(Fsrpc * t)2379a747e4fSDavid du Colombier Xstat(Fsrpc *t)
2383e12c5d1SDavid du Colombier {
2399a747e4fSDavid du Colombier char err[ERRMAX], *path;
2409a747e4fSDavid du Colombier Fcall rhdr;
2413e12c5d1SDavid du Colombier Fid *f;
2429a747e4fSDavid du Colombier Dir *d;
2433e12c5d1SDavid du Colombier int s;
2449a747e4fSDavid du Colombier uchar *statbuf;
2453e12c5d1SDavid du Colombier
2469a747e4fSDavid du Colombier f = getfid(t->work.fid);
2473e12c5d1SDavid du Colombier if(f == 0) {
2489a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
2499a747e4fSDavid du Colombier t->busy = 0;
2503e12c5d1SDavid du Colombier return;
2513e12c5d1SDavid du Colombier }
2523e12c5d1SDavid du Colombier if(f->fid >= 0)
2539a747e4fSDavid du Colombier d = dirfstat(f->fid);
2543e12c5d1SDavid du Colombier else {
2559a747e4fSDavid du Colombier path = makepath(f->f, "");
2569a747e4fSDavid du Colombier d = dirstat(path);
2579a747e4fSDavid du Colombier free(path);
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier
2609a747e4fSDavid du Colombier if(d == nil) {
2619a747e4fSDavid du Colombier errstr(err, sizeof err);
2629a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
2639a747e4fSDavid du Colombier t->busy = 0;
2643e12c5d1SDavid du Colombier return;
2653e12c5d1SDavid du Colombier }
2669a747e4fSDavid du Colombier
2679a747e4fSDavid du Colombier d->qid.path = f->f->qidt->uniqpath;
2689a747e4fSDavid du Colombier s = sizeD2M(d);
2699a747e4fSDavid du Colombier statbuf = emallocz(s);
2709a747e4fSDavid du Colombier s = convD2M(d, statbuf, s);
2719a747e4fSDavid du Colombier free(d);
2729a747e4fSDavid du Colombier rhdr.nstat = s;
2739a747e4fSDavid du Colombier rhdr.stat = statbuf;
2749a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
2759a747e4fSDavid du Colombier free(statbuf);
2769a747e4fSDavid du Colombier t->busy = 0;
2779a747e4fSDavid du Colombier }
2789a747e4fSDavid du Colombier
2799a747e4fSDavid du Colombier static int
getiounit(int fd)2809a747e4fSDavid du Colombier getiounit(int fd)
2819a747e4fSDavid du Colombier {
2829a747e4fSDavid du Colombier int n;
2839a747e4fSDavid du Colombier
2849a747e4fSDavid du Colombier n = iounit(fd);
2859a747e4fSDavid du Colombier if(n > messagesize-IOHDRSZ)
2869a747e4fSDavid du Colombier n = messagesize-IOHDRSZ;
2879a747e4fSDavid du Colombier return n;
2883e12c5d1SDavid du Colombier }
2893e12c5d1SDavid du Colombier
2903e12c5d1SDavid du Colombier void
Xcreate(Fsrpc * t)2919a747e4fSDavid du Colombier Xcreate(Fsrpc *t)
2923e12c5d1SDavid du Colombier {
2939a747e4fSDavid du Colombier char err[ERRMAX], *path;
2949a747e4fSDavid du Colombier Fcall rhdr;
2953e12c5d1SDavid du Colombier Fid *f;
2963e12c5d1SDavid du Colombier File *nf;
2973e12c5d1SDavid du Colombier
29824b9ac62SDavid du Colombier if(readonly) {
29924b9ac62SDavid du Colombier reply(&t->work, &rhdr, Ereadonly);
30024b9ac62SDavid du Colombier t->busy = 0;
30124b9ac62SDavid du Colombier return;
30224b9ac62SDavid du Colombier }
3039a747e4fSDavid du Colombier f = getfid(t->work.fid);
3043e12c5d1SDavid du Colombier if(f == 0) {
3059a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3069a747e4fSDavid du Colombier t->busy = 0;
3073e12c5d1SDavid du Colombier return;
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier
3103e12c5d1SDavid du Colombier
3119a747e4fSDavid du Colombier path = makepath(f->f, t->work.name);
3129a747e4fSDavid du Colombier f->fid = create(path, t->work.mode, t->work.perm);
3139a747e4fSDavid du Colombier free(path);
3143e12c5d1SDavid du Colombier if(f->fid < 0) {
3159a747e4fSDavid du Colombier errstr(err, sizeof err);
3169a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
3179a747e4fSDavid du Colombier t->busy = 0;
3183e12c5d1SDavid du Colombier return;
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier
3219a747e4fSDavid du Colombier nf = file(f->f, t->work.name);
3223e12c5d1SDavid du Colombier if(nf == 0) {
3239a747e4fSDavid du Colombier errstr(err, sizeof err);
3249a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
3259a747e4fSDavid du Colombier t->busy = 0;
3263e12c5d1SDavid du Colombier return;
3273e12c5d1SDavid du Colombier }
3283e12c5d1SDavid du Colombier
3299a747e4fSDavid du Colombier f->mode = t->work.mode;
3307dd7cddfSDavid du Colombier freefile(f->f);
3313e12c5d1SDavid du Colombier f->f = nf;
3329a747e4fSDavid du Colombier rhdr.qid = f->f->qid;
3339a747e4fSDavid du Colombier rhdr.iounit = getiounit(f->fid);
3349a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
3359a747e4fSDavid du Colombier t->busy = 0;
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier
3383e12c5d1SDavid du Colombier void
Xremove(Fsrpc * t)3399a747e4fSDavid du Colombier Xremove(Fsrpc *t)
3403e12c5d1SDavid du Colombier {
3419a747e4fSDavid du Colombier char err[ERRMAX], *path;
3429a747e4fSDavid du Colombier Fcall rhdr;
3433e12c5d1SDavid du Colombier Fid *f;
3443e12c5d1SDavid du Colombier
34524b9ac62SDavid du Colombier if(readonly) {
34624b9ac62SDavid du Colombier reply(&t->work, &rhdr, Ereadonly);
34724b9ac62SDavid du Colombier t->busy = 0;
34824b9ac62SDavid du Colombier return;
34924b9ac62SDavid du Colombier }
3509a747e4fSDavid du Colombier f = getfid(t->work.fid);
3513e12c5d1SDavid du Colombier if(f == 0) {
3529a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3539a747e4fSDavid du Colombier t->busy = 0;
3543e12c5d1SDavid du Colombier return;
3553e12c5d1SDavid du Colombier }
3563e12c5d1SDavid du Colombier
3579a747e4fSDavid du Colombier path = makepath(f->f, "");
3587dd7cddfSDavid du Colombier DEBUG(DFD, "\tremove: %s\n", path);
3593e12c5d1SDavid du Colombier if(remove(path) < 0) {
3609a747e4fSDavid du Colombier free(path);
3619a747e4fSDavid du Colombier errstr(err, sizeof err);
3629a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
3639a747e4fSDavid du Colombier t->busy = 0;
3643e12c5d1SDavid du Colombier return;
3653e12c5d1SDavid du Colombier }
3669a747e4fSDavid du Colombier free(path);
3673e12c5d1SDavid du Colombier
3687dd7cddfSDavid du Colombier f->f->inval = 1;
3693e12c5d1SDavid du Colombier if(f->fid >= 0)
3703e12c5d1SDavid du Colombier close(f->fid);
3719a747e4fSDavid du Colombier freefid(t->work.fid);
3723e12c5d1SDavid du Colombier
3739a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
3749a747e4fSDavid du Colombier t->busy = 0;
3753e12c5d1SDavid du Colombier }
3763e12c5d1SDavid du Colombier
3773e12c5d1SDavid du Colombier void
Xwstat(Fsrpc * t)3789a747e4fSDavid du Colombier Xwstat(Fsrpc *t)
3793e12c5d1SDavid du Colombier {
3809a747e4fSDavid du Colombier char err[ERRMAX], *path;
3819a747e4fSDavid du Colombier Fcall rhdr;
3823e12c5d1SDavid du Colombier Fid *f;
3833e12c5d1SDavid du Colombier int s;
3849a747e4fSDavid du Colombier char *strings;
3859a747e4fSDavid du Colombier Dir d;
3863e12c5d1SDavid du Colombier
38724b9ac62SDavid du Colombier if(readonly) {
38824b9ac62SDavid du Colombier reply(&t->work, &rhdr, Ereadonly);
38924b9ac62SDavid du Colombier t->busy = 0;
39024b9ac62SDavid du Colombier return;
39124b9ac62SDavid du Colombier }
3929a747e4fSDavid du Colombier f = getfid(t->work.fid);
3933e12c5d1SDavid du Colombier if(f == 0) {
3949a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3959a747e4fSDavid du Colombier t->busy = 0;
3963e12c5d1SDavid du Colombier return;
3973e12c5d1SDavid du Colombier }
3989a747e4fSDavid du Colombier strings = emallocz(t->work.nstat); /* ample */
39974f16c81SDavid du Colombier if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
4009a747e4fSDavid du Colombier rerrstr(err, sizeof err);
4019a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
4029a747e4fSDavid du Colombier t->busy = 0;
4039a747e4fSDavid du Colombier free(strings);
4049a747e4fSDavid du Colombier return;
4059a747e4fSDavid du Colombier }
4069a747e4fSDavid du Colombier
4073e12c5d1SDavid du Colombier if(f->fid >= 0)
4089a747e4fSDavid du Colombier s = dirfwstat(f->fid, &d);
4093e12c5d1SDavid du Colombier else {
4109a747e4fSDavid du Colombier path = makepath(f->f, "");
4119a747e4fSDavid du Colombier s = dirwstat(path, &d);
4129a747e4fSDavid du Colombier free(path);
4133e12c5d1SDavid du Colombier }
4143e12c5d1SDavid du Colombier if(s < 0) {
4159a747e4fSDavid du Colombier rerrstr(err, sizeof err);
4169a747e4fSDavid du Colombier reply(&t->work, &rhdr, err);
4173e12c5d1SDavid du Colombier }
418219b2ee8SDavid du Colombier else {
419219b2ee8SDavid du Colombier /* wstat may really be rename */
420d9306527SDavid du Colombier if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
4219a747e4fSDavid du Colombier free(f->f->name);
4229a747e4fSDavid du Colombier f->f->name = estrdup(d.name);
423219b2ee8SDavid du Colombier }
4249a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0);
4253e12c5d1SDavid du Colombier }
4269a747e4fSDavid du Colombier free(strings);
4279a747e4fSDavid du Colombier t->busy = 0;
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier
430*7ec5746aSDavid du Colombier /*
431*7ec5746aSDavid du Colombier * based on libthread's threadsetname, but drags in less library code.
432*7ec5746aSDavid du Colombier * actually just sets the arguments displayed.
433*7ec5746aSDavid du Colombier */
434*7ec5746aSDavid du Colombier void
procsetname(char * fmt,...)435*7ec5746aSDavid du Colombier procsetname(char *fmt, ...)
436*7ec5746aSDavid du Colombier {
437*7ec5746aSDavid du Colombier int fd;
438*7ec5746aSDavid du Colombier char *cmdname;
439*7ec5746aSDavid du Colombier char buf[128];
440*7ec5746aSDavid du Colombier va_list arg;
441*7ec5746aSDavid du Colombier
442*7ec5746aSDavid du Colombier va_start(arg, fmt);
443*7ec5746aSDavid du Colombier cmdname = vsmprint(fmt, arg);
444*7ec5746aSDavid du Colombier va_end(arg);
445*7ec5746aSDavid du Colombier if (cmdname == nil)
446*7ec5746aSDavid du Colombier return;
447*7ec5746aSDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid());
448*7ec5746aSDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){
449*7ec5746aSDavid du Colombier write(fd, cmdname, strlen(cmdname)+1);
450*7ec5746aSDavid du Colombier close(fd);
451*7ec5746aSDavid du Colombier }
452*7ec5746aSDavid du Colombier free(cmdname);
453*7ec5746aSDavid du Colombier }
454*7ec5746aSDavid du Colombier
4553e12c5d1SDavid du Colombier void
slave(Fsrpc * f)4563e12c5d1SDavid du Colombier slave(Fsrpc *f)
4573e12c5d1SDavid du Colombier {
4583e12c5d1SDavid du Colombier Proc *p;
45974f16c81SDavid du Colombier uintptr pid;
46024b9ac62SDavid du Colombier Fcall rhdr;
4613e12c5d1SDavid du Colombier static int nproc;
4623e12c5d1SDavid du Colombier
46324b9ac62SDavid du Colombier if(readonly){
46424b9ac62SDavid du Colombier switch(f->work.type){
46524b9ac62SDavid du Colombier case Twrite:
46624b9ac62SDavid du Colombier reply(&f->work, &rhdr, Ereadonly);
46724b9ac62SDavid du Colombier f->busy = 0;
46824b9ac62SDavid du Colombier return;
46924b9ac62SDavid du Colombier case Topen:
47024b9ac62SDavid du Colombier if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){
47124b9ac62SDavid du Colombier reply(&f->work, &rhdr, Ereadonly);
47224b9ac62SDavid du Colombier f->busy = 0;
47324b9ac62SDavid du Colombier return;
47424b9ac62SDavid du Colombier }
47524b9ac62SDavid du Colombier }
47624b9ac62SDavid du Colombier }
4773e12c5d1SDavid du Colombier for(;;) {
4783e12c5d1SDavid du Colombier for(p = Proclist; p; p = p->next) {
4793e12c5d1SDavid du Colombier if(p->busy == 0) {
4803e12c5d1SDavid du Colombier f->pid = p->pid;
4813e12c5d1SDavid du Colombier p->busy = 1;
48274f16c81SDavid du Colombier pid = (uintptr)rendezvous((void*)p->pid, f);
4833e12c5d1SDavid du Colombier if(pid != p->pid)
4843e12c5d1SDavid du Colombier fatal("rendezvous sync fail");
4853e12c5d1SDavid du Colombier return;
4863e12c5d1SDavid du Colombier }
4873e12c5d1SDavid du Colombier }
4883e12c5d1SDavid du Colombier
4893e12c5d1SDavid du Colombier if(++nproc > MAXPROC)
4903e12c5d1SDavid du Colombier fatal("too many procs");
4913e12c5d1SDavid du Colombier
4923e12c5d1SDavid du Colombier pid = rfork(RFPROC|RFMEM);
4933e12c5d1SDavid du Colombier switch(pid) {
4943e12c5d1SDavid du Colombier case -1:
4953e12c5d1SDavid du Colombier fatal("rfork");
4963e12c5d1SDavid du Colombier
4973e12c5d1SDavid du Colombier case 0:
498*7ec5746aSDavid du Colombier if (local[0] != '\0')
499*7ec5746aSDavid du Colombier if (netdir[0] != '\0')
500*7ec5746aSDavid du Colombier procsetname("%s: %s -> %s", netdir,
501*7ec5746aSDavid du Colombier local, remote);
502*7ec5746aSDavid du Colombier else
503*7ec5746aSDavid du Colombier procsetname("%s -> %s", local, remote);
5043e12c5d1SDavid du Colombier blockingslave();
5053e12c5d1SDavid du Colombier fatal("slave");
5063e12c5d1SDavid du Colombier
5073e12c5d1SDavid du Colombier default:
5083e12c5d1SDavid du Colombier p = malloc(sizeof(Proc));
5093e12c5d1SDavid du Colombier if(p == 0)
5103e12c5d1SDavid du Colombier fatal("out of memory");
5113e12c5d1SDavid du Colombier
5123e12c5d1SDavid du Colombier p->busy = 0;
5133e12c5d1SDavid du Colombier p->pid = pid;
5143e12c5d1SDavid du Colombier p->next = Proclist;
5153e12c5d1SDavid du Colombier Proclist = p;
5163e12c5d1SDavid du Colombier
51774f16c81SDavid du Colombier rendezvous((void*)pid, p);
5183e12c5d1SDavid du Colombier }
5193e12c5d1SDavid du Colombier }
5203e12c5d1SDavid du Colombier }
5213e12c5d1SDavid du Colombier
5223e12c5d1SDavid du Colombier void
blockingslave(void)5233e12c5d1SDavid du Colombier blockingslave(void)
5243e12c5d1SDavid du Colombier {
5253e12c5d1SDavid du Colombier Fsrpc *p;
5269a747e4fSDavid du Colombier Fcall rhdr;
5273e12c5d1SDavid du Colombier Proc *m;
52874f16c81SDavid du Colombier uintptr pid;
5293e12c5d1SDavid du Colombier
5303e12c5d1SDavid du Colombier notify(flushaction);
5313e12c5d1SDavid du Colombier
5323e12c5d1SDavid du Colombier pid = getpid();
5333e12c5d1SDavid du Colombier
53474f16c81SDavid du Colombier m = rendezvous((void*)pid, 0);
5353e12c5d1SDavid du Colombier
5363e12c5d1SDavid du Colombier for(;;) {
53774f16c81SDavid du Colombier p = rendezvous((void*)pid, (void*)pid);
53874f16c81SDavid du Colombier if(p == (void*)~0) /* Interrupted */
5393e12c5d1SDavid du Colombier continue;
5403e12c5d1SDavid du Colombier
54174f16c81SDavid du Colombier DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
5423e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
5433e12c5d1SDavid du Colombier goto flushme;
5443e12c5d1SDavid du Colombier
5453e12c5d1SDavid du Colombier switch(p->work.type) {
5463e12c5d1SDavid du Colombier case Tread:
5473e12c5d1SDavid du Colombier slaveread(p);
5483e12c5d1SDavid du Colombier break;
5493e12c5d1SDavid du Colombier
5503e12c5d1SDavid du Colombier case Twrite:
5513e12c5d1SDavid du Colombier slavewrite(p);
5523e12c5d1SDavid du Colombier break;
5533e12c5d1SDavid du Colombier
5543e12c5d1SDavid du Colombier case Topen:
5553e12c5d1SDavid du Colombier slaveopen(p);
5563e12c5d1SDavid du Colombier break;
5573e12c5d1SDavid du Colombier
5583e12c5d1SDavid du Colombier default:
5599a747e4fSDavid du Colombier reply(&p->work, &rhdr, "exportfs: slave type error");
5603e12c5d1SDavid du Colombier }
5613e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) {
5623e12c5d1SDavid du Colombier flushme:
5633e12c5d1SDavid du Colombier p->work.type = Tflush;
5643e12c5d1SDavid du Colombier p->work.tag = p->flushtag;
5659a747e4fSDavid du Colombier reply(&p->work, &rhdr, 0);
5663e12c5d1SDavid du Colombier }
5673e12c5d1SDavid du Colombier p->busy = 0;
5683e12c5d1SDavid du Colombier m->busy = 0;
5693e12c5d1SDavid du Colombier }
5703e12c5d1SDavid du Colombier }
5713e12c5d1SDavid du Colombier
5729a747e4fSDavid du Colombier int
openmount(int sfd)5739a747e4fSDavid du Colombier openmount(int sfd)
574219b2ee8SDavid du Colombier {
5759a747e4fSDavid du Colombier int p[2];
5769a747e4fSDavid du Colombier char *arg[10], fdbuf[20], mbuf[20];
577219b2ee8SDavid du Colombier
5789a747e4fSDavid du Colombier if(pipe(p) < 0)
5799a747e4fSDavid du Colombier return -1;
580219b2ee8SDavid du Colombier
5819a747e4fSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){
5829a747e4fSDavid du Colombier case -1:
5839a747e4fSDavid du Colombier return -1;
5849a747e4fSDavid du Colombier
5859a747e4fSDavid du Colombier default:
5869a747e4fSDavid du Colombier close(sfd);
5879a747e4fSDavid du Colombier close(p[0]);
5889a747e4fSDavid du Colombier return p[1];
5899a747e4fSDavid du Colombier
5909a747e4fSDavid du Colombier case 0:
591219b2ee8SDavid du Colombier break;
592219b2ee8SDavid du Colombier }
593219b2ee8SDavid du Colombier
5949a747e4fSDavid du Colombier close(p[1]);
595219b2ee8SDavid du Colombier
5969a747e4fSDavid du Colombier arg[0] = "exportfs";
5979a747e4fSDavid du Colombier snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);
5989a747e4fSDavid du Colombier arg[1] = fdbuf;
5999a747e4fSDavid du Colombier snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);
6009a747e4fSDavid du Colombier arg[2] = mbuf;
6019a747e4fSDavid du Colombier arg[3] = nil;
602219b2ee8SDavid du Colombier
6039a747e4fSDavid du Colombier close(0);
6049a747e4fSDavid du Colombier close(1);
6059a747e4fSDavid du Colombier dup(p[0], 0);
6069a747e4fSDavid du Colombier dup(p[0], 1);
6079a747e4fSDavid du Colombier exec("/bin/exportfs", arg);
6089a747e4fSDavid du Colombier _exits("whoops: exec failed");
6099a747e4fSDavid du Colombier return -1;
610219b2ee8SDavid du Colombier }
611219b2ee8SDavid du Colombier
6123e12c5d1SDavid du Colombier void
slaveopen(Fsrpc * p)6133e12c5d1SDavid du Colombier slaveopen(Fsrpc *p)
6143e12c5d1SDavid du Colombier {
6159a747e4fSDavid du Colombier char err[ERRMAX], *path;
6169a747e4fSDavid du Colombier Fcall *work, rhdr;
6173e12c5d1SDavid du Colombier Fid *f;
6189a747e4fSDavid du Colombier Dir *d;
6193e12c5d1SDavid du Colombier
6203e12c5d1SDavid du Colombier work = &p->work;
6213e12c5d1SDavid du Colombier
6223e12c5d1SDavid du Colombier f = getfid(work->fid);
6233e12c5d1SDavid du Colombier if(f == 0) {
6249a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid);
6253e12c5d1SDavid du Colombier return;
6263e12c5d1SDavid du Colombier }
6273e12c5d1SDavid du Colombier if(f->fid >= 0) {
6283e12c5d1SDavid du Colombier close(f->fid);
6293e12c5d1SDavid du Colombier f->fid = -1;
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier
6329a747e4fSDavid du Colombier path = makepath(f->f, "");
6337dd7cddfSDavid du Colombier DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
6343e12c5d1SDavid du Colombier
6353e12c5d1SDavid du Colombier p->canint = 1;
6369a747e4fSDavid du Colombier if(p->flushtag != NOTAG){
6379a747e4fSDavid du Colombier free(path);
6383e12c5d1SDavid du Colombier return;
6399a747e4fSDavid du Colombier }
6403e12c5d1SDavid du Colombier /* There is a race here I ignore because there are no locks */
6413e12c5d1SDavid du Colombier f->fid = open(path, work->mode);
6429a747e4fSDavid du Colombier free(path);
6433e12c5d1SDavid du Colombier p->canint = 0;
6449a747e4fSDavid du Colombier if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
6459a747e4fSDavid du Colombier Error:
6469a747e4fSDavid du Colombier errstr(err, sizeof err);
6479a747e4fSDavid du Colombier reply(work, &rhdr, err);
6483e12c5d1SDavid du Colombier return;
6493e12c5d1SDavid du Colombier }
6509a747e4fSDavid du Colombier f->f->qid = d->qid;
6519a747e4fSDavid du Colombier free(d);
6529a747e4fSDavid du Colombier if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
6539a747e4fSDavid du Colombier f->fid = openmount(f->fid);
6549a747e4fSDavid du Colombier if(f->fid < 0)
6559a747e4fSDavid du Colombier goto Error;
6569a747e4fSDavid du Colombier }
6573e12c5d1SDavid du Colombier
6587dd7cddfSDavid du Colombier DEBUG(DFD, "\topen: fd %d\n", f->fid);
6593e12c5d1SDavid du Colombier f->mode = work->mode;
660a960ed1cSDavid du Colombier f->offset = 0;
6619a747e4fSDavid du Colombier rhdr.iounit = getiounit(f->fid);
6629a747e4fSDavid du Colombier rhdr.qid = f->f->qid;
6639a747e4fSDavid du Colombier reply(work, &rhdr, 0);
6643e12c5d1SDavid du Colombier }
6653e12c5d1SDavid du Colombier
6663e12c5d1SDavid du Colombier void
slaveread(Fsrpc * p)6673e12c5d1SDavid du Colombier slaveread(Fsrpc *p)
6683e12c5d1SDavid du Colombier {
6693e12c5d1SDavid du Colombier Fid *f;
6703e12c5d1SDavid du Colombier int n, r;
6719a747e4fSDavid du Colombier Fcall *work, rhdr;
6729a747e4fSDavid du Colombier char *data, err[ERRMAX];
6733e12c5d1SDavid du Colombier
6743e12c5d1SDavid du Colombier work = &p->work;
6753e12c5d1SDavid du Colombier
6763e12c5d1SDavid du Colombier f = getfid(work->fid);
6773e12c5d1SDavid du Colombier if(f == 0) {
6789a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid);
6793e12c5d1SDavid du Colombier return;
6803e12c5d1SDavid du Colombier }
6813e12c5d1SDavid du Colombier
6829a747e4fSDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
6833e12c5d1SDavid du Colombier p->canint = 1;
6843e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
6853e12c5d1SDavid du Colombier return;
6869a747e4fSDavid du Colombier data = malloc(n);
6879a747e4fSDavid du Colombier if(data == nil)
6889a747e4fSDavid du Colombier fatal(Enomem);
6899a747e4fSDavid du Colombier
6909a747e4fSDavid du Colombier /* can't just call pread, since directories must update the offset */
691a960ed1cSDavid du Colombier if(patternfile != nil && (f->f->qid.type&QTDIR))
692a960ed1cSDavid du Colombier r = preaddir(f, (uchar*)data, n, work->offset);
693a960ed1cSDavid du Colombier else
6949a747e4fSDavid du Colombier r = pread(f->fid, data, n, work->offset);
6953e12c5d1SDavid du Colombier p->canint = 0;
6963e12c5d1SDavid du Colombier if(r < 0) {
6979a747e4fSDavid du Colombier free(data);
6989a747e4fSDavid du Colombier errstr(err, sizeof err);
6999a747e4fSDavid du Colombier reply(work, &rhdr, err);
7003e12c5d1SDavid du Colombier return;
7013e12c5d1SDavid du Colombier }
7023e12c5d1SDavid du Colombier
7037dd7cddfSDavid du Colombier DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
7043e12c5d1SDavid du Colombier
7059a747e4fSDavid du Colombier rhdr.data = data;
7069a747e4fSDavid du Colombier rhdr.count = r;
7079a747e4fSDavid du Colombier reply(work, &rhdr, 0);
7089a747e4fSDavid du Colombier free(data);
7093e12c5d1SDavid du Colombier }
7103e12c5d1SDavid du Colombier
7113e12c5d1SDavid du Colombier void
slavewrite(Fsrpc * p)7123e12c5d1SDavid du Colombier slavewrite(Fsrpc *p)
7133e12c5d1SDavid du Colombier {
7149a747e4fSDavid du Colombier char err[ERRMAX];
7159a747e4fSDavid du Colombier Fcall *work, rhdr;
7163e12c5d1SDavid du Colombier Fid *f;
7173e12c5d1SDavid du Colombier int n;
7183e12c5d1SDavid du Colombier
7193e12c5d1SDavid du Colombier work = &p->work;
7203e12c5d1SDavid du Colombier
7213e12c5d1SDavid du Colombier f = getfid(work->fid);
7223e12c5d1SDavid du Colombier if(f == 0) {
7239a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid);
7243e12c5d1SDavid du Colombier return;
7253e12c5d1SDavid du Colombier }
7263e12c5d1SDavid du Colombier
7279a747e4fSDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
7283e12c5d1SDavid du Colombier p->canint = 1;
7293e12c5d1SDavid du Colombier if(p->flushtag != NOTAG)
7303e12c5d1SDavid du Colombier return;
7319a747e4fSDavid du Colombier n = pwrite(f->fid, work->data, n, work->offset);
7323e12c5d1SDavid du Colombier p->canint = 0;
7333e12c5d1SDavid du Colombier if(n < 0) {
7349a747e4fSDavid du Colombier errstr(err, sizeof err);
7359a747e4fSDavid du Colombier reply(work, &rhdr, err);
7363e12c5d1SDavid du Colombier return;
7373e12c5d1SDavid du Colombier }
7383e12c5d1SDavid du Colombier
7397dd7cddfSDavid du Colombier DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
7403e12c5d1SDavid du Colombier
7419a747e4fSDavid du Colombier rhdr.count = n;
7429a747e4fSDavid du Colombier reply(work, &rhdr, 0);
7433e12c5d1SDavid du Colombier }
7443e12c5d1SDavid du Colombier
7453e12c5d1SDavid du Colombier void
reopen(Fid * f)7463e12c5d1SDavid du Colombier reopen(Fid *f)
7473e12c5d1SDavid du Colombier {
7483e12c5d1SDavid du Colombier USED(f);
7493e12c5d1SDavid du Colombier fatal("reopen");
7503e12c5d1SDavid du Colombier }
7513e12c5d1SDavid du Colombier
7523e12c5d1SDavid du Colombier void
flushaction(void * a,char * cause)7533e12c5d1SDavid du Colombier flushaction(void *a, char *cause)
7543e12c5d1SDavid du Colombier {
7553e12c5d1SDavid du Colombier USED(a);
7563e12c5d1SDavid du Colombier if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
7573e12c5d1SDavid du Colombier fprint(2, "exportsrv: note: %s\n", cause);
7583e12c5d1SDavid du Colombier exits("noted");
7593e12c5d1SDavid du Colombier }
7603e12c5d1SDavid du Colombier if(strncmp(cause, "kill", 4) == 0)
7613e12c5d1SDavid du Colombier noted(NDFLT);
7623e12c5d1SDavid du Colombier
7633e12c5d1SDavid du Colombier noted(NCONT);
7643e12c5d1SDavid du Colombier }
765