1 64f7506b 2006-02-24 devnull #include <u.h>
2 64f7506b 2006-02-24 devnull #include <libc.h>
3 64f7506b 2006-02-24 devnull #include <authsrv.h>
4 64f7506b 2006-02-24 devnull #include <fcall.h>
5 64f7506b 2006-02-24 devnull #include "tapefs.h"
7 64f7506b 2006-02-24 devnull Fid *fids;
9 64f7506b 2006-02-24 devnull int mfd[2];
10 64f7506b 2006-02-24 devnull char *user;
11 64f7506b 2006-02-24 devnull uchar mdata[Maxbuf+IOHDRSZ];
12 64f7506b 2006-02-24 devnull int messagesize = Maxbuf+IOHDRSZ;
13 64f7506b 2006-02-24 devnull Fcall rhdr;
14 64f7506b 2006-02-24 devnull Fcall thdr;
15 64f7506b 2006-02-24 devnull ulong path;
16 64f7506b 2006-02-24 devnull Idmap *uidmap;
17 64f7506b 2006-02-24 devnull Idmap *gidmap;
18 64f7506b 2006-02-24 devnull int replete;
19 38c7eb9b 2006-05-21 devnull int blocksize; /* for 32v */
20 64f7506b 2006-02-24 devnull int verbose;
21 64f7506b 2006-02-24 devnull int newtap; /* tap with time in sec */
23 64f7506b 2006-02-24 devnull Fid * newfid(int);
24 64f7506b 2006-02-24 devnull int ramstat(Ram*, uchar*, int);
25 64f7506b 2006-02-24 devnull void io(void);
26 64f7506b 2006-02-24 devnull void usage(void);
27 64f7506b 2006-02-24 devnull int perm(int);
29 64f7506b 2006-02-24 devnull char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
30 64f7506b 2006-02-24 devnull *rattach(Fid*), *rwalk(Fid*),
31 64f7506b 2006-02-24 devnull *ropen(Fid*), *rcreate(Fid*),
32 64f7506b 2006-02-24 devnull *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
33 64f7506b 2006-02-24 devnull *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
35 cbeb0b26 2006-04-01 devnull char *(*fcalls[Tmax])(Fid*);
37 cbeb0b26 2006-04-01 devnull initfcalls(void)
39 cbeb0b26 2006-04-01 devnull fcalls[Tflush]= rflush;
40 cbeb0b26 2006-04-01 devnull fcalls[Tversion]= rversion;
41 cbeb0b26 2006-04-01 devnull fcalls[Tauth]= rauth;
42 cbeb0b26 2006-04-01 devnull fcalls[Tattach]= rattach;
43 cbeb0b26 2006-04-01 devnull fcalls[Twalk]= rwalk;
44 cbeb0b26 2006-04-01 devnull fcalls[Topen]= ropen;
45 cbeb0b26 2006-04-01 devnull fcalls[Tcreate]= rcreate;
46 cbeb0b26 2006-04-01 devnull fcalls[Tread]= rread;
47 cbeb0b26 2006-04-01 devnull fcalls[Twrite]= rwrite;
48 cbeb0b26 2006-04-01 devnull fcalls[Tclunk]= rclunk;
49 cbeb0b26 2006-04-01 devnull fcalls[Tremove]= rremove;
50 cbeb0b26 2006-04-01 devnull fcalls[Tstat]= rstat;
51 cbeb0b26 2006-04-01 devnull fcalls[Twstat]= rwstat;
54 64f7506b 2006-02-24 devnull char Eperm[] = "permission denied";
55 64f7506b 2006-02-24 devnull char Enotdir[] = "not a directory";
56 64f7506b 2006-02-24 devnull char Enoauth[] = "tapefs: authentication not required";
57 64f7506b 2006-02-24 devnull char Enotexist[] = "file does not exist";
58 64f7506b 2006-02-24 devnull char Einuse[] = "file in use";
59 64f7506b 2006-02-24 devnull char Eexist[] = "file exists";
60 64f7506b 2006-02-24 devnull char Enotowner[] = "not owner";
61 64f7506b 2006-02-24 devnull char Eisopen[] = "file already open for I/O";
62 64f7506b 2006-02-24 devnull char Excl[] = "exclusive use file already open";
63 64f7506b 2006-02-24 devnull char Ename[] = "illegal name";
66 64f7506b 2006-02-24 devnull notifyf(void *a, char *s)
69 64f7506b 2006-02-24 devnull if(strncmp(s, "interrupt", 9) == 0)
70 64f7506b 2006-02-24 devnull noted(NCONT);
71 64f7506b 2006-02-24 devnull noted(NDFLT);
75 64f7506b 2006-02-24 devnull main(int argc, char *argv[])
78 64f7506b 2006-02-24 devnull char *defmnt;
79 64f7506b 2006-02-24 devnull int p[2];
80 64f7506b 2006-02-24 devnull char buf[TICKREQLEN];
82 64f7506b 2006-02-24 devnull fmtinstall('F', fcallfmt);
83 cbeb0b26 2006-04-01 devnull initfcalls();
85 58ecf387 2006-02-25 devnull defmnt = "tapefs";
86 64f7506b 2006-02-24 devnull ARGBEGIN{
87 64f7506b 2006-02-24 devnull case 'm':
88 64f7506b 2006-02-24 devnull defmnt = ARGF();
90 64f7506b 2006-02-24 devnull case 'p': /* password file */
91 64f7506b 2006-02-24 devnull uidmap = getpass(ARGF());
93 64f7506b 2006-02-24 devnull case 'g': /* group file */
94 64f7506b 2006-02-24 devnull gidmap = getpass(ARGF());
96 64f7506b 2006-02-24 devnull case 'v':
97 64f7506b 2006-02-24 devnull verbose++;
99 64f7506b 2006-02-24 devnull case 'n':
100 64f7506b 2006-02-24 devnull newtap++;
102 64f7506b 2006-02-24 devnull default:
103 64f7506b 2006-02-24 devnull usage();
106 64f7506b 2006-02-24 devnull if(argc==0)
107 64f7506b 2006-02-24 devnull error("no file to mount");
108 64f7506b 2006-02-24 devnull user = getuser();
109 64f7506b 2006-02-24 devnull if(user == nil)
110 64f7506b 2006-02-24 devnull user = "dmr";
111 64f7506b 2006-02-24 devnull ram = r = (Ram *)emalloc(sizeof(Ram));
112 64f7506b 2006-02-24 devnull r->busy = 1;
113 64f7506b 2006-02-24 devnull r->data = 0;
114 64f7506b 2006-02-24 devnull r->ndata = 0;
115 64f7506b 2006-02-24 devnull r->perm = DMDIR | 0775;
116 64f7506b 2006-02-24 devnull r->qid.path = 0;
117 64f7506b 2006-02-24 devnull r->qid.vers = 0;
118 64f7506b 2006-02-24 devnull r->qid.type = QTDIR;
119 64f7506b 2006-02-24 devnull r->parent = 0;
120 64f7506b 2006-02-24 devnull r->child = 0;
121 64f7506b 2006-02-24 devnull r->next = 0;
122 64f7506b 2006-02-24 devnull r->user = user;
123 64f7506b 2006-02-24 devnull r->group = user;
124 64f7506b 2006-02-24 devnull r->atime = time(0);
125 64f7506b 2006-02-24 devnull r->mtime = r->atime;
126 64f7506b 2006-02-24 devnull r->replete = 0;
127 64f7506b 2006-02-24 devnull r->name = estrdup(".");
128 64f7506b 2006-02-24 devnull populate(argv[0]);
129 64f7506b 2006-02-24 devnull r->replete |= replete;
130 64f7506b 2006-02-24 devnull if(pipe(p) < 0)
131 64f7506b 2006-02-24 devnull error("pipe failed");
132 64f7506b 2006-02-24 devnull mfd[0] = mfd[1] = p[0];
133 64f7506b 2006-02-24 devnull notify(notifyf);
135 64f7506b 2006-02-24 devnull switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
136 64f7506b 2006-02-24 devnull case -1:
137 64f7506b 2006-02-24 devnull error("fork");
139 64f7506b 2006-02-24 devnull close(p[1]);
140 64f7506b 2006-02-24 devnull notify(notifyf);
143 64f7506b 2006-02-24 devnull default:
144 64f7506b 2006-02-24 devnull close(p[0]); /* don't deadlock if child fails */
145 64f7506b 2006-02-24 devnull if(post9pservice(p[1], defmnt) < 0) {
146 64f7506b 2006-02-24 devnull sprint(buf, "post on `%s' failed", defmnt);
147 64f7506b 2006-02-24 devnull error(buf);
150 64f7506b 2006-02-24 devnull exits(0);
154 64f7506b 2006-02-24 devnull rversion(Fid *unused)
158 64f7506b 2006-02-24 devnull USED(unused);
160 64f7506b 2006-02-24 devnull if(rhdr.msize < 256)
161 64f7506b 2006-02-24 devnull return "version: message too small";
162 64f7506b 2006-02-24 devnull if(rhdr.msize > messagesize)
163 64f7506b 2006-02-24 devnull rhdr.msize = messagesize;
165 64f7506b 2006-02-24 devnull messagesize = rhdr.msize;
166 64f7506b 2006-02-24 devnull thdr.msize = messagesize;
167 64f7506b 2006-02-24 devnull if(strncmp(rhdr.version, "9P2000", 6) != 0)
168 64f7506b 2006-02-24 devnull return "unrecognized 9P version";
169 64f7506b 2006-02-24 devnull thdr.version = "9P2000";
171 64f7506b 2006-02-24 devnull for(f = fids; f; f = f->next)
172 64f7506b 2006-02-24 devnull if(f->busy)
173 64f7506b 2006-02-24 devnull rclunk(f);
174 64f7506b 2006-02-24 devnull return 0;
178 64f7506b 2006-02-24 devnull rauth(Fid *unused)
180 64f7506b 2006-02-24 devnull USED(unused);
182 64f7506b 2006-02-24 devnull return Enoauth;
186 64f7506b 2006-02-24 devnull rflush(Fid *f)
188 64f7506b 2006-02-24 devnull USED(f);
189 64f7506b 2006-02-24 devnull return 0;
193 64f7506b 2006-02-24 devnull rattach(Fid *f)
195 64f7506b 2006-02-24 devnull /* no authentication! */
196 64f7506b 2006-02-24 devnull f->busy = 1;
197 64f7506b 2006-02-24 devnull f->rclose = 0;
198 64f7506b 2006-02-24 devnull f->ram = ram;
199 64f7506b 2006-02-24 devnull thdr.qid = f->ram->qid;
200 64f7506b 2006-02-24 devnull if(rhdr.uname[0])
201 64f7506b 2006-02-24 devnull f->user = strdup(rhdr.uname);
203 64f7506b 2006-02-24 devnull f->user = "none";
204 64f7506b 2006-02-24 devnull return 0;
208 64f7506b 2006-02-24 devnull rwalk(Fid *f)
210 64f7506b 2006-02-24 devnull Fid *nf;
212 64f7506b 2006-02-24 devnull char *err;
213 64f7506b 2006-02-24 devnull char *name;
214 64f7506b 2006-02-24 devnull Ram *dir;
217 64f7506b 2006-02-24 devnull nf = nil;
218 64f7506b 2006-02-24 devnull if(f->ram->busy == 0)
219 64f7506b 2006-02-24 devnull return Enotexist;
220 64f7506b 2006-02-24 devnull if(f->open)
221 64f7506b 2006-02-24 devnull return Eisopen;
222 64f7506b 2006-02-24 devnull if(rhdr.newfid != rhdr.fid){
223 64f7506b 2006-02-24 devnull nf = newfid(rhdr.newfid);
224 64f7506b 2006-02-24 devnull nf->busy = 1;
225 64f7506b 2006-02-24 devnull nf->open = 0;
226 64f7506b 2006-02-24 devnull nf->rclose = 0;
227 64f7506b 2006-02-24 devnull nf->ram = f->ram;
228 64f7506b 2006-02-24 devnull nf->user = f->user; /* no ref count; the leakage is minor */
232 64f7506b 2006-02-24 devnull thdr.nwqid = 0;
233 64f7506b 2006-02-24 devnull err = nil;
234 64f7506b 2006-02-24 devnull r = f->ram;
236 64f7506b 2006-02-24 devnull if(rhdr.nwname > 0){
237 64f7506b 2006-02-24 devnull for(i=0; i<rhdr.nwname; i++){
238 64f7506b 2006-02-24 devnull if((r->qid.type & QTDIR) == 0){
239 64f7506b 2006-02-24 devnull err = Enotdir;
242 64f7506b 2006-02-24 devnull if(r->busy == 0){
243 64f7506b 2006-02-24 devnull err = Enotexist;
246 64f7506b 2006-02-24 devnull r->atime = time(0);
247 64f7506b 2006-02-24 devnull name = rhdr.wname[i];
248 64f7506b 2006-02-24 devnull dir = r;
249 64f7506b 2006-02-24 devnull if(!perm(Pexec)){
250 64f7506b 2006-02-24 devnull err = Eperm;
253 64f7506b 2006-02-24 devnull if(strcmp(name, "..") == 0){
254 64f7506b 2006-02-24 devnull r = dir->parent;
256 64f7506b 2006-02-24 devnull if(i == MAXWELEM){
257 64f7506b 2006-02-24 devnull err = "name too long";
260 64f7506b 2006-02-24 devnull thdr.wqid[thdr.nwqid++] = r->qid;
261 64f7506b 2006-02-24 devnull continue;
263 64f7506b 2006-02-24 devnull if(!dir->replete)
264 64f7506b 2006-02-24 devnull popdir(dir);
265 64f7506b 2006-02-24 devnull for(r=dir->child; r; r=r->next)
266 64f7506b 2006-02-24 devnull if(r->busy && strcmp(name, r->name)==0)
267 64f7506b 2006-02-24 devnull goto Accept;
268 64f7506b 2006-02-24 devnull break; /* file not found */
271 64f7506b 2006-02-24 devnull if(i==0 && err == nil)
272 64f7506b 2006-02-24 devnull err = Enotexist;
275 64f7506b 2006-02-24 devnull if(err!=nil || thdr.nwqid<rhdr.nwname){
277 64f7506b 2006-02-24 devnull nf->busy = 0;
278 64f7506b 2006-02-24 devnull nf->open = 0;
279 64f7506b 2006-02-24 devnull nf->ram = 0;
281 64f7506b 2006-02-24 devnull }else if(thdr.nwqid == rhdr.nwname)
282 64f7506b 2006-02-24 devnull f->ram = r;
284 64f7506b 2006-02-24 devnull return err;
289 64f7506b 2006-02-24 devnull ropen(Fid *f)
292 64f7506b 2006-02-24 devnull int mode, trunc;
294 64f7506b 2006-02-24 devnull if(f->open)
295 64f7506b 2006-02-24 devnull return Eisopen;
296 64f7506b 2006-02-24 devnull r = f->ram;
297 64f7506b 2006-02-24 devnull if(r->busy == 0)
298 64f7506b 2006-02-24 devnull return Enotexist;
299 64f7506b 2006-02-24 devnull if(r->perm & DMEXCL)
300 64f7506b 2006-02-24 devnull if(r->open)
301 64f7506b 2006-02-24 devnull return Excl;
302 64f7506b 2006-02-24 devnull mode = rhdr.mode;
303 64f7506b 2006-02-24 devnull if(r->qid.type & QTDIR){
304 64f7506b 2006-02-24 devnull if(mode != OREAD)
305 64f7506b 2006-02-24 devnull return Eperm;
306 64f7506b 2006-02-24 devnull thdr.qid = r->qid;
307 64f7506b 2006-02-24 devnull return 0;
309 64f7506b 2006-02-24 devnull if(mode & ORCLOSE)
310 64f7506b 2006-02-24 devnull return Eperm;
311 64f7506b 2006-02-24 devnull trunc = mode & OTRUNC;
312 64f7506b 2006-02-24 devnull mode &= OPERM;
313 64f7506b 2006-02-24 devnull if(mode==OWRITE || mode==ORDWR || trunc)
314 64f7506b 2006-02-24 devnull if(!perm(Pwrite))
315 64f7506b 2006-02-24 devnull return Eperm;
316 64f7506b 2006-02-24 devnull if(mode==OREAD || mode==ORDWR)
317 64f7506b 2006-02-24 devnull if(!perm(Pread))
318 64f7506b 2006-02-24 devnull return Eperm;
319 64f7506b 2006-02-24 devnull if(mode==OEXEC)
320 64f7506b 2006-02-24 devnull if(!perm(Pexec))
321 64f7506b 2006-02-24 devnull return Eperm;
322 64f7506b 2006-02-24 devnull if(trunc && (r->perm&DMAPPEND)==0){
323 64f7506b 2006-02-24 devnull r->ndata = 0;
324 64f7506b 2006-02-24 devnull dotrunc(r);
325 64f7506b 2006-02-24 devnull r->qid.vers++;
327 64f7506b 2006-02-24 devnull thdr.qid = r->qid;
328 64f7506b 2006-02-24 devnull thdr.iounit = messagesize-IOHDRSZ;
329 64f7506b 2006-02-24 devnull f->open = 1;
330 64f7506b 2006-02-24 devnull r->open++;
331 64f7506b 2006-02-24 devnull return 0;
335 64f7506b 2006-02-24 devnull rcreate(Fid *f)
337 64f7506b 2006-02-24 devnull USED(f);
339 64f7506b 2006-02-24 devnull return Eperm;
343 64f7506b 2006-02-24 devnull rread(Fid *f)
345 64f7506b 2006-02-24 devnull int i, len;
347 64f7506b 2006-02-24 devnull char *buf;
348 64f7506b 2006-02-24 devnull uvlong off, end;
349 64f7506b 2006-02-24 devnull int n, cnt;
351 64f7506b 2006-02-24 devnull if(f->ram->busy == 0)
352 64f7506b 2006-02-24 devnull return Enotexist;
354 64f7506b 2006-02-24 devnull thdr.count = 0;
355 64f7506b 2006-02-24 devnull off = rhdr.offset;
356 64f7506b 2006-02-24 devnull end = rhdr.offset + rhdr.count;
357 64f7506b 2006-02-24 devnull cnt = rhdr.count;
358 64f7506b 2006-02-24 devnull if(cnt > messagesize-IOHDRSZ)
359 64f7506b 2006-02-24 devnull cnt = messagesize-IOHDRSZ;
360 64f7506b 2006-02-24 devnull buf = thdr.data;
361 64f7506b 2006-02-24 devnull if(f->ram->qid.type & QTDIR){
362 64f7506b 2006-02-24 devnull if(!f->ram->replete)
363 64f7506b 2006-02-24 devnull popdir(f->ram);
364 64f7506b 2006-02-24 devnull for(i=0,r=f->ram->child; r!=nil && i<end; r=r->next){
365 64f7506b 2006-02-24 devnull if(!r->busy)
366 64f7506b 2006-02-24 devnull continue;
367 64f7506b 2006-02-24 devnull len = ramstat(r, (uchar*)buf+n, cnt-n);
368 64f7506b 2006-02-24 devnull if(len <= BIT16SZ)
370 64f7506b 2006-02-24 devnull if(i >= off)
371 64f7506b 2006-02-24 devnull n += len;
372 64f7506b 2006-02-24 devnull i += len;
374 64f7506b 2006-02-24 devnull thdr.count = n;
375 64f7506b 2006-02-24 devnull return 0;
377 64f7506b 2006-02-24 devnull r = f->ram;
378 64f7506b 2006-02-24 devnull if(off >= r->ndata)
379 64f7506b 2006-02-24 devnull return 0;
380 64f7506b 2006-02-24 devnull r->atime = time(0);
381 64f7506b 2006-02-24 devnull n = cnt;
382 64f7506b 2006-02-24 devnull if(off+n > r->ndata)
383 64f7506b 2006-02-24 devnull n = r->ndata - off;
384 64f7506b 2006-02-24 devnull thdr.data = doread(r, off, n);
385 64f7506b 2006-02-24 devnull thdr.count = n;
386 64f7506b 2006-02-24 devnull return 0;
390 64f7506b 2006-02-24 devnull rwrite(Fid *f)
393 64f7506b 2006-02-24 devnull ulong off;
394 64f7506b 2006-02-24 devnull int cnt;
396 64f7506b 2006-02-24 devnull r = f->ram;
397 64f7506b 2006-02-24 devnull if(dopermw(f->ram)==0)
398 64f7506b 2006-02-24 devnull return Eperm;
399 64f7506b 2006-02-24 devnull if(r->busy == 0)
400 64f7506b 2006-02-24 devnull return Enotexist;
401 64f7506b 2006-02-24 devnull off = rhdr.offset;
402 64f7506b 2006-02-24 devnull if(r->perm & DMAPPEND)
403 64f7506b 2006-02-24 devnull off = r->ndata;
404 64f7506b 2006-02-24 devnull cnt = rhdr.count;
405 64f7506b 2006-02-24 devnull if(r->qid.type & QTDIR)
406 64f7506b 2006-02-24 devnull return "file is a directory";
407 64f7506b 2006-02-24 devnull if(off > 100*1024*1024) /* sanity check */
408 64f7506b 2006-02-24 devnull return "write too big";
409 64f7506b 2006-02-24 devnull dowrite(r, rhdr.data, off, cnt);
410 64f7506b 2006-02-24 devnull r->qid.vers++;
411 64f7506b 2006-02-24 devnull r->mtime = time(0);
412 64f7506b 2006-02-24 devnull thdr.count = cnt;
413 64f7506b 2006-02-24 devnull return 0;
417 64f7506b 2006-02-24 devnull rclunk(Fid *f)
419 64f7506b 2006-02-24 devnull if(f->open)
420 64f7506b 2006-02-24 devnull f->ram->open--;
421 64f7506b 2006-02-24 devnull f->busy = 0;
422 64f7506b 2006-02-24 devnull f->open = 0;
423 64f7506b 2006-02-24 devnull f->ram = 0;
424 64f7506b 2006-02-24 devnull return 0;
428 64f7506b 2006-02-24 devnull rremove(Fid *f)
430 64f7506b 2006-02-24 devnull USED(f);
431 64f7506b 2006-02-24 devnull return Eperm;
435 64f7506b 2006-02-24 devnull rstat(Fid *f)
437 64f7506b 2006-02-24 devnull if(f->ram->busy == 0)
438 64f7506b 2006-02-24 devnull return Enotexist;
439 64f7506b 2006-02-24 devnull thdr.nstat = ramstat(f->ram, thdr.stat, messagesize-IOHDRSZ);
440 64f7506b 2006-02-24 devnull return 0;
444 64f7506b 2006-02-24 devnull rwstat(Fid *f)
446 64f7506b 2006-02-24 devnull if(f->ram->busy == 0)
447 64f7506b 2006-02-24 devnull return Enotexist;
448 64f7506b 2006-02-24 devnull return Eperm;
452 64f7506b 2006-02-24 devnull ramstat(Ram *r, uchar *buf, int nbuf)
454 64f7506b 2006-02-24 devnull Dir dir;
456 64f7506b 2006-02-24 devnull dir.name = r->name;
457 64f7506b 2006-02-24 devnull dir.qid = r->qid;
458 64f7506b 2006-02-24 devnull dir.mode = r->perm;
459 64f7506b 2006-02-24 devnull dir.length = r->ndata;
460 64f7506b 2006-02-24 devnull dir.uid = r->user;
461 64f7506b 2006-02-24 devnull dir.gid = r->group;
462 64f7506b 2006-02-24 devnull dir.muid = r->user;
463 64f7506b 2006-02-24 devnull dir.atime = r->atime;
464 64f7506b 2006-02-24 devnull dir.mtime = r->mtime;
465 64f7506b 2006-02-24 devnull return convD2M(&dir, buf, nbuf);
469 64f7506b 2006-02-24 devnull newfid(int fid)
471 64f7506b 2006-02-24 devnull Fid *f, *ff;
474 64f7506b 2006-02-24 devnull for(f = fids; f; f = f->next)
475 64f7506b 2006-02-24 devnull if(f->fid == fid)
476 64f7506b 2006-02-24 devnull return f;
477 64f7506b 2006-02-24 devnull else if(!ff && !f->busy)
480 64f7506b 2006-02-24 devnull ff->fid = fid;
481 64f7506b 2006-02-24 devnull ff->open = 0;
482 64f7506b 2006-02-24 devnull ff->busy = 1;
484 64f7506b 2006-02-24 devnull f = emalloc(sizeof *f);
485 64f7506b 2006-02-24 devnull f->ram = 0;
486 64f7506b 2006-02-24 devnull f->fid = fid;
487 64f7506b 2006-02-24 devnull f->busy = 1;
488 64f7506b 2006-02-24 devnull f->open = 0;
489 64f7506b 2006-02-24 devnull f->next = fids;
490 64f7506b 2006-02-24 devnull fids = f;
491 64f7506b 2006-02-24 devnull return f;
495 64f7506b 2006-02-24 devnull io(void)
497 64f7506b 2006-02-24 devnull char *err;
498 64f7506b 2006-02-24 devnull int n, nerr;
499 64f7506b 2006-02-24 devnull char buf[ERRMAX];
501 64f7506b 2006-02-24 devnull errstr(buf, sizeof buf);
502 64f7506b 2006-02-24 devnull for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
504 64f7506b 2006-02-24 devnull * reading from a pipe or a network device
505 64f7506b 2006-02-24 devnull * will give an error after a few eof reads
506 64f7506b 2006-02-24 devnull * however, we cannot tell the difference
507 64f7506b 2006-02-24 devnull * between a zero-length read and an interrupt
508 64f7506b 2006-02-24 devnull * on the processes writing to us,
509 64f7506b 2006-02-24 devnull * so we wait for the error
511 64f7506b 2006-02-24 devnull n = read9pmsg(mfd[0], mdata, sizeof mdata);
512 64f7506b 2006-02-24 devnull if(n==0)
513 64f7506b 2006-02-24 devnull continue;
514 64f7506b 2006-02-24 devnull if(n < 0){
515 64f7506b 2006-02-24 devnull if(buf[0]=='\0')
516 64f7506b 2006-02-24 devnull errstr(buf, sizeof buf);
517 64f7506b 2006-02-24 devnull continue;
519 64f7506b 2006-02-24 devnull nerr = 0;
520 64f7506b 2006-02-24 devnull buf[0] = '\0';
521 64f7506b 2006-02-24 devnull if(convM2S(mdata, n, &rhdr) != n)
522 64f7506b 2006-02-24 devnull error("convert error in convM2S");
524 64f7506b 2006-02-24 devnull if(verbose)
525 64f7506b 2006-02-24 devnull fprint(2, "tapefs: <=%F\n", &rhdr);/**/
527 64f7506b 2006-02-24 devnull thdr.data = (char*)mdata + IOHDRSZ;
528 64f7506b 2006-02-24 devnull thdr.stat = mdata + IOHDRSZ;
529 64f7506b 2006-02-24 devnull if(!fcalls[rhdr.type])
530 64f7506b 2006-02-24 devnull err = "bad fcall type";
532 64f7506b 2006-02-24 devnull err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
533 64f7506b 2006-02-24 devnull if(err){
534 64f7506b 2006-02-24 devnull thdr.type = Rerror;
535 64f7506b 2006-02-24 devnull thdr.ename = err;
537 64f7506b 2006-02-24 devnull thdr.type = rhdr.type + 1;
538 64f7506b 2006-02-24 devnull thdr.fid = rhdr.fid;
540 64f7506b 2006-02-24 devnull thdr.tag = rhdr.tag;
541 64f7506b 2006-02-24 devnull n = convS2M(&thdr, mdata, messagesize);
542 64f7506b 2006-02-24 devnull if(n <= 0)
543 64f7506b 2006-02-24 devnull error("convert error in convS2M");
544 64f7506b 2006-02-24 devnull if(verbose)
545 64f7506b 2006-02-24 devnull fprint(2, "tapefs: =>%F\n", &thdr);/**/
546 64f7506b 2006-02-24 devnull if(write(mfd[1], mdata, n) != n)
547 64f7506b 2006-02-24 devnull error("mount write");
549 64f7506b 2006-02-24 devnull if(buf[0]=='\0' || strstr(buf, "hungup"))
550 64f7506b 2006-02-24 devnull exits("");
551 64f7506b 2006-02-24 devnull fprint(2, "%s: mount read: %s\n", argv0, buf);
552 64f7506b 2006-02-24 devnull exits(buf);
556 64f7506b 2006-02-24 devnull perm(int p)
558 64f7506b 2006-02-24 devnull if(p==Pwrite)
559 64f7506b 2006-02-24 devnull return 0;
560 64f7506b 2006-02-24 devnull return 1;
564 64f7506b 2006-02-24 devnull error(char *s)
566 64f7506b 2006-02-24 devnull fprint(2, "%s: %s: ", argv0, s);
567 64f7506b 2006-02-24 devnull perror("");
568 64f7506b 2006-02-24 devnull exits(s);
572 64f7506b 2006-02-24 devnull estrdup(char *s)
574 64f7506b 2006-02-24 devnull char *t;
576 64f7506b 2006-02-24 devnull t = emalloc(strlen(s)+1);
577 64f7506b 2006-02-24 devnull strcpy(t, s);
578 64f7506b 2006-02-24 devnull return t;
582 64f7506b 2006-02-24 devnull emalloc(ulong n)
584 64f7506b 2006-02-24 devnull void *p;
585 64f7506b 2006-02-24 devnull p = mallocz(n, 1);
587 64f7506b 2006-02-24 devnull error("out of memory");
588 64f7506b 2006-02-24 devnull return p;
592 64f7506b 2006-02-24 devnull erealloc(void *p, ulong n)
594 64f7506b 2006-02-24 devnull p = realloc(p, n);
596 64f7506b 2006-02-24 devnull error("out of memory");
597 64f7506b 2006-02-24 devnull return p;
601 64f7506b 2006-02-24 devnull usage(void)
603 64f7506b 2006-02-24 devnull fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0);
604 64f7506b 2006-02-24 devnull exits("usage");