8 extern char *netdir, *local, *remote;
10 char Ebadfid[] = "Bad fid";
11 char Enotdir[] = "Not a directory";
12 char Edupfid[] = "Fid already in use";
13 char Eopen[] = "Fid already opened";
14 char Exmnt[] = "Cannot .. past mount point";
15 char Emip[] = "Mount in progress";
16 char Enopsmt[] = "Out of pseudo mount points";
17 char Enomem[] = "No memory";
18 char Eversion[] = "Bad 9P2000 version";
19 char Ereadonly[] = "File system read only";
29 if(t->work.msize > messagesize)
30 t->work.msize = messagesize;
31 messagesize = t->work.msize;
32 if(strncmp(t->work.version, "9P2000", 6) != 0){
33 reply(&t->work, &rhdr, Eversion);
36 rhdr.version = "9P2000";
37 rhdr.msize = t->work.msize;
38 reply(&t->work, &rhdr, 0);
47 reply(&t->work, &rhdr, "exportfs: authentication not required");
57 e = &Workq[Nr_workbufs];
59 for(w = Workq; w < e; w++) {
60 if(w->work.tag == t->work.oldtag) {
61 DEBUG(DFD, "\tQ busy %d pid %p can %d\n", w->busy, w->pid, w->canint);
62 if(w->busy && w->pid) {
63 w->flushtag = t->work.tag;
64 DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
66 postnote(PNPROC, w->pid, "flush");
73 reply(&t->work, &rhdr, 0);
74 DEBUG(DFD, "\tflush reply\n");
86 f = newfid(t->work.fid);
88 reply(&t->work, &rhdr, Ebadfid);
96 reply(&t->work, &rhdr, Enopsmt);
101 for(i=0; i<Npsmpt; i++)
106 sprint(buf, "%d", i);
107 f->f = file(psmpt, buf);
110 sprint(buf, "/mnt/exportfs/%d", i);
111 nfd = dup(srvfd, -1);
112 if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
113 errstr(buf, sizeof buf);
114 reply(&t->work, &rhdr, buf);
116 freefid(t->work.fid);
127 rhdr.qid = f->f->qid;
128 reply(&t->work, &rhdr, 0);
133 clonefid(Fid *f, int new)
141 fatal("inconsistent fids");
147 fatal("inconsistent fids2");
157 char err[ERRMAX], *e;
163 f = getfid(t->work.fid);
165 reply(&t->work, &rhdr, Ebadfid);
171 if(t->work.newfid != t->work.fid){
172 nf = clonefid(f, t->work.newfid);
178 for(i=0; i<t->work.nwname; i++){
180 e = "Too many path elements";
184 if(strcmp(t->work.wname[i], "..") == 0) {
185 if(f->f->parent == nil) {
194 wf = file(f->f, t->work.wname[i]);
196 errstr(err, sizeof err);
202 rhdr.wqid[rhdr.nwqid++] = wf->qid;
207 if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
208 freefid(t->work.newfid);
211 reply(&t->work, &rhdr, e);
221 f = getfid(t->work.fid);
223 reply(&t->work, &rhdr, Ebadfid);
231 freefid(t->work.fid);
232 reply(&t->work, &rhdr, 0);
239 char err[ERRMAX], *path;
246 f = getfid(t->work.fid);
248 reply(&t->work, &rhdr, Ebadfid);
253 d = dirfstat(f->fid);
255 path = makepath(f->f, "");
261 errstr(err, sizeof err);
262 reply(&t->work, &rhdr, err);
267 d->qid.path = f->f->qidt->uniqpath;
269 statbuf = emallocz(s);
270 s = convD2M(d, statbuf, s);
274 reply(&t->work, &rhdr, 0);
285 if(n > messagesize-IOHDRSZ)
286 n = messagesize-IOHDRSZ;
293 char err[ERRMAX], *path;
299 reply(&t->work, &rhdr, Ereadonly);
303 f = getfid(t->work.fid);
305 reply(&t->work, &rhdr, Ebadfid);
311 path = makepath(f->f, t->work.name);
312 f->fid = create(path, t->work.mode, t->work.perm);
315 errstr(err, sizeof err);
316 reply(&t->work, &rhdr, err);
321 nf = file(f->f, t->work.name);
323 errstr(err, sizeof err);
324 reply(&t->work, &rhdr, err);
329 f->mode = t->work.mode;
332 rhdr.qid = f->f->qid;
333 rhdr.iounit = getiounit(f->fid);
334 reply(&t->work, &rhdr, 0);
341 char err[ERRMAX], *path;
346 reply(&t->work, &rhdr, Ereadonly);
350 f = getfid(t->work.fid);
352 reply(&t->work, &rhdr, Ebadfid);
357 path = makepath(f->f, "");
358 DEBUG(DFD, "\tremove: %s\n", path);
359 if(remove(path) < 0) {
361 errstr(err, sizeof err);
362 reply(&t->work, &rhdr, err);
371 freefid(t->work.fid);
373 reply(&t->work, &rhdr, 0);
380 char err[ERRMAX], *path;
388 reply(&t->work, &rhdr, Ereadonly);
392 f = getfid(t->work.fid);
394 reply(&t->work, &rhdr, Ebadfid);
398 strings = emallocz(t->work.nstat); /* ample */
399 if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
400 rerrstr(err, sizeof err);
401 reply(&t->work, &rhdr, err);
408 s = dirfwstat(f->fid, &d);
410 path = makepath(f->f, "");
411 s = dirwstat(path, &d);
415 rerrstr(err, sizeof err);
416 reply(&t->work, &rhdr, err);
419 /* wstat may really be rename */
420 if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
422 f->f->name = estrdup(d.name);
424 reply(&t->work, &rhdr, 0);
431 * based on libthread's threadsetname, but drags in less library code.
432 * actually just sets the arguments displayed.
435 procsetname(char *fmt, ...)
443 cmdname = vsmprint(fmt, arg);
447 snprint(buf, sizeof buf, "#p/%d/args", getpid());
448 if((fd = open(buf, OWRITE)) >= 0){
449 write(fd, cmdname, strlen(cmdname)+1);
464 switch(f->work.type){
466 reply(&f->work, &rhdr, Ereadonly);
470 if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){
471 reply(&f->work, &rhdr, Ereadonly);
478 for(p = Proclist; p; p = p->next) {
482 pid = (uintptr)rendezvous((void*)p->pid, f);
484 fatal("rendezvous sync fail");
489 if(++nproc > MAXPROC)
490 fatal("too many procs");
492 pid = rfork(RFPROC|RFMEM);
498 if (local[0] != '\0')
499 if (netdir[0] != '\0')
500 procsetname("%s: %s -> %s", netdir,
503 procsetname("%s -> %s", local, remote);
508 p = malloc(sizeof(Proc));
510 fatal("out of memory");
517 rendezvous((void*)pid, p);
534 m = rendezvous((void*)pid, 0);
537 p = rendezvous((void*)pid, (void*)pid);
538 if(p == (void*)~0) /* Interrupted */
541 DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
542 if(p->flushtag != NOTAG)
545 switch(p->work.type) {
559 reply(&p->work, &rhdr, "exportfs: slave type error");
561 if(p->flushtag != NOTAG) {
563 p->work.type = Tflush;
564 p->work.tag = p->flushtag;
565 reply(&p->work, &rhdr, 0);
576 char *arg[10], fdbuf[20], mbuf[20];
581 switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){
597 snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);
599 snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);
607 exec("/bin/exportfs", arg);
608 _exits("whoops: exec failed");
615 char err[ERRMAX], *path;
622 f = getfid(work->fid);
624 reply(work, &rhdr, Ebadfid);
632 path = makepath(f->f, "");
633 DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
636 if(p->flushtag != NOTAG){
640 /* There is a race here I ignore because there are no locks */
641 f->fid = open(path, work->mode);
644 if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
646 errstr(err, sizeof err);
647 reply(work, &rhdr, err);
652 if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
653 f->fid = openmount(f->fid);
658 DEBUG(DFD, "\topen: fd %d\n", f->fid);
659 f->mode = work->mode;
661 rhdr.iounit = getiounit(f->fid);
662 rhdr.qid = f->f->qid;
663 reply(work, &rhdr, 0);
672 char *data, err[ERRMAX];
676 f = getfid(work->fid);
678 reply(work, &rhdr, Ebadfid);
682 n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
684 if(p->flushtag != NOTAG)
690 /* can't just call pread, since directories must update the offset */
691 if(patternfile != nil && (f->f->qid.type&QTDIR))
692 r = preaddir(f, (uchar*)data, n, work->offset);
694 r = pread(f->fid, data, n, work->offset);
698 errstr(err, sizeof err);
699 reply(work, &rhdr, err);
703 DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
707 reply(work, &rhdr, 0);
721 f = getfid(work->fid);
723 reply(work, &rhdr, Ebadfid);
727 n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
729 if(p->flushtag != NOTAG)
731 n = pwrite(f->fid, work->data, n, work->offset);
734 errstr(err, sizeof err);
735 reply(work, &rhdr, err);
739 DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
742 reply(work, &rhdr, 0);
753 flushaction(void *a, char *cause)
756 if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
757 fprint(2, "exportsrv: note: %s\n", cause);
760 if(strncmp(cause, "kill", 4) == 0)