tvacfs.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tvacfs.c (14671B) | |
--- | |
1 #include "stdinc.h" | |
2 #include <fcall.h> | |
3 #include "vac.h" | |
4 | |
5 typedef struct Fid Fid; | |
6 | |
7 enum | |
8 { | |
9 OPERM = 0x3 /* mask of all permission type… | |
10 }; | |
11 | |
12 struct Fid | |
13 { | |
14 short busy; | |
15 short open; | |
16 int fid; | |
17 char *user; | |
18 Qid qid; | |
19 VacFile *file; | |
20 VacDirEnum *vde; | |
21 Fid *next; | |
22 }; | |
23 | |
24 enum | |
25 { | |
26 Pexec = 1, | |
27 Pwrite = 2, | |
28 Pread = 4, | |
29 Pother = 1, | |
30 Pgroup = 8, | |
31 Powner = 64 | |
32 }; | |
33 | |
34 Fid *fids; | |
35 uchar *data; | |
36 int mfd[2]; | |
37 int srvfd = -1; | |
38 char *user; | |
39 uchar mdata[8192+IOHDRSZ]; | |
40 int messagesize = sizeof mdata; | |
41 Fcall rhdr; | |
42 Fcall thdr; | |
43 VacFs *fs; | |
44 VtConn *conn; | |
45 int noperm; | |
46 char *defmnt; | |
47 | |
48 Fid * newfid(int); | |
49 void error(char*); | |
50 void io(void); | |
51 void vacshutdown(void); | |
52 void usage(void); | |
53 int perm(Fid*, int); | |
54 int permf(VacFile*, char*, int); | |
55 ulong getl(void *p); | |
56 void init(char*, char*, long, int); | |
57 int vacdirread(Fid *f, char *p, long off, long cnt); | |
58 int vacstat(VacFile *parent, VacDir *vd, uchar *p, int np); | |
59 void srv(void* a); | |
60 | |
61 | |
62 char *rflush(Fid*), *rversion(Fid*), | |
63 *rauth(Fid*), *rattach(Fid*), *rwalk(Fid*), | |
64 *ropen(Fid*), *rcreate(Fid*), | |
65 *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*), | |
66 *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*); | |
67 | |
68 char *(*fcalls[Tmax])(Fid*); | |
69 | |
70 void | |
71 initfcalls(void) | |
72 { | |
73 fcalls[Tflush]= rflush; | |
74 fcalls[Tversion]= rversion; | |
75 fcalls[Tattach]= rattach; | |
76 fcalls[Tauth]= rauth; | |
77 fcalls[Twalk]= rwalk; | |
78 fcalls[Topen]= ropen; | |
79 fcalls[Tcreate]= rcreate; | |
80 fcalls[Tread]= rread; | |
81 fcalls[Twrite]= rwrite; | |
82 fcalls[Tclunk]= rclunk; | |
83 fcalls[Tremove]= rremove; | |
84 fcalls[Tstat]= rstat; | |
85 fcalls[Twstat]= rwstat; | |
86 } | |
87 | |
88 char Eperm[] = "permission denied"; | |
89 char Enotdir[] = "not a directory"; | |
90 char Enotexist[] = "file does not exist"; | |
91 char Einuse[] = "file in use"; | |
92 char Eexist[] = "file exists"; | |
93 char Enotowner[] = "not owner"; | |
94 char Eisopen[] = "file already open for I/O"; | |
95 char Excl[] = "exclusive use file already open"; | |
96 char Ename[] = "illegal name"; | |
97 char Erdonly[] = "read only file system"; | |
98 char Eio[] = "i/o error"; | |
99 char Eempty[] = "directory is not empty"; | |
100 char Emode[] = "illegal mode"; | |
101 | |
102 int dflag; | |
103 | |
104 void | |
105 notifyf(void *a, char *s) | |
106 { | |
107 USED(a); | |
108 if(strncmp(s, "interrupt", 9) == 0) | |
109 noted(NCONT); | |
110 noted(NDFLT); | |
111 } | |
112 | |
113 #define TWID64 ~(u64int)0 | |
114 static u64int | |
115 unittoull(char *s) | |
116 { | |
117 char *es; | |
118 u64int n; | |
119 | |
120 if(s == nil) | |
121 return TWID64; | |
122 n = strtoul(s, &es, 0); | |
123 if(*es == 'k' || *es == 'K'){ | |
124 n *= 1024; | |
125 es++; | |
126 }else if(*es == 'm' || *es == 'M'){ | |
127 n *= 1024*1024; | |
128 es++; | |
129 }else if(*es == 'g' || *es == 'G'){ | |
130 n *= 1024*1024*1024; | |
131 es++; | |
132 } | |
133 if(*es != '\0') | |
134 return TWID64; | |
135 return n; | |
136 } | |
137 | |
138 void | |
139 threadmain(int argc, char *argv[]) | |
140 { | |
141 char *defsrv, *srvname; | |
142 int p[2], fd; | |
143 int stdio; | |
144 char *host = nil; | |
145 ulong mem; | |
146 | |
147 mem = 16<<20; | |
148 stdio = 0; | |
149 fmtinstall('H', encodefmt); | |
150 fmtinstall('V', vtscorefmt); | |
151 fmtinstall('F', vtfcallfmt); | |
152 | |
153 defmnt = nil; | |
154 defsrv = nil; | |
155 ARGBEGIN{ | |
156 case 'd': | |
157 fmtinstall('F', fcallfmt); | |
158 dflag = 1; | |
159 break; | |
160 case 'i': | |
161 defmnt = nil; | |
162 stdio = 1; | |
163 mfd[0] = 0; | |
164 mfd[1] = 1; | |
165 break; | |
166 case 'h': | |
167 host = EARGF(usage()); | |
168 break; | |
169 case 'S': | |
170 defsrv = EARGF(usage()); | |
171 break; | |
172 case 's': | |
173 defsrv = "vacfs"; | |
174 break; | |
175 case 'M': | |
176 mem = unittoull(EARGF(usage())); | |
177 break; | |
178 case 'm': | |
179 defmnt = EARGF(usage()); | |
180 break; | |
181 case 'p': | |
182 noperm = 1; | |
183 break; | |
184 case 'V': | |
185 chattyventi = 1; | |
186 break; | |
187 default: | |
188 usage(); | |
189 }ARGEND | |
190 | |
191 if(argc != 1) | |
192 usage(); | |
193 | |
194 #ifdef PLAN9PORT | |
195 if(defsrv == nil && defmnt == nil && !stdio){ | |
196 srvname = strchr(argv[0], '/'); | |
197 if(srvname) | |
198 srvname++; | |
199 else | |
200 srvname = argv[0]; | |
201 defsrv = vtmalloc(6+strlen(srvname)+1); | |
202 strcpy(defsrv, "vacfs."); | |
203 strcat(defsrv, srvname); | |
204 if(strcmp(defsrv+strlen(defsrv)-4, ".vac") == 0) | |
205 defsrv[strlen(defsrv)-4] = 0; | |
206 } | |
207 #else | |
208 if(defsrv == nil && defmnt == nil && !stdio) | |
209 defmnt = "/n/vac"; | |
210 #endif | |
211 if(stdio && defmnt) | |
212 sysfatal("cannot use -m with -i"); | |
213 | |
214 initfcalls(); | |
215 | |
216 notify(notifyf); | |
217 user = getuser(); | |
218 | |
219 conn = vtdial(host); | |
220 if(conn == nil) | |
221 sysfatal("could not connect to server: %r"); | |
222 | |
223 if(vtconnect(conn) < 0) | |
224 sysfatal("vtconnect: %r"); | |
225 | |
226 fs = vacfsopen(conn, argv[0], VtOREAD, mem); | |
227 if(fs == nil) | |
228 sysfatal("vacfsopen: %r"); | |
229 | |
230 if(!stdio){ | |
231 if(pipe(p) < 0) | |
232 sysfatal("pipe failed: %r"); | |
233 mfd[0] = p[0]; | |
234 mfd[1] = p[0]; | |
235 srvfd = p[1]; | |
236 #ifndef PLAN9PORT | |
237 if(defsrv){ | |
238 srvname = smprint("/srv/%s", defsrv); | |
239 fd = create(srvname, OWRITE|ORCLOSE, 0666); | |
240 if(fd < 0) | |
241 sysfatal("create %s: %r", srvname); | |
242 if(fprint(fd, "%d", srvfd) < 0) | |
243 sysfatal("write %s: %r", srvname); | |
244 free(srvname); | |
245 } | |
246 #endif | |
247 } | |
248 | |
249 #ifdef PLAN9PORT | |
250 USED(fd); | |
251 proccreate(srv, 0, 32 * 1024); | |
252 if(!stdio && post9pservice(p[1], defsrv, defmnt) < 0) | |
253 sysfatal("post9pservice"); | |
254 #else | |
255 procrfork(srv, 0, 32 * 1024, RFFDG|RFNAMEG|RFNOTEG); | |
256 | |
257 if(!stdio){ | |
258 close(p[0]); | |
259 if(defmnt){ | |
260 if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") <… | |
261 sysfatal("mount %s: %r", defmnt); | |
262 } | |
263 } | |
264 #endif | |
265 threadexits(0); | |
266 } | |
267 | |
268 void | |
269 srv(void *a) | |
270 { | |
271 USED(a); | |
272 io(); | |
273 vacshutdown(); | |
274 } | |
275 | |
276 void | |
277 usage(void) | |
278 { | |
279 fprint(2, "usage: %s [-sd] [-h host] [-m mountpoint] [-M mem] va… | |
280 threadexitsall("usage"); | |
281 } | |
282 | |
283 char* | |
284 rversion(Fid *unused) | |
285 { | |
286 Fid *f; | |
287 | |
288 USED(unused); | |
289 | |
290 for(f = fids; f; f = f->next) | |
291 if(f->busy) | |
292 rclunk(f); | |
293 | |
294 if(rhdr.msize < 256) | |
295 return vtstrdup("version: message size too small"); | |
296 messagesize = rhdr.msize; | |
297 if(messagesize > sizeof mdata) | |
298 messagesize = sizeof mdata; | |
299 thdr.msize = messagesize; | |
300 if(strncmp(rhdr.version, "9P2000", 6) != 0) | |
301 return vtstrdup("unrecognized 9P version"); | |
302 thdr.version = "9P2000"; | |
303 return nil; | |
304 } | |
305 | |
306 char* | |
307 rflush(Fid *f) | |
308 { | |
309 USED(f); | |
310 return 0; | |
311 } | |
312 | |
313 char* | |
314 rauth(Fid *f) | |
315 { | |
316 USED(f); | |
317 return vtstrdup("vacfs: authentication not required"); | |
318 } | |
319 | |
320 char* | |
321 rattach(Fid *f) | |
322 { | |
323 /* no authentication for the momment */ | |
324 VacFile *file; | |
325 char err[80]; | |
326 | |
327 file = vacfsgetroot(fs); | |
328 if(file == nil) { | |
329 rerrstr(err, sizeof err); | |
330 return vtstrdup(err); | |
331 } | |
332 | |
333 f->busy = 1; | |
334 f->file = file; | |
335 f->qid.path = vacfilegetid(f->file); | |
336 f->qid.vers = 0; | |
337 f->qid.type = QTDIR; | |
338 thdr.qid = f->qid; | |
339 if(rhdr.uname[0]) | |
340 f->user = vtstrdup(rhdr.uname); | |
341 else | |
342 f->user = "none"; | |
343 return 0; | |
344 } | |
345 | |
346 char* | |
347 rwalk(Fid *f) | |
348 { | |
349 VacFile *file, *nfile; | |
350 Fid *nf; | |
351 int nqid, nwname; | |
352 Qid qid; | |
353 char *err = nil; | |
354 | |
355 if(f->busy == 0) | |
356 return Enotexist; | |
357 nf = nil; | |
358 if(rhdr.fid != rhdr.newfid){ | |
359 if(f->open) | |
360 return vtstrdup(Eisopen); | |
361 if(f->busy == 0) | |
362 return vtstrdup(Enotexist); | |
363 nf = newfid(rhdr.newfid); | |
364 if(nf->busy) | |
365 return vtstrdup(Eisopen); | |
366 nf->busy = 1; | |
367 nf->open = 0; | |
368 nf->qid = f->qid; | |
369 nf->file = vacfileincref(f->file); | |
370 nf->user = vtstrdup(f->user); | |
371 f = nf; | |
372 } | |
373 | |
374 nwname = rhdr.nwname; | |
375 | |
376 /* easy case */ | |
377 if(nwname == 0) { | |
378 thdr.nwqid = 0; | |
379 return 0; | |
380 } | |
381 | |
382 file = f->file; | |
383 vacfileincref(file); | |
384 qid = f->qid; | |
385 | |
386 for(nqid = 0; nqid < nwname; nqid++){ | |
387 if((qid.type & QTDIR) == 0){ | |
388 err = Enotdir; | |
389 break; | |
390 } | |
391 if(!permf(file, f->user, Pexec)) { | |
392 err = Eperm; | |
393 break; | |
394 } | |
395 nfile = vacfilewalk(file, rhdr.wname[nqid]); | |
396 if(nfile == nil) | |
397 break; | |
398 vacfiledecref(file); | |
399 file = nfile; | |
400 qid.type = QTFILE; | |
401 if(vacfileisdir(file)) | |
402 qid.type = QTDIR; | |
403 #ifdef PLAN9PORT | |
404 if(vacfilegetmode(file)&ModeLink) | |
405 qid.type = QTSYMLINK; | |
406 #endif | |
407 qid.vers = vacfilegetmcount(file); | |
408 qid.path = vacfilegetid(file); | |
409 thdr.wqid[nqid] = qid; | |
410 } | |
411 | |
412 thdr.nwqid = nqid; | |
413 | |
414 if(nqid == nwname){ | |
415 /* success */ | |
416 f->qid = thdr.wqid[nqid-1]; | |
417 vacfiledecref(f->file); | |
418 f->file = file; | |
419 return 0; | |
420 } | |
421 | |
422 vacfiledecref(file); | |
423 if(nf != nil) | |
424 rclunk(nf); | |
425 | |
426 /* only error on the first element */ | |
427 if(nqid == 0) | |
428 return vtstrdup(err); | |
429 | |
430 return 0; | |
431 } | |
432 | |
433 char * | |
434 ropen(Fid *f) | |
435 { | |
436 int mode, trunc; | |
437 | |
438 if(f->open) | |
439 return vtstrdup(Eisopen); | |
440 if(!f->busy) | |
441 return vtstrdup(Enotexist); | |
442 | |
443 mode = rhdr.mode; | |
444 thdr.iounit = messagesize - IOHDRSZ; | |
445 if(f->qid.type & QTDIR){ | |
446 if(mode != OREAD) | |
447 return vtstrdup(Eperm); | |
448 if(!perm(f, Pread)) | |
449 return vtstrdup(Eperm); | |
450 thdr.qid = f->qid; | |
451 f->vde = nil; | |
452 f->open = 1; | |
453 return 0; | |
454 } | |
455 if(mode & ORCLOSE) | |
456 return vtstrdup(Erdonly); | |
457 trunc = mode & OTRUNC; | |
458 mode &= OPERM; | |
459 if(mode==OWRITE || mode==ORDWR || trunc) | |
460 if(!perm(f, Pwrite)) | |
461 return vtstrdup(Eperm); | |
462 if(mode==OREAD || mode==ORDWR) | |
463 if(!perm(f, Pread)) | |
464 return vtstrdup(Eperm); | |
465 if(mode==OEXEC) | |
466 if(!perm(f, Pexec)) | |
467 return vtstrdup(Eperm); | |
468 thdr.qid = f->qid; | |
469 thdr.iounit = messagesize - IOHDRSZ; | |
470 f->open = 1; | |
471 return 0; | |
472 } | |
473 | |
474 char* | |
475 rcreate(Fid* fid) | |
476 { | |
477 VacFile *vf; | |
478 ulong mode; | |
479 | |
480 if(fid->open) | |
481 return vtstrdup(Eisopen); | |
482 if(!fid->busy) | |
483 return vtstrdup(Enotexist); | |
484 if(fs->mode & ModeSnapshot) | |
485 return vtstrdup(Erdonly); | |
486 vf = fid->file; | |
487 if(!vacfileisdir(vf)) | |
488 return vtstrdup(Enotdir); | |
489 if(!permf(vf, fid->user, Pwrite)) | |
490 return vtstrdup(Eperm); | |
491 | |
492 mode = rhdr.perm & 0777; | |
493 | |
494 if(rhdr.perm & DMDIR){ | |
495 if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND)) | |
496 return vtstrdup(Emode); | |
497 switch(rhdr.mode & OPERM){ | |
498 default: | |
499 return vtstrdup(Emode); | |
500 case OEXEC: | |
501 case OREAD: | |
502 break; | |
503 case OWRITE: | |
504 case ORDWR: | |
505 return vtstrdup(Eperm); | |
506 } | |
507 mode |= ModeDir; | |
508 } | |
509 vf = vacfilecreate(vf, rhdr.name, mode); | |
510 if(vf == nil) { | |
511 char err[80]; | |
512 rerrstr(err, sizeof err); | |
513 | |
514 return vtstrdup(err); | |
515 } | |
516 | |
517 vacfiledecref(fid->file); | |
518 | |
519 fid->file = vf; | |
520 fid->qid.type = QTFILE; | |
521 if(vacfileisdir(vf)) | |
522 fid->qid.type = QTDIR; | |
523 fid->qid.vers = vacfilegetmcount(vf); | |
524 fid->qid.path = vacfilegetid(vf); | |
525 | |
526 thdr.qid = fid->qid; | |
527 thdr.iounit = messagesize - IOHDRSZ; | |
528 | |
529 return 0; | |
530 } | |
531 | |
532 char* | |
533 rread(Fid *f) | |
534 { | |
535 char *buf; | |
536 vlong off; | |
537 int cnt; | |
538 VacFile *vf; | |
539 char err[80]; | |
540 int n; | |
541 | |
542 if(!f->busy) | |
543 return vtstrdup(Enotexist); | |
544 vf = f->file; | |
545 thdr.count = 0; | |
546 off = rhdr.offset; | |
547 buf = thdr.data; | |
548 cnt = rhdr.count; | |
549 if(f->qid.type & QTDIR) | |
550 n = vacdirread(f, buf, off, cnt); | |
551 else if(vacfilegetmode(f->file)&ModeDevice) | |
552 return vtstrdup("device"); | |
553 else if(vacfilegetmode(f->file)&ModeLink) | |
554 return vtstrdup("symbolic link"); | |
555 else if(vacfilegetmode(f->file)&ModeNamedPipe) | |
556 return vtstrdup("named pipe"); | |
557 else | |
558 n = vacfileread(vf, buf, cnt, off); | |
559 if(n < 0) { | |
560 rerrstr(err, sizeof err); | |
561 return vtstrdup(err); | |
562 } | |
563 thdr.count = n; | |
564 return 0; | |
565 } | |
566 | |
567 char* | |
568 rwrite(Fid *f) | |
569 { | |
570 USED(f); | |
571 return vtstrdup(Erdonly); | |
572 } | |
573 | |
574 char * | |
575 rclunk(Fid *f) | |
576 { | |
577 f->busy = 0; | |
578 f->open = 0; | |
579 vtfree(f->user); | |
580 f->user = nil; | |
581 if(f->file) | |
582 vacfiledecref(f->file); | |
583 f->file = nil; | |
584 vdeclose(f->vde); | |
585 f->vde = nil; | |
586 return 0; | |
587 } | |
588 | |
589 char * | |
590 rremove(Fid *f) | |
591 { | |
592 VacFile *vf, *vfp; | |
593 char errbuf[80]; | |
594 char *err = nil; | |
595 | |
596 if(!f->busy) | |
597 return vtstrdup(Enotexist); | |
598 vf = f->file; | |
599 vfp = vacfilegetparent(vf); | |
600 | |
601 if(!permf(vfp, f->user, Pwrite)) { | |
602 err = Eperm; | |
603 goto Exit; | |
604 } | |
605 | |
606 if(!vacfileremove(vf)) { | |
607 rerrstr(errbuf, sizeof errbuf); | |
608 err = errbuf; | |
609 } | |
610 | |
611 Exit: | |
612 vacfiledecref(vfp); | |
613 rclunk(f); | |
614 return vtstrdup(err); | |
615 } | |
616 | |
617 char * | |
618 rstat(Fid *f) | |
619 { | |
620 VacDir dir; | |
621 static uchar statbuf[1024]; | |
622 VacFile *parent; | |
623 | |
624 if(!f->busy) | |
625 return vtstrdup(Enotexist); | |
626 parent = vacfilegetparent(f->file); | |
627 vacfilegetdir(f->file, &dir); | |
628 thdr.stat = statbuf; | |
629 thdr.nstat = vacstat(parent, &dir, thdr.stat, sizeof statbuf); | |
630 vdcleanup(&dir); | |
631 vacfiledecref(parent); | |
632 return 0; | |
633 } | |
634 | |
635 char * | |
636 rwstat(Fid *f) | |
637 { | |
638 if(!f->busy) | |
639 return vtstrdup(Enotexist); | |
640 return vtstrdup(Erdonly); | |
641 } | |
642 | |
643 int | |
644 vacstat(VacFile *parent, VacDir *vd, uchar *p, int np) | |
645 { | |
646 int ret; | |
647 Dir dir; | |
648 #ifdef PLAN9PORT | |
649 int n; | |
650 VacFile *vf; | |
651 uvlong size; | |
652 char *ext = nil; | |
653 #endif | |
654 | |
655 memset(&dir, 0, sizeof(dir)); | |
656 | |
657 dir.qid.path = vd->qid + vacfilegetqidoffset(parent); | |
658 if(vd->qidspace) | |
659 dir.qid.path += vd->qidoffset; | |
660 dir.qid.vers = vd->mcount; | |
661 dir.mode = vd->mode & 0777; | |
662 if(vd->mode & ModeAppend){ | |
663 dir.qid.type |= QTAPPEND; | |
664 dir.mode |= DMAPPEND; | |
665 } | |
666 if(vd->mode & ModeExclusive){ | |
667 dir.qid.type |= QTEXCL; | |
668 dir.mode |= DMEXCL; | |
669 } | |
670 if(vd->mode & ModeDir){ | |
671 dir.qid.type |= QTDIR; | |
672 dir.mode |= DMDIR; | |
673 } | |
674 | |
675 #ifdef PLAN9PORT | |
676 if(vd->mode & (ModeLink|ModeDevice|ModeNamedPipe)){ | |
677 vf = vacfilewalk(parent, vd->elem); | |
678 if(vf == nil) | |
679 return 0; | |
680 vacfilegetsize(vf, &size); | |
681 ext = malloc(size+1); | |
682 if(ext == nil) | |
683 return 0; | |
684 n = vacfileread(vf, ext, size, 0); | |
685 USED(n); | |
686 ext[size] = 0; | |
687 vacfiledecref(vf); | |
688 if(vd->mode & ModeLink){ | |
689 dir.qid.type |= QTSYMLINK; | |
690 dir.mode |= DMSYMLINK; | |
691 } | |
692 if(vd->mode & ModeDevice) | |
693 dir.mode |= DMDEVICE; | |
694 if(vd->mode & ModeNamedPipe) | |
695 dir.mode |= DMNAMEDPIPE; | |
696 } | |
697 #endif | |
698 | |
699 dir.atime = vd->atime; | |
700 dir.mtime = vd->mtime; | |
701 dir.length = vd->size; | |
702 | |
703 dir.name = vd->elem; | |
704 dir.uid = vd->uid; | |
705 dir.gid = vd->gid; | |
706 dir.muid = vd->mid; | |
707 | |
708 ret = convD2M(&dir, p, np); | |
709 #ifdef PLAN9PORT | |
710 free(ext); | |
711 #endif | |
712 return ret; | |
713 } | |
714 | |
715 int | |
716 vacdirread(Fid *f, char *p, long off, long cnt) | |
717 { | |
718 int i, n, nb; | |
719 VacDir vd; | |
720 | |
721 /* | |
722 * special case of rewinding a directory | |
723 * otherwise ignore the offset | |
724 */ | |
725 if(off == 0 && f->vde){ | |
726 vdeclose(f->vde); | |
727 f->vde = nil; | |
728 } | |
729 | |
730 if(f->vde == nil){ | |
731 f->vde = vdeopen(f->file); | |
732 if(f->vde == nil) | |
733 return -1; | |
734 } | |
735 | |
736 for(nb = 0; nb < cnt; nb += n) { | |
737 i = vderead(f->vde, &vd); | |
738 if(i < 0) | |
739 return -1; | |
740 if(i == 0) | |
741 break; | |
742 n = vacstat(f->file, &vd, (uchar*)p, cnt-nb); | |
743 if(n <= BIT16SZ) { | |
744 vdeunread(f->vde); | |
745 break; | |
746 } | |
747 vdcleanup(&vd); | |
748 p += n; | |
749 } | |
750 return nb; | |
751 } | |
752 | |
753 Fid * | |
754 newfid(int fid) | |
755 { | |
756 Fid *f, *ff; | |
757 | |
758 ff = 0; | |
759 for(f = fids; f; f = f->next) | |
760 if(f->fid == fid) | |
761 return f; | |
762 else if(!ff && !f->busy) | |
763 ff = f; | |
764 if(ff){ | |
765 ff->fid = fid; | |
766 return ff; | |
767 } | |
768 f = vtmallocz(sizeof *f); | |
769 f->fid = fid; | |
770 f->next = fids; | |
771 fids = f; | |
772 return f; | |
773 } | |
774 | |
775 void | |
776 io(void) | |
777 { | |
778 char *err; | |
779 int n; | |
780 | |
781 for(;;){ | |
782 n = read9pmsg(mfd[0], mdata, sizeof mdata); | |
783 if(n <= 0) | |
784 break; | |
785 if(convM2S(mdata, n, &rhdr) != n) | |
786 sysfatal("convM2S conversion error"); | |
787 | |
788 if(dflag) | |
789 fprint(2, "vacfs:<-%F\n", &rhdr); | |
790 | |
791 thdr.data = (char*)mdata + IOHDRSZ; | |
792 if(!fcalls[rhdr.type]) | |
793 err = "bad fcall type"; | |
794 else | |
795 err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); | |
796 if(err){ | |
797 thdr.type = Rerror; | |
798 thdr.ename = err; | |
799 #ifdef PLAN9PORT | |
800 thdr.errornum = 0; | |
801 #endif | |
802 }else{ | |
803 thdr.type = rhdr.type + 1; | |
804 thdr.fid = rhdr.fid; | |
805 } | |
806 thdr.tag = rhdr.tag; | |
807 if(dflag) | |
808 fprint(2, "vacfs:->%F\n", &thdr); | |
809 n = convS2M(&thdr, mdata, messagesize); | |
810 if(n <= BIT16SZ) | |
811 sysfatal("convS2M conversion error"); | |
812 if(err) | |
813 vtfree(err); | |
814 | |
815 if(write(mfd[1], mdata, n) != n) | |
816 sysfatal("mount write: %r"); | |
817 } | |
818 } | |
819 | |
820 int | |
821 permf(VacFile *vf, char *user, int p) | |
822 { | |
823 VacDir dir; | |
824 ulong perm; | |
825 | |
826 if(vacfilegetdir(vf, &dir)) | |
827 return 0; | |
828 perm = dir.mode & 0777; | |
829 | |
830 if(noperm) | |
831 goto Good; | |
832 if((p*Pother) & perm) | |
833 goto Good; | |
834 if(strcmp(user, dir.gid)==0 && ((p*Pgroup) & perm)) | |
835 goto Good; | |
836 if(strcmp(user, dir.uid)==0 && ((p*Powner) & perm)) | |
837 goto Good; | |
838 vdcleanup(&dir); | |
839 return 0; | |
840 Good: | |
841 vdcleanup(&dir); | |
842 return 1; | |
843 } | |
844 | |
845 int | |
846 perm(Fid *f, int p) | |
847 { | |
848 return permf(f->file, f->user, p); | |
849 } | |
850 | |
851 void | |
852 vacshutdown(void) | |
853 { | |
854 Fid *f; | |
855 | |
856 for(f = fids; f; f = f->next) { | |
857 if(!f->busy) | |
858 continue; | |
859 rclunk(f); | |
860 } | |
861 | |
862 vacfsclose(fs); | |
863 vthangup(conn); | |
864 } |