Exemple #1
0
static int try_mount(struct libmnt_context *cxt, int bg)
{
    struct libmnt_fs *fs;
    const char *p;
    char *src = NULL, *tgt = NULL, *type = NULL, *opts = NULL;
    unsigned long flags = 0;
    int fake, ret = 0;

    fs = mnt_context_get_fs(cxt);

    /* libmount returns read-only pointers (const char)
     * so, reallocate for nfsmount() functions.
     */
    if ((p = mnt_fs_get_source(fs)))	/* spec */
        src = strdup(p);
    if ((p = mnt_fs_get_target(fs)))	/* mountpoint */
        tgt = strdup(p);
    if ((p = mnt_fs_get_fstype(fs)))	/* FS type */
        type = strdup(p);
    if ((p = mnt_fs_get_fs_options(fs)))	/* mount options */
        opts = strdup(p);

    mnt_context_get_mflags(cxt, &flags);	/* mount(2) flags */
    fake = mnt_context_is_fake(cxt);

    if (string)
        ret = nfsmount_string(src, tgt, type, flags, &opts, fake, bg);

    else if (strcmp(type, "nfs4") == 0)
        ret = nfs4mount(src, tgt, flags, &opts, fake, bg);
    else
        ret = nfsmount(src, tgt, flags, &opts, fake, bg);

    /* Store mount options if not called with mount --no-mtab */
    if (!ret && !mnt_context_is_nomtab(cxt))
        store_mount_options(fs, opts);

    free(src);
    free(tgt);
    free(type);
    free(opts);

    return ret;
}
Exemple #2
0
/**
 * mnt_context_do_umount:
 * @cxt: mount context
 *
 * Umount filesystem by umount(2) or fork()+exec(/sbin/umount.type).
 * Unnecessary for mnt_context_umount().
 *
 * See also mnt_context_disable_helpers().
 *
 * WARNING: non-zero return code does not mean that umount(2) syscall or
 *          umount.type helper wasn't successfully called.
 *
 *          Check mnt_context_get_status() after error!
*
 * Returns: 0 on success;
 *         >0 in case of umount(2) error (returns syscall errno),
 *         <0 in case of other errors.
 */
int mnt_context_do_umount(struct libmnt_context *cxt)
{
	int rc;

	assert(cxt);
	assert(cxt->fs);
	assert(cxt->helper_exec_status == 1);
	assert(cxt->syscall_status == 1);
	assert((cxt->flags & MNT_FL_PREPARED));
	assert((cxt->action == MNT_ACT_UMOUNT));
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	rc = do_umount(cxt);
	if (rc)
		return rc;

	if (mnt_context_get_status(cxt) && !mnt_context_is_fake(cxt)) {
		/*
		 * Umounted, do some post-umount operations
		 *	- remove loopdev
		 *	- refresh in-memory mtab stuff if remount rather than
		 *	  umount has been performed
		 */
		if (mnt_context_is_loopdel(cxt)
		    && !(cxt->mountflags & MS_REMOUNT))
			rc = mnt_context_delete_loopdev(cxt);

		if (!mnt_context_is_nomtab(cxt)
		    && mnt_context_get_status(cxt)
		    && !cxt->helper
		    && mnt_context_is_rdonly_umount(cxt)
		    && (cxt->mountflags & MS_REMOUNT)) {

			/* use "remount" instead of "umount" in /etc/mtab */
			if (!rc && cxt->update && cxt->mtab_writable)
				rc = mnt_update_set_fs(cxt->update,
						       cxt->mountflags, NULL, cxt->fs);
		}
	}
	return rc;
}
Exemple #3
0
static int exec_helper(struct libmnt_context *cxt)
{
	int rc;

	assert(cxt);
	assert(cxt->fs);
	assert(cxt->helper);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
	assert(cxt->helper_exec_status == 1);

	DBG_FLUSH;

	switch (fork()) {
	case 0:
	{
		const char *args[10], *type;
		int i = 0;

		if (setgid(getgid()) < 0)
			exit(EXIT_FAILURE);

		if (setuid(getuid()) < 0)
			exit(EXIT_FAILURE);

		type = mnt_fs_get_fstype(cxt->fs);

		args[i++] = cxt->helper;			/* 1 */
		args[i++] = mnt_fs_get_target(cxt->fs);		/* 2 */

		if (mnt_context_is_nomtab(cxt))
			args[i++] = "-n";			/* 3 */
		if (mnt_context_is_lazy(cxt))
			args[i++] = "-l";			/* 4 */
		if (mnt_context_is_force(cxt))
			args[i++] = "-f";			/* 5 */
		if (mnt_context_is_verbose(cxt))
			args[i++] = "-v";			/* 6 */
		if (mnt_context_is_rdonly_umount(cxt))
			args[i++] = "-r";			/* 7 */
		if (type && !endswith(cxt->helper, type)) {
			args[i++] = "-t";			/* 8 */
			args[i++] = (char *) type;	/* 9 */
		}

		args[i] = NULL;					/* 10 */
#ifdef CONFIG_LIBMOUNT_DEBUG
		for (i = 0; args[i]; i++)
			DBG(CXT, mnt_debug_h(cxt, "argv[%d] = \"%s\"",
							i, args[i]));
#endif
		DBG_FLUSH;
		execv(cxt->helper, (char * const *) args);
		exit(EXIT_FAILURE);
	}
	default:
	{
		int st;
		wait(&st);
		cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;

		DBG(CXT, mnt_debug_h(cxt, "%s executed [status=%d]",
					cxt->helper, cxt->helper_status));
		cxt->helper_exec_status = rc = 0;
		break;
	}

	case -1:
		cxt->helper_exec_status = rc = -errno;
		DBG(CXT, mnt_debug_h(cxt, "fork() failed"));
		break;
	}

	return rc;
}
Exemple #4
0
static int exec_helper(struct libmnt_context *cxt)
{
	char *o = NULL;
	int rc;

	assert(cxt);
	assert(cxt->fs);
	assert(cxt->helper);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	DBG(CXT, mnt_debug_h(cxt, "mount: executing helper %s", cxt->helper));

	rc = generate_helper_optstr(cxt, &o);
	if (rc)
		return -EINVAL;

	DBG_FLUSH;

	switch (fork()) {
	case 0:
	{
		const char *args[12], *type;
		int i = 0;

		if (setgid(getgid()) < 0)
			exit(EXIT_FAILURE);

		if (setuid(getuid()) < 0)
			exit(EXIT_FAILURE);

		type = mnt_fs_get_fstype(cxt->fs);

		args[i++] = cxt->helper;		/* 1 */
		args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */
		args[i++] = mnt_fs_get_target(cxt->fs);	/* 3 */

		/*
		 * TODO: remove the exception for "nfs", -s is documented
		 *       for years should be usable everywhere.
		 */
		if (mnt_context_is_sloppy(cxt) &&
		    type && startswith(type, "nfs"))
			args[i++] = "-s";		/* 4 */
		if (mnt_context_is_fake(cxt))
			args[i++] = "-f";		/* 5 */
		if (mnt_context_is_nomtab(cxt))
			args[i++] = "-n";		/* 6 */
		if (mnt_context_is_verbose(cxt))
			args[i++] = "-v";		/* 7 */
		if (o) {
			args[i++] = "-o";		/* 8 */
			args[i++] = o;			/* 9 */
		}
		if (type && !endswith(cxt->helper, type)) {
			args[i++] = "-t";		/* 10 */
			args[i++] = type;		/* 11 */
		}
		args[i] = NULL;				/* 12 */
#ifdef CONFIG_LIBMOUNT_DEBUG
		for (i = 0; args[i]; i++)
			DBG(CXT, mnt_debug_h(cxt, "argv[%d] = \"%s\"",
							i, args[i]));
#endif
		DBG_FLUSH;
		execv(cxt->helper, (char * const *) args);
		exit(EXIT_FAILURE);
	}
	default:
	{
		int st;
		wait(&st);
		cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;

		DBG(CXT, mnt_debug_h(cxt, "%s executed [status=%d]",
					cxt->helper, cxt->helper_status));
		cxt->helper_exec_status = rc = 0;
		break;
	}

	case -1:
		cxt->helper_exec_status = rc = -errno;
		DBG(CXT, mnt_debug_h(cxt, "fork() failed"));
		break;
	}

	return rc;
}
Exemple #5
0
static int mount_main(struct libmnt_context *cxt, int argc, char **argv)
{
    int rc, c;
    struct libmnt_fs *fs;
    char *spec = NULL, *mount_point = NULL, *opts = NULL;

    static const struct option longopts[] = {
        { "fake", 0, 0, 'f' },
        { "help", 0, 0, 'h' },
        { "no-mtab", 0, 0, 'n' },
        { "read-only", 0, 0, 'r' },
        { "ro", 0, 0, 'r' },
        { "verbose", 0, 0, 'v' },
        { "version", 0, 0, 'V' },
        { "read-write", 0, 0, 'w' },
        { "rw", 0, 0, 'w' },
        { "options", 1, 0, 'o' },
        { "sloppy", 0, 0, 's' },
        { NULL, 0, 0, 0 }
    };

    mount_config_init(progname);
    mnt_context_init_helper(cxt, MNT_ACT_MOUNT, 0);

    while ((c = getopt_long(argc, argv, "fhnrVvwo:s", longopts, NULL)) != -1) {

        rc = mnt_context_helper_setopt(cxt, c, optarg);
        if (rc == 0)		/* valid option */
            continue;
        if (rc < 0)		/* error (probably ENOMEM) */
            goto err;
        /* rc==1 means unknow option */
        switch (c) {
        case 'V':
            printf("%s: ("PACKAGE_STRING")\n", progname);
            return EX_SUCCESS;
        case 'h':
        default:
            mount_usage();
            return EX_USAGE;
        }
    }

    if (optind < argc)
        spec = argv[optind++];
    if (optind < argc)
        mount_point = argv[optind++];

    if (!mount_point) {
        nfs_error(_("%s: no mount point provided"), progname);
        goto err;
    }
    if (!spec) {
        nfs_error(_("%s: no mount spec provided"), progname);
        goto err;
    }

    if (geteuid() != 0) {
        nfs_error(_("%s: not installed setuid - "
                    "\"user\" NFS mounts not supported."), progname);
        goto err;
    }

    verbose = mnt_context_is_verbose(cxt);
    sloppy = mnt_context_is_sloppy(cxt);
    nomtab = mnt_context_is_nomtab(cxt);

    if (strcmp(progname, "mount.nfs4") == 0)
        mnt_context_set_fstype(cxt, "nfs4");
    else
        mnt_context_set_fstype(cxt, "nfs");	/* default */

    rc = mnt_context_set_source(cxt, spec);
    if (!rc)
        mnt_context_set_target(cxt, mount_point);
    if (rc) {
        nfs_error(_("%s: failed to set spec or mountpoint: %s"),
                  progname, strerror(errno));
        goto err;
    }

    mount_point = mnt_resolve_path(mount_point,
                                   mnt_context_get_cache(cxt));

    if (chk_mountpoint(mount_point))
        goto err;
    /*
     * Concatenate mount options from the configuration file
     */
    fs = mnt_context_get_fs(cxt);
    if (fs) {
        opts = mnt_fs_strdup_options(fs);

        opts = mount_config_opts(spec, mount_point, opts);
        mnt_fs_set_options(fs, opts);
    }

    rc = mnt_context_prepare_mount(cxt);
    if (rc) {
        nfs_error(_("%s: failed to prepare mount: %s\n"),
                  progname, strerror(-rc));
        goto err;
    }

    rc = try_mount(cxt, FOREGROUND);

    if (rc == EX_BG) {
        printf(_("%s: backgrounding \"%s\"\n"),
               progname, mnt_context_get_source(cxt));
        printf(_("%s: mount options: \"%s\"\n"),
               progname, opts);

        fflush(stdout);

        if (daemon(0, 0)) {
            nfs_error(_("%s: failed to start "
                        "background process: %s\n"),
                      progname, strerror(errno));
            exit(EX_FAIL);
        }

        rc = try_mount(cxt, BACKGROUND);

        if (verbose && rc)
            printf(_("%s: giving up \"%s\"\n"),
                   progname, mnt_context_get_source(cxt));
    }

    mnt_context_set_syscall_status(cxt, rc == EX_SUCCESS ? 0 : -1);
    mnt_context_finalize_mount(cxt);	/* mtab update */
    return rc;
err:
    return EX_FAIL;
}