5 #define convM2Su(a, b, c, d) convM2S(a, b, c)
6 #define convS2Mu(a, b, c, d) convS2M(a, b, c)
7 #define convM2Du(a, b, c, d) convM2D(a, b, c)
8 #define convD2Mu(a, b, c, d) convD2M(a, b, c)
10 typedef struct Fid Fid;
14 Stacksize = 320 * 1024, /* was 32K */
15 OPERM = 0x3 /* mask of all permission types in open mode */
45 uchar mdata[8192+IOHDRSZ];
46 int messagesize = sizeof mdata;
58 void vacshutdown(void);
61 int permf(VacFile*, char*, int);
63 void init(char*, char*, long, int);
64 int vacdirread(Fid *f, char *p, long off, long cnt);
65 int vacstat(VacFile *parent, VacDir *vd, uchar *p, int np);
69 char *rflush(Fid*), *rversion(Fid*),
70 *rauth(Fid*), *rattach(Fid*), *rwalk(Fid*),
71 *ropen(Fid*), *rcreate(Fid*),
72 *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
73 *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
75 char *(*fcalls[Tmax])(Fid*);
80 fcalls[Tflush]= rflush;
81 fcalls[Tversion]= rversion;
82 fcalls[Tattach]= rattach;
86 fcalls[Tcreate]= rcreate;
88 fcalls[Twrite]= rwrite;
89 fcalls[Tclunk]= rclunk;
90 fcalls[Tremove]= rremove;
92 fcalls[Twstat]= rwstat;
95 char Eperm[] = "permission denied";
96 char Enotdir[] = "not a directory";
97 char Enotexist[] = "file does not exist";
98 char Einuse[] = "file in use";
99 char Eexist[] = "file exists";
100 char Enotowner[] = "not owner";
101 char Eisopen[] = "file already open for I/O";
102 char Excl[] = "exclusive use file already open";
103 char Ename[] = "illegal name";
104 char Erdonly[] = "read only file system";
105 char Eio[] = "i/o error";
106 char Eempty[] = "directory is not empty";
107 char Emode[] = "illegal mode";
112 notifyf(void *a, char *s)
115 if(strncmp(s, "interrupt", 9) == 0)
121 threadmain(int argc, char *argv[])
123 char *defsrv, *srvname;
131 fmtinstall('H', encodefmt);
132 fmtinstall('V', vtscorefmt);
133 fmtinstall('F', vtfcallfmt);
139 fmtinstall('F', fcallfmt);
143 ncache = atoi(EARGF(usage()));
152 host = EARGF(usage());
155 defsrv = EARGF(usage());
161 defmnt = EARGF(usage());
176 if(defsrv == nil && defmnt == nil && !stdio)
179 sysfatal("cannot use -m with -i");
188 sysfatal("could not connect to server: %r");
190 if(vtconnect(conn) < 0)
191 sysfatal("vtconnect: %r");
193 fs = vacfsopen(conn, argv[0], VtOREAD, ncache);
195 sysfatal("vacfsopen: %r");
199 sysfatal("pipe failed: %r");
204 srvname = smprint("/srv/%s", defsrv);
205 fd = create(srvname, OWRITE|ORCLOSE, 0666);
207 sysfatal("create %s: %r", srvname);
208 if(fprint(fd, "%d", srvfd) < 0)
209 sysfatal("write %s: %r", srvname);
214 procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG);
219 if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
220 sysfatal("mount %s: %r", defmnt);
237 fprint(2, "usage: %s [-sd] [-h host] [-c ncache] [-m mountpoint] vacfile\n", argv0);
238 threadexitsall("usage");
242 rversion(Fid *unused)
248 for(f = fids; f; f = f->next)
253 return vtstrdup("version: message size too small");
254 messagesize = rhdr.msize;
255 if(messagesize > sizeof mdata)
256 messagesize = sizeof mdata;
257 thdr.msize = messagesize;
258 if(strncmp(rhdr.version, "9P2000", 6) != 0)
259 return vtstrdup("unrecognized 9P version");
260 thdr.version = "9P2000";
261 if(strncmp(rhdr.version, "9P2000.u", 8) == 0){
263 thdr.version = "9P2000.u";
279 return vtstrdup("vacfs: authentication not required");
285 /* no authentication for the momment */
289 file = vacfsgetroot(fs);
291 rerrstr(err, sizeof err);
292 return vtstrdup(err);
297 f->qid.path = vacfilegetid(f->file);
302 f->user = vtstrdup(rhdr.uname);
311 VacFile *file, *nfile;
320 if(rhdr.fid != rhdr.newfid){
322 return vtstrdup(Eisopen);
324 return vtstrdup(Enotexist);
325 nf = newfid(rhdr.newfid);
327 return vtstrdup(Eisopen);
331 nf->file = vacfileincref(f->file);
332 nf->user = vtstrdup(f->user);
336 nwname = rhdr.nwname;
348 for(nqid = 0; nqid < nwname; nqid++){
349 if((qid.type & QTDIR) == 0){
353 if(!permf(file, f->user, Pexec)) {
357 nfile = vacfilewalk(file, rhdr.wname[nqid]);
363 if(vacfileisdir(file))
365 qid.vers = vacfilegetmcount(file);
366 qid.path = vacfilegetid(file);
367 thdr.wqid[nqid] = qid;
374 f->qid = thdr.wqid[nqid-1];
375 vacfiledecref(f->file);
384 /* only error on the first element */
386 return vtstrdup(err);
397 return vtstrdup(Eisopen);
399 return vtstrdup(Enotexist);
402 thdr.iounit = messagesize - IOHDRSZ;
403 if(f->qid.type & QTDIR){
405 return vtstrdup(Eperm);
407 return vtstrdup(Eperm);
414 return vtstrdup(Erdonly);
415 trunc = mode & OTRUNC;
417 if(mode==OWRITE || mode==ORDWR || trunc)
419 return vtstrdup(Eperm);
420 if(mode==OREAD || mode==ORDWR)
422 return vtstrdup(Eperm);
425 return vtstrdup(Eperm);
427 thdr.iounit = messagesize - IOHDRSZ;
439 return vtstrdup(Eisopen);
441 return vtstrdup(Enotexist);
442 if(fs->mode & ModeSnapshot)
443 return vtstrdup(Erdonly);
445 if(!vacfileisdir(vf))
446 return vtstrdup(Enotdir);
447 if(!permf(vf, fid->user, Pwrite))
448 return vtstrdup(Eperm);
450 mode = rhdr.perm & 0777;
452 if(rhdr.perm & DMDIR){
453 if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND))
454 return vtstrdup(Emode);
455 switch(rhdr.mode & OPERM){
457 return vtstrdup(Emode);
463 return vtstrdup(Eperm);
467 vf = vacfilecreate(vf, rhdr.name, mode);
470 rerrstr(err, sizeof err);
472 return vtstrdup(err);
475 vacfiledecref(fid->file);
478 fid->qid.type = QTFILE;
480 fid->qid.type = QTDIR;
481 fid->qid.vers = vacfilegetmcount(vf);
482 fid->qid.path = vacfilegetid(vf);
485 thdr.iounit = messagesize - IOHDRSZ;
501 return vtstrdup(Enotexist);
507 if(f->qid.type & QTDIR)
508 n = vacdirread(f, buf, off, cnt);
509 else if(vacfilegetmode(f->file)&ModeDevice)
510 return vtstrdup("device");
511 else if(vacfilegetmode(f->file)&ModeLink)
512 return vtstrdup("symbolic link");
513 else if(vacfilegetmode(f->file)&ModeNamedPipe)
514 return vtstrdup("named pipe");
516 n = vacfileread(vf, buf, cnt, off);
518 rerrstr(err, sizeof err);
519 return vtstrdup(err);
529 return vtstrdup(Erdonly);
540 vacfiledecref(f->file);
555 return vtstrdup(Enotexist);
557 vfp = vacfilegetparent(vf);
559 if(!permf(vfp, f->user, Pwrite)) {
564 if(!vacfileremove(vf)) {
565 rerrstr(errbuf, sizeof errbuf);
572 return vtstrdup(err);
579 static uchar statbuf[1024];
583 return vtstrdup(Enotexist);
584 parent = vacfilegetparent(f->file);
585 vacfilegetdir(f->file, &dir);
587 thdr.nstat = vacstat(parent, &dir, thdr.stat, sizeof statbuf);
589 vacfiledecref(parent);
597 return vtstrdup(Enotexist);
598 return vtstrdup(Erdonly);
602 vacstat(VacFile *parent, VacDir *vd, uchar *p, int np)
607 memset(&dir, 0, sizeof(dir));
609 dir.qid.path = vd->qid + vacfilegetqidoffset(parent);
611 dir.qid.path += vd->qidoffset;
612 dir.qid.vers = vd->mcount;
613 dir.mode = vd->mode & 0777;
614 if(vd->mode & ModeAppend){
615 dir.qid.type |= QTAPPEND;
616 dir.mode |= DMAPPEND;
618 if(vd->mode & ModeExclusive){
619 dir.qid.type |= QTEXCL;
622 if(vd->mode & ModeDir){
623 dir.qid.type |= QTDIR;
628 dir.atime = vd->atime;
629 dir.mtime = vd->mtime;
630 dir.length = vd->size;
637 ret = convD2Mu(&dir, p, np, dotu);
642 vacdirread(Fid *f, char *p, long off, long cnt)
648 * special case of rewinding a directory
649 * otherwise ignore the offset
651 if(off == 0 && f->vde){
657 f->vde = vdeopen(f->file);
662 for(nb = 0; nb < cnt; nb += n) {
663 i = vderead(f->vde, &vd);
668 n = vacstat(f->file, &vd, (uchar*)p, cnt-nb);
685 for(f = fids; f; f = f->next)
688 else if(!ff && !f->busy)
694 f = vtmallocz(sizeof *f);
708 n = read9pmsg(mfd[0], mdata, sizeof mdata);
713 if(convM2Su(mdata, n, &rhdr, dotu) != n)
714 sysfatal("convM2S conversion error");
717 fprint(2, "vacfs:<-%F\n", &rhdr);
719 thdr.data = (char*)mdata + IOHDRSZ;
720 if(!fcalls[rhdr.type])
721 err = "bad fcall type";
723 err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
728 thdr.type = rhdr.type + 1;
733 fprint(2, "vacfs:->%F\n", &thdr);
734 n = convS2Mu(&thdr, mdata, messagesize, dotu);
736 sysfatal("convS2Mu conversion error");
740 if(write(mfd[1], mdata, n) != n)
741 sysfatal("mount write: %r");
746 permf(VacFile *vf, char *user, int p)
751 if(vacfilegetdir(vf, &dir))
753 perm = dir.mode & 0777;
757 if((p*Pother) & perm)
759 if(strcmp(user, dir.gid)==0 && ((p*Pgroup) & perm))
761 if(strcmp(user, dir.uid)==0 && ((p*Powner) & perm))
773 return permf(f->file, f->user, p);
781 for(f = fids; f; f = f->next) {