1 /* $OpenBSD: fuse.c,v 1.43 2017/12/18 14:20:23 helg Exp $ */ 2 /* 3 * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/wait.h> 19 #include <sys/types.h> 20 #include <sys/ioctl.h> 21 22 #include <miscfs/fuse/fusefs.h> 23 24 #include <errno.h> 25 #include <signal.h> 26 #include <stddef.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "fuse_opt.h" 32 #include "fuse_private.h" 33 #include "debug.h" 34 35 static volatile sig_atomic_t sigraised = 0; 36 static volatile sig_atomic_t signum = 0; 37 static struct fuse_context *ictx = NULL; 38 39 enum { 40 KEY_DEBUG, 41 KEY_FOREGROUND, 42 KEY_HELP, 43 KEY_HELP_WITHOUT_HEADER, 44 KEY_VERSION, 45 KEY_MAXREAD, 46 KEY_STUB 47 }; 48 49 /* options supported by fuse_parse_cmdline */ 50 static struct fuse_opt fuse_core_opts[] = { 51 FUSE_OPT_KEY("-d", KEY_DEBUG), 52 FUSE_OPT_KEY("debug", KEY_DEBUG), 53 FUSE_OPT_KEY("-f", KEY_FOREGROUND), 54 FUSE_OPT_KEY("-h", KEY_HELP), 55 FUSE_OPT_KEY("--help", KEY_HELP), 56 FUSE_OPT_KEY("-ho", KEY_HELP_WITHOUT_HEADER), 57 FUSE_OPT_KEY("-s", KEY_STUB), 58 FUSE_OPT_KEY("-V", KEY_VERSION), 59 FUSE_OPT_KEY("--version", KEY_VERSION), 60 FUSE_OPT_END 61 }; 62 63 /* options supported by fuse_new */ 64 #define FUSE_LIB_OPT(o, m) {o, offsetof(struct fuse_config, m), 1} 65 static struct fuse_opt fuse_lib_opts[] = { 66 FUSE_OPT_KEY("ac_attr_timeout=", KEY_STUB), 67 FUSE_OPT_KEY("allow_other", KEY_STUB), 68 FUSE_OPT_KEY("allow_root", KEY_STUB), 69 FUSE_OPT_KEY("attr_timeout=", KEY_STUB), 70 FUSE_OPT_KEY("auto_cache", KEY_STUB), 71 FUSE_OPT_KEY("noauto_cache", KEY_STUB), 72 FUSE_OPT_KEY("big_writes", KEY_STUB), 73 FUSE_OPT_KEY("debug", KEY_DEBUG), 74 FUSE_OPT_KEY("-d", KEY_DEBUG), 75 FUSE_OPT_KEY("entry_timeout=", KEY_STUB), 76 FUSE_LIB_OPT("gid=", set_gid), 77 FUSE_LIB_OPT("gid=%u", gid), 78 FUSE_OPT_KEY("hard_remove", KEY_STUB), 79 FUSE_OPT_KEY("intr_signal", KEY_STUB), 80 FUSE_OPT_KEY("kernel_cache", KEY_STUB), 81 FUSE_OPT_KEY("large_read", KEY_STUB), 82 FUSE_OPT_KEY("modules=", KEY_STUB), 83 FUSE_OPT_KEY("negative_timeout=", KEY_STUB), 84 FUSE_OPT_KEY("readdir_ino", KEY_STUB), 85 FUSE_OPT_KEY("relatime", KEY_STUB), 86 FUSE_OPT_KEY("subtype=", KEY_STUB), 87 FUSE_LIB_OPT("uid=", set_uid), 88 FUSE_LIB_OPT("uid=%u", uid), 89 FUSE_OPT_KEY("use_ino", KEY_STUB), 90 FUSE_OPT_KEY("dmask=%o", KEY_STUB), 91 FUSE_OPT_KEY("fmask=%o", KEY_STUB), 92 FUSE_LIB_OPT("umask=", set_mode), 93 FUSE_LIB_OPT("umask=%o", umask), 94 FUSE_OPT_END 95 }; 96 97 /* options supported by fuse_mount */ 98 #define FUSE_MOUNT_OPT(o, m) {o, offsetof(struct fuse_mount_opts, m), 1} 99 static struct fuse_opt fuse_mount_opts[] = { 100 FUSE_OPT_KEY("async_read", KEY_STUB), 101 FUSE_OPT_KEY("blkdev", KEY_STUB), 102 FUSE_OPT_KEY("blksize=", KEY_STUB), 103 FUSE_MOUNT_OPT("default_permissions", def_perms), 104 FUSE_OPT_KEY("direct_io", KEY_STUB), 105 FUSE_MOUNT_OPT("fsname=%s", fsname), 106 FUSE_MOUNT_OPT("max_read=%u", max_read), 107 FUSE_OPT_KEY("max_readahead", KEY_STUB), 108 FUSE_OPT_KEY("max_write", KEY_STUB), 109 FUSE_MOUNT_OPT("noatime", noatime), 110 FUSE_MOUNT_OPT("nonempty", nonempty), 111 FUSE_MOUNT_OPT("-r", rdonly), 112 FUSE_MOUNT_OPT("ro", rdonly), 113 FUSE_OPT_KEY("ro_fallback", KEY_STUB), 114 FUSE_OPT_KEY("sync_read", KEY_STUB), 115 FUSE_OPT_END 116 }; 117 118 static void 119 ifuse_sighdlr(int num) 120 { 121 if (!sigraised || (num == SIGCHLD)) { 122 sigraised = 1; 123 signum = num; 124 } 125 } 126 127 static void 128 ifuse_try_unmount(struct fuse *f) 129 { 130 pid_t child; 131 132 signal(SIGCHLD, ifuse_sighdlr); 133 134 /* unmount in another thread so fuse_loop() doesn't deadlock */ 135 child = fork(); 136 137 if (child < 0) { 138 DPERROR(__func__); 139 return; 140 } 141 142 if (child == 0) { 143 fuse_remove_signal_handlers(fuse_get_session(f)); 144 errno = 0; 145 fuse_unmount(f->fc->dir, f->fc); 146 _exit(errno); 147 } 148 } 149 150 static void 151 ifuse_child_exit(const struct fuse *f) 152 { 153 int status; 154 155 signal(SIGCHLD, SIG_DFL); 156 if (waitpid(WAIT_ANY, &status, WNOHANG) == -1) 157 fprintf(stderr, "fuse: %s\n", strerror(errno)); 158 159 if (WIFEXITED(status) && (WEXITSTATUS(status) != 0)) 160 fprintf(stderr, "fuse: %s: %s\n", 161 f->fc->dir, strerror(WEXITSTATUS(status))); 162 163 sigraised = 0; 164 return; 165 } 166 167 int 168 fuse_loop(struct fuse *fuse) 169 { 170 struct fusebuf fbuf; 171 struct fuse_context ctx; 172 struct fb_ioctl_xch ioexch; 173 struct kevent ev; 174 ssize_t n; 175 int ret; 176 177 if (fuse == NULL) 178 return (-1); 179 180 fuse->fc->kq = kqueue(); 181 if (fuse->fc->kq == -1) 182 return (-1); 183 184 EV_SET(&fuse->fc->event, fuse->fc->fd, EVFILT_READ, EV_ADD | 185 EV_ENABLE, 0, 0, 0); 186 187 while (!fuse->fc->dead) { 188 ret = kevent(fuse->fc->kq, &fuse->fc->event, 1, &ev, 1, NULL); 189 if (ret == -1) { 190 if (errno == EINTR) { 191 switch (signum) { 192 case SIGCHLD: 193 ifuse_child_exit(fuse); 194 break; 195 case SIGHUP: 196 case SIGINT: 197 case SIGTERM: 198 ifuse_try_unmount(fuse); 199 break; 200 default: 201 fprintf(stderr, "%s: %s\n", __func__, 202 strsignal(signum)); 203 } 204 } else 205 DPERROR(__func__); 206 } else if (ret > 0) { 207 n = read(fuse->fc->fd, &fbuf, sizeof(fbuf)); 208 if (n != sizeof(fbuf)) { 209 fprintf(stderr, "%s: bad fusebuf read\n", 210 __func__); 211 return (-1); 212 } 213 214 /* check if there is data something present */ 215 if (fbuf.fb_len) { 216 fbuf.fb_dat = malloc(fbuf.fb_len); 217 if (fbuf.fb_dat == NULL) 218 return (-1); 219 ioexch.fbxch_uuid = fbuf.fb_uuid; 220 ioexch.fbxch_len = fbuf.fb_len; 221 ioexch.fbxch_data = fbuf.fb_dat; 222 223 if (ioctl(fuse->fc->fd, FIOCGETFBDAT, 224 &ioexch)) { 225 free(fbuf.fb_dat); 226 return (-1); 227 } 228 } 229 230 ctx.fuse = fuse; 231 ctx.uid = fuse->conf.uid; 232 ctx.gid = fuse->conf.gid; 233 ctx.pid = fuse->conf.pid; 234 ctx.umask = fuse->conf.umask; 235 ctx.private_data = fuse->private_data; 236 ictx = &ctx; 237 238 ret = ifuse_exec_opcode(fuse, &fbuf); 239 if (ret) { 240 ictx = NULL; 241 return (-1); 242 } 243 244 n = write(fuse->fc->fd, &fbuf, sizeof(fbuf)); 245 if (fbuf.fb_len) { 246 if (fbuf.fb_dat == NULL) { 247 fprintf(stderr, "%s: fb_dat is Null\n", 248 __func__); 249 return (-1); 250 } 251 ioexch.fbxch_uuid = fbuf.fb_uuid; 252 ioexch.fbxch_len = fbuf.fb_len; 253 ioexch.fbxch_data = fbuf.fb_dat; 254 255 if (ioctl(fuse->fc->fd, FIOCSETFBDAT, &ioexch)) { 256 free(fbuf.fb_dat); 257 return (-1); 258 } 259 free(fbuf.fb_dat); 260 } 261 ictx = NULL; 262 263 if (n != FUSEBUFSIZE) { 264 errno = EINVAL; 265 return (-1); 266 } 267 } 268 } 269 270 return (0); 271 } 272 DEF(fuse_loop); 273 274 struct fuse_chan * 275 fuse_mount(const char *dir, struct fuse_args *args) 276 { 277 struct fusefs_args fargs; 278 struct fuse_mount_opts opts; 279 struct fuse_chan *fc; 280 const char *errcause; 281 int mnt_flags; 282 283 if (dir == NULL) 284 return (NULL); 285 286 fc = calloc(1, sizeof(*fc)); 287 if (fc == NULL) 288 return (NULL); 289 290 fc->dir = realpath(dir, NULL); 291 if (fc->dir == NULL) 292 goto bad; 293 294 if ((fc->fd = open("/dev/fuse0", O_RDWR)) == -1) { 295 perror(__func__); 296 goto bad; 297 } 298 299 bzero(&opts, sizeof(opts)); 300 if (fuse_opt_parse(args, &opts, fuse_mount_opts, NULL) == -1) 301 goto bad; 302 303 mnt_flags = 0; 304 if (opts.rdonly) 305 mnt_flags |= MNT_RDONLY; 306 if (opts.noatime) 307 mnt_flags |= MNT_NOATIME; 308 309 if (opts.max_read > FUSEBUFMAXSIZE) { 310 fprintf(stderr, "fuse: invalid max_read (%d > %d)\n", 311 opts.max_read, FUSEBUFMAXSIZE); 312 goto bad; 313 } 314 315 bzero(&fargs, sizeof(fargs)); 316 fargs.fd = fc->fd; 317 fargs.max_read = opts.max_read; 318 319 if (mount(MOUNT_FUSEFS, fc->dir, mnt_flags, &fargs)) { 320 switch (errno) { 321 case EMFILE: 322 errcause = "mount table full"; 323 break; 324 case EOPNOTSUPP: 325 errcause = "filesystem not supported by kernel"; 326 break; 327 default: 328 errcause = strerror(errno); 329 break; 330 } 331 fprintf(stderr, "%s on %s: %s\n", __func__, dir, errcause); 332 goto bad; 333 } 334 335 return (fc); 336 bad: 337 if (fc->fd != -1) 338 close(fc->fd); 339 free(fc->dir); 340 free(fc); 341 return (NULL); 342 } 343 DEF(fuse_mount); 344 345 void 346 fuse_unmount(const char *dir, struct fuse_chan *ch) 347 { 348 if (ch == NULL || ch->dead) 349 return; 350 351 if (unmount(dir, MNT_UPDATE) == -1) 352 DPERROR(__func__); 353 } 354 DEF(fuse_unmount); 355 356 int 357 fuse_is_lib_option(const char *opt) 358 { 359 return (fuse_opt_match(fuse_lib_opts, opt)); 360 } 361 362 int 363 fuse_chan_fd(struct fuse_chan *ch) 364 { 365 if (ch == NULL) 366 return (-1); 367 368 return (ch->fd); 369 } 370 371 struct fuse_session * 372 fuse_get_session(struct fuse *f) 373 { 374 return (&f->se); 375 } 376 DEF(fuse_get_session); 377 378 int 379 fuse_loop_mt(unused struct fuse *fuse) 380 { 381 return (-1); 382 } 383 384 static int 385 ifuse_lib_opt_proc(void *data, const char *arg, int key, 386 unused struct fuse_args *args) 387 { 388 switch (key) { 389 case KEY_STUB: 390 return (0); 391 case KEY_DEBUG: 392 ifuse_debug_init(); 393 break; 394 default: 395 fprintf(stderr, "fuse: unrecognised option %s\n", arg); 396 return (-1); 397 } 398 399 /* Keep unknown options. */ 400 return (1); 401 } 402 403 struct fuse * 404 fuse_new(struct fuse_chan *fc, struct fuse_args *args, 405 const struct fuse_operations *ops, unused size_t size, 406 void *userdata) 407 { 408 struct fuse *fuse; 409 struct fuse_vnode *root; 410 411 if (fc == NULL || ops == NULL) 412 return (NULL); 413 414 if ((fuse = calloc(1, sizeof(*fuse))) == NULL) 415 return (NULL); 416 417 /* copy fuse ops to their own structure */ 418 memcpy(&fuse->op, ops, sizeof(fuse->op)); 419 420 if (fuse_opt_parse(args, &fuse->conf, fuse_lib_opts, 421 ifuse_lib_opt_proc) == -1) { 422 free(fuse); 423 return (NULL); 424 } 425 426 fuse->fc = fc; 427 fuse->max_ino = FUSE_ROOT_INO; 428 fuse->se.args = fuse; 429 fuse->private_data = userdata; 430 431 if ((root = alloc_vn(fuse, "/", FUSE_ROOT_INO, 0)) == NULL) { 432 free(fuse); 433 return (NULL); 434 } 435 436 tree_init(&fuse->vnode_tree); 437 tree_init(&fuse->name_tree); 438 if (!set_vn(fuse, root)) { 439 free(fuse); 440 return (NULL); 441 } 442 443 return (fuse); 444 } 445 DEF(fuse_new); 446 447 int 448 fuse_daemonize(int foreground) 449 { 450 if (foreground) 451 return (0); 452 453 return (daemon(0, 0)); 454 } 455 DEF(fuse_daemonize); 456 457 void 458 fuse_destroy(struct fuse *f) 459 { 460 if (f == NULL) 461 return; 462 463 /* 464 * Even though these were allocated in fuse_mount(), we can't free them 465 * in fuse_unmount() since fuse_loop() will not have terminated yet so 466 * we free them here. 467 */ 468 close(f->fc->fd); 469 free(f->fc->dir); 470 free(f->fc); 471 free(f); 472 } 473 DEF(fuse_destroy); 474 475 void 476 fuse_remove_signal_handlers(unused struct fuse_session *se) 477 { 478 signal(SIGHUP, SIG_DFL); 479 signal(SIGINT, SIG_DFL); 480 signal(SIGTERM, SIG_DFL); 481 signal(SIGPIPE, SIG_DFL); 482 } 483 DEF(fuse_remove_signal_handlers); 484 485 int 486 fuse_set_signal_handlers(unused struct fuse_session *se) 487 { 488 signal(SIGHUP, ifuse_sighdlr); 489 signal(SIGINT, ifuse_sighdlr); 490 signal(SIGTERM, ifuse_sighdlr); 491 signal(SIGPIPE, SIG_IGN); 492 return (0); 493 } 494 495 static void 496 dump_help(void) 497 { 498 fprintf(stderr, "FUSE options:\n" 499 " -d -o debug enable debug output (implies -f)\n" 500 " -f run in foreground\n" 501 " -V --version print fuse version\n" 502 "\n"); 503 } 504 505 static void 506 dump_version(void) 507 { 508 fprintf(stderr, "FUSE library version: %d.%d\n", FUSE_MAJOR_VERSION, 509 FUSE_MINOR_VERSION); 510 } 511 512 static int 513 ifuse_process_opt(void *data, const char *arg, int key, 514 unused struct fuse_args *args) 515 { 516 struct fuse_core_opts *opt = data; 517 struct stat st; 518 int res; 519 520 switch (key) { 521 case KEY_STUB: 522 return (0); 523 case KEY_DEBUG: 524 ifuse_debug_init(); 525 /* falls through */ 526 case KEY_FOREGROUND: 527 opt->foreground = 1; 528 return (0); 529 case KEY_HELP: 530 case KEY_HELP_WITHOUT_HEADER: 531 dump_help(); 532 return (-1); 533 case KEY_VERSION: 534 dump_version(); 535 return (-1); 536 case FUSE_OPT_KEY_NONOPT: 537 if (opt->mp == NULL) { 538 opt->mp = realpath(arg, opt->mp); 539 if (opt->mp == NULL) { 540 fprintf(stderr, "fuse: realpath: " 541 "%s : %s\n", arg, strerror(errno)); 542 return (-1); 543 } 544 545 res = stat(opt->mp, &st); 546 if (res == -1) { 547 fprintf(stderr, "fuse: bad mount point " 548 "%s : %s\n", arg, strerror(errno)); 549 return (-1); 550 } 551 552 if (!S_ISDIR(st.st_mode)) { 553 fprintf(stderr, "fuse: bad mount point " 554 "%s : %s\n", arg, strerror(ENOTDIR)); 555 return (-1); 556 } 557 } 558 return (0); 559 } 560 561 /* Pass through unknown options. */ 562 return (1); 563 } 564 565 int 566 fuse_parse_cmdline(struct fuse_args *args, char **mp, int *mt, int *fg) 567 { 568 struct fuse_core_opts opt; 569 570 bzero(&opt, sizeof(opt)); 571 if (fuse_opt_parse(args, &opt, fuse_core_opts, ifuse_process_opt) == -1) 572 return (-1); 573 574 if (opt.mp == NULL) { 575 fprintf(stderr, "fuse: missing mountpoint parameter\n"); 576 return (-1); 577 } 578 579 if (mp != NULL) { 580 *mp = strdup(opt.mp); 581 if (*mp == NULL) 582 return (-1); 583 } 584 585 if (mt != NULL) 586 *mt = 0; 587 588 if (fg != NULL) 589 *fg = opt.foreground; 590 591 return (0); 592 } 593 DEF(fuse_parse_cmdline); 594 595 struct fuse_context * 596 fuse_get_context(void) 597 { 598 return (ictx); 599 } 600 DEF(fuse_get_context); 601 602 int 603 fuse_version(void) 604 { 605 return (FUSE_VERSION); 606 } 607 608 void 609 fuse_teardown(struct fuse *fuse, char *mp) 610 { 611 if (fuse == NULL || mp == NULL) 612 return; 613 614 fuse_remove_signal_handlers(fuse_get_session(fuse)); 615 fuse_unmount(mp, fuse->fc); 616 fuse_destroy(fuse); 617 } 618 619 int 620 fuse_invalidate(unused struct fuse *f, unused const char *path) 621 { 622 return (EINVAL); 623 } 624 625 struct fuse * 626 fuse_setup(int argc, char **argv, const struct fuse_operations *ops, 627 size_t size, char **mp, int *mt, void *data) 628 { 629 struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 630 struct fuse_chan *fc; 631 struct fuse *fuse; 632 char *dir; 633 int fg; 634 635 dir = NULL; 636 if (fuse_parse_cmdline(&args, &dir, mt, &fg)) 637 goto err; 638 639 fuse_daemonize(fg); 640 641 if ((fc = fuse_mount(dir, &args)) == NULL) 642 goto err; 643 644 if ((fuse = fuse_new(fc, &args, ops, size, data)) == NULL) { 645 fuse_unmount(dir, fc); 646 close(fc->fd); 647 free(fc->dir); 648 free(fc); 649 goto err; 650 } 651 652 /* args are no longer needed */ 653 fuse_opt_free_args(&args); 654 655 if (fuse_set_signal_handlers(fuse_get_session(fuse)) == -1) { 656 fuse_unmount(dir, fc); 657 fuse_destroy(fuse); 658 goto err; 659 } 660 661 /* the caller frees dir, but we do it if the caller doesn't want it */ 662 if (mp == NULL) 663 free(dir); 664 else 665 *mp = dir; 666 667 return (fuse); 668 err: 669 free(dir); 670 return (NULL); 671 } 672 DEF(fuse_setup); 673 674 int 675 fuse_main(int argc, char **argv, const struct fuse_operations *ops, void *data) 676 { 677 struct fuse *fuse; 678 679 fuse = fuse_setup(argc, argv, ops, sizeof(*ops), NULL, NULL, data); 680 if (fuse == NULL) 681 return (-1); 682 683 return (fuse_loop(fuse)); 684 } 685