Exemple #1
0
static int get_mnt_flag_opts(char **mnt_optsp, int flags)
{
	int i;

	if (!(flags & MS_RDONLY) && fuse_opt_add_opt(mnt_optsp, "rw") == -1)
		return -1;

	for (i = 0; mount_flags[i].opt != NULL; i++) {
		if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
		    fuse_opt_add_opt(mnt_optsp, mount_flags[i].opt) == -1)
			return -1;
	}
	return 0;
}
Exemple #2
0
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
                                struct fuse_args *outargs)
{
    struct helper_opts *hopts = data;

    switch (key) {
    case KEY_HELP:
        usage(outargs->argv[0]);
        /* fall through */

    case KEY_HELP_NOHEADER:
        helper_help();
        return fuse_opt_add_arg(outargs, "-h");

    case KEY_VERSION:
        helper_version();
        return 1;

    case FUSE_OPT_KEY_NONOPT:
        if (!hopts->mountpoint) {
            char mountpoint[PATH_MAX];
            if (realpath(arg, mountpoint) == NULL) {
                fprintf(stderr, "fuse: bad mount point `%s': %s\n", arg, strerror(errno));
                return -1;
            }
            return fuse_opt_add_opt(&hopts->mountpoint, mountpoint);
        } else {
            fprintf(stderr, "fuse: invalid argument `%s'\n", arg);
            return -1;
        }

    default:
        return 1;
    }
}
Exemple #3
0
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));
    if (getuid())
        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.flags & MS_NODEV) && fuse_opt_add_opt(&mnt_opts, "dev") == -1)
        goto out;
    if (!(mo.flags & MS_NOSUID) && fuse_opt_add_opt(&mnt_opts, "suid") == -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;
    if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) < 0)
        goto out;

    res = fusermount(0, 0, 0, mnt_opts ? mnt_opts : "", mountpoint);

out:
    free(mnt_opts);
    free(mo.fsname);
    free(mo.fusermount_opts);
    free(mo.kernel_opts);
    free(mo.mtab_opts);
    return res;
}
Exemple #4
0
static int fuse_mount_opt_proc(void *data, const char *arg, int key,
                               struct fuse_args *outargs)
{
    struct mount_opts *mo = data;

    switch (key) {
    case KEY_ALLOW_ROOT:
        if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
            fuse_opt_add_arg(outargs, "-oallow_root") == -1)
            return -1;
        return 0;

    case KEY_RO:
        arg = "ro";
        /* fall through */
    case KEY_KERN_FLAG:
        set_mount_flag(arg, &mo->flags);
        return 0;

    case KEY_KERN_OPT:
        return fuse_opt_add_opt(&mo->kernel_opts, arg);

    case KEY_FUSERMOUNT_OPT:
        return fuse_opt_add_opt(&mo->fusermount_opts, arg);

    case KEY_SUBTYPE_OPT:
        return fuse_opt_add_opt(&mo->subtype_opt, arg);

    case KEY_MTAB_OPT:
        return fuse_opt_add_opt(&mo->mtab_opts, arg);

    case KEY_HELP:
        mount_help();
        mo->ishelp = 1;
        break;

    case KEY_VERSION:
        mount_version();
        mo->ishelp = 1;
        break;
    }
    return 1;
}
int SMTPFileSystem::SMTPFileSystemOptions::opt_proc(void *data, const char *arg, int key,
    struct fuse_args *outargs)
{
    SMTPFileSystemOptions *options = static_cast<SMTPFileSystemOptions*>(data);

    if (key == FUSE_OPT_KEY_NONOPT) {
        if (options->m_mount_point && options->m_device_file) {
            // Unknown positional argument supplied
            return -1;
        }
        if (options->m_device_file) {
            fuse_opt_add_opt(&options->m_mount_point, arg);
            return 0;
        }

        fuse_opt_add_opt(&options->m_device_file, arg);
        return 0;
    }
    return 1;
}
Exemple #6
0
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
				struct fuse_args *outargs)
{
	struct helper_opts *hopts = data;

	switch (key) {
	case KEY_HELP:
		usage(outargs->argv[0]);
		/* fall through */

	case KEY_HELP_NOHEADER:
		helper_help();
		return fuse_opt_add_arg(outargs, "-h");

	case KEY_VERSION:
		helper_version();
		return 1;

	case FUSE_OPT_KEY_NONOPT:
		if (!hopts->mountpoint) {
			char mountpoint[PATH_MAX];
			if (realpath(arg, mountpoint) == NULL) {
				fprintf(stderr,
					"fuse: bad mount point `%s': %s\n",
					arg, strerror(errno));
				return -1;
			}
#ifdef __APPLE__
			else {
				struct stat sb;
				if (stat(mountpoint, &sb) != 0) {
					fprintf(stderr,
						"fuse: failed to stat mount point `%s': %s\n",
						mountpoint, strerror(errno));
					return -1;
				}
				if ((sb.st_mode & S_IFMT) != S_IFDIR) {
					fprintf(stderr,
						"fuse: mount point is not a directory `%s'\n",
						mountpoint);
					return -1;
				}
			}
#endif
			return fuse_opt_add_opt(&hopts->mountpoint, mountpoint);
		} else {
			fprintf(stderr, "fuse: invalid argument `%s'\n", arg);
			return -1;
		}

	default:
		return 1;
	}
}
Exemple #7
0
static int add_opt(struct fuse_opt_context *ctx, const char *opt)
{
    return fuse_opt_add_opt(&ctx->opts, opt);
}
Exemple #8
0
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;
}
Exemple #9
0
static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
                          const char *mnt_opts)
{
    char tmp[128];
    const char *devname = "/dev/fuse";
    char *source = NULL;
    char *type = NULL;
    struct stat stbuf;
    int fd;
    int res;

    if (!mnt) {
        fprintf(stderr, "fuse: missing mountpoint\n");
        return -1;
    }

    res = lstat(mnt, &stbuf);
    if (res == -1) {
        fprintf(stderr ,"fuse: failed to access mountpoint %s: %s\n",
                mnt, strerror(errno));
        return -1;
    }

    if (!mo->nonempty) {
        res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode, stbuf.st_size);
        if (res == -1)
            return -1;
    }

    fd = open(devname, O_RDWR);
    if (fd == -1) {
        if (errno == ENODEV || errno == ENOENT)
            fprintf(stderr,
                    "fuse: device not found, try 'modprobe fuse' first\n");
        else
            fprintf(stderr, "fuse: failed to open %s: %s\n", devname,
                    strerror(errno));
        return -1;
    }

    snprintf(tmp, sizeof(tmp),  "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd,
             stbuf.st_mode & S_IFMT, getuid(), getgid());

    res = fuse_opt_add_opt(&mo->kernel_opts, tmp);
    if (res == -1)
        goto out_close;

    source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
                    (mo->subtype ? strlen(mo->subtype) : 0) +
                    strlen(devname) + 32);

    type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
    if (!type || !source) {
        fprintf(stderr, "fuse: failed to allocate memory\n");
        goto out_close;
    }

    strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
    if (mo->subtype) {
        strcat(type, ".");
        strcat(type, mo->subtype);
    }
    strcpy(source,
           mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));

#ifdef __SOLARIS__
	res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
	    mo->kernel_opts, MAX_MNTOPT_STR);
#else
    res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
#endif /* __SOLARIS__ */

#ifdef __SOLARIS__
    if (res == -1 && errno == EINVAL && mo->subtype) {
#else
    if (res == -1 && errno == ENODEV && mo->subtype) {
#endif
        /* Probably missing subtype support */
        strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
        if (mo->fsname) {
            if (!mo->blkdev)
                sprintf(source, "%s#%s", mo->subtype, mo->fsname);
        } else {
            strcpy(source, type);
        }
#ifdef __SOLARIS__
		res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
		    mo->kernel_opts, MAX_MNTOPT_STR);
#else
        res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
#endif /* __SOLARIS__ */
    }
    if (res == -1) {
        /*
         * Maybe kernel doesn't support unprivileged mounts, in this
         * case try falling back to fusermount
         */
        if (errno == EPERM) {
            res = -2;
        } else {
            int errno_save = errno;
            if (mo->blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
                fprintf(stderr, "fuse: 'fuseblk' support missing\n");
            else
                fprintf(stderr, "fuse: mount failed: %s\n",
                        strerror(errno_save));
        }

        goto out_close;
    }

#ifndef __SOLARIS__
    if (geteuid() == 0) {
        char *newmnt = fuse_mnt_resolve_path("fuse", mnt);
        res = -1;
        if (!newmnt)
            goto out_umount;

        res = fuse_mnt_add_mount("fuse", source, newmnt, type, mnt_opts);
        free(newmnt);
        if (res == -1)
            goto out_umount;
    }
#endif /* __SOLARIS__ */

    return fd;

 out_umount:
    umount2(mnt, 2); /* lazy umount */
 out_close:
    free(type);
    free(source);
    close(fd);
    return res;
}

static int get_mnt_flag_opts(char **mnt_optsp, int flags)
{
    int i;

    if (!(flags & MS_RDONLY) && fuse_opt_add_opt(mnt_optsp, "rw") == -1)
        return -1;

    for (i = 0; mount_flags[i].opt != NULL; i++) {
        if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
	    fuse_opt_add_opt(mnt_optsp, mount_flags[i].opt) == -1)
                return -1;
    }
    return 0;
}
Exemple #10
0
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;
}
Exemple #11
0
static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
			  const char *mnt_opts)
{
	char tmp[128];
	const char *devname = "/dev/fuse";
	char *source = NULL;
	char *type = NULL;
	struct stat stbuf;
	int fd;
	int res;

	if (!mnt) {
		fprintf(stderr, "fuse: missing mountpoint parameter\n");
		return -1;
	}

	res = stat(mnt, &stbuf);
	if (res == -1) {
		fprintf(stderr ,"fuse: failed to access mountpoint %s: %s\n",
			mnt, strerror(errno));
		return -1;
	}

	if (!mo->nonempty) {
		res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode,
					   stbuf.st_size);
		if (res == -1)
			return -1;
	}

	if (mo->auto_unmount) {
		/* Tell the caller to fallback to fusermount because
		   auto-unmount does not work otherwise. */
		return -2;
	}

	fd = open(devname, O_RDWR);
	if (fd == -1) {
		if (errno == ENODEV || errno == ENOENT)
			fprintf(stderr, "fuse: device not found, try 'modprobe fuse' first\n");
		else
			fprintf(stderr, "fuse: failed to open %s: %s\n",
				devname, strerror(errno));
		return -1;
	}

	snprintf(tmp, sizeof(tmp),  "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
		 fd, stbuf.st_mode & S_IFMT, getuid(), getgid());

	res = fuse_opt_add_opt(&mo->kernel_opts, tmp);
	if (res == -1)
		goto out_close;

	source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
			(mo->subtype ? strlen(mo->subtype) : 0) +
			strlen(devname) + 32);

	type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
	if (!type || !source) {
		fprintf(stderr, "fuse: failed to allocate memory\n");
		goto out_close;
	}

	strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
	if (mo->subtype) {
		strcat(type, ".");
		strcat(type, mo->subtype);
	}
	strcpy(source,
	       mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));

	res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
	if (res == -1 && errno == ENODEV && mo->subtype) {
		/* Probably missing subtype support */
		strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
		if (mo->fsname) {
			if (!mo->blkdev)
				sprintf(source, "%s#%s", mo->subtype,
					mo->fsname);
		} else {
			strcpy(source, type);
		}
		res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
	}
	if (res == -1) {
		/*
		 * Maybe kernel doesn't support unprivileged mounts, in this
		 * case try falling back to fusermount
		 */
		if (errno == EPERM) {
			res = -2;
		} else {
			int errno_save = errno;
			if (mo->blkdev && errno == ENODEV &&
			    !fuse_mnt_check_fuseblk())
				fprintf(stderr,
					"fuse: 'fuseblk' support missing\n");
			else
				fprintf(stderr, "fuse: mount failed: %s\n",
					strerror(errno_save));
		}

		goto out_close;
	}

#ifndef __NetBSD__
#ifndef IGNORE_MTAB
	if (geteuid() == 0) {
		char *newmnt = fuse_mnt_resolve_path("fuse", mnt);
		res = -1;
		if (!newmnt)
			goto out_umount;

		res = fuse_mnt_add_mount("fuse", source, newmnt, type,
					 mnt_opts);
		free(newmnt);
		if (res == -1)
			goto out_umount;
	}
#endif /* IGNORE_MTAB */
#endif /* __NetBSD__ */
	free(type);
	free(source);

	return fd;

out_umount:
	umount2(mnt, 2); /* lazy umount */
out_close:
	free(type);
	free(source);
	close(fd);
	return res;
}