int gf_fuse_mount (const char *mountpoint, char *fsname, unsigned long mountflags, char *mnt_param, pid_t *mnt_pid, int status_fd) { int fd = -1; pid_t pid = -1; int ret = -1; fd = open ("/dev/fuse", O_RDWR); if (fd == -1) { GFFUSE_LOGERR ("cannot open /dev/fuse (%s)", strerror (errno)); return -1; } /* start mount agent */ pid = fork(); switch (pid) { case 0: /* hello it's mount agent */ if (!mnt_pid) { /* daemonize mount agent, caller is * not interested in waiting for it */ pid = fork (); if (pid) exit (pid == -1 ? 1 : 0); } ret = fuse_mount_sys (mountpoint, fsname, mountflags, mnt_param, fd); if (ret == -1) { gf_log ("glusterfs-fuse", GF_LOG_INFO, "direct mount failed (%s) errno %d, " "retry to mount via fusermount", strerror (errno), errno); ret = fuse_mount_fusermount (mountpoint, fsname, mountflags, mnt_param, fd); } if (ret == -1) GFFUSE_LOGERR ("mount of %s to %s (%s) failed", fsname, mountpoint, mnt_param); if (status_fd >= 0) (void)write (status_fd, &ret, sizeof (ret)); exit (!!ret); /* bye mount agent */ case -1: close (fd); fd = -1; } if (mnt_pid) *mnt_pid = pid; return fd; }
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) { struct mount_opts mo; int res = -1; char *mnt_opts = NULL; #ifdef __SOLARIS__ struct solaris_mount_opts smo; struct fuse_args sa = FUSE_ARGS_INIT(0, NULL); #endif /* __SOLARIS__ */ memset(&mo, 0, sizeof(mo)); #ifdef __SOLARIS__ mo.flags = 0; memset(&smo, 0, sizeof(smo)); if (args != NULL) { while (args->argv[sa.argc] != NULL) fuse_opt_add_arg(&sa, args->argv[sa.argc]); } #else mo.flags = MS_NOSUID | MS_NODEV; #endif /* __SOLARIS__ */ if (args && fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) goto out; /* if SOLARIS, clean up 'sa' */ #ifdef __SOLARIS__ /* * In Solaris, nosuid is equivalent to nosetuid + nodevices. We only * have MS_NOSUID for mount flags (no MS_(NO)SETUID, etc.). But if * we set that as a default, it restricts specifying just nosetuid * or nodevices; there is no way for the user to specify setuid + * nodevices or vice-verse. So we parse the existing options, then * add restrictive defaults if needed. */ if (fuse_opt_parse(&sa, &smo, solaris_mnt_opts, NULL) == -1) goto out; if (smo.nosuid || (!smo.nodevices && !smo.devices && !smo.nosetuid && !smo.setuid)) { mo.flags |= MS_NOSUID; } else { /* * Defaults; if neither nodevices|devices,nosetuid|setuid has * been specified, add the default negative option string. If * both have been specified (i.e., -osuid,nosuid), leave them * alone; the last option will have precedence. */ if (!smo.nodevices && !smo.devices) if (fuse_opt_add_opt(&mo.kernel_opts, "nodevices") == -1) goto out; if (!smo.nosetuid && !smo.setuid) if (fuse_opt_add_opt(&mo.kernel_opts, "nosetuid") == -1) goto out; } #endif /* __SOLARIS__ */ if (mo.allow_other && mo.allow_root) { fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n"); goto out; } res = 0; if (mo.ishelp) goto out; res = -1; if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1) goto out; if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1) goto out; if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1) goto out; res = fuse_mount_sys(mountpoint, &mo, mnt_opts); if (res == -2) { if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1) goto out; if (mo.subtype) { char *tmp_opts = NULL; res = -1; if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 || fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) { free(tmp_opts); goto out; } res = fuse_mount_fusermount(mountpoint, tmp_opts, 1); free(tmp_opts); if (res == -1) res = fuse_mount_fusermount(mountpoint, mnt_opts, 0); } else { res = fuse_mount_fusermount(mountpoint, mnt_opts, 0); } } out: #ifdef __SOLARIS__ fuse_opt_free_args(&sa); #endif /* __SOLARIS__ */ free(mnt_opts); free(mo.fsname); free(mo.subtype); free(mo.fusermount_opts); free(mo.subtype_opt); free(mo.kernel_opts); free(mo.mtab_opts); return res; }
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) { struct mount_opts mo; int res = -1; char *mnt_opts = NULL; memset(&mo, 0, sizeof(mo)); mo.flags = MS_NOSUID | MS_NODEV; if (args && fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) return -1; if (mo.allow_other && mo.allow_root) { fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n"); goto out; } res = 0; if (mo.ishelp) goto out; res = -1; if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1) goto out; if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1) goto out; if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1) goto out; res = fuse_mount_sys(mountpoint, &mo, mnt_opts); if (res == -2) { if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1) goto out; if (mo.subtype) { char *tmp_opts = NULL; res = -1; if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 || fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) { free(tmp_opts); goto out; } res = fuse_mount_fusermount(mountpoint, &mo, tmp_opts, 1); free(tmp_opts); if (res == -1) res = fuse_mount_fusermount(mountpoint, &mo, mnt_opts, 0); } else { res = fuse_mount_fusermount(mountpoint, &mo, mnt_opts, 0); } } out: free(mnt_opts); free(mo.fsname); free(mo.subtype); free(mo.fusermount_opts); free(mo.subtype_opt); free(mo.kernel_opts); free(mo.mtab_opts); return res; }