1bd389b36SDavid du Colombier #include <u.h>
2bd389b36SDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <authsrv.h>
4bd389b36SDavid du Colombier #include <fcall.h>
541fe996aSDavid du Colombier #include "tapefs.h"
6bd389b36SDavid du Colombier
7bd389b36SDavid du Colombier Fid *fids;
8bd389b36SDavid du Colombier Ram *ram;
9bd389b36SDavid du Colombier int mfd[2];
109a747e4fSDavid du Colombier char *user;
119a747e4fSDavid du Colombier uchar mdata[Maxbuf+IOHDRSZ];
129a747e4fSDavid du Colombier int messagesize = Maxbuf+IOHDRSZ;
13bd389b36SDavid du Colombier Fcall rhdr;
14bd389b36SDavid du Colombier Fcall thdr;
15bd389b36SDavid du Colombier ulong path;
16bd389b36SDavid du Colombier Idmap *uidmap;
17bd389b36SDavid du Colombier Idmap *gidmap;
18bd389b36SDavid du Colombier int replete;
19*bbd061d4SDavid du Colombier int blocksize; /* for 32v */
207dd7cddfSDavid du Colombier int verbose;
217dd7cddfSDavid du Colombier int newtap; /* tap with time in sec */
22*bbd061d4SDavid du Colombier int blocksize;
23bd389b36SDavid du Colombier
24bd389b36SDavid du Colombier Fid * newfid(int);
259a747e4fSDavid du Colombier int ramstat(Ram*, uchar*, int);
26bd389b36SDavid du Colombier void io(void);
27bd389b36SDavid du Colombier void usage(void);
289a747e4fSDavid du Colombier int perm(int);
29bd389b36SDavid du Colombier
309a747e4fSDavid du Colombier char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
319a747e4fSDavid du Colombier *rattach(Fid*), *rwalk(Fid*),
329a747e4fSDavid du Colombier *ropen(Fid*), *rcreate(Fid*),
33bd389b36SDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
349a747e4fSDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
35bd389b36SDavid du Colombier
36bd389b36SDavid du Colombier char *(*fcalls[])(Fid*) = {
37bd389b36SDavid du Colombier [Tflush] rflush,
389a747e4fSDavid du Colombier [Tversion] rversion,
399a747e4fSDavid du Colombier [Tauth] rauth,
40bd389b36SDavid du Colombier [Tattach] rattach,
41bd389b36SDavid du Colombier [Twalk] rwalk,
42bd389b36SDavid du Colombier [Topen] ropen,
43bd389b36SDavid du Colombier [Tcreate] rcreate,
44bd389b36SDavid du Colombier [Tread] rread,
45bd389b36SDavid du Colombier [Twrite] rwrite,
46bd389b36SDavid du Colombier [Tclunk] rclunk,
47bd389b36SDavid du Colombier [Tremove] rremove,
48bd389b36SDavid du Colombier [Tstat] rstat,
49bd389b36SDavid du Colombier [Twstat] rwstat,
50bd389b36SDavid du Colombier };
51bd389b36SDavid du Colombier
52bd389b36SDavid du Colombier char Eperm[] = "permission denied";
53bd389b36SDavid du Colombier char Enotdir[] = "not a directory";
543ff48bf5SDavid du Colombier char Enoauth[] = "tapefs: authentication not required";
55bd389b36SDavid du Colombier char Enotexist[] = "file does not exist";
56bd389b36SDavid du Colombier char Einuse[] = "file in use";
57bd389b36SDavid du Colombier char Eexist[] = "file exists";
58bd389b36SDavid du Colombier char Enotowner[] = "not owner";
59bd389b36SDavid du Colombier char Eisopen[] = "file already open for I/O";
60bd389b36SDavid du Colombier char Excl[] = "exclusive use file already open";
61bd389b36SDavid du Colombier char Ename[] = "illegal name";
62bd389b36SDavid du Colombier
63bd389b36SDavid du Colombier void
notifyf(void * a,char * s)64bd389b36SDavid du Colombier notifyf(void *a, char *s)
65bd389b36SDavid du Colombier {
66bd389b36SDavid du Colombier USED(a);
67bd389b36SDavid du Colombier if(strncmp(s, "interrupt", 9) == 0)
68bd389b36SDavid du Colombier noted(NCONT);
69bd389b36SDavid du Colombier noted(NDFLT);
70bd389b36SDavid du Colombier }
71bd389b36SDavid du Colombier
72bd389b36SDavid du Colombier void
main(int argc,char * argv[])73bd389b36SDavid du Colombier main(int argc, char *argv[])
74bd389b36SDavid du Colombier {
75bd389b36SDavid du Colombier Ram *r;
76bd389b36SDavid du Colombier char *defmnt;
77bd389b36SDavid du Colombier int p[2];
789a747e4fSDavid du Colombier char buf[TICKREQLEN];
799a747e4fSDavid du Colombier
809a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
81bd389b36SDavid du Colombier
82219b2ee8SDavid du Colombier defmnt = "/n/tapefs";
83bd389b36SDavid du Colombier ARGBEGIN{
84bd389b36SDavid du Colombier case 'm':
85*bbd061d4SDavid du Colombier defmnt = EARGF(usage());
86bd389b36SDavid du Colombier break;
87bd389b36SDavid du Colombier case 'p': /* password file */
88*bbd061d4SDavid du Colombier uidmap = getpass(EARGF(usage()));
89bd389b36SDavid du Colombier break;
90bd389b36SDavid du Colombier case 'g': /* group file */
91*bbd061d4SDavid du Colombier gidmap = getpass(EARGF(usage()));
92bd389b36SDavid du Colombier break;
937dd7cddfSDavid du Colombier case 'v':
947dd7cddfSDavid du Colombier verbose++;
95*bbd061d4SDavid du Colombier break;
967dd7cddfSDavid du Colombier case 'n':
977dd7cddfSDavid du Colombier newtap++;
987dd7cddfSDavid du Colombier break;
99*bbd061d4SDavid du Colombier case 'b':
100*bbd061d4SDavid du Colombier blocksize = atoi(EARGF(usage()));
101*bbd061d4SDavid du Colombier break;
102bd389b36SDavid du Colombier default:
103bd389b36SDavid du Colombier usage();
104bd389b36SDavid du Colombier }ARGEND
105bd389b36SDavid du Colombier
106bd389b36SDavid du Colombier if(argc==0)
107bd389b36SDavid du Colombier error("no file to mount");
1089a747e4fSDavid du Colombier user = getuser();
1099a747e4fSDavid du Colombier if(user == nil)
1109a747e4fSDavid du Colombier user = "dmr";
111bd389b36SDavid du Colombier ram = r = (Ram *)emalloc(sizeof(Ram));
112bd389b36SDavid du Colombier r->busy = 1;
113bd389b36SDavid du Colombier r->data = 0;
114bd389b36SDavid du Colombier r->ndata = 0;
1159a747e4fSDavid du Colombier r->perm = DMDIR | 0775;
1169a747e4fSDavid du Colombier r->qid.path = 0;
117bd389b36SDavid du Colombier r->qid.vers = 0;
1189a747e4fSDavid du Colombier r->qid.type = QTDIR;
119bd389b36SDavid du Colombier r->parent = 0;
120bd389b36SDavid du Colombier r->child = 0;
121bd389b36SDavid du Colombier r->next = 0;
122bd389b36SDavid du Colombier r->user = user;
123bd389b36SDavid du Colombier r->group = user;
124bd389b36SDavid du Colombier r->atime = time(0);
125bd389b36SDavid du Colombier r->mtime = r->atime;
126bd389b36SDavid du Colombier r->replete = 0;
1279a747e4fSDavid du Colombier r->name = estrdup(".");
128bd389b36SDavid du Colombier populate(argv[0]);
129bd389b36SDavid du Colombier r->replete |= replete;
130bd389b36SDavid du Colombier if(pipe(p) < 0)
131bd389b36SDavid du Colombier error("pipe failed");
132bd389b36SDavid du Colombier mfd[0] = mfd[1] = p[0];
133bd389b36SDavid du Colombier notify(notifyf);
134bd389b36SDavid du Colombier
135bd389b36SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
136bd389b36SDavid du Colombier case -1:
137bd389b36SDavid du Colombier error("fork");
138bd389b36SDavid du Colombier case 0:
139bd389b36SDavid du Colombier close(p[1]);
140bd389b36SDavid du Colombier notify(notifyf);
141bd389b36SDavid du Colombier io();
142bd389b36SDavid du Colombier break;
143bd389b36SDavid du Colombier default:
144bd389b36SDavid du Colombier close(p[0]); /* don't deadlock if child fails */
1459a747e4fSDavid du Colombier if(mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0) {
146219b2ee8SDavid du Colombier sprint(buf, "mount on `%s' failed", defmnt);
147219b2ee8SDavid du Colombier error(buf);
148219b2ee8SDavid du Colombier }
149bd389b36SDavid du Colombier }
150bd389b36SDavid du Colombier exits(0);
151bd389b36SDavid du Colombier }
152bd389b36SDavid du Colombier
153bd389b36SDavid du Colombier char*
rversion(Fid * unused)1549a747e4fSDavid du Colombier rversion(Fid *unused)
155bd389b36SDavid du Colombier {
156bd389b36SDavid du Colombier Fid *f;
157bd389b36SDavid du Colombier
158bd389b36SDavid du Colombier USED(unused);
159bd389b36SDavid du Colombier
1609a747e4fSDavid du Colombier if(rhdr.msize < 256)
1619a747e4fSDavid du Colombier return "version: message too small";
1629a747e4fSDavid du Colombier if(rhdr.msize > messagesize)
1639a747e4fSDavid du Colombier rhdr.msize = messagesize;
1649a747e4fSDavid du Colombier else
1659a747e4fSDavid du Colombier messagesize = rhdr.msize;
1669a747e4fSDavid du Colombier thdr.msize = messagesize;
1679a747e4fSDavid du Colombier if(strncmp(rhdr.version, "9P2000", 6) != 0)
1689a747e4fSDavid du Colombier return "unrecognized 9P version";
1699a747e4fSDavid du Colombier thdr.version = "9P2000";
1709a747e4fSDavid du Colombier
171bd389b36SDavid du Colombier for(f = fids; f; f = f->next)
172bd389b36SDavid du Colombier if(f->busy)
173bd389b36SDavid du Colombier rclunk(f);
174bd389b36SDavid du Colombier return 0;
175bd389b36SDavid du Colombier }
176bd389b36SDavid du Colombier
177bd389b36SDavid du Colombier char*
rauth(Fid * unused)1789a747e4fSDavid du Colombier rauth(Fid *unused)
1799a747e4fSDavid du Colombier {
1809a747e4fSDavid du Colombier USED(unused);
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier return Enoauth;
1839a747e4fSDavid du Colombier }
1849a747e4fSDavid du Colombier
1859a747e4fSDavid du Colombier char*
rflush(Fid * f)186bd389b36SDavid du Colombier rflush(Fid *f)
187bd389b36SDavid du Colombier {
188bd389b36SDavid du Colombier USED(f);
189bd389b36SDavid du Colombier return 0;
190bd389b36SDavid du Colombier }
191bd389b36SDavid du Colombier
192bd389b36SDavid du Colombier char*
rattach(Fid * f)193bd389b36SDavid du Colombier rattach(Fid *f)
194bd389b36SDavid du Colombier {
195bd389b36SDavid du Colombier /* no authentication! */
196bd389b36SDavid du Colombier f->busy = 1;
197bd389b36SDavid du Colombier f->rclose = 0;
198bd389b36SDavid du Colombier f->ram = ram;
199bd389b36SDavid du Colombier thdr.qid = f->ram->qid;
200bd389b36SDavid du Colombier if(rhdr.uname[0])
201bd389b36SDavid du Colombier f->user = strdup(rhdr.uname);
202bd389b36SDavid du Colombier else
203bd389b36SDavid du Colombier f->user = "none";
204bd389b36SDavid du Colombier return 0;
205bd389b36SDavid du Colombier }
206bd389b36SDavid du Colombier
207bd389b36SDavid du Colombier char*
rwalk(Fid * f)2089a747e4fSDavid du Colombier rwalk(Fid *f)
209bd389b36SDavid du Colombier {
210bd389b36SDavid du Colombier Fid *nf;
2119a747e4fSDavid du Colombier Ram *r;
2129a747e4fSDavid du Colombier char *err;
2139a747e4fSDavid du Colombier char *name;
2149a747e4fSDavid du Colombier Ram *dir;
2159a747e4fSDavid du Colombier int i;
216bd389b36SDavid du Colombier
2179a747e4fSDavid du Colombier nf = nil;
218bd389b36SDavid du Colombier if(f->ram->busy == 0)
219bd389b36SDavid du Colombier return Enotexist;
2209a747e4fSDavid du Colombier if(f->open)
2219a747e4fSDavid du Colombier return Eisopen;
2229a747e4fSDavid du Colombier if(rhdr.newfid != rhdr.fid){
223bd389b36SDavid du Colombier nf = newfid(rhdr.newfid);
224bd389b36SDavid du Colombier nf->busy = 1;
225bd389b36SDavid du Colombier nf->open = 0;
226bd389b36SDavid du Colombier nf->rclose = 0;
227bd389b36SDavid du Colombier nf->ram = f->ram;
228bd389b36SDavid du Colombier nf->user = f->user; /* no ref count; the leakage is minor */
2299a747e4fSDavid du Colombier f = nf;
230bd389b36SDavid du Colombier }
231bd389b36SDavid du Colombier
2329a747e4fSDavid du Colombier thdr.nwqid = 0;
2339a747e4fSDavid du Colombier err = nil;
2349a747e4fSDavid du Colombier r = f->ram;
235bd389b36SDavid du Colombier
2369a747e4fSDavid du Colombier if(rhdr.nwname > 0){
2379a747e4fSDavid du Colombier for(i=0; i<rhdr.nwname; i++){
2389a747e4fSDavid du Colombier if((r->qid.type & QTDIR) == 0){
2399a747e4fSDavid du Colombier err = Enotdir;
2409a747e4fSDavid du Colombier break;
241bd389b36SDavid du Colombier }
2429a747e4fSDavid du Colombier if(r->busy == 0){
2439a747e4fSDavid du Colombier err = Enotexist;
2449a747e4fSDavid du Colombier break;
2459a747e4fSDavid du Colombier }
2469a747e4fSDavid du Colombier r->atime = time(0);
2479a747e4fSDavid du Colombier name = rhdr.wname[i];
2489a747e4fSDavid du Colombier dir = r;
2499a747e4fSDavid du Colombier if(!perm(Pexec)){
2509a747e4fSDavid du Colombier err = Eperm;
2519a747e4fSDavid du Colombier break;
2529a747e4fSDavid du Colombier }
253bd389b36SDavid du Colombier if(strcmp(name, "..") == 0){
2549a747e4fSDavid du Colombier r = dir->parent;
2559a747e4fSDavid du Colombier Accept:
2569a747e4fSDavid du Colombier if(i == MAXWELEM){
2579a747e4fSDavid du Colombier err = "name too long";
2589a747e4fSDavid du Colombier break;
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier thdr.wqid[thdr.nwqid++] = r->qid;
2619a747e4fSDavid du Colombier continue;
262bd389b36SDavid du Colombier }
263bd389b36SDavid du Colombier if(!dir->replete)
264bd389b36SDavid du Colombier popdir(dir);
265bd389b36SDavid du Colombier for(r=dir->child; r; r=r->next)
2669a747e4fSDavid du Colombier if(r->busy && strcmp(name, r->name)==0)
2679a747e4fSDavid du Colombier goto Accept;
2689a747e4fSDavid du Colombier break; /* file not found */
2699a747e4fSDavid du Colombier }
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier if(i==0 && err == nil)
2729a747e4fSDavid du Colombier err = Enotexist;
2739a747e4fSDavid du Colombier }
2749a747e4fSDavid du Colombier
2759a747e4fSDavid du Colombier if(err!=nil || thdr.nwqid<rhdr.nwname){
2769a747e4fSDavid du Colombier if(nf){
2779a747e4fSDavid du Colombier nf->busy = 0;
2789a747e4fSDavid du Colombier nf->open = 0;
2799a747e4fSDavid du Colombier nf->ram = 0;
2809a747e4fSDavid du Colombier }
2819a747e4fSDavid du Colombier }else if(thdr.nwqid == rhdr.nwname)
282bd389b36SDavid du Colombier f->ram = r;
283bd389b36SDavid du Colombier
284bd389b36SDavid du Colombier return err;
2859a747e4fSDavid du Colombier
286bd389b36SDavid du Colombier }
287bd389b36SDavid du Colombier
288bd389b36SDavid du Colombier char *
ropen(Fid * f)289bd389b36SDavid du Colombier ropen(Fid *f)
290bd389b36SDavid du Colombier {
291bd389b36SDavid du Colombier Ram *r;
292bd389b36SDavid du Colombier int mode, trunc;
293bd389b36SDavid du Colombier
294bd389b36SDavid du Colombier if(f->open)
295bd389b36SDavid du Colombier return Eisopen;
296bd389b36SDavid du Colombier r = f->ram;
297bd389b36SDavid du Colombier if(r->busy == 0)
298bd389b36SDavid du Colombier return Enotexist;
2999a747e4fSDavid du Colombier if(r->perm & DMEXCL)
300bd389b36SDavid du Colombier if(r->open)
301bd389b36SDavid du Colombier return Excl;
302bd389b36SDavid du Colombier mode = rhdr.mode;
3039a747e4fSDavid du Colombier if(r->qid.type & QTDIR){
304bd389b36SDavid du Colombier if(mode != OREAD)
305bd389b36SDavid du Colombier return Eperm;
306bd389b36SDavid du Colombier thdr.qid = r->qid;
307bd389b36SDavid du Colombier return 0;
308bd389b36SDavid du Colombier }
309bd389b36SDavid du Colombier if(mode & ORCLOSE)
310bd389b36SDavid du Colombier return Eperm;
311bd389b36SDavid du Colombier trunc = mode & OTRUNC;
312bd389b36SDavid du Colombier mode &= OPERM;
313bd389b36SDavid du Colombier if(mode==OWRITE || mode==ORDWR || trunc)
3149a747e4fSDavid du Colombier if(!perm(Pwrite))
315bd389b36SDavid du Colombier return Eperm;
316bd389b36SDavid du Colombier if(mode==OREAD || mode==ORDWR)
3179a747e4fSDavid du Colombier if(!perm(Pread))
318bd389b36SDavid du Colombier return Eperm;
319bd389b36SDavid du Colombier if(mode==OEXEC)
3209a747e4fSDavid du Colombier if(!perm(Pexec))
321bd389b36SDavid du Colombier return Eperm;
3229a747e4fSDavid du Colombier if(trunc && (r->perm&DMAPPEND)==0){
323bd389b36SDavid du Colombier r->ndata = 0;
324bd389b36SDavid du Colombier dotrunc(r);
325bd389b36SDavid du Colombier r->qid.vers++;
326bd389b36SDavid du Colombier }
327bd389b36SDavid du Colombier thdr.qid = r->qid;
3289a747e4fSDavid du Colombier thdr.iounit = messagesize-IOHDRSZ;
329bd389b36SDavid du Colombier f->open = 1;
330bd389b36SDavid du Colombier r->open++;
331bd389b36SDavid du Colombier return 0;
332bd389b36SDavid du Colombier }
333bd389b36SDavid du Colombier
334bd389b36SDavid du Colombier char *
rcreate(Fid * f)335bd389b36SDavid du Colombier rcreate(Fid *f)
336bd389b36SDavid du Colombier {
337bd389b36SDavid du Colombier USED(f);
338bd389b36SDavid du Colombier
339bd389b36SDavid du Colombier return Eperm;
340bd389b36SDavid du Colombier }
341bd389b36SDavid du Colombier
342bd389b36SDavid du Colombier char*
rread(Fid * f)343bd389b36SDavid du Colombier rread(Fid *f)
344bd389b36SDavid du Colombier {
3459a747e4fSDavid du Colombier int i, len;
346bd389b36SDavid du Colombier Ram *r;
347bd389b36SDavid du Colombier char *buf;
3489a747e4fSDavid du Colombier uvlong off, end;
349bd389b36SDavid du Colombier int n, cnt;
350bd389b36SDavid du Colombier
351bd389b36SDavid du Colombier if(f->ram->busy == 0)
352bd389b36SDavid du Colombier return Enotexist;
353bd389b36SDavid du Colombier n = 0;
354bd389b36SDavid du Colombier thdr.count = 0;
355bd389b36SDavid du Colombier off = rhdr.offset;
3569a747e4fSDavid du Colombier end = rhdr.offset + rhdr.count;
357bd389b36SDavid du Colombier cnt = rhdr.count;
3589a747e4fSDavid du Colombier if(cnt > messagesize-IOHDRSZ)
3599a747e4fSDavid du Colombier cnt = messagesize-IOHDRSZ;
360bd389b36SDavid du Colombier buf = thdr.data;
3619a747e4fSDavid du Colombier if(f->ram->qid.type & QTDIR){
362bd389b36SDavid du Colombier if(!f->ram->replete)
363bd389b36SDavid du Colombier popdir(f->ram);
3649a747e4fSDavid du Colombier for(i=0,r=f->ram->child; r!=nil && i<end; r=r->next){
365bd389b36SDavid du Colombier if(!r->busy)
366bd389b36SDavid du Colombier continue;
3679a747e4fSDavid du Colombier len = ramstat(r, (uchar*)buf+n, cnt-n);
3689a747e4fSDavid du Colombier if(len <= BIT16SZ)
3699a747e4fSDavid du Colombier break;
3709a747e4fSDavid du Colombier if(i >= off)
3719a747e4fSDavid du Colombier n += len;
3729a747e4fSDavid du Colombier i += len;
373bd389b36SDavid du Colombier }
374bd389b36SDavid du Colombier thdr.count = n;
375bd389b36SDavid du Colombier return 0;
376bd389b36SDavid du Colombier }
377bd389b36SDavid du Colombier r = f->ram;
378bd389b36SDavid du Colombier if(off >= r->ndata)
379bd389b36SDavid du Colombier return 0;
380bd389b36SDavid du Colombier r->atime = time(0);
381bd389b36SDavid du Colombier n = cnt;
382bd389b36SDavid du Colombier if(off+n > r->ndata)
383bd389b36SDavid du Colombier n = r->ndata - off;
384bd389b36SDavid du Colombier thdr.data = doread(r, off, n);
385bd389b36SDavid du Colombier thdr.count = n;
386bd389b36SDavid du Colombier return 0;
387bd389b36SDavid du Colombier }
388bd389b36SDavid du Colombier
389bd389b36SDavid du Colombier char*
rwrite(Fid * f)390bd389b36SDavid du Colombier rwrite(Fid *f)
391bd389b36SDavid du Colombier {
392bd389b36SDavid du Colombier Ram *r;
393bd389b36SDavid du Colombier ulong off;
394bd389b36SDavid du Colombier int cnt;
395bd389b36SDavid du Colombier
396bd389b36SDavid du Colombier r = f->ram;
397bd389b36SDavid du Colombier if(dopermw(f->ram)==0)
398bd389b36SDavid du Colombier return Eperm;
399bd389b36SDavid du Colombier if(r->busy == 0)
400bd389b36SDavid du Colombier return Enotexist;
401bd389b36SDavid du Colombier off = rhdr.offset;
4029a747e4fSDavid du Colombier if(r->perm & DMAPPEND)
403bd389b36SDavid du Colombier off = r->ndata;
404bd389b36SDavid du Colombier cnt = rhdr.count;
4059a747e4fSDavid du Colombier if(r->qid.type & QTDIR)
406bd389b36SDavid du Colombier return "file is a directory";
407bd389b36SDavid du Colombier if(off > 100*1024*1024) /* sanity check */
408bd389b36SDavid du Colombier return "write too big";
409bd389b36SDavid du Colombier dowrite(r, rhdr.data, off, cnt);
410bd389b36SDavid du Colombier r->qid.vers++;
411bd389b36SDavid du Colombier r->mtime = time(0);
412bd389b36SDavid du Colombier thdr.count = cnt;
413bd389b36SDavid du Colombier return 0;
414bd389b36SDavid du Colombier }
415bd389b36SDavid du Colombier
416bd389b36SDavid du Colombier char *
rclunk(Fid * f)417bd389b36SDavid du Colombier rclunk(Fid *f)
418bd389b36SDavid du Colombier {
419bd389b36SDavid du Colombier if(f->open)
420bd389b36SDavid du Colombier f->ram->open--;
421bd389b36SDavid du Colombier f->busy = 0;
422bd389b36SDavid du Colombier f->open = 0;
423bd389b36SDavid du Colombier f->ram = 0;
424bd389b36SDavid du Colombier return 0;
425bd389b36SDavid du Colombier }
426bd389b36SDavid du Colombier
427bd389b36SDavid du Colombier char *
rremove(Fid * f)428bd389b36SDavid du Colombier rremove(Fid *f)
429bd389b36SDavid du Colombier {
430bd389b36SDavid du Colombier USED(f);
431bd389b36SDavid du Colombier return Eperm;
432bd389b36SDavid du Colombier }
433bd389b36SDavid du Colombier
434bd389b36SDavid du Colombier char *
rstat(Fid * f)435bd389b36SDavid du Colombier rstat(Fid *f)
436bd389b36SDavid du Colombier {
437bd389b36SDavid du Colombier if(f->ram->busy == 0)
438bd389b36SDavid du Colombier return Enotexist;
4399a747e4fSDavid du Colombier thdr.nstat = ramstat(f->ram, thdr.stat, messagesize-IOHDRSZ);
440bd389b36SDavid du Colombier return 0;
441bd389b36SDavid du Colombier }
442bd389b36SDavid du Colombier
443bd389b36SDavid du Colombier char *
rwstat(Fid * f)444bd389b36SDavid du Colombier rwstat(Fid *f)
445bd389b36SDavid du Colombier {
446bd389b36SDavid du Colombier if(f->ram->busy == 0)
447bd389b36SDavid du Colombier return Enotexist;
448bd389b36SDavid du Colombier return Eperm;
449bd389b36SDavid du Colombier }
450bd389b36SDavid du Colombier
4519a747e4fSDavid du Colombier int
ramstat(Ram * r,uchar * buf,int nbuf)4529a747e4fSDavid du Colombier ramstat(Ram *r, uchar *buf, int nbuf)
453bd389b36SDavid du Colombier {
454bd389b36SDavid du Colombier Dir dir;
455bd389b36SDavid du Colombier
4569a747e4fSDavid du Colombier dir.name = r->name;
457bd389b36SDavid du Colombier dir.qid = r->qid;
458bd389b36SDavid du Colombier dir.mode = r->perm;
459bd389b36SDavid du Colombier dir.length = r->ndata;
4609a747e4fSDavid du Colombier dir.uid = r->user;
4619a747e4fSDavid du Colombier dir.gid = r->group;
4629a747e4fSDavid du Colombier dir.muid = r->user;
463bd389b36SDavid du Colombier dir.atime = r->atime;
464bd389b36SDavid du Colombier dir.mtime = r->mtime;
4659a747e4fSDavid du Colombier return convD2M(&dir, buf, nbuf);
466bd389b36SDavid du Colombier }
467bd389b36SDavid du Colombier
468bd389b36SDavid du Colombier Fid *
newfid(int fid)469bd389b36SDavid du Colombier newfid(int fid)
470bd389b36SDavid du Colombier {
471bd389b36SDavid du Colombier Fid *f, *ff;
472bd389b36SDavid du Colombier
473bd389b36SDavid du Colombier ff = 0;
474bd389b36SDavid du Colombier for(f = fids; f; f = f->next)
475bd389b36SDavid du Colombier if(f->fid == fid)
476bd389b36SDavid du Colombier return f;
477bd389b36SDavid du Colombier else if(!ff && !f->busy)
478bd389b36SDavid du Colombier ff = f;
479bd389b36SDavid du Colombier if(ff){
480bd389b36SDavid du Colombier ff->fid = fid;
481bd389b36SDavid du Colombier ff->open = 0;
482bd389b36SDavid du Colombier ff->busy = 1;
483bd389b36SDavid du Colombier }
484bd389b36SDavid du Colombier f = emalloc(sizeof *f);
485bd389b36SDavid du Colombier f->ram = 0;
486bd389b36SDavid du Colombier f->fid = fid;
487bd389b36SDavid du Colombier f->busy = 1;
488bd389b36SDavid du Colombier f->open = 0;
489bd389b36SDavid du Colombier f->next = fids;
490bd389b36SDavid du Colombier fids = f;
491bd389b36SDavid du Colombier return f;
492bd389b36SDavid du Colombier }
493bd389b36SDavid du Colombier
494bd389b36SDavid du Colombier void
io(void)495bd389b36SDavid du Colombier io(void)
496bd389b36SDavid du Colombier {
497bd389b36SDavid du Colombier char *err;
498bd389b36SDavid du Colombier int n, nerr;
4999a747e4fSDavid du Colombier char buf[ERRMAX];
500bd389b36SDavid du Colombier
5019a747e4fSDavid du Colombier errstr(buf, sizeof buf);
502bd389b36SDavid du Colombier for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
503bd389b36SDavid du Colombier /*
504bd389b36SDavid du Colombier * reading from a pipe or a network device
505bd389b36SDavid du Colombier * will give an error after a few eof reads
506bd389b36SDavid du Colombier * however, we cannot tell the difference
507bd389b36SDavid du Colombier * between a zero-length read and an interrupt
508bd389b36SDavid du Colombier * on the processes writing to us,
509bd389b36SDavid du Colombier * so we wait for the error
510bd389b36SDavid du Colombier */
5119a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata);
512bd389b36SDavid du Colombier if(n==0)
513bd389b36SDavid du Colombier continue;
514bd389b36SDavid du Colombier if(n < 0){
515bd389b36SDavid du Colombier if(buf[0]=='\0')
5169a747e4fSDavid du Colombier errstr(buf, sizeof buf);
517bd389b36SDavid du Colombier continue;
518bd389b36SDavid du Colombier }
519bd389b36SDavid du Colombier nerr = 0;
520bd389b36SDavid du Colombier buf[0] = '\0';
5219a747e4fSDavid du Colombier if(convM2S(mdata, n, &rhdr) != n)
5229a747e4fSDavid du Colombier error("convert error in convM2S");
523bd389b36SDavid du Colombier
5249a747e4fSDavid du Colombier if(verbose)
5259a747e4fSDavid du Colombier fprint(2, "tapefs: <=%F\n", &rhdr);/**/
526bd389b36SDavid du Colombier
5279a747e4fSDavid du Colombier thdr.data = (char*)mdata + IOHDRSZ;
5289a747e4fSDavid du Colombier thdr.stat = mdata + IOHDRSZ;
529bd389b36SDavid du Colombier if(!fcalls[rhdr.type])
530bd389b36SDavid du Colombier err = "bad fcall type";
531bd389b36SDavid du Colombier else
532bd389b36SDavid du Colombier err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
533bd389b36SDavid du Colombier if(err){
534bd389b36SDavid du Colombier thdr.type = Rerror;
5359a747e4fSDavid du Colombier thdr.ename = err;
536bd389b36SDavid du Colombier }else{
537bd389b36SDavid du Colombier thdr.type = rhdr.type + 1;
538bd389b36SDavid du Colombier thdr.fid = rhdr.fid;
539bd389b36SDavid du Colombier }
540bd389b36SDavid du Colombier thdr.tag = rhdr.tag;
5419a747e4fSDavid du Colombier n = convS2M(&thdr, mdata, messagesize);
5429a747e4fSDavid du Colombier if(n <= 0)
5439a747e4fSDavid du Colombier error("convert error in convS2M");
5449a747e4fSDavid du Colombier if(verbose)
5459a747e4fSDavid du Colombier fprint(2, "tapefs: =>%F\n", &thdr);/**/
546bd389b36SDavid du Colombier if(write(mfd[1], mdata, n) != n)
547bd389b36SDavid du Colombier error("mount write");
548bd389b36SDavid du Colombier }
54924e2e655SDavid du Colombier if(buf[0]=='\0' || strstr(buf, "hungup"))
550bd389b36SDavid du Colombier exits("");
551bd389b36SDavid du Colombier fprint(2, "%s: mount read: %s\n", argv0, buf);
552bd389b36SDavid du Colombier exits(buf);
553bd389b36SDavid du Colombier }
554bd389b36SDavid du Colombier
555bd389b36SDavid du Colombier int
perm(int p)5569a747e4fSDavid du Colombier perm(int p)
557bd389b36SDavid du Colombier {
5587dd7cddfSDavid du Colombier if(p==Pwrite)
559bd389b36SDavid du Colombier return 0;
560bd389b36SDavid du Colombier return 1;
561bd389b36SDavid du Colombier }
562bd389b36SDavid du Colombier
563bd389b36SDavid du Colombier void
error(char * s)564bd389b36SDavid du Colombier error(char *s)
565bd389b36SDavid du Colombier {
566bd389b36SDavid du Colombier fprint(2, "%s: %s: ", argv0, s);
567bd389b36SDavid du Colombier perror("");
568bd389b36SDavid du Colombier exits(s);
569bd389b36SDavid du Colombier }
570bd389b36SDavid du Colombier
5719a747e4fSDavid du Colombier char*
estrdup(char * s)5729a747e4fSDavid du Colombier estrdup(char *s)
5739a747e4fSDavid du Colombier {
5749a747e4fSDavid du Colombier char *t;
5759a747e4fSDavid du Colombier
5769a747e4fSDavid du Colombier t = emalloc(strlen(s)+1);
5779a747e4fSDavid du Colombier strcpy(t, s);
5789a747e4fSDavid du Colombier return t;
5799a747e4fSDavid du Colombier }
5809a747e4fSDavid du Colombier
581bd389b36SDavid du Colombier void *
emalloc(ulong n)582bd389b36SDavid du Colombier emalloc(ulong n)
583bd389b36SDavid du Colombier {
584bd389b36SDavid du Colombier void *p;
5857dd7cddfSDavid du Colombier p = mallocz(n, 1);
586bd389b36SDavid du Colombier if(!p)
587bd389b36SDavid du Colombier error("out of memory");
588bd389b36SDavid du Colombier return p;
589bd389b36SDavid du Colombier }
590bd389b36SDavid du Colombier
591bd389b36SDavid du Colombier void *
erealloc(void * p,ulong n)592bd389b36SDavid du Colombier erealloc(void *p, ulong n)
593bd389b36SDavid du Colombier {
594bd389b36SDavid du Colombier p = realloc(p, n);
595bd389b36SDavid du Colombier if(!p)
596bd389b36SDavid du Colombier error("out of memory");
597bd389b36SDavid du Colombier return p;
598bd389b36SDavid du Colombier }
599bd389b36SDavid du Colombier
600bd389b36SDavid du Colombier void
usage(void)601bd389b36SDavid du Colombier usage(void)
602bd389b36SDavid du Colombier {
603bd389b36SDavid du Colombier fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0);
604bd389b36SDavid du Colombier exits("usage");
605bd389b36SDavid du Colombier }
606