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";
20 char Enoprocs[] = "Out of processes";
30 if(t->work.msize < 256){
31 reply(&t->work, &rhdr, "version: message size too small");
35 if(t->work.msize > messagesize)
36 t->work.msize = messagesize;
37 messagesize = t->work.msize;
38 if(strncmp(t->work.version, "9P2000", 6) != 0){
39 reply(&t->work, &rhdr, Eversion);
43 rhdr.version = "9P2000";
44 rhdr.msize = t->work.msize;
45 reply(&t->work, &rhdr, 0);
54 reply(&t->work, &rhdr, "exportfs: authentication not required");
65 for(m = Proclist; m != nil; m = m->next){
67 if(w == nil || w->work.tag != t->work.oldtag)
72 if(w != nil && w->work.tag == t->work.oldtag) {
73 w->flushtag = t->work.tag;
74 DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
75 postnote(PNPROC, m->pid, "flush");
83 reply(&t->work, &rhdr, 0);
84 DEBUG(DFD, "\tflush reply\n");
96 f = newfid(t->work.fid);
98 reply(&t->work, &rhdr, Ebadfid);
106 reply(&t->work, &rhdr, Enopsmt);
107 freefid(t->work.fid);
111 for(i=0; i<Npsmpt; i++)
116 sprint(buf, "%d", i);
117 f->f = file(psmpt, buf);
120 sprint(buf, "/mnt/exportfs/%d", i);
121 nfd = dup(srvfd, -1);
122 if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
123 errstr(buf, sizeof buf);
124 reply(&t->work, &rhdr, buf);
125 freefid(t->work.fid);
137 rhdr.qid = f->f->qid;
138 reply(&t->work, &rhdr, 0);
143 clonefid(Fid *f, int new)
151 fatal("inconsistent fids");
157 fatal("inconsistent fids2");
167 char err[ERRMAX], *e;
173 f = getfid(t->work.fid);
175 reply(&t->work, &rhdr, Ebadfid);
181 if(t->work.newfid != t->work.fid){
182 nf = clonefid(f, t->work.newfid);
188 for(i=0; i<t->work.nwname; i++){
190 e = "Too many path elements";
194 if(strcmp(t->work.wname[i], "..") == 0) {
195 if(f->f->parent == nil) {
204 wf = file(f->f, t->work.wname[i]);
206 errstr(err, sizeof err);
212 rhdr.wqid[rhdr.nwqid++] = wf->qid;
217 if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
218 freefid(t->work.newfid);
221 reply(&t->work, &rhdr, e);
231 f = getfid(t->work.fid);
233 reply(&t->work, &rhdr, Ebadfid);
241 freefid(t->work.fid);
242 reply(&t->work, &rhdr, 0);
249 char err[ERRMAX], *path;
256 f = getfid(t->work.fid);
258 reply(&t->work, &rhdr, Ebadfid);
263 d = dirfstat(f->fid);
265 path = makepath(f->f, "");
271 errstr(err, sizeof err);
272 reply(&t->work, &rhdr, err);
277 d->qid.path = f->f->qidt->uniqpath;
279 statbuf = emallocz(s);
280 s = convD2M(d, statbuf, s);
284 reply(&t->work, &rhdr, 0);
295 if(n > messagesize-IOHDRSZ)
296 n = messagesize-IOHDRSZ;
303 char err[ERRMAX], *path;
309 reply(&t->work, &rhdr, Ereadonly);
313 f = getfid(t->work.fid);
315 reply(&t->work, &rhdr, Ebadfid);
321 path = makepath(f->f, t->work.name);
322 f->fid = create(path, t->work.mode, t->work.perm);
325 errstr(err, sizeof err);
326 reply(&t->work, &rhdr, err);
331 nf = file(f->f, t->work.name);
333 errstr(err, sizeof err);
334 reply(&t->work, &rhdr, err);
339 f->mode = t->work.mode;
342 rhdr.qid = f->f->qid;
343 rhdr.iounit = getiounit(f->fid);
344 reply(&t->work, &rhdr, 0);
351 char err[ERRMAX], *path;
356 reply(&t->work, &rhdr, Ereadonly);
360 f = getfid(t->work.fid);
362 reply(&t->work, &rhdr, Ebadfid);
367 path = makepath(f->f, "");
368 DEBUG(DFD, "\tremove: %s\n", path);
369 if(remove(path) < 0) {
371 errstr(err, sizeof err);
372 reply(&t->work, &rhdr, err);
381 freefid(t->work.fid);
383 reply(&t->work, &rhdr, 0);
390 char err[ERRMAX], *path;
398 reply(&t->work, &rhdr, Ereadonly);
402 f = getfid(t->work.fid);
404 reply(&t->work, &rhdr, Ebadfid);
408 strings = emallocz(t->work.nstat); /* ample */
409 if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
410 rerrstr(err, sizeof err);
411 reply(&t->work, &rhdr, err);
418 s = dirfwstat(f->fid, &d);
420 path = makepath(f->f, "");
421 s = dirwstat(path, &d);
425 rerrstr(err, sizeof err);
426 reply(&t->work, &rhdr, err);
429 /* wstat may really be rename */
430 if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
432 f->f->name = estrdup(d.name);
434 reply(&t->work, &rhdr, 0);
449 switch(f->work.type){
451 reply(&f->work, &rhdr, Ereadonly);
455 if((f->work.mode&3) == OWRITE || (f->work.mode&(OTRUNC|ORCLOSE))){
456 reply(&f->work, &rhdr, Ereadonly);
463 for(l = &Proclist; (m = *l) != nil; l = &m->next) {
468 while(rendezvous(m, f) == (void*)~0)
471 /* swept a slave proc */
481 * as long as the number of slave procs
482 * is small, dont bother sweeping.
490 m = emallocz(sizeof(Proc));
491 pid = rfork(RFPROC|RFMEM|RFNOWAIT);
494 reply(&f->work, &rhdr, Enoprocs);
500 if (local[0] != '\0')
501 if (netdir[0] != '\0')
502 procsetname("%s: %s -> %s", netdir,
505 procsetname("%s -> %s", local, remote);
519 blockingslave(Proc *m)
527 p = rendezvous(m, nil);
528 if(p == (void*)~0) /* Interrupted */
530 if(p == nil) /* Swept */
533 DEBUG(DFD, "\tslave: %d %F\n", m->pid, &p->work);
534 if(p->flushtag != NOTAG)
537 switch(p->work.type) {
551 reply(&p->work, &rhdr, "exportfs: slave type error");
558 /* no more flushes can come in now */
559 if(p->flushtag != NOTAG) {
560 p->work.type = Tflush;
561 p->work.tag = p->flushtag;
562 reply(&p->work, &rhdr, 0);
572 char *arg[10], fdbuf[20], mbuf[20];
578 switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG|RFREND)){
596 /* close all remaining file descriptors except sfd */
597 if((fd = open("/fd", OREAD)) < 0)
598 _exits("open /fd failed");
599 n = dirreadall(fd, &dir);
601 if(strstr(dir[i].name, "ctl"))
603 fd = atoi(dir[i].name);
604 if(fd > 2 && fd != sfd)
609 arg[0] = argv0; /* "/bin/exportfs" */
610 snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);
612 snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);
617 arg[0] = "/bin/exportfs";
619 _exits("whoops: exec failed");
626 char err[ERRMAX], *path;
633 f = getfid(work->fid);
635 reply(work, &rhdr, Ebadfid);
643 path = makepath(f->f, "");
644 DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
645 f->fid = open(path, work->mode);
647 if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
649 errstr(err, sizeof err);
650 reply(work, &rhdr, err);
655 if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
656 f->fid = openmount(f->fid);
661 DEBUG(DFD, "\topen: fd %d\n", f->fid);
662 f->mode = work->mode;
664 rhdr.iounit = getiounit(f->fid);
665 rhdr.qid = f->f->qid;
666 reply(work, &rhdr, 0);
675 char *data, err[ERRMAX];
679 f = getfid(work->fid);
681 reply(work, &rhdr, Ebadfid);
685 n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
688 reply(work, &rhdr, Enomem);
692 /* can't just call pread, since directories must update the offset */
693 if(patternfile != nil && (f->f->qid.type&QTDIR))
694 r = preaddir(f, (uchar*)data, n, work->offset);
696 r = pread(f->fid, data, n, work->offset);
699 errstr(err, sizeof err);
700 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;
728 n = pwrite(f->fid, work->data, n, work->offset);
730 errstr(err, sizeof err);
731 reply(work, &rhdr, err);
735 DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
738 reply(work, &rhdr, 0);
749 flushaction(void *a, char *cause)
752 if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
753 fprint(2, "exportsrv: note: %s\n", cause);
756 if(strncmp(cause, "kill", 4) == 0)