"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.1/lib/helper.c" (14 Nov 2017, 11342 Bytes) of package /linux/misc/fuse-3.2.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "helper.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.2.0_vs_3.2.1.

    1 /*
    2   FUSE: Filesystem in Userspace
    3   Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
    4 
    5   Helper functions to create (simple) standalone programs. With the
    6   aid of these functions it should be possible to create full FUSE
    7   file system by implementing nothing but the request handlers.
    8 
    9   This program can be distributed under the terms of the GNU LGPLv2.
   10   See the file COPYING.LIB.
   11 */
   12 
   13 #include "config.h"
   14 #include "fuse_i.h"
   15 #include "fuse_misc.h"
   16 #include "fuse_opt.h"
   17 #include "fuse_lowlevel.h"
   18 
   19 #include <stdio.h>
   20 #include <stdlib.h>
   21 #include <stddef.h>
   22 #include <unistd.h>
   23 #include <string.h>
   24 #include <limits.h>
   25 #include <errno.h>
   26 #include <sys/param.h>
   27 
   28 #define FUSE_HELPER_OPT(t, p) \
   29     { t, offsetof(struct fuse_cmdline_opts, p), 1 }
   30 
   31 static const struct fuse_opt fuse_helper_opts[] = {
   32     FUSE_HELPER_OPT("-h",       show_help),
   33     FUSE_HELPER_OPT("--help",   show_help),
   34     FUSE_HELPER_OPT("-V",       show_version),
   35     FUSE_HELPER_OPT("--version",    show_version),
   36     FUSE_HELPER_OPT("-d",       debug),
   37     FUSE_HELPER_OPT("debug",    debug),
   38     FUSE_HELPER_OPT("-d",       foreground),
   39     FUSE_HELPER_OPT("debug",    foreground),
   40     FUSE_OPT_KEY("-d",      FUSE_OPT_KEY_KEEP),
   41     FUSE_OPT_KEY("debug",       FUSE_OPT_KEY_KEEP),
   42     FUSE_HELPER_OPT("-f",       foreground),
   43     FUSE_HELPER_OPT("-s",       singlethread),
   44     FUSE_HELPER_OPT("fsname=",  nodefault_subtype),
   45     FUSE_OPT_KEY("fsname=",     FUSE_OPT_KEY_KEEP),
   46 #ifndef __FreeBSD__
   47     FUSE_HELPER_OPT("subtype=", nodefault_subtype),
   48     FUSE_OPT_KEY("subtype=",    FUSE_OPT_KEY_KEEP),
   49 #endif
   50     FUSE_HELPER_OPT("clone_fd", clone_fd),
   51     FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
   52     FUSE_OPT_END
   53 };
   54 
   55 struct fuse_conn_info_opts {
   56     int atomic_o_trunc;
   57     int no_remote_posix_lock;
   58     int no_remote_flock;
   59     int splice_write;
   60     int splice_move;
   61     int splice_read;
   62     int no_splice_write;
   63     int no_splice_move;
   64     int no_splice_read;
   65     int auto_inval_data;
   66     int no_auto_inval_data;
   67     int no_readdirplus;
   68     int no_readdirplus_auto;
   69     int async_dio;
   70     int no_async_dio;
   71     int writeback_cache;
   72     int no_writeback_cache;
   73     int async_read;
   74     int sync_read;
   75     unsigned max_write;
   76     unsigned max_readahead;
   77     unsigned max_background;
   78     unsigned congestion_threshold;
   79     unsigned time_gran;
   80     int set_max_write;
   81     int set_max_readahead;
   82     int set_max_background;
   83     int set_congestion_threshold;
   84     int set_time_gran;
   85 };
   86 
   87 #define CONN_OPTION(t, p, v)                    \
   88     { t, offsetof(struct fuse_conn_info_opts, p), v }
   89 static const struct fuse_opt conn_info_opt_spec[] = {
   90     CONN_OPTION("max_write=%u", max_write, 0),
   91     CONN_OPTION("max_write=", set_max_write, 1),
   92     CONN_OPTION("max_readahead=%u", max_readahead, 0),
   93     CONN_OPTION("max_readahead=", set_max_readahead, 1),
   94     CONN_OPTION("max_background=%u", max_background, 0),
   95     CONN_OPTION("max_background=", set_max_background, 1),
   96     CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
   97     CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
   98     CONN_OPTION("sync_read", sync_read, 1),
   99     CONN_OPTION("async_read", async_read, 1),
  100     CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
  101     CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
  102     CONN_OPTION("no_remote_lock", no_remote_flock, 1),
  103     CONN_OPTION("no_remote_flock", no_remote_flock, 1),
  104     CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
  105     CONN_OPTION("splice_write", splice_write, 1),
  106     CONN_OPTION("no_splice_write", no_splice_write, 1),
  107     CONN_OPTION("splice_move", splice_move, 1),
  108     CONN_OPTION("no_splice_move", no_splice_move, 1),
  109     CONN_OPTION("splice_read", splice_read, 1),
  110     CONN_OPTION("no_splice_read", no_splice_read, 1),
  111     CONN_OPTION("auto_inval_data", auto_inval_data, 1),
  112     CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
  113     CONN_OPTION("readdirplus=no", no_readdirplus, 1),
  114     CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
  115     CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
  116     CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
  117     CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
  118     CONN_OPTION("async_dio", async_dio, 1),
  119     CONN_OPTION("no_async_dio", no_async_dio, 1),
  120     CONN_OPTION("writeback_cache", writeback_cache, 1),
  121     CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
  122     CONN_OPTION("time_gran=%u", time_gran, 0),
  123     CONN_OPTION("time_gran=", set_time_gran, 1),
  124     FUSE_OPT_END
  125 };
  126 
  127 
  128 void fuse_cmdline_help(void)
  129 {
  130     printf("    -h   --help            print help\n"
  131            "    -V   --version         print version\n"
  132            "    -d   -o debug          enable debug output (implies -f)\n"
  133            "    -f                     foreground operation\n"
  134            "    -s                     disable multi-threaded operation\n"
  135            "    -o clone_fd            use separate fuse device fd for each thread\n"
  136            "                           (may improve performance)\n"
  137            "    -o max_idle_threads    the maximum number of idle worker threads\n"
  138            "                           allowed (default: 10)\n");
  139 }
  140 
  141 static int fuse_helper_opt_proc(void *data, const char *arg, int key,
  142                 struct fuse_args *outargs)
  143 {
  144     (void) outargs;
  145     struct fuse_cmdline_opts *opts = data;
  146 
  147     switch (key) {
  148     case FUSE_OPT_KEY_NONOPT:
  149         if (!opts->mountpoint) {
  150             char mountpoint[PATH_MAX];
  151             if (realpath(arg, mountpoint) == NULL) {
  152                 fprintf(stderr,
  153                     "fuse: bad mount point `%s': %s\n",
  154                     arg, strerror(errno));
  155                 return -1;
  156             }
  157             return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
  158         } else {
  159             fprintf(stderr, "fuse: invalid argument `%s'\n", arg);
  160             return -1;
  161         }
  162 
  163     default:
  164         /* Pass through unknown options */
  165         return 1;
  166     }
  167 }
  168 
  169 /* Under FreeBSD, there is no subtype option so this
  170    function actually sets the fsname */
  171 static int add_default_subtype(const char *progname, struct fuse_args *args)
  172 {
  173     int res;
  174     char *subtype_opt;
  175 
  176     const char *basename = strrchr(progname, '/');
  177     if (basename == NULL)
  178         basename = progname;
  179     else if (basename[1] != '\0')
  180         basename++;
  181 
  182     subtype_opt = (char *) malloc(strlen(basename) + 64);
  183     if (subtype_opt == NULL) {
  184         fprintf(stderr, "fuse: memory allocation failed\n");
  185         return -1;
  186     }
  187 #ifdef __FreeBSD__
  188     sprintf(subtype_opt, "-ofsname=%s", basename);
  189 #else
  190     sprintf(subtype_opt, "-osubtype=%s", basename);
  191 #endif
  192     res = fuse_opt_add_arg(args, subtype_opt);
  193     free(subtype_opt);
  194     return res;
  195 }
  196 
  197 int fuse_parse_cmdline(struct fuse_args *args,
  198                struct fuse_cmdline_opts *opts)
  199 {
  200     memset(opts, 0, sizeof(struct fuse_cmdline_opts));
  201 
  202     opts->max_idle_threads = 10;
  203 
  204     if (fuse_opt_parse(args, opts, fuse_helper_opts,
  205                fuse_helper_opt_proc) == -1)
  206         return -1;
  207 
  208     /* *Linux*: if neither -o subtype nor -o fsname are specified,
  209        set subtype to program's basename.
  210        *FreeBSD*: if fsname is not specified, set to program's
  211        basename. */
  212     if (!opts->nodefault_subtype)
  213         if (add_default_subtype(args->argv[0], args) == -1)
  214             return -1;
  215 
  216     return 0;
  217 }
  218 
  219 
  220 int fuse_daemonize(int foreground)
  221 {
  222     if (!foreground) {
  223         int nullfd;
  224         int waiter[2];
  225         char completed;
  226 
  227         if (pipe(waiter)) {
  228             perror("fuse_daemonize: pipe");
  229             return -1;
  230         }
  231 
  232         /*
  233          * demonize current process by forking it and killing the
  234          * parent.  This makes current process as a child of 'init'.
  235          */
  236         switch(fork()) {
  237         case -1:
  238             perror("fuse_daemonize: fork");
  239             return -1;
  240         case 0:
  241             break;
  242         default:
  243             (void) read(waiter[0], &completed, sizeof(completed));
  244             _exit(0);
  245         }
  246 
  247         if (setsid() == -1) {
  248             perror("fuse_daemonize: setsid");
  249             return -1;
  250         }
  251 
  252         (void) chdir("/");
  253 
  254         nullfd = open("/dev/null", O_RDWR, 0);
  255         if (nullfd != -1) {
  256             (void) dup2(nullfd, 0);
  257             (void) dup2(nullfd, 1);
  258             (void) dup2(nullfd, 2);
  259             if (nullfd > 2)
  260                 close(nullfd);
  261         }
  262 
  263         /* Propagate completion of daemon initializatation */
  264         completed = 1;
  265         (void) write(waiter[1], &completed, sizeof(completed));
  266         close(waiter[0]);
  267         close(waiter[1]);
  268     } else {
  269         (void) chdir("/");
  270     }
  271     return 0;
  272 }
  273 
  274 int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
  275            size_t op_size, void *user_data)
  276 {
  277     struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  278     struct fuse *fuse;
  279     struct fuse_cmdline_opts opts;
  280     int res;
  281 
  282     if (fuse_parse_cmdline(&args, &opts) != 0)
  283         return 1;
  284 
  285     if (opts.show_version) {
  286         printf("FUSE library version %s\n", PACKAGE_VERSION);
  287         fuse_lowlevel_version();
  288         res = 0;
  289         goto out1;
  290     }
  291 
  292     if (opts.show_help) {
  293         if(args.argv[0][0] != '\0')
  294             printf("usage: %s [options] <mountpoint>\n\n",
  295                    args.argv[0]);
  296         printf("FUSE options:\n");
  297         fuse_cmdline_help();
  298         fuse_lib_help(&args);
  299         res = 0;
  300         goto out1;
  301     }
  302 
  303     if (!opts.show_help &&
  304         !opts.mountpoint) {
  305         fprintf(stderr, "error: no mountpoint specified\n");
  306         res = 1;
  307         goto out1;
  308     }
  309 
  310 
  311     fuse = fuse_new_31(&args, op, op_size, user_data);
  312     if (fuse == NULL) {
  313         res = 1;
  314         goto out1;
  315     }
  316 
  317     if (fuse_mount(fuse,opts.mountpoint) != 0) {
  318         res = 1;
  319         goto out2;
  320     }
  321 
  322     if (fuse_daemonize(opts.foreground) != 0) {
  323         res = 1;
  324         goto out3;
  325     }
  326 
  327     struct fuse_session *se = fuse_get_session(fuse);
  328     if (fuse_set_signal_handlers(se) != 0) {
  329         res = 1;
  330         goto out3;
  331     }
  332 
  333     if (opts.singlethread)
  334         res = fuse_loop(fuse);
  335     else {
  336         struct fuse_loop_config loop_config;
  337         loop_config.clone_fd = opts.clone_fd;
  338         loop_config.max_idle_threads = opts.max_idle_threads;
  339         res = fuse_loop_mt_32(fuse, &loop_config);
  340     }
  341     if (res)
  342         res = 1;
  343 
  344     fuse_remove_signal_handlers(se);
  345 out3:
  346     fuse_unmount(fuse);
  347 out2:
  348     fuse_destroy(fuse);
  349 out1:
  350     free(opts.mountpoint);
  351     fuse_opt_free_args(&args);
  352     return res;
  353 }
  354 
  355 
  356 void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
  357                    struct fuse_conn_info *conn)
  358 {
  359     if(opts->set_max_write)
  360         conn->max_write = opts->max_write;
  361     if(opts->set_max_background)
  362         conn->max_background = opts->max_background;
  363     if(opts->set_congestion_threshold)
  364         conn->congestion_threshold = opts->congestion_threshold;
  365     if(opts->set_time_gran)
  366         conn->time_gran = opts->time_gran;
  367     if(opts->set_max_readahead)
  368         conn->max_readahead = opts->max_readahead;
  369 
  370 #define LL_ENABLE(cond,cap) \
  371     if (cond) conn->want |= (cap)
  372 #define LL_DISABLE(cond,cap) \
  373     if (cond) conn->want &= ~(cap)
  374 
  375     LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
  376     LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
  377 
  378     LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
  379     LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
  380 
  381     LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
  382     LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
  383 
  384     LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
  385     LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
  386 
  387     LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
  388     LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
  389 
  390     LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
  391     LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
  392 
  393     LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
  394     LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
  395 
  396     LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
  397     LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
  398 
  399     LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
  400     LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
  401 }
  402 
  403 struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
  404 {
  405     struct fuse_conn_info_opts *opts;
  406 
  407     opts = calloc(1, sizeof(struct fuse_conn_info_opts));
  408     if(opts == NULL) {
  409         fprintf(stderr, "calloc failed\n");
  410         return NULL;
  411     }
  412     if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
  413         free(opts);
  414         return NULL;
  415     }
  416     return opts;
  417 }