"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.1/lib/mount_bsd.c" (14 Nov 2017, 6244 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 "mount_bsd.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.1.1_vs_3.2.0.

    1 /*
    2   FUSE: Filesystem in Userspace
    3   Copyright (C) 2005-2008 Csaba Henk <csaba.henk@creo.hu>
    4 
    5   Architecture specific file system mounting (FreeBSD).
    6 
    7   This program can be distributed under the terms of the GNU LGPLv2.
    8   See the file COPYING.LIB.
    9 */
   10 
   11 #include "config.h"
   12 #include "fuse_i.h"
   13 #include "fuse_misc.h"
   14 #include "fuse_opt.h"
   15 
   16 #include <sys/param.h>
   17 #include <sys/mount.h>
   18 
   19 #include <sys/stat.h>
   20 #include <sys/wait.h>
   21 #include <sys/sysctl.h>
   22 #include <sys/user.h>
   23 #include <stdio.h>
   24 #include <stdlib.h>
   25 #include <unistd.h>
   26 #include <stddef.h>
   27 #include <fcntl.h>
   28 #include <errno.h>
   29 #include <string.h>
   30 #include <paths.h>
   31 #include <limits.h>
   32 
   33 #define FUSERMOUNT_PROG     "mount_fusefs"
   34 #define FUSE_DEV_TRUNK      "/dev/fuse"
   35 
   36 enum {
   37     KEY_RO,
   38     KEY_KERN
   39 };
   40 
   41 struct mount_opts {
   42     int allow_other;
   43     char *kernel_opts;
   44     unsigned max_read;
   45 };
   46 
   47 #define FUSE_DUAL_OPT_KEY(templ, key)               \
   48     FUSE_OPT_KEY(templ, key), FUSE_OPT_KEY("no" templ, key)
   49 
   50 static const struct fuse_opt fuse_mount_opts[] = {
   51     { "allow_other", offsetof(struct mount_opts, allow_other), 1 },
   52     { "max_read=%u", offsetof(struct mount_opts, max_read), 1 },
   53     FUSE_OPT_KEY("-r",          KEY_RO),
   54     /* standard FreeBSD mount options */
   55     FUSE_DUAL_OPT_KEY("dev",        KEY_KERN),
   56     FUSE_DUAL_OPT_KEY("async",      KEY_KERN),
   57     FUSE_DUAL_OPT_KEY("atime",      KEY_KERN),
   58     FUSE_DUAL_OPT_KEY("dev",        KEY_KERN),
   59     FUSE_DUAL_OPT_KEY("exec",       KEY_KERN),
   60     FUSE_DUAL_OPT_KEY("suid",       KEY_KERN),
   61     FUSE_DUAL_OPT_KEY("symfollow",      KEY_KERN),
   62     FUSE_DUAL_OPT_KEY("rdonly",     KEY_KERN),
   63     FUSE_DUAL_OPT_KEY("sync",       KEY_KERN),
   64     FUSE_DUAL_OPT_KEY("union",      KEY_KERN),
   65     FUSE_DUAL_OPT_KEY("userquota",      KEY_KERN),
   66     FUSE_DUAL_OPT_KEY("groupquota",     KEY_KERN),
   67     FUSE_DUAL_OPT_KEY("clusterr",       KEY_KERN),
   68     FUSE_DUAL_OPT_KEY("clusterw",       KEY_KERN),
   69     FUSE_DUAL_OPT_KEY("suiddir",        KEY_KERN),
   70     FUSE_DUAL_OPT_KEY("snapshot",       KEY_KERN),
   71     FUSE_DUAL_OPT_KEY("multilabel",     KEY_KERN),
   72     FUSE_DUAL_OPT_KEY("acls",       KEY_KERN),
   73     FUSE_DUAL_OPT_KEY("force",      KEY_KERN),
   74     FUSE_DUAL_OPT_KEY("update",     KEY_KERN),
   75     FUSE_DUAL_OPT_KEY("ro",         KEY_KERN),
   76     FUSE_DUAL_OPT_KEY("rw",         KEY_KERN),
   77     FUSE_DUAL_OPT_KEY("auto",       KEY_KERN),
   78     FUSE_DUAL_OPT_KEY("automounted",    KEY_KERN),
   79     /* options supported under both Linux and FBSD */
   80     FUSE_DUAL_OPT_KEY("allow_other",    KEY_KERN),
   81     FUSE_DUAL_OPT_KEY("default_permissions",KEY_KERN),
   82     FUSE_OPT_KEY("max_read=",       KEY_KERN),
   83     FUSE_OPT_KEY("subtype=",        KEY_KERN),
   84     /* FBSD FUSE specific mount options */
   85     FUSE_DUAL_OPT_KEY("private",        KEY_KERN),
   86     FUSE_DUAL_OPT_KEY("neglect_shares", KEY_KERN),
   87     FUSE_DUAL_OPT_KEY("push_symlinks_in",   KEY_KERN),
   88     FUSE_OPT_KEY("nosync_unmount",      KEY_KERN),
   89     /* stock FBSD mountopt parsing routine lets anything be negated... */
   90     /*
   91      * Linux specific mount options, but let just the mount util
   92      * handle them
   93      */
   94     FUSE_OPT_KEY("fsname=",         KEY_KERN),
   95     FUSE_OPT_END
   96 };
   97 
   98 void fuse_mount_version(void)
   99 {
  100     system(FUSERMOUNT_PROG " --version");
  101 }
  102 
  103 unsigned get_max_read(struct mount_opts *o)
  104 {
  105     return o->max_read;
  106 }
  107 
  108 static int fuse_mount_opt_proc(void *data, const char *arg, int key,
  109                    struct fuse_args *outargs)
  110 {
  111     (void) outargs;
  112     struct mount_opts *mo = data;
  113 
  114     switch (key) {
  115     case KEY_RO:
  116         arg = "ro";
  117         /* fall through */
  118 
  119     case KEY_KERN:
  120         return fuse_opt_add_opt(&mo->kernel_opts, arg);
  121     }
  122 
  123     /* Pass through unknown options */
  124     return 1;
  125 }
  126 
  127 void fuse_kern_unmount(const char *mountpoint, int fd)
  128 {
  129     close(fd);
  130     unmount(mountpoint, MNT_FORCE);
  131 }
  132 
  133 /* Check if kernel is doing init in background */
  134 static int init_backgrounded(void)
  135 {
  136     unsigned ibg;
  137     size_t len;
  138 
  139     len = sizeof(ibg);
  140 
  141     if (sysctlbyname("vfs.fuse.init_backgrounded", &ibg, &len, NULL, 0))
  142         return 0;
  143 
  144     return ibg;
  145 }
  146 
  147 
  148 static int fuse_mount_core(const char *mountpoint, const char *opts)
  149 {
  150     const char *mountprog = FUSERMOUNT_PROG;
  151     int fd;
  152     char *fdnam, *dev;
  153     pid_t pid, cpid;
  154     int status;
  155 
  156     fdnam = getenv("FUSE_DEV_FD");
  157 
  158     if (fdnam) {
  159         char *ep;
  160 
  161         fd = strtol(fdnam, &ep, 10);
  162 
  163         if (*ep != '\0') {
  164             fprintf(stderr, "invalid value given in FUSE_DEV_FD\n");
  165             return -1;
  166         }
  167 
  168         if (fd < 0)
  169             return -1;
  170 
  171         goto mount;
  172     }
  173 
  174     dev = getenv("FUSE_DEV_NAME");
  175 
  176     if (! dev)
  177         dev = (char *)FUSE_DEV_TRUNK;
  178 
  179     if ((fd = open(dev, O_RDWR)) < 0) {
  180         perror("fuse: failed to open fuse device");
  181         return -1;
  182     }
  183 
  184 mount:
  185     if (getenv("FUSE_NO_MOUNT") || ! mountpoint)
  186         goto out;
  187 
  188     pid = fork();
  189     cpid = pid;
  190 
  191     if (pid == -1) {
  192         perror("fuse: fork() failed");
  193         close(fd);
  194         return -1;
  195     }
  196 
  197     if (pid == 0) {
  198         if (! init_backgrounded()) {
  199             /*
  200              * If init is not backgrounded, we have to
  201              * call the mount util backgrounded, to avoid
  202              * deadlock.
  203              */
  204 
  205             pid = fork();
  206 
  207             if (pid == -1) {
  208                 perror("fuse: fork() failed");
  209                 close(fd);
  210                 exit(1);
  211             }
  212         }
  213 
  214         if (pid == 0) {
  215             const char *argv[32];
  216             int a = 0;
  217             int ret = -1; 
  218             
  219             if (! fdnam)
  220             {
  221                 ret = asprintf(&fdnam, "%d", fd); 
  222                 if(ret == -1)
  223                 {
  224                     perror("fuse: failed to assemble mount arguments");
  225                     exit(1);
  226                 }
  227             }
  228 
  229             argv[a++] = mountprog;
  230             if (opts) {
  231                 argv[a++] = "-o";
  232                 argv[a++] = opts;
  233             }
  234             argv[a++] = fdnam;
  235             
  236             if(ret != -1)
  237                 free(fdnam);
  238             
  239             argv[a++] = mountpoint;
  240             argv[a++] = NULL;
  241             execvp(mountprog, (char **) argv);
  242             perror("fuse: failed to exec mount program");
  243             exit(1);
  244         }
  245 
  246         exit(0);
  247     }
  248 
  249     if (waitpid(cpid, &status, 0) == -1 || WEXITSTATUS(status) != 0) {
  250         perror("fuse: failed to mount file system");
  251         close(fd);
  252         return -1;
  253     }
  254 
  255 out:
  256     return fd;
  257 }
  258 
  259 struct mount_opts *parse_mount_opts(struct fuse_args *args)
  260 {
  261     struct mount_opts *mo;
  262 
  263     mo = (struct mount_opts*) malloc(sizeof(struct mount_opts));
  264     if (mo == NULL)
  265         return NULL;
  266 
  267     memset(mo, 0, sizeof(struct mount_opts));
  268 
  269     if (args &&
  270         fuse_opt_parse(args, mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
  271         goto err_out;
  272 
  273     return mo;
  274 
  275 err_out:
  276     destroy_mount_opts(mo);
  277     return NULL;
  278 }
  279 
  280 void destroy_mount_opts(struct mount_opts *mo)
  281 {
  282     free(mo->kernel_opts);
  283     free(mo);
  284 }
  285 
  286 int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo)
  287 {
  288     /* mount util should not try to spawn the daemon */
  289     setenv("MOUNT_FUSEFS_SAFE", "1", 1);
  290     /* to notify the mount util it's called from lib */
  291     setenv("MOUNT_FUSEFS_CALL_BY_LIB", "1", 1);
  292 
  293     return fuse_mount_core(mountpoint, mo->kernel_opts);
  294 }