| ---
tmain.c (26392B)
---
1 /*
2 * 9P to FUSE translator. Acts as FUSE server, 9P client.
3 * Mounts 9P servers via FUSE kernel module.
4 *
5 * There are four procs in this threaded program
6 * (ignoring the one that runs main and then exits).
7 * The first proc reads FUSE requests from /dev/fuse.
8 * It sends the requests over a channel to a second proc,
9 * which serves the requests. Each request runs in a
10 * thread in that second proc. Those threads do write
11 * FUSE replies, which in theory might block, but in practice don't.
12 * The 9P interactions are handled by lib9pclient, which
13 * allocates two more procs, one for reading and one for
14 * writing the 9P connection. Thus the many threads in the
15 * request proc can do 9P interactions without blocking.
16 */
17
18 #define _GNU_SOURCE 1 /* for O_DIRECTORY on Linux */
19 #include "a.h"
20
21 /* GNUisms */
22 #ifndef O_DIRECTORY
23 #define O_DIRECTORY 0
24 #endif
25
26 #ifndef O_LARGEFILE
27 # define O_LARGEFILE 0
28 #endif
29
30 /*
31 * Work around glibc's broken which defines
32 * O_LARGEFILE to 0 on 64 bit architectures. But, on those same
33 * architectures, linux _forces_ O_LARGEFILE (which is always
34 * 0100000 in the kernel) at each file open. FUSE is all too
35 * happy to pass the flag onto us, where we'd have no idea what
36 * to do with it if we trusted glibc.
37 *
38 * On ARM however, the O_LARGEFILE is set correctly.
39 */
40
41 #if defined(__linux__) && !defined(__arm__)
42 # undef O_LARGEFILE
43 # define O_LARGEFILE 0100000
44 #endif
45
46 #ifndef O_CLOEXEC
47 # if defined(__linux__)
48 # define O_CLOEXEC 02000000 /* Sigh */
49 # else
50 # define O_CLOEXEC 0
51 # endif
52 #endif
53
54 #ifndef FMODE_EXEC
55 # if defined(__linux__)
56 # define FMODE_EXEC 040
57 # else
58 # define FMODE_EXEC 0
59 # endif
60 #endif
61
62 int debug;
63 char *argv0;
64 char *aname = "";
65 void fusedispatch(void*);
66 Channel *fusechan;
67
68 enum
69 {
70 STACK = 8192
71 };
72
73 /*
74 * The number of seconds that the kernel can cache
75 * returned file attributes. FUSE's default is 1.0.
76 * I haven't experimented with using 0.
77 */
78 double attrtimeout = 1.0;
79
80 /*
81 * The number of seconds that the kernel can cache
82 * the returned entry nodeids returned by lookup.
83 * I haven't experimented with other values.
84 */
85 double entrytimeout = 1.0;
86
87 CFsys *fsys;
88 CFid *fsysroot;
89 void init9p(char*, char*);
90
91 void
92 usage(void)
93 {
94 fprint(2, "usage: 9pfuse [-D] [-A attrtimeout] [-a aname] address mtpt\n");
95 exit(1);
96 }
97
98 void fusereader(void*);
99 void watchfd(void*);
100
101 int
102 threadmaybackground(void)
103 {
104 return 1;
105 }
106
107 void
108 threadmain(int argc, char **argv)
109 {
110 ARGBEGIN{
111 case 'D':
112 chatty9pclient++;
113 debug++;
114 break;
115 case 'A':
116 attrtimeout = atof(EARGF(usage()));
117 break;
118 case 'a':
119 aname = EARGF(usage());
120 break;
121 default:
122 usage();
123 }ARGEND
124
125 if(argc != 2)
126 usage();
127
128 quotefmtinstall();
129 fmtinstall('F', fcallfmt);
130 fmtinstall('M', dirmodefmt);
131 fmtinstall('G', fusefmt);
132
133 setsid(); /* won't be able to use console, but can't be interrupted */
134
135 init9p(argv[0], aname);
136 initfuse(argv[1]);
137
138 fusechan = chancreate(sizeof(void*), 0);
139 proccreate(fusedispatch, nil, STACK);
140 sendp(fusechan, nil); /* sync */
141
142 proccreate(fusereader, nil, STACK);
143 /*
144 * Now that we're serving FUSE, we can wait
145 * for the mount to finish and exit back to the user.
146 */
147 waitfuse();
148 threadexits(0);
149 }
150
151 void
152 fusereader(void *v)
153 {
154 FuseMsg *m;
155
156 while((m = readfusemsg()) != nil)
157 sendp(fusechan, m);
158
159 fusemtpt = nil; /* no need to unmount */
160 threadexitsall(0);
161 }
162
163 void
164 init9p(char *addr, char *spec)
165 {
166 int fd;
167
168 if(strcmp(addr, "-") == 0)
169 fd = 0;
170 else
171 if((fd = dial(netmkaddr(addr, "tcp", "564"), nil, nil, nil)) < 0)
172 sysfatal("dial %s: %r", addr);
173 proccreate(watchfd, (void*)(uintptr)fd, STACK);
174 if((fsys = fsmount(fd, spec)) == nil)
175 sysfatal("fsmount: %r");
176 fsysroot = fsroot(fsys);
177 }
178
179 /*
180 * FUSE uses nodeids to refer to active "struct inodes"
181 * (9P's unopened fids). FUSE uses fhs to refer to active
182 * "struct fuse_files" (9P's opened fids). The choice of
183 * numbers is up to us except that nodeid 1 is the root directory.
184 * We use the same number space for both and call the
185 * bookkeeping structure a FuseFid.
186 *
187 * FUSE requires nodeids to have associated generation
188 * numbers. If we reuse a nodeid, we have to bump the
189 * generation number to guarantee that the nodeid,gen
190 * combination is never reused.
191 *
192 * There are also inode numbers returned in directory reads
193 * and file attributes, but these do NOT need to match the nodeids.
194 * We use a combination of qid.path and qid.type as the inode
195 * number.
196 */
197 /*
198 * TO DO: reference count the fids.
199 */
200 typedef struct Fusefid Fusefid;
201 struct Fusefid
202 {
203 Fusefid *next;
204 CFid *fid;
205 int ref;
206 int id;
207 int gen;
208 int isnodeid;
209
210 /* directory read state */
211 Dir *d0;
212 Dir *d;
213 int nd;
214 int off;
215 };
216
217 Fusefid **fusefid;
218 int nfusefid;
219 Fusefid *freefusefidlist;
220
221 Fusefid*
222 allocfusefid(void)
223 {
224 Fusefid *f;
225
226 if((f = freefusefidlist) == nil){
227 f = emalloc(sizeof *f);
228 fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid);
229 f->id = nfusefid;
230 fusefid[f->id] = f;
231 nfusefid++;
232 }else
233 freefusefidlist = f->next;
234 f->next = nil;
235 f->ref = 1;
236 f->isnodeid = -1;
237 return f;
238 }
239
240 void
241 freefusefid(Fusefid *f)
242 {
243 if(--f->ref > 0)
244 return;
245 assert(f->ref == 0);
246 if(f->fid)
247 fsclose(f->fid);
248 if(f->d0)
249 free(f->d0);
250 f->off = 0;
251 f->d0 = nil;
252 f->fid = nil;
253 f->d = nil;
254 f->nd = 0;
255 f->next = freefusefidlist;
256 f->isnodeid = -1;
257 freefusefidlist = f;
258 }
259
260 uvlong
261 _alloc(CFid *fid, int isnodeid)
262 {
263 Fusefid *ff;
264
265 ff = allocfusefid();
266 ff->fid = fid;
267 ff->isnodeid = isnodeid;
268 ff->gen++;
269 return ff->id+2; /* skip 0 and 1 */
270 }
271
272 uvlong
273 allocfh(CFid *fid)
274 {
275 return _alloc(fid, 0);
276 }
277
278 uvlong
279 allocnodeid(CFid *fid)
280 {
281 return _alloc(fid, 1);
282 }
283
284 Fusefid*
285 lookupfusefid(uvlong id, int isnodeid)
286 {
287 Fusefid *ff;
288 if(id < 2 || id >= nfusefid+2)
289 return nil;
290 ff = fusefid[(int)id-2];
291 if(ff->isnodeid != isnodeid)
292 return nil;
293 return ff;
294 }
295
296 CFid*
297 _lookupcfid(uvlong id, int isnodeid)
298 {
299 Fusefid *ff;
300
301 if((ff = lookupfusefid(id, isnodeid)) == nil)
302 return nil;
303 return ff->fid;
304 }
305
306 CFid*
307 fh2fid(uvlong fh)
308 {
309 return _lookupcfid(fh, 0);
310 }
311
312 CFid*
313 nodeid2fid(uvlong nodeid)
314 {
315 if(nodeid == 1)
316 return fsysroot;
317 return _lookupcfid(nodeid, 1);
318 }
319
320 uvlong
321 qid2inode(Qid q)
322 {
323 return q.path | ((uvlong)q.type<<56);
324 }
325
326 void
327 dir2attr(Dir *d, struct fuse_attr *attr)
328 {
329 attr->ino = qid2inode(d->qid);
330 attr->size = d->length;
331 attr->blocks = (d->length+8191)/8192;
332 attr->atime = d->atime;
333 attr->mtime = d->mtime;
334 attr->ctime = d->mtime; /* not right */
335 attr->atimensec = 0;
336 attr->mtimensec = 0;
337 attr->ctimensec = 0;
338 attr->mode = d->mode&0777;
339 if(d->mode&DMDIR)
340 attr->mode |= S_IFDIR;
341 else if(d->mode&DMSYMLINK)
342 attr->mode |= S_IFLNK;
343 else
344 attr->mode |= S_IFREG;
345 attr->nlink = 1; /* works for directories! - see FUSE FAQ */
346 attr->uid = getuid();
347 attr->gid = getgid();
348 attr->rdev = 0;
349 }
350
351 void
352 f2timeout(double f, __u64 *s, __u32 *ns)
353 {
354 *s = f;
355 *ns = (f - (int)f)*1e9;
356 }
357
358 void
359 dir2attrout(Dir *d, struct fuse_attr_out *out)
360 {
361 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
362 dir2attr(d, &out->attr);
363 }
364
365 /*
366 * Lookup. Walk to the name given as the argument.
367 * The response is a fuse_entry_out giving full stat info.
368 */
369 void
370 fuselookup(FuseMsg *m)
371 {
372 char *name;
373 Fusefid *ff;
374 CFid *fid, *newfid;
375 Dir *d;
376 struct fuse_entry_out out;
377
378 name = m->tx;
379 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
380 replyfuseerrno(m, ESTALE);
381 return;
382 }
383 if(strchr(name, '/')){
384 replyfuseerrno(m, ENOENT);
385 return;
386 }
387 if((newfid = fswalk(fid, name)) == nil){
388 replyfuseerrstr(m);
389 return;
390 }
391 if((d = fsdirfstat(newfid)) == nil){
392 fsclose(newfid);
393 replyfuseerrstr(m);
394 return;
395 }
396 out.nodeid = allocnodeid(newfid);
397 ff = lookupfusefid(out.nodeid, 1);
398 out.generation = ff->gen;
399 f2timeout(attrtimeout, &out.attr_valid, &out.attr_valid_nsec);
400 f2timeout(entrytimeout, &out.entry_valid, &out.entry_valid_nsec);
401 dir2attr(d, &out.attr);
402 free(d);
403 replyfuse(m, &out, sizeof out);
404 }
405
406 /*
407 * Forget. Reference-counted clunk for nodeids.
408 * Does not send a reply.
409 * Each lookup response gives the kernel an additional reference
410 * to the returned nodeid. Forget says "drop this many references
411 * to this nodeid". Our fuselookup, when presented with the same query,
412 * does not return the same results (it allocates a new nodeid for each
413 * call), but if that ever changes, fuseforget already handles the ref
414 * counts properly.
415 */
416 void
417 fuseforget(FuseMsg *m)
418 {
419 struct fuse_forget_in *in;
420 Fusefid *ff;
421
422 in = m->tx;
423 if((ff = lookupfusefid(m->hdr->nodeid, 1)) == nil)
424 return;
425 if(ff->ref > in->nlookup){
426 ff->ref -= in->nlookup;
427 return;
428 }
429 if(ff->ref < in->nlookup)
430 fprint(2, "bad count in forget\n");
431 ff->ref = 1;
432 freefusefid(ff);
433 freefusemsg(m);
434 }
435
436 /*
437 * Getattr.
438 * Replies with a fuse_attr_out structure giving the
439 * attr for the requested nodeid in out.attr.
440 * Out.attr_valid and out.attr_valid_nsec give
441 * the amount of time that the attributes can
442 * be cached.
443 *
444 * Empirically, though, if I run ls -ld on the root
445 * twice back to back, I still get two getattrs,
446 * even with a one second attribute timeout!
447 */
448 void
449 fusegetattr(FuseMsg *m)
450 {
451 CFid *fid;
452 struct fuse_attr_out out;
453 Dir *d;
454
455 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
456 replyfuseerrno(m, ESTALE);
457 return;
458 }
459 if((d = fsdirfstat(fid)) == nil){
460 replyfuseerrstr(m);
461 return;
462 }
463 memset(&out, 0, sizeof out);
464 dir2attrout(d, &out);
465 free(d);
466 replyfuse(m, &out, sizeof out);
467 }
468
469 /*
470 * Setattr.
471 * FUSE treats the many Unix attribute setting routines
472 * more or less like 9P does, with a single message.
473 */
474 void
475 fusesetattr(FuseMsg *m)
476 {
477 CFid *fid, *nfid;
478 Dir d, *dd;
479 struct fuse_setattr_in *in;
480 struct fuse_attr_out out;
481
482 in = m->tx;
483 if(in->valid&FATTR_FH){
484 if((fid = fh2fid(in->fh)) == nil){
485 replyfuseerrno(m, ESTALE);
486 return;
487 }
488 }else{
489 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
490 replyfuseerrno(m, ESTALE);
491 return;
492 }
493 /*
494 * Special case: Linux issues a size change to
495 * truncate a file before opening it OTRUNC.
496 * Synthetic file servers (e.g., plumber) honor
497 * open(OTRUNC) but not wstat.
498 */
499 if(in->valid == FATTR_SIZE && in->size == 0){
500 if((nfid = fswalk(fid, nil)) == nil){
501 replyfuseerrstr(m);
502 return;
503 }
504 if(fsfopen(nfid, OWRITE|OTRUNC) < 0){
505 replyfuseerrstr(m);
506 fsclose(nfid);
507 return;
508 }
509 fsclose(nfid);
510 goto stat;
511 }
512 }
513
514 nulldir(&d);
515 if(in->valid&FATTR_SIZE)
516 d.length = in->size;
517 if(in->valid&FATTR_ATIME)
518 d.atime = in->atime;
519 if(in->valid&FATTR_MTIME)
520 d.mtime = in->mtime;
521 if(in->valid&FATTR_MODE)
522 d.mode = in->mode & 0777;
523 if((in->mode&S_IFMT) == S_IFDIR)
524 d.mode |= DMDIR;
525 if((in->valid&FATTR_UID) || (in->valid&FATTR_GID)){
526 /*
527 * I can't be bothered with these yet.
528 */
529 replyfuseerrno(m, EPERM);
530 return;
531 }
532 if(fsdirfwstat(fid, &d) < 0){
533 replyfuseerrstr(m);
534 return;
535 }
536 stat:
537 if((dd = fsdirfstat(fid)) == nil){
538 replyfuseerrstr(m);
539 return;
540 }
541 memset(&out, 0, sizeof out);
542 dir2attrout(dd, &out);
543 free(dd);
544 replyfuse(m, &out, sizeof out);
545 }
546
547 CFid*
548 _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err)
549 {
550 CFid *fid, *newfid;
551
552 if((fid = nodeid2fid(nodeid)) == nil){
553 *err = ESTALE;
554 return nil;
555 }
556 if(isdir && !(fsqid(fid).type&QTDIR)){
557 *err = ENOTDIR;
558 return nil;
559 }
560 if(openmode != OREAD && fsqid(fid).type&QTDIR){
561 *err = EISDIR;
562 return nil;
563 }
564
565 /* Clone fid to get one we can open. */
566 newfid = fswalk(fid, nil);
567 if(newfid == nil){
568 *err = errstr2errno();
569 return nil;
570 }
571
572 if(fsfopen(newfid, openmode) < 0){
573 *err = errstr2errno();
574 fsclose(newfid);
575 return nil;
576 }
577
578 return newfid;
579 }
580
581 /*
582 * Open & Opendir.
583 * Argument is a struct fuse_open_in.
584 * The mode field is ignored (presumably permission bits)
585 * and flags is the open mode.
586 * Replies with a struct fuse_open_out.
587 */
588 void
589 _fuseopen(FuseMsg *m, int isdir)
590 {
591 struct fuse_open_in *in;
592 struct fuse_open_out out;
593 CFid *fid;
594 int openmode, flags, err;
595
596 in = m->tx;
597 flags = in->flags;
598 openmode = flags&3;
599 flags &= ~3;
600 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|FMODE_EXEC);
601 #ifdef O_NOFOLLOW
602 flags &= ~O_NOFOLLOW;
603 #endif
604 #ifdef O_LARGEFILE
605 flags &= ~O_LARGEFILE;
606 #endif
607
608 /*
609 * Discarding O_APPEND here is not completely wrong,
610 * because the host kernel will rewrite the offsets
611 * of write system calls for us. That's the best we
612 * can do on Unix anyway.
613 */
614 flags &= ~O_APPEND;
615 if(flags & O_TRUNC){
616 openmode |= OTRUNC;
617 flags &= ~O_TRUNC;
618 }
619
620 /*
621 * Could translate but not standard 9P:
622 * O_DIRECT -> ODIRECT
623 * O_NONBLOCK -> ONONBLOCK
624 */
625 if(flags){
626 fprint(2, "unexpected open flags requested=%#uo unhandled=%#uo\n", (uint)in->flags, (uint)flags);
627 replyfuseerrno(m, EACCES);
628 return;
629 }
630 if((fid = _fuseopenfid(m->hdr->nodeid, isdir, openmode, &err)) == nil){
631 replyfuseerrno(m, err);
632 return;
633 }
634 out.fh = allocfh(fid);
635 out.open_flags = FOPEN_DIRECT_IO; /* no page cache */
636 replyfuse(m, &out, sizeof out);
637 }
638
639 void
640 fuseopen(FuseMsg *m)
641 {
642 _fuseopen(m, 0);
643 }
644
645 void
646 fuseopendir(FuseMsg *m)
647 {
648 _fuseopen(m, 1);
649 }
650
651 /*
652 * Create & Mkdir.
653 */
654 CFid*
655 _fusecreate(uvlong nodeid, char *name, int perm, int ismkdir, int omode, struct fuse_entry_out *out, int *err)
656 {
657 CFid *fid, *newfid, *newfid2;
658 Dir *d;
659 Fusefid *ff;
660
661 if((fid = nodeid2fid(nodeid)) == nil){
662 *err = ESTALE;
663 return nil;
664 }
665 perm &= 0777;
666 if(ismkdir)
667 perm |= DMDIR;
668 if(ismkdir && omode != OREAD){
669 *err = EPERM;
670 return nil;
671 }
672 if((newfid = fswalk(fid, nil)) == nil){
673 *err = errstr2errno();
674 return nil;
675 }
676 if(fsfcreate(newfid, name, omode, perm) < 0){
677 *err = errstr2errno();
678 fsclose(newfid);
679 return nil;
680 }
681 if((d = fsdirfstat(newfid)) == nil){
682 *err = errstr2errno();
683 fsfremove(newfid);
684 return nil;
685 }
686 /*
687 * This fid is no good, because it's open.
688 * We need an unopened fid. Sigh.
689 */
690 if((newfid2 = fswalk(fid, name)) == nil){
691 *err = errstr2errno();
692 free(d);
693 fsfremove(newfid);
694 return nil;
695 }
696 out->nodeid = allocnodeid(newfid2);
697 ff = lookupfusefid(out->nodeid, 1);
698 out->generation = ff->gen;
699 f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
700 f2timeout(entrytimeout, &out->entry_valid, &out->entry_valid_nsec);
701 dir2attr(d, &out->attr);
702 free(d);
703 return newfid;
704 }
705
706 void
707 fusemkdir(FuseMsg *m)
708 {
709 struct fuse_mkdir_in *in;
710 struct fuse_entry_out out;
711 CFid *fid;
712 int err;
713 char *name;
714
715 in = m->tx;
716 name = (char*)(in+1);
717 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){
718 replyfuseerrno(m, err);
719 return;
720 }
721 /* Toss the open fid. */
722 fsclose(fid);
723 replyfuse(m, &out, sizeof out);
724 }
725
726 void
727 fusecreate(FuseMsg *m)
728 {
729 struct fuse_open_in *in;
730 struct fuse_create_out out;
731 CFid *fid;
732 int err, openmode, flags;
733 char *name;
734
735 in = m->tx;
736 flags = in->flags;
737 openmode = in->flags&3;
738 flags &= ~3;
739 flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_EXCL);
740 flags &= ~O_APPEND; /* see comment in _fuseopen */
741 flags &= ~(O_CREAT|O_TRUNC); /* huh? */
742 if(flags){
743 fprint(2, "bad mode %#uo\n", in->flags);
744 replyfuseerrno(m, EACCES);
745 return;
746 }
747 name = (char*)(in+1);
748 if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 0, openmode, &out.e, &err)) == nil){
749 replyfuseerrno(m, err);
750 return;
751 }
752 out.o.fh = allocfh(fid);
753 out.o.open_flags = FOPEN_DIRECT_IO; /* no page cache */
754 replyfuse(m, &out, sizeof out);
755 }
756
757 /*
758 * Access.
759 * Lib9pclient implements this just as Plan 9 does,
760 * by opening the file (or not) and then closing it.
761 */
762 void
763 fuseaccess(FuseMsg *m)
764 {
765 struct fuse_access_in *in;
766 CFid *fid;
767 int err, omode;
768 static int a2o[] = {
769 0,
770 OEXEC,
771 OWRITE,
772 ORDWR,
773 OREAD,
774 OEXEC,
775 ORDWR,
776 ORDWR
777 };
778
779 in = m->tx;
780 if(in->mask >= nelem(a2o)){
781 replyfuseerrno(m, EINVAL);
782 return;
783 }
784 omode = a2o[in->mask];
785 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
786 replyfuseerrno(m, ESTALE);
787 return;
788 }
789 if(fsqid(fid).type&QTDIR)
790 omode = OREAD;
791 if((fid = _fuseopenfid(m->hdr->nodeid, 0, omode, &err)) == nil){
792 replyfuseerrno(m, err);
793 return;
794 }
795 fsclose(fid);
796 replyfuse(m, nil, 0);
797 }
798
799 /*
800 * Release.
801 * Equivalent of clunk for file handles.
802 * in->flags is the open mode used in Open or Opendir.
803 */
804 void
805 fuserelease(FuseMsg *m)
806 {
807 struct fuse_release_in *in;
808 Fusefid *ff;
809
810 in = m->tx;
811 if((ff = lookupfusefid(in->fh, 0)) != nil)
812 freefusefid(ff);
813 else
814 fprint(2, "fuserelease: fh not found\n");
815 replyfuse(m, nil, 0);
816 }
817
818 void
819 fusereleasedir(FuseMsg *m)
820 {
821 fuserelease(m);
822 }
823
824 /*
825 * Read.
826 * Read from file handle in->fh at offset in->offset for size in->size.
827 * We truncate size to maxwrite just to keep the buffer reasonable.
828 */
829 void
830 fuseread(FuseMsg *m)
831 {
832 int n;
833 uchar *buf;
834 CFid *fid;
835 struct fuse_read_in *in;
836
837 in = m->tx;
838 if((fid = fh2fid(in->fh)) == nil){
839 replyfuseerrno(m, ESTALE);
840 return;
841 }
842 n = in->size;
843 if(n > fusemaxwrite)
844 n = fusemaxwrite;
845 buf = emalloc(n);
846 n = fspread(fid, buf, n, in->offset);
847 if(n < 0){
848 free(buf);
849 replyfuseerrstr(m);
850 return;
851 }
852 replyfuse(m, buf, n);
853 free(buf);
854 }
855
856 /*
857 * Readlink.
858 */
859 void
860 fusereadlink(FuseMsg *m)
861 {
862 Dir *d;
863 CFid *fid;
864
865 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
866 replyfuseerrno(m, ESTALE);
867 return;
868 }
869 if((d = fsdirfstat(fid)) == nil){
870 replyfuseerrstr(m);
871 return;
872 }
873 if(!(d->mode&DMSYMLINK)){
874 replyfuseerrno(m, EINVAL);
875 return;
876 }
877 replyfuse(m, d->ext, strlen(d->ext));
878 free(d);
879 return;
880 }
881
882 /*
883 * Readdir.
884 * Read from file handle in->fh at offset in->offset for size in->size.
885 * We truncate size to maxwrite just to keep the buffer reasonable.
886 * We assume 9P directory read semantics: a read at offset 0 rewinds
887 * and a read at any other offset starts where we left off.
888 * If it became necessary, we could implement a crude seek
889 * or cache the entire list of directory entries.
890 * Directory entries read from 9P but not yet handed to FUSE
891 * are stored in m->d,nd,d0.
892 */
893 int canpack(Dir*, uvlong, uchar**, uchar*);
894 Dir *dotdir(CFid*);
895 void
896 fusereaddir(FuseMsg *m)
897 {
898 struct fuse_read_in *in;
899 uchar *buf, *p, *ep;
900 int n;
901 Fusefid *ff;
902
903 in = m->tx;
904 if((ff = lookupfusefid(in->fh, 0)) == nil){
905 replyfuseerrno(m, ESTALE);
906 return;
907 }
908 if(in->offset == 0){
909 fsseek(ff->fid, 0, 0);
910 free(ff->d0);
911 ff->d0 = ff->d = dotdir(ff->fid);
912 ff->nd = 1;
913 }
914 n = in->size;
915 if(n > fusemaxwrite)
916 n = fusemaxwrite;
917 buf = emalloc(n);
918 p = buf;
919 ep = buf + n;
920 for(;;){
921 while(ff->nd > 0){
922 if(!canpack(ff->d, ff->off, &p, ep))
923 goto out;
924 ff->off++;
925 ff->d++;
926 ff->nd--;
927 }
928 free(ff->d0);
929 ff->d0 = nil;
930 ff->d = nil;
931 if((ff->nd = fsdirread(ff->fid, &ff->d0)) < 0){
932 replyfuseerrstr(m);
933 free(buf);
934 return;
935 }
936 if(ff->nd == 0)
937 break;
938 ff->d = ff->d0;
939 }
940 out:
941 replyfuse(m, buf, p - buf);
942 free(buf);
943 }
944
945 /*
946 * Fuse assumes that it can always read two directory entries.
947 * If it gets just one, it will double it in the dirread results.
948 * Thus if a directory contains just "a", you see "a" twice.
949 * Adding . as the first directory entry works around this.
950 * We could add .. too, but it isn't necessary.
951 */
952 Dir*
953 dotdir(CFid *f)
954 {
955 Dir *d;
956
957 d = emalloc(1*sizeof *d);
958 d[0].name = ".";
959 d[0].qid = fsqid(f);
960 return d;
961 }
962
963 int
964 canpack(Dir *d, uvlong off, uchar **pp, uchar *ep)
965 {
966 uchar *p;
967 struct fuse_dirent *de;
968 int pad, size;
969
970 p = *pp;
971 size = FUSE_NAME_OFFSET + strlen(d->name);
972 pad = 0;
973 if(size%8)
974 pad = 8 - size%8;
975 if(size+pad > ep - p)
976 return 0;
977 de = (struct fuse_dirent*)p;
978 de->ino = qid2inode(d->qid);
979 de->off = off;
980 de->namelen = strlen(d->name);
981 memmove(de->name, d->name, de->namelen);
982 if(pad > 0)
983 memset(de->name+de->namelen, 0, pad);
984 *pp = p+size+pad;
985 return 1;
986 }
987
988 /*
989 * Write.
990 * Write from file handle in->fh at offset in->offset for size in->size.
991 * Don't know what in->write_flags means.
992 *
993 * Apparently implementations are allowed to buffer these writes
994 * and wait until Flush is sent, but FUSE docs say flush may be
995 * called zero, one, or even more times per close. So better do the
996 * actual writing here. Also, errors that happen during Flush just
997 * show up in the close() return status, which no one checks anyway.
998 */
999 void
1000 fusewrite(FuseMsg *m)
1001 {
1002 struct fuse_write_in *in;
1003 struct fuse_write_out out;
1004 void *a;
1005 CFid *fid;
1006 int n;
1007
1008 in = m->tx;
1009 a = in+1;
1010 if((fid = fh2fid(in->fh)) == nil){
1011 replyfuseerrno(m, ESTALE);
1012 return;
1013 }
1014 if(in->size > fusemaxwrite){
1015 replyfuseerrno(m, EINVAL);
1016 return;
1017 }
1018 n = fspwrite(fid, a, in->size, in->offset);
1019 if(n < 0){
1020 replyfuseerrstr(m);
1021 return;
1022 }
1023 out.size = n;
1024 replyfuse(m, &out, sizeof out);
1025 }
1026
1027 /*
1028 * Flush. Supposed to flush any buffered writes. Don't use this.
1029 *
1030 * Flush is a total crock. It gets called on close() of a file descriptor
1031 * associated with this open file. Some open files have multiple file
1032 * descriptors and thus multiple closes of those file descriptors.
1033 * In those cases, Flush is called multiple times. Some open files
1034 * have file descriptors that are closed on process exit instead of
1035 * closed explicitly. For those files, Flush is never called.
1036 * Even more amusing, Flush gets called before close() of read-only
1037 * file descriptors too!
1038 *
1039 * This is just a bad idea.
1040 */
1041 void
1042 fuseflush(FuseMsg *m)
1043 {
1044 replyfuse(m, nil, 0);
1045 }
1046
1047 /*
1048 * Unlink & Rmdir.
1049 */
1050 void
1051 _fuseremove(FuseMsg *m, int isdir)
1052 {
1053 char *name;
1054 CFid *fid, *newfid;
1055
1056 name = m->tx;
1057 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1058 replyfuseerrno(m, ESTALE);
1059 return;
1060 }
1061 if(strchr(name, '/')){
1062 replyfuseerrno(m, ENOENT);
1063 return;
1064 }
1065 if((newfid = fswalk(fid, name)) == nil){
1066 replyfuseerrstr(m);
1067 return;
1068 }
1069 if(isdir && !(fsqid(newfid).type&QTDIR)){
1070 replyfuseerrno(m, ENOTDIR);
1071 fsclose(newfid);
1072 return;
1073 }
1074 if(!isdir && (fsqid(newfid).type&QTDIR)){
1075 replyfuseerrno(m, EISDIR);
1076 fsclose(newfid);
1077 return;
1078 }
1079 if(fsfremove(newfid) < 0){
1080 replyfuseerrstr(m);
1081 return;
1082 }
1083 replyfuse(m, nil, 0);
1084 }
1085
1086 void
1087 fuseunlink(FuseMsg *m)
1088 {
1089 _fuseremove(m, 0);
1090 }
1091
1092 void
1093 fusermdir(FuseMsg *m)
1094 {
1095 _fuseremove(m, 1);
1096 }
1097
1098 /*
1099 * Rename.
1100 *
1101 * FUSE sends the nodeid for the source and destination
1102 * directory and then the before and after names as strings.
1103 * 9P can only do the rename if the source and destination
1104 * are the same. If the same nodeid is used for source and
1105 * destination, we're fine, but if FUSE gives us different nodeids
1106 * that happen to correspond to the same directory, we have
1107 * no way of figuring that out. Let's hope it doesn't happen too often.
1108 */
1109 void
1110 fuserename(FuseMsg *m)
1111 {
1112 struct fuse_rename_in *in;
1113 char *before, *after;
1114 CFid *fid, *newfid;
1115 Dir d;
1116
1117 in = m->tx;
1118 if(in->newdir != m->hdr->nodeid){
1119 replyfuseerrno(m, EXDEV);
1120 return;
1121 }
1122 before = (char*)(in+1);
1123 after = before + strlen(before) + 1;
1124 if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1125 replyfuseerrno(m, ESTALE);
1126 return;
1127 }
1128 if(strchr(before, '/') || strchr(after, '/')){
1129 replyfuseerrno(m, ENOENT);
1130 return;
1131 }
1132 if((newfid = fswalk(fid, before)) == nil){
1133 replyfuseerrstr(m);
1134 return;
1135 }
1136 nulldir(&d);
1137 d.name = after;
1138 if(fsdirfwstat(newfid, &d) < 0){
1139 replyfuseerrstr(m);
1140 fsclose(newfid);
1141 return;
1142 }
1143 fsclose(newfid);
1144 replyfuse(m, nil, 0);
1145 }
1146
1147 /*
1148 * Fsync. Commit file info to stable storage.
1149 * Not sure what in->fsync_flags are.
1150 */
1151 void
1152 fusefsync(FuseMsg *m)
1153 {
1154 struct fuse_fsync_in *in;
1155 CFid *fid;
1156 Dir d;
1157
1158 in = m->tx;
1159 if((fid = fh2fid(in->fh)) == nil){
1160 replyfuseerrno(m, ESTALE);
1161 return;
1162 }
1163 nulldir(&d);
1164 if(fsdirfwstat(fid, &d) < 0){
1165 replyfuseerrstr(m);
1166 return;
1167 }
1168 replyfuse(m, nil, 0);
1169 }
1170
1171 /*
1172 * Fsyncdir. Commit dir info to stable storage?
1173 */
1174 void
1175 fusefsyncdir(FuseMsg *m)
1176 {
1177 fusefsync(m);
1178 }
1179
1180 /*
1181 * Statfs. Send back information about file system.
1182 * Not really worth implementing, except that if we
1183 * reply with ENOSYS, programs like df print messages like
1184 * df: `/tmp/z': Function not implemented
1185 * and that gets annoying. Returning all zeros excludes
1186 * us from df without appearing to cause any problems.
1187 */
1188 void
1189 fusestatfs(FuseMsg *m)
1190 {
1191 struct fuse_statfs_out out;
1192
1193 memset(&out, 0, sizeof out);
1194 replyfuse(m, &out, sizeof out);
1195 }
1196
1197 void (*fusehandlers[100])(FuseMsg*);
1198
1199 struct {
1200 int op;
1201 void (*fn)(FuseMsg*);
1202 } fuselist[] = {
1203 { FUSE_LOOKUP, fuselookup },
1204 { FUSE_FORGET, fuseforget },
1205 { FUSE_GETATTR, fusegetattr },
1206 { FUSE_SETATTR, fusesetattr },
1207 /*
1208 * FUSE_SYMLINK, FUSE_MKNOD are unimplemented.
1209 */
1210 { FUSE_READLINK, fusereadlink },
1211 { FUSE_MKDIR, fusemkdir },
1212 { FUSE_UNLINK, fuseunlink },
1213 { FUSE_RMDIR, fusermdir },
1214 { FUSE_RENAME, fuserename },
1215 /*
1216 * FUSE_LINK is unimplemented.
1217 */
1218 { FUSE_OPEN, fuseopen },
1219 { FUSE_READ, fuseread },
1220 { FUSE_WRITE, fusewrite },
1221 { FUSE_STATFS, fusestatfs },
1222 { FUSE_RELEASE, fuserelease },
1223 { FUSE_FSYNC, fusefsync },
1224 /*
1225 * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and
1226 * FUSE_REMOVEXATTR are unimplemented.
1227 * FUSE will stop sending these requests after getting
1228 * an -ENOSYS reply (see dispatch below).
1229 */
1230 { FUSE_FLUSH, fuseflush },
1231 /*
1232 * FUSE_INIT is handled in initfuse and should not be seen again.
1233 */
1234 { FUSE_OPENDIR, fuseopendir },
1235 { FUSE_READDIR, fusereaddir },
1236 { FUSE_RELEASEDIR, fusereleasedir },
1237 { FUSE_FSYNCDIR, fusefsyncdir },
1238 { FUSE_ACCESS, fuseaccess },
1239 { FUSE_CREATE, fusecreate },
1240 };
1241
1242 void
1243 fusethread(void *v)
1244 {
1245 FuseMsg *m;
1246
1247 m = v;
1248 if((uint)m->hdr->opcode >= nelem(fusehandlers)
1249 || !fusehandlers[m->hdr->opcode]){
1250 replyfuseerrno(m, ENOSYS);
1251 return;
1252 }
1253 fusehandlers[m->hdr->opcode](m);
1254 }
1255
1256 void
1257 fusedispatch(void *v)
1258 {
1259 int i;
1260 FuseMsg *m;
1261
1262 eofkill9pclient = 1; /* threadexitsall on 9P eof */
1263 atexit(unmountatexit);
1264
1265 recvp(fusechan); /* sync */
1266
1267 for(i=0; i= nelem(fusehandlers))
1269 sysfatal("make fusehandlers bigger op=%d", fuselist[i].op);
1270 fusehandlers[fuselist[i].op] = fuselist[i].fn;
1271 }
1272
1273 while((m = recvp(fusechan)) != nil) {
1274 switch(m->hdr->opcode) {
1275 case FUSE_FORGET:
1276 fusehandlers[m->hdr->opcode](m);
1277 break;
1278 default:
1279 threadcreate(fusethread, m, STACK);
1280 }
1281 }
1282 }
1283
1284 void*
1285 emalloc(uint n)
1286 {
1287 void *p;
1288
1289 p = malloc(n);
1290 if(p == nil)
1291 sysfatal("malloc(%d): %r", n);
1292 memset(p, 0, n);
1293 return p;
1294 }
1295
1296 void*
1297 erealloc(void *p, uint n)
1298 {
1299 p = realloc(p, n);
1300 if(p == nil)
1301 sysfatal("realloc(..., %d): %r", n);
1302 return p;
1303 }
1304
1305 char*
1306 estrdup(char *p)
1307 {
1308 char *pp;
1309 pp = strdup(p);
1310 if(pp == nil)
1311 sysfatal("strdup(%.20s): %r", p);
1312 return pp;
1313 }
1314
1315 void
1316 watchfd(void *v)
1317 {
1318 int fd = (int)(uintptr)v;
1319
1320 /* wait for exception (file closed) */
1321 fd_set set;
1322 FD_ZERO(&set);
1323 FD_SET(fd, &set);
1324 if(select(fd+1, NULL, NULL, &set, NULL) >= 0)
1325 threadexitsall(nil);
1326 return;
1327 } |