8 char Ebadfid[] = "Bad fid";
9 char Enotdir[] = "Not a directory";
10 char Edupfid[] = "Fid already in use";
11 char Eopen[] = "Fid already opened";
12 char Exmnt[] = "Cannot .. past mount point";
13 char Emip[] = "Mount in progress";
14 char Enopsmt[] = "Out of pseudo mount points";
15 char Enomem[] = "No memory";
16 char Ereadonly[] = "File system read only";
17 char Enoprocs[] = "Out of processes";
27 if(t->work.msize < 256){
28 reply(&t->work, &rhdr, "version: message size too small");
32 if(t->work.msize > messagesize)
33 t->work.msize = messagesize;
34 messagesize = t->work.msize;
35 rhdr.msize = t->work.msize;
36 rhdr.version = "9P2000";
37 if(strncmp(t->work.version, "9P", 2) != 0)
38 rhdr.version = "unknown";
39 reply(&t->work, &rhdr, 0);
48 reply(&t->work, &rhdr, "exportfs: authentication not required");
59 for(m = Proclist; m != nil; m = m->next){
61 if(w == nil || w->work.tag != t->work.oldtag)
66 if(w != nil && w->work.tag == t->work.oldtag) {
67 w->flushtag = t->work.tag;
68 DEBUG(2, "\tset flushtag %d\n", t->work.tag);
69 postnote(PNPROC, m->pid, "flush");
77 reply(&t->work, &rhdr, 0);
78 DEBUG(2, "\tflush reply\n");
90 f = newfid(t->work.fid);
92 reply(&t->work, &rhdr, Ebadfid);
100 reply(&t->work, &rhdr, Enopsmt);
101 freefid(t->work.fid);
105 for(i=0; i<Npsmpt; i++)
110 sprint(buf, "%d", i);
111 f->f = file(psmpt, buf);
114 sprint(buf, "/mnt/exportfs/%d", i);
115 nfd = dup(srvfd, -1);
116 if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) == -1){
117 errstr(buf, sizeof buf);
118 reply(&t->work, &rhdr, buf);
119 freefid(t->work.fid);
131 rhdr.qid = f->f->qid;
132 reply(&t->work, &rhdr, 0);
137 clonefid(Fid *f, int new)
145 fatal("inconsistent fids");
151 fatal("inconsistent fids2");
161 char err[ERRMAX], *e;
167 f = getfid(t->work.fid);
169 reply(&t->work, &rhdr, Ebadfid);
175 if(t->work.newfid != t->work.fid){
176 nf = clonefid(f, t->work.newfid);
182 for(i=0; i<t->work.nwname; i++){
184 e = "Too many path elements";
188 if(strcmp(t->work.wname[i], "..") == 0) {
189 if(f->f->parent == nil) {
198 wf = file(f->f, t->work.wname[i]);
200 errstr(err, sizeof err);
206 rhdr.wqid[rhdr.nwqid++] = wf->qid;
211 if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
212 freefid(t->work.newfid);
215 reply(&t->work, &rhdr, e);
225 f = getfid(t->work.fid);
227 reply(&t->work, &rhdr, Ebadfid);
235 freefid(t->work.fid);
236 reply(&t->work, &rhdr, 0);
243 char err[ERRMAX], *path;
250 f = getfid(t->work.fid);
252 reply(&t->work, &rhdr, Ebadfid);
257 d = dirfstat(f->fid);
259 path = makepath(f->f, "");
265 errstr(err, sizeof err);
266 reply(&t->work, &rhdr, err);
271 d->qid.path = f->f->qidt->uniqpath;
273 statbuf = emallocz(s);
274 s = convD2M(d, statbuf, s);
278 reply(&t->work, &rhdr, 0);
289 if(n > messagesize-IOHDRSZ)
290 n = messagesize-IOHDRSZ;
297 char err[ERRMAX], *path;
303 reply(&t->work, &rhdr, Ereadonly);
307 f = getfid(t->work.fid);
309 reply(&t->work, &rhdr, Ebadfid);
315 path = makepath(f->f, t->work.name);
316 f->fid = create(path, t->work.mode, t->work.perm);
319 errstr(err, sizeof err);
320 reply(&t->work, &rhdr, err);
325 nf = file(f->f, t->work.name);
327 errstr(err, sizeof err);
328 reply(&t->work, &rhdr, err);
333 f->mode = t->work.mode;
336 rhdr.qid = f->f->qid;
337 rhdr.iounit = getiounit(f->fid);
338 reply(&t->work, &rhdr, 0);
345 char err[ERRMAX], *path;
350 reply(&t->work, &rhdr, Ereadonly);
354 f = getfid(t->work.fid);
356 reply(&t->work, &rhdr, Ebadfid);
361 path = makepath(f->f, "");
362 DEBUG(2, "\tremove: %s\n", path);
363 if(remove(path) < 0) {
365 errstr(err, sizeof err);
366 reply(&t->work, &rhdr, err);
375 freefid(t->work.fid);
377 reply(&t->work, &rhdr, 0);
384 char err[ERRMAX], *path;
392 reply(&t->work, &rhdr, Ereadonly);
396 f = getfid(t->work.fid);
398 reply(&t->work, &rhdr, Ebadfid);
402 strings = emallocz(t->work.nstat); /* ample */
403 if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
404 rerrstr(err, sizeof err);
405 reply(&t->work, &rhdr, err);
412 s = dirfwstat(f->fid, &d);
414 path = makepath(f->f, "");
415 s = dirwstat(path, &d);
419 rerrstr(err, sizeof err);
420 reply(&t->work, &rhdr, err);
423 /* wstat may really be rename */
424 if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
426 f->f->name = estrdup(d.name);
428 reply(&t->work, &rhdr, 0);
443 switch(f->work.type){
445 reply(&f->work, &rhdr, Ereadonly);
449 if((f->work.mode&3) == OWRITE || (f->work.mode&(OTRUNC|ORCLOSE))){
450 reply(&f->work, &rhdr, Ereadonly);
457 for(l = &Proclist; (m = *l) != nil; l = &m->next) {
462 while(rendezvous(m, f) == (void*)~0)
465 /* swept a slave proc */
475 * as long as the number of slave procs
476 * is small, dont bother sweeping.
484 m = emallocz(sizeof(Proc));
485 pid = rfork(RFPROC|RFMEM|RFNOWAIT);
488 reply(&f->work, &rhdr, Enoprocs);
507 blockingslave(Proc *m)
515 p = rendezvous(m, nil);
516 if(p == (void*)~0) /* Interrupted */
518 if(p == nil) /* Swept */
521 DEBUG(2, "\tslave: %d %F\n", m->pid, &p->work);
522 if(p->flushtag != NOTAG)
525 switch(p->work.type) {
539 reply(&p->work, &rhdr, "exportfs: slave type error");
546 /* no more flushes can come in now */
547 if(p->flushtag != NOTAG) {
548 p->work.type = Tflush;
549 p->work.tag = p->flushtag;
550 reply(&p->work, &rhdr, 0);
560 char *arg[10], fdbuf[20], mbuf[20];
566 switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG|RFREND)){
584 /* close all remaining file descriptors except sfd */
585 if((fd = open("/fd", OREAD)) < 0)
586 _exits("open /fd failed");
587 n = dirreadall(fd, &dir);
589 if(strstr(dir[i].name, "ctl"))
591 fd = atoi(dir[i].name);
592 if(fd > 2 && fd != sfd)
597 arg[0] = argv0; /* "/bin/exportfs" */
598 snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);
600 snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);
605 arg[0] = "/bin/exportfs";
607 _exits("whoops: exec failed");
614 char err[ERRMAX], *path;
621 f = getfid(work->fid);
623 reply(work, &rhdr, Ebadfid);
631 path = makepath(f->f, "");
632 DEBUG(2, "\topen: %s %d\n", path, work->mode);
633 f->fid = open(path, work->mode);
635 if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
637 errstr(err, sizeof err);
638 reply(work, &rhdr, err);
643 if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
644 f->fid = openmount(f->fid);
649 DEBUG(2, "\topen: fd %d\n", f->fid);
650 f->mode = work->mode;
652 rhdr.iounit = getiounit(f->fid);
653 rhdr.qid = f->f->qid;
654 reply(work, &rhdr, 0);
663 char *data, err[ERRMAX];
667 f = getfid(work->fid);
669 reply(work, &rhdr, Ebadfid);
673 n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
676 reply(work, &rhdr, Enomem);
680 /* can't just call pread, since directories must update the offset */
681 if(patternfile != nil && (f->f->qid.type&QTDIR))
682 r = preaddir(f, (uchar*)data, n, work->offset);
684 r = pread(f->fid, data, n, work->offset);
687 errstr(err, sizeof err);
688 reply(work, &rhdr, err);
691 DEBUG(2, "\tread: fd=%d %d bytes\n", f->fid, r);
695 reply(work, &rhdr, 0);
709 f = getfid(work->fid);
711 reply(work, &rhdr, Ebadfid);
715 n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
716 n = pwrite(f->fid, work->data, n, work->offset);
718 errstr(err, sizeof err);
719 reply(work, &rhdr, err);
723 DEBUG(2, "\twrite: %d bytes fd=%d\n", n, f->fid);
726 reply(work, &rhdr, 0);
737 flushaction(void *a, char *cause)
740 if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
741 fprint(2, "exportsrv: note: %s\n", cause);
744 if(strncmp(cause, "kill", 4) == 0)