10 uchar mdata[Maxbuf+IOHDRSZ];
11 int messagesize = Maxbuf+IOHDRSZ;
18 int blocksize; /* for 32v */
20 int newtap; /* tap with time in sec */
24 int ramstat(Ram*, uchar*, int);
29 char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
30 *rattach(Fid*), *rwalk(Fid*),
31 *ropen(Fid*), *rcreate(Fid*),
32 *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
33 *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
35 char *(*fcalls[])(Fid*) = {
51 char Eperm[] = "permission denied";
52 char Enotdir[] = "not a directory";
53 char Enoauth[] = "tapefs: authentication not required";
54 char Enotexist[] = "file does not exist";
55 char Einuse[] = "file in use";
56 char Eexist[] = "file exists";
57 char Enotowner[] = "not owner";
58 char Eisopen[] = "file already open for I/O";
59 char Excl[] = "exclusive use file already open";
60 char Ename[] = "illegal name";
63 notifyf(void *a, char *s)
66 if(strncmp(s, "interrupt", 9) == 0)
72 main(int argc, char *argv[])
78 fmtinstall('F', fcallfmt);
83 defmnt = EARGF(usage());
85 case 'p': /* password file */
86 uidmap = getpass(EARGF(usage()));
88 case 'g': /* group file */
89 gidmap = getpass(EARGF(usage()));
98 blocksize = atoi(EARGF(usage()));
105 error("no file to mount");
109 ram = r = (Ram *)emalloc(sizeof(Ram));
113 r->perm = DMDIR | 0775;
125 r->name = estrdup(".");
127 r->replete |= replete;
129 error("pipe failed");
130 mfd[0] = mfd[1] = p[0];
133 switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
142 close(p[0]); /* don't deadlock if child fails */
143 if(mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0)
144 error("mount failed");
150 rversion(Fid *unused)
157 return "version: message too small";
158 if(rhdr.msize > messagesize)
159 rhdr.msize = messagesize;
161 messagesize = rhdr.msize;
162 thdr.msize = messagesize;
163 if(strncmp(rhdr.version, "9P2000", 6) != 0)
164 return "unrecognized 9P version";
165 thdr.version = "9P2000";
167 for(f = fids; f; f = f->next)
191 /* no authentication! */
195 thdr.qid = f->ram->qid;
197 f->user = strdup(rhdr.uname);
214 if(f->ram->busy == 0)
218 if(rhdr.newfid != rhdr.fid){
219 nf = newfid(rhdr.newfid);
224 nf->user = f->user; /* no ref count; the leakage is minor */
233 for(i=0; i<rhdr.nwname; i++){
234 if((r->qid.type & QTDIR) == 0){
243 name = rhdr.wname[i];
249 if(strcmp(name, "..") == 0){
253 err = "name too long";
256 thdr.wqid[thdr.nwqid++] = r->qid;
261 for(r=dir->child; r; r=r->next)
262 if(r->busy && cistrcmp(name, r->name)==0)
264 break; /* file not found */
267 if(i==0 && err == nil)
271 if(err!=nil || thdr.nwqid<rhdr.nwname){
277 }else if(thdr.nwqid == rhdr.nwname)
299 if(r->qid.type & QTDIR){
307 trunc = mode & OTRUNC;
309 if(mode==OWRITE || mode==ORDWR || trunc)
312 if(mode==OREAD || mode==ORDWR)
318 if(trunc && (r->perm&DMAPPEND)==0){
324 thdr.iounit = messagesize-IOHDRSZ;
347 if(f->ram->busy == 0)
352 end = rhdr.offset + rhdr.count;
354 if(cnt > messagesize-IOHDRSZ)
355 cnt = messagesize-IOHDRSZ;
357 if(f->ram->qid.type & QTDIR){
360 for(i=0,r=f->ram->child; r!=nil && i<end; r=r->next){
363 len = ramstat(r, (uchar*)buf+n, cnt-n);
380 thdr.data = doread(r, off, n);
393 if(dopermw(f->ram)==0)
398 if(r->perm & DMAPPEND)
401 if(r->qid.type & QTDIR)
402 return "file is a directory";
403 if(off > 100*1024*1024) /* sanity check */
404 return "write too big";
405 dowrite(r, rhdr.data, off, cnt);
433 if(f->ram->busy == 0)
435 thdr.nstat = ramstat(f->ram, thdr.stat, messagesize-IOHDRSZ);
442 if(f->ram->busy == 0)
448 ramstat(Ram *r, uchar *buf, int nbuf)
455 dir.length = r->ndata;
459 dir.atime = r->atime;
460 dir.mtime = r->mtime;
461 return convD2M(&dir, buf, nbuf);
470 for(f = fids; f; f = f->next)
473 else if(!ff && !f->busy)
480 f = emalloc(sizeof *f);
496 while((n = read9pmsg(mfd[0], mdata, sizeof mdata)) != 0){
499 if(convM2S(mdata, n, &rhdr) != n)
500 error("convert error in convM2S");
502 fprint(2, "tapefs: <=%F\n", &rhdr);/**/
503 thdr.data = (char*)mdata + IOHDRSZ;
504 thdr.stat = mdata + IOHDRSZ;
505 if(!fcalls[rhdr.type])
506 err = "bad fcall type";
508 err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
513 thdr.type = rhdr.type + 1;
517 n = convS2M(&thdr, mdata, messagesize);
519 error("convert error in convS2M");
521 fprint(2, "tapefs: =>%F\n", &thdr);/**/
522 if(write(mfd[1], mdata, n) != n)
523 error("mount write");
538 fprint(2, "%s: %s: ", argv0, s);
548 t = emalloc(strlen(s)+1);
559 error("out of memory");
564 erealloc(void *p, ulong n)
568 error("out of memory");
575 fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0);