main.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 <bits/fcntl.h> 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(fuselist); i++){ 1268 if(fuselist[i].op >= 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 }