11 uchar mdata[Maxbuf+IOHDRSZ];
12 int messagesize = Maxbuf+IOHDRSZ;
19 int blocksize; /* for 32v */
21 int newtap; /* tap with time in sec */
25 int ramstat(Ram*, uchar*, int);
30 char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
31 *rattach(Fid*), *rwalk(Fid*),
32 *ropen(Fid*), *rcreate(Fid*),
33 *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
34 *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
36 char *(*fcalls[])(Fid*) = {
52 char Eperm[] = "permission denied";
53 char Enotdir[] = "not a directory";
54 char Enoauth[] = "tapefs: authentication not required";
55 char Enotexist[] = "file does not exist";
56 char Einuse[] = "file in use";
57 char Eexist[] = "file exists";
58 char Enotowner[] = "not owner";
59 char Eisopen[] = "file already open for I/O";
60 char Excl[] = "exclusive use file already open";
61 char Ename[] = "illegal name";
64 notifyf(void *a, char *s)
67 if(strncmp(s, "interrupt", 9) == 0)
73 main(int argc, char *argv[])
80 fmtinstall('F', fcallfmt);
85 defmnt = EARGF(usage());
87 case 'p': /* password file */
88 uidmap = getpass(EARGF(usage()));
90 case 'g': /* group file */
91 gidmap = getpass(EARGF(usage()));
100 blocksize = atoi(EARGF(usage()));
107 error("no file to mount");
111 ram = r = (Ram *)emalloc(sizeof(Ram));
115 r->perm = DMDIR | 0775;
127 r->name = estrdup(".");
129 r->replete |= replete;
131 error("pipe failed");
132 mfd[0] = mfd[1] = p[0];
135 switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
144 close(p[0]); /* don't deadlock if child fails */
145 if(mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0) {
146 sprint(buf, "mount on `%s' failed", defmnt);
154 rversion(Fid *unused)
161 return "version: message too small";
162 if(rhdr.msize > messagesize)
163 rhdr.msize = messagesize;
165 messagesize = rhdr.msize;
166 thdr.msize = messagesize;
167 if(strncmp(rhdr.version, "9P2000", 6) != 0)
168 return "unrecognized 9P version";
169 thdr.version = "9P2000";
171 for(f = fids; f; f = f->next)
195 /* no authentication! */
199 thdr.qid = f->ram->qid;
201 f->user = strdup(rhdr.uname);
218 if(f->ram->busy == 0)
222 if(rhdr.newfid != rhdr.fid){
223 nf = newfid(rhdr.newfid);
228 nf->user = f->user; /* no ref count; the leakage is minor */
237 for(i=0; i<rhdr.nwname; i++){
238 if((r->qid.type & QTDIR) == 0){
247 name = rhdr.wname[i];
253 if(strcmp(name, "..") == 0){
257 err = "name too long";
260 thdr.wqid[thdr.nwqid++] = r->qid;
265 for(r=dir->child; r; r=r->next)
266 if(r->busy && cistrcmp(name, r->name)==0)
268 break; /* file not found */
271 if(i==0 && err == nil)
275 if(err!=nil || thdr.nwqid<rhdr.nwname){
281 }else if(thdr.nwqid == rhdr.nwname)
303 if(r->qid.type & QTDIR){
311 trunc = mode & OTRUNC;
313 if(mode==OWRITE || mode==ORDWR || trunc)
316 if(mode==OREAD || mode==ORDWR)
322 if(trunc && (r->perm&DMAPPEND)==0){
328 thdr.iounit = messagesize-IOHDRSZ;
351 if(f->ram->busy == 0)
356 end = rhdr.offset + rhdr.count;
358 if(cnt > messagesize-IOHDRSZ)
359 cnt = messagesize-IOHDRSZ;
361 if(f->ram->qid.type & QTDIR){
364 for(i=0,r=f->ram->child; r!=nil && i<end; r=r->next){
367 len = ramstat(r, (uchar*)buf+n, cnt-n);
384 thdr.data = doread(r, off, n);
397 if(dopermw(f->ram)==0)
402 if(r->perm & DMAPPEND)
405 if(r->qid.type & QTDIR)
406 return "file is a directory";
407 if(off > 100*1024*1024) /* sanity check */
408 return "write too big";
409 dowrite(r, rhdr.data, off, cnt);
437 if(f->ram->busy == 0)
439 thdr.nstat = ramstat(f->ram, thdr.stat, messagesize-IOHDRSZ);
446 if(f->ram->busy == 0)
452 ramstat(Ram *r, uchar *buf, int nbuf)
459 dir.length = r->ndata;
463 dir.atime = r->atime;
464 dir.mtime = r->mtime;
465 return convD2M(&dir, buf, nbuf);
474 for(f = fids; f; f = f->next)
477 else if(!ff && !f->busy)
484 f = emalloc(sizeof *f);
501 errstr(buf, sizeof buf);
502 for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
504 * reading from a pipe or a network device
505 * will give an error after a few eof reads
506 * however, we cannot tell the difference
507 * between a zero-length read and an interrupt
508 * on the processes writing to us,
509 * so we wait for the error
511 n = read9pmsg(mfd[0], mdata, sizeof mdata);
516 errstr(buf, sizeof buf);
521 if(convM2S(mdata, n, &rhdr) != n)
522 error("convert error in convM2S");
525 fprint(2, "tapefs: <=%F\n", &rhdr);/**/
527 thdr.data = (char*)mdata + IOHDRSZ;
528 thdr.stat = mdata + IOHDRSZ;
529 if(!fcalls[rhdr.type])
530 err = "bad fcall type";
532 err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
537 thdr.type = rhdr.type + 1;
541 n = convS2M(&thdr, mdata, messagesize);
543 error("convert error in convS2M");
545 fprint(2, "tapefs: =>%F\n", &thdr);/**/
546 if(write(mfd[1], mdata, n) != n)
547 error("mount write");
549 if(buf[0]=='\0' || strstr(buf, "hungup"))
551 fprint(2, "%s: mount read: %s\n", argv0, buf);
566 fprint(2, "%s: %s: ", argv0, s);
576 t = emalloc(strlen(s)+1);
587 error("out of memory");
592 erealloc(void *p, ulong n)
596 error("out of memory");
603 fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0);