16881f68fSopenharmony_ci/* 26881f68fSopenharmony_ci FUSE: Filesystem in Userspace 36881f68fSopenharmony_ci Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 46881f68fSopenharmony_ci 56881f68fSopenharmony_ci Helper functions to create (simple) standalone programs. With the 66881f68fSopenharmony_ci aid of these functions it should be possible to create full FUSE 76881f68fSopenharmony_ci file system by implementing nothing but the request handlers. 86881f68fSopenharmony_ci 96881f68fSopenharmony_ci This program can be distributed under the terms of the GNU LGPLv2. 106881f68fSopenharmony_ci See the file COPYING.LIB. 116881f68fSopenharmony_ci*/ 126881f68fSopenharmony_ci 136881f68fSopenharmony_ci#include "fuse_config.h" 146881f68fSopenharmony_ci#include "fuse_i.h" 156881f68fSopenharmony_ci#include "fuse_misc.h" 166881f68fSopenharmony_ci#include "fuse_opt.h" 176881f68fSopenharmony_ci#include "fuse_lowlevel.h" 186881f68fSopenharmony_ci#include "mount_util.h" 196881f68fSopenharmony_ci 206881f68fSopenharmony_ci#include <stdio.h> 216881f68fSopenharmony_ci#include <stdlib.h> 226881f68fSopenharmony_ci#include <stddef.h> 236881f68fSopenharmony_ci#include <unistd.h> 246881f68fSopenharmony_ci#include <string.h> 256881f68fSopenharmony_ci#include <limits.h> 266881f68fSopenharmony_ci#include <errno.h> 276881f68fSopenharmony_ci#include <sys/param.h> 286881f68fSopenharmony_ci 296881f68fSopenharmony_ci#define FUSE_HELPER_OPT(t, p) \ 306881f68fSopenharmony_ci { t, offsetof(struct fuse_cmdline_opts, p), 1 } 316881f68fSopenharmony_ci 326881f68fSopenharmony_cistatic const struct fuse_opt fuse_helper_opts[] = { 336881f68fSopenharmony_ci FUSE_HELPER_OPT("-h", show_help), 346881f68fSopenharmony_ci FUSE_HELPER_OPT("--help", show_help), 356881f68fSopenharmony_ci FUSE_HELPER_OPT("-V", show_version), 366881f68fSopenharmony_ci FUSE_HELPER_OPT("--version", show_version), 376881f68fSopenharmony_ci FUSE_HELPER_OPT("-d", debug), 386881f68fSopenharmony_ci FUSE_HELPER_OPT("debug", debug), 396881f68fSopenharmony_ci FUSE_HELPER_OPT("-d", foreground), 406881f68fSopenharmony_ci FUSE_HELPER_OPT("debug", foreground), 416881f68fSopenharmony_ci FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), 426881f68fSopenharmony_ci FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), 436881f68fSopenharmony_ci FUSE_HELPER_OPT("-f", foreground), 446881f68fSopenharmony_ci FUSE_HELPER_OPT("-s", singlethread), 456881f68fSopenharmony_ci FUSE_HELPER_OPT("fsname=", nodefault_subtype), 466881f68fSopenharmony_ci FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), 476881f68fSopenharmony_ci#ifndef __FreeBSD__ 486881f68fSopenharmony_ci FUSE_HELPER_OPT("subtype=", nodefault_subtype), 496881f68fSopenharmony_ci FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), 506881f68fSopenharmony_ci#endif 516881f68fSopenharmony_ci FUSE_HELPER_OPT("clone_fd", clone_fd), 526881f68fSopenharmony_ci FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), 536881f68fSopenharmony_ci FUSE_HELPER_OPT("max_threads=%u", max_threads), 546881f68fSopenharmony_ci FUSE_OPT_END 556881f68fSopenharmony_ci}; 566881f68fSopenharmony_ci 576881f68fSopenharmony_cistruct fuse_conn_info_opts { 586881f68fSopenharmony_ci int atomic_o_trunc; 596881f68fSopenharmony_ci int no_remote_posix_lock; 606881f68fSopenharmony_ci int no_remote_flock; 616881f68fSopenharmony_ci int splice_write; 626881f68fSopenharmony_ci int splice_move; 636881f68fSopenharmony_ci int splice_read; 646881f68fSopenharmony_ci int no_splice_write; 656881f68fSopenharmony_ci int no_splice_move; 666881f68fSopenharmony_ci int no_splice_read; 676881f68fSopenharmony_ci int auto_inval_data; 686881f68fSopenharmony_ci int no_auto_inval_data; 696881f68fSopenharmony_ci int no_readdirplus; 706881f68fSopenharmony_ci int no_readdirplus_auto; 716881f68fSopenharmony_ci int async_dio; 726881f68fSopenharmony_ci int no_async_dio; 736881f68fSopenharmony_ci int writeback_cache; 746881f68fSopenharmony_ci int no_writeback_cache; 756881f68fSopenharmony_ci int async_read; 766881f68fSopenharmony_ci int sync_read; 776881f68fSopenharmony_ci unsigned max_write; 786881f68fSopenharmony_ci unsigned max_readahead; 796881f68fSopenharmony_ci unsigned max_background; 806881f68fSopenharmony_ci unsigned congestion_threshold; 816881f68fSopenharmony_ci unsigned time_gran; 826881f68fSopenharmony_ci int set_max_write; 836881f68fSopenharmony_ci int set_max_readahead; 846881f68fSopenharmony_ci int set_max_background; 856881f68fSopenharmony_ci int set_congestion_threshold; 866881f68fSopenharmony_ci int set_time_gran; 876881f68fSopenharmony_ci}; 886881f68fSopenharmony_ci 896881f68fSopenharmony_ci#define CONN_OPTION(t, p, v) \ 906881f68fSopenharmony_ci { t, offsetof(struct fuse_conn_info_opts, p), v } 916881f68fSopenharmony_cistatic const struct fuse_opt conn_info_opt_spec[] = { 926881f68fSopenharmony_ci CONN_OPTION("max_write=%u", max_write, 0), 936881f68fSopenharmony_ci CONN_OPTION("max_write=", set_max_write, 1), 946881f68fSopenharmony_ci CONN_OPTION("max_readahead=%u", max_readahead, 0), 956881f68fSopenharmony_ci CONN_OPTION("max_readahead=", set_max_readahead, 1), 966881f68fSopenharmony_ci CONN_OPTION("max_background=%u", max_background, 0), 976881f68fSopenharmony_ci CONN_OPTION("max_background=", set_max_background, 1), 986881f68fSopenharmony_ci CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0), 996881f68fSopenharmony_ci CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1), 1006881f68fSopenharmony_ci CONN_OPTION("sync_read", sync_read, 1), 1016881f68fSopenharmony_ci CONN_OPTION("async_read", async_read, 1), 1026881f68fSopenharmony_ci CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1), 1036881f68fSopenharmony_ci CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1), 1046881f68fSopenharmony_ci CONN_OPTION("no_remote_lock", no_remote_flock, 1), 1056881f68fSopenharmony_ci CONN_OPTION("no_remote_flock", no_remote_flock, 1), 1066881f68fSopenharmony_ci CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1), 1076881f68fSopenharmony_ci CONN_OPTION("splice_write", splice_write, 1), 1086881f68fSopenharmony_ci CONN_OPTION("no_splice_write", no_splice_write, 1), 1096881f68fSopenharmony_ci CONN_OPTION("splice_move", splice_move, 1), 1106881f68fSopenharmony_ci CONN_OPTION("no_splice_move", no_splice_move, 1), 1116881f68fSopenharmony_ci CONN_OPTION("splice_read", splice_read, 1), 1126881f68fSopenharmony_ci CONN_OPTION("no_splice_read", no_splice_read, 1), 1136881f68fSopenharmony_ci CONN_OPTION("auto_inval_data", auto_inval_data, 1), 1146881f68fSopenharmony_ci CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1), 1156881f68fSopenharmony_ci CONN_OPTION("readdirplus=no", no_readdirplus, 1), 1166881f68fSopenharmony_ci CONN_OPTION("readdirplus=yes", no_readdirplus, 0), 1176881f68fSopenharmony_ci CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1), 1186881f68fSopenharmony_ci CONN_OPTION("readdirplus=auto", no_readdirplus, 0), 1196881f68fSopenharmony_ci CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0), 1206881f68fSopenharmony_ci CONN_OPTION("async_dio", async_dio, 1), 1216881f68fSopenharmony_ci CONN_OPTION("no_async_dio", no_async_dio, 1), 1226881f68fSopenharmony_ci CONN_OPTION("writeback_cache", writeback_cache, 1), 1236881f68fSopenharmony_ci CONN_OPTION("no_writeback_cache", no_writeback_cache, 1), 1246881f68fSopenharmony_ci CONN_OPTION("time_gran=%u", time_gran, 0), 1256881f68fSopenharmony_ci CONN_OPTION("time_gran=", set_time_gran, 1), 1266881f68fSopenharmony_ci FUSE_OPT_END 1276881f68fSopenharmony_ci}; 1286881f68fSopenharmony_ci 1296881f68fSopenharmony_ci 1306881f68fSopenharmony_civoid fuse_cmdline_help(void) 1316881f68fSopenharmony_ci{ 1326881f68fSopenharmony_ci printf(" -h --help print help\n" 1336881f68fSopenharmony_ci " -V --version print version\n" 1346881f68fSopenharmony_ci " -d -o debug enable debug output (implies -f)\n" 1356881f68fSopenharmony_ci " -f foreground operation\n" 1366881f68fSopenharmony_ci " -s disable multi-threaded operation\n" 1376881f68fSopenharmony_ci " -o clone_fd use separate fuse device fd for each thread\n" 1386881f68fSopenharmony_ci " (may improve performance)\n" 1396881f68fSopenharmony_ci " -o max_idle_threads the maximum number of idle worker threads\n" 1406881f68fSopenharmony_ci " allowed (default: -1)\n" 1416881f68fSopenharmony_ci " -o max_threads the maximum number of worker threads\n" 1426881f68fSopenharmony_ci " allowed (default: 10)\n"); 1436881f68fSopenharmony_ci} 1446881f68fSopenharmony_ci 1456881f68fSopenharmony_cistatic int fuse_helper_opt_proc(void *data, const char *arg, int key, 1466881f68fSopenharmony_ci struct fuse_args *outargs) 1476881f68fSopenharmony_ci{ 1486881f68fSopenharmony_ci (void) outargs; 1496881f68fSopenharmony_ci struct fuse_cmdline_opts *opts = data; 1506881f68fSopenharmony_ci 1516881f68fSopenharmony_ci switch (key) { 1526881f68fSopenharmony_ci case FUSE_OPT_KEY_NONOPT: 1536881f68fSopenharmony_ci if (!opts->mountpoint) { 1546881f68fSopenharmony_ci if (fuse_mnt_parse_fuse_fd(arg) != -1) { 1556881f68fSopenharmony_ci return fuse_opt_add_opt(&opts->mountpoint, arg); 1566881f68fSopenharmony_ci } 1576881f68fSopenharmony_ci 1586881f68fSopenharmony_ci char mountpoint[PATH_MAX] = ""; 1596881f68fSopenharmony_ci if (realpath(arg, mountpoint) == NULL) { 1606881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, 1616881f68fSopenharmony_ci "fuse: bad mount point `%s': %s\n", 1626881f68fSopenharmony_ci arg, strerror(errno)); 1636881f68fSopenharmony_ci return -1; 1646881f68fSopenharmony_ci } 1656881f68fSopenharmony_ci return fuse_opt_add_opt(&opts->mountpoint, mountpoint); 1666881f68fSopenharmony_ci } else { 1676881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg); 1686881f68fSopenharmony_ci return -1; 1696881f68fSopenharmony_ci } 1706881f68fSopenharmony_ci 1716881f68fSopenharmony_ci default: 1726881f68fSopenharmony_ci /* Pass through unknown options */ 1736881f68fSopenharmony_ci return 1; 1746881f68fSopenharmony_ci } 1756881f68fSopenharmony_ci} 1766881f68fSopenharmony_ci 1776881f68fSopenharmony_ci/* Under FreeBSD, there is no subtype option so this 1786881f68fSopenharmony_ci function actually sets the fsname */ 1796881f68fSopenharmony_cistatic int add_default_subtype(const char *progname, struct fuse_args *args) 1806881f68fSopenharmony_ci{ 1816881f68fSopenharmony_ci int res; 1826881f68fSopenharmony_ci char *subtype_opt; 1836881f68fSopenharmony_ci 1846881f68fSopenharmony_ci const char *basename = strrchr(progname, '/'); 1856881f68fSopenharmony_ci if (basename == NULL) 1866881f68fSopenharmony_ci basename = progname; 1876881f68fSopenharmony_ci else if (basename[1] != '\0') 1886881f68fSopenharmony_ci basename++; 1896881f68fSopenharmony_ci 1906881f68fSopenharmony_ci subtype_opt = (char *) malloc(strlen(basename) + 64); 1916881f68fSopenharmony_ci if (subtype_opt == NULL) { 1926881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n"); 1936881f68fSopenharmony_ci return -1; 1946881f68fSopenharmony_ci } 1956881f68fSopenharmony_ci#ifdef __FreeBSD__ 1966881f68fSopenharmony_ci sprintf(subtype_opt, "-ofsname=%s", basename); 1976881f68fSopenharmony_ci#else 1986881f68fSopenharmony_ci sprintf(subtype_opt, "-osubtype=%s", basename); 1996881f68fSopenharmony_ci#endif 2006881f68fSopenharmony_ci res = fuse_opt_add_arg(args, subtype_opt); 2016881f68fSopenharmony_ci free(subtype_opt); 2026881f68fSopenharmony_ci return res; 2036881f68fSopenharmony_ci} 2046881f68fSopenharmony_ci 2056881f68fSopenharmony_ciint fuse_parse_cmdline_312(struct fuse_args *args, 2066881f68fSopenharmony_ci struct fuse_cmdline_opts *opts); 2076881f68fSopenharmony_ciFUSE_SYMVER("fuse_parse_cmdline_312", "fuse_parse_cmdline@@FUSE_3.12") 2086881f68fSopenharmony_ciint fuse_parse_cmdline_312(struct fuse_args *args, 2096881f68fSopenharmony_ci struct fuse_cmdline_opts *opts) 2106881f68fSopenharmony_ci{ 2116881f68fSopenharmony_ci memset(opts, 0, sizeof(struct fuse_cmdline_opts)); 2126881f68fSopenharmony_ci 2136881f68fSopenharmony_ci opts->max_idle_threads = UINT_MAX; /* new default in fuse version 3.12 */ 2146881f68fSopenharmony_ci opts->max_threads = 10; 2156881f68fSopenharmony_ci 2166881f68fSopenharmony_ci if (fuse_opt_parse(args, opts, fuse_helper_opts, 2176881f68fSopenharmony_ci fuse_helper_opt_proc) == -1) 2186881f68fSopenharmony_ci return -1; 2196881f68fSopenharmony_ci 2206881f68fSopenharmony_ci /* *Linux*: if neither -o subtype nor -o fsname are specified, 2216881f68fSopenharmony_ci set subtype to program's basename. 2226881f68fSopenharmony_ci *FreeBSD*: if fsname is not specified, set to program's 2236881f68fSopenharmony_ci basename. */ 2246881f68fSopenharmony_ci if (!opts->nodefault_subtype) 2256881f68fSopenharmony_ci if (add_default_subtype(args->argv[0], args) == -1) 2266881f68fSopenharmony_ci return -1; 2276881f68fSopenharmony_ci 2286881f68fSopenharmony_ci return 0; 2296881f68fSopenharmony_ci} 2306881f68fSopenharmony_ci 2316881f68fSopenharmony_ci/** 2326881f68fSopenharmony_ci * struct fuse_cmdline_opts got extended in libfuse-3.12 2336881f68fSopenharmony_ci */ 2346881f68fSopenharmony_ciint fuse_parse_cmdline_30(struct fuse_args *args, 2356881f68fSopenharmony_ci struct fuse_cmdline_opts *opts); 2366881f68fSopenharmony_ciFUSE_SYMVER("fuse_parse_cmdline_30", "fuse_parse_cmdline@FUSE_3.0") 2376881f68fSopenharmony_ciint fuse_parse_cmdline_30(struct fuse_args *args, 2386881f68fSopenharmony_ci struct fuse_cmdline_opts *out_opts) 2396881f68fSopenharmony_ci{ 2406881f68fSopenharmony_ci struct fuse_cmdline_opts opts; 2416881f68fSopenharmony_ci 2426881f68fSopenharmony_ci int rc = fuse_parse_cmdline_312(args, &opts); 2436881f68fSopenharmony_ci if (rc == 0) { 2446881f68fSopenharmony_ci /* copy up to the size of the old pre 3.12 struct */ 2456881f68fSopenharmony_ci memcpy(out_opts, &opts, 2466881f68fSopenharmony_ci offsetof(struct fuse_cmdline_opts, max_idle_threads) + 2476881f68fSopenharmony_ci sizeof(opts.max_idle_threads)); 2486881f68fSopenharmony_ci } 2496881f68fSopenharmony_ci 2506881f68fSopenharmony_ci return rc; 2516881f68fSopenharmony_ci} 2526881f68fSopenharmony_ci 2536881f68fSopenharmony_ciint fuse_daemonize(int foreground) 2546881f68fSopenharmony_ci{ 2556881f68fSopenharmony_ci if (!foreground) { 2566881f68fSopenharmony_ci int nullfd; 2576881f68fSopenharmony_ci int waiter[2]; 2586881f68fSopenharmony_ci char completed; 2596881f68fSopenharmony_ci 2606881f68fSopenharmony_ci if (pipe(waiter)) { 2616881f68fSopenharmony_ci perror("fuse_daemonize: pipe"); 2626881f68fSopenharmony_ci return -1; 2636881f68fSopenharmony_ci } 2646881f68fSopenharmony_ci 2656881f68fSopenharmony_ci /* 2666881f68fSopenharmony_ci * demonize current process by forking it and killing the 2676881f68fSopenharmony_ci * parent. This makes current process as a child of 'init'. 2686881f68fSopenharmony_ci */ 2696881f68fSopenharmony_ci switch(fork()) { 2706881f68fSopenharmony_ci case -1: 2716881f68fSopenharmony_ci perror("fuse_daemonize: fork"); 2726881f68fSopenharmony_ci return -1; 2736881f68fSopenharmony_ci case 0: 2746881f68fSopenharmony_ci break; 2756881f68fSopenharmony_ci default: 2766881f68fSopenharmony_ci (void) read(waiter[0], &completed, sizeof(completed)); 2776881f68fSopenharmony_ci _exit(0); 2786881f68fSopenharmony_ci } 2796881f68fSopenharmony_ci 2806881f68fSopenharmony_ci if (setsid() == -1) { 2816881f68fSopenharmony_ci perror("fuse_daemonize: setsid"); 2826881f68fSopenharmony_ci return -1; 2836881f68fSopenharmony_ci } 2846881f68fSopenharmony_ci 2856881f68fSopenharmony_ci (void) chdir("/"); 2866881f68fSopenharmony_ci 2876881f68fSopenharmony_ci nullfd = open("/dev/null", O_RDWR, 0); 2886881f68fSopenharmony_ci if (nullfd != -1) { 2896881f68fSopenharmony_ci (void) dup2(nullfd, 0); 2906881f68fSopenharmony_ci (void) dup2(nullfd, 1); 2916881f68fSopenharmony_ci (void) dup2(nullfd, 2); 2926881f68fSopenharmony_ci if (nullfd > 2) 2936881f68fSopenharmony_ci close(nullfd); 2946881f68fSopenharmony_ci } 2956881f68fSopenharmony_ci 2966881f68fSopenharmony_ci /* Propagate completion of daemon initialization */ 2976881f68fSopenharmony_ci completed = 1; 2986881f68fSopenharmony_ci (void) write(waiter[1], &completed, sizeof(completed)); 2996881f68fSopenharmony_ci close(waiter[0]); 3006881f68fSopenharmony_ci close(waiter[1]); 3016881f68fSopenharmony_ci } else { 3026881f68fSopenharmony_ci (void) chdir("/"); 3036881f68fSopenharmony_ci } 3046881f68fSopenharmony_ci return 0; 3056881f68fSopenharmony_ci} 3066881f68fSopenharmony_ci 3076881f68fSopenharmony_ciint fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, 3086881f68fSopenharmony_ci size_t op_size, void *user_data) 3096881f68fSopenharmony_ci{ 3106881f68fSopenharmony_ci struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 3116881f68fSopenharmony_ci struct fuse *fuse; 3126881f68fSopenharmony_ci struct fuse_cmdline_opts opts; 3136881f68fSopenharmony_ci int res; 3146881f68fSopenharmony_ci struct fuse_loop_config *loop_config = NULL; 3156881f68fSopenharmony_ci 3166881f68fSopenharmony_ci if (fuse_parse_cmdline(&args, &opts) != 0) 3176881f68fSopenharmony_ci return 1; 3186881f68fSopenharmony_ci 3196881f68fSopenharmony_ci if (opts.show_version) { 3206881f68fSopenharmony_ci printf("FUSE library version %s\n", PACKAGE_VERSION); 3216881f68fSopenharmony_ci fuse_lowlevel_version(); 3226881f68fSopenharmony_ci res = 0; 3236881f68fSopenharmony_ci goto out1; 3246881f68fSopenharmony_ci } 3256881f68fSopenharmony_ci 3266881f68fSopenharmony_ci if (opts.show_help) { 3276881f68fSopenharmony_ci if(args.argv[0][0] != '\0') 3286881f68fSopenharmony_ci printf("usage: %s [options] <mountpoint>\n\n", 3296881f68fSopenharmony_ci args.argv[0]); 3306881f68fSopenharmony_ci printf("FUSE options:\n"); 3316881f68fSopenharmony_ci fuse_cmdline_help(); 3326881f68fSopenharmony_ci fuse_lib_help(&args); 3336881f68fSopenharmony_ci res = 0; 3346881f68fSopenharmony_ci goto out1; 3356881f68fSopenharmony_ci } 3366881f68fSopenharmony_ci 3376881f68fSopenharmony_ci if (!opts.show_help && 3386881f68fSopenharmony_ci !opts.mountpoint) { 3396881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "error: no mountpoint specified\n"); 3406881f68fSopenharmony_ci res = 2; 3416881f68fSopenharmony_ci goto out1; 3426881f68fSopenharmony_ci } 3436881f68fSopenharmony_ci 3446881f68fSopenharmony_ci 3456881f68fSopenharmony_ci fuse = fuse_new_31(&args, op, op_size, user_data); 3466881f68fSopenharmony_ci if (fuse == NULL) { 3476881f68fSopenharmony_ci res = 3; 3486881f68fSopenharmony_ci goto out1; 3496881f68fSopenharmony_ci } 3506881f68fSopenharmony_ci 3516881f68fSopenharmony_ci if (fuse_mount(fuse,opts.mountpoint) != 0) { 3526881f68fSopenharmony_ci res = 4; 3536881f68fSopenharmony_ci goto out2; 3546881f68fSopenharmony_ci } 3556881f68fSopenharmony_ci 3566881f68fSopenharmony_ci if (fuse_daemonize(opts.foreground) != 0) { 3576881f68fSopenharmony_ci res = 5; 3586881f68fSopenharmony_ci goto out3; 3596881f68fSopenharmony_ci } 3606881f68fSopenharmony_ci 3616881f68fSopenharmony_ci struct fuse_session *se = fuse_get_session(fuse); 3626881f68fSopenharmony_ci if (fuse_set_signal_handlers(se) != 0) { 3636881f68fSopenharmony_ci res = 6; 3646881f68fSopenharmony_ci goto out3; 3656881f68fSopenharmony_ci } 3666881f68fSopenharmony_ci 3676881f68fSopenharmony_ci if (opts.singlethread) 3686881f68fSopenharmony_ci res = fuse_loop(fuse); 3696881f68fSopenharmony_ci else { 3706881f68fSopenharmony_ci loop_config = fuse_loop_cfg_create(); 3716881f68fSopenharmony_ci if (loop_config == NULL) { 3726881f68fSopenharmony_ci res = 7; 3736881f68fSopenharmony_ci goto out3; 3746881f68fSopenharmony_ci } 3756881f68fSopenharmony_ci 3766881f68fSopenharmony_ci fuse_loop_cfg_set_clone_fd(loop_config, opts.clone_fd); 3776881f68fSopenharmony_ci 3786881f68fSopenharmony_ci fuse_loop_cfg_set_idle_threads(loop_config, opts.max_idle_threads); 3796881f68fSopenharmony_ci fuse_loop_cfg_set_max_threads(loop_config, opts.max_threads); 3806881f68fSopenharmony_ci res = fuse_loop_mt(fuse, loop_config); 3816881f68fSopenharmony_ci } 3826881f68fSopenharmony_ci if (res) 3836881f68fSopenharmony_ci res = 8; 3846881f68fSopenharmony_ci 3856881f68fSopenharmony_ci fuse_remove_signal_handlers(se); 3866881f68fSopenharmony_ciout3: 3876881f68fSopenharmony_ci fuse_unmount(fuse); 3886881f68fSopenharmony_ciout2: 3896881f68fSopenharmony_ci fuse_destroy(fuse); 3906881f68fSopenharmony_ciout1: 3916881f68fSopenharmony_ci fuse_loop_cfg_destroy(loop_config); 3926881f68fSopenharmony_ci free(opts.mountpoint); 3936881f68fSopenharmony_ci fuse_opt_free_args(&args); 3946881f68fSopenharmony_ci return res; 3956881f68fSopenharmony_ci} 3966881f68fSopenharmony_ci 3976881f68fSopenharmony_ci 3986881f68fSopenharmony_civoid fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts, 3996881f68fSopenharmony_ci struct fuse_conn_info *conn) 4006881f68fSopenharmony_ci{ 4016881f68fSopenharmony_ci if(opts->set_max_write) 4026881f68fSopenharmony_ci conn->max_write = opts->max_write; 4036881f68fSopenharmony_ci if(opts->set_max_background) 4046881f68fSopenharmony_ci conn->max_background = opts->max_background; 4056881f68fSopenharmony_ci if(opts->set_congestion_threshold) 4066881f68fSopenharmony_ci conn->congestion_threshold = opts->congestion_threshold; 4076881f68fSopenharmony_ci if(opts->set_time_gran) 4086881f68fSopenharmony_ci conn->time_gran = opts->time_gran; 4096881f68fSopenharmony_ci if(opts->set_max_readahead) 4106881f68fSopenharmony_ci conn->max_readahead = opts->max_readahead; 4116881f68fSopenharmony_ci 4126881f68fSopenharmony_ci#define LL_ENABLE(cond,cap) \ 4136881f68fSopenharmony_ci if (cond) conn->want |= (cap) 4146881f68fSopenharmony_ci#define LL_DISABLE(cond,cap) \ 4156881f68fSopenharmony_ci if (cond) conn->want &= ~(cap) 4166881f68fSopenharmony_ci 4176881f68fSopenharmony_ci LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ); 4186881f68fSopenharmony_ci LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ); 4196881f68fSopenharmony_ci 4206881f68fSopenharmony_ci LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE); 4216881f68fSopenharmony_ci LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE); 4226881f68fSopenharmony_ci 4236881f68fSopenharmony_ci LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE); 4246881f68fSopenharmony_ci LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE); 4256881f68fSopenharmony_ci 4266881f68fSopenharmony_ci LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); 4276881f68fSopenharmony_ci LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); 4286881f68fSopenharmony_ci 4296881f68fSopenharmony_ci LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS); 4306881f68fSopenharmony_ci LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO); 4316881f68fSopenharmony_ci 4326881f68fSopenharmony_ci LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO); 4336881f68fSopenharmony_ci LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO); 4346881f68fSopenharmony_ci 4356881f68fSopenharmony_ci LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE); 4366881f68fSopenharmony_ci LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE); 4376881f68fSopenharmony_ci 4386881f68fSopenharmony_ci LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ); 4396881f68fSopenharmony_ci LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ); 4406881f68fSopenharmony_ci 4416881f68fSopenharmony_ci LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS); 4426881f68fSopenharmony_ci LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS); 4436881f68fSopenharmony_ci} 4446881f68fSopenharmony_ci 4456881f68fSopenharmony_cistruct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args) 4466881f68fSopenharmony_ci{ 4476881f68fSopenharmony_ci struct fuse_conn_info_opts *opts; 4486881f68fSopenharmony_ci 4496881f68fSopenharmony_ci opts = calloc(1, sizeof(struct fuse_conn_info_opts)); 4506881f68fSopenharmony_ci if(opts == NULL) { 4516881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "calloc failed\n"); 4526881f68fSopenharmony_ci return NULL; 4536881f68fSopenharmony_ci } 4546881f68fSopenharmony_ci if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) { 4556881f68fSopenharmony_ci free(opts); 4566881f68fSopenharmony_ci return NULL; 4576881f68fSopenharmony_ci } 4586881f68fSopenharmony_ci return opts; 4596881f68fSopenharmony_ci} 4606881f68fSopenharmony_ci 4616881f68fSopenharmony_ciint fuse_open_channel(const char *mountpoint, const char* options) 4626881f68fSopenharmony_ci{ 4636881f68fSopenharmony_ci struct mount_opts *opts = NULL; 4646881f68fSopenharmony_ci int fd = -1; 4656881f68fSopenharmony_ci const char *argv[] = { "", "-o", options }; 4666881f68fSopenharmony_ci int argc = sizeof(argv) / sizeof(argv[0]); 4676881f68fSopenharmony_ci struct fuse_args args = FUSE_ARGS_INIT(argc, (char**) argv); 4686881f68fSopenharmony_ci 4696881f68fSopenharmony_ci opts = parse_mount_opts(&args); 4706881f68fSopenharmony_ci if (opts == NULL) 4716881f68fSopenharmony_ci return -1; 4726881f68fSopenharmony_ci 4736881f68fSopenharmony_ci fd = fuse_kern_mount(mountpoint, opts); 4746881f68fSopenharmony_ci destroy_mount_opts(opts); 4756881f68fSopenharmony_ci 4766881f68fSopenharmony_ci return fd; 4776881f68fSopenharmony_ci} 478