Ejemplo n.º 1
0
/**
 * mnt_update_force_rdonly:
 * @upd: update
 * @rdonly: is read-only?
 *
 * Returns: 0 on success and negative number in case of error.
 */
int mnt_update_force_rdonly(struct libmnt_update *upd, int rdonly)
{
	int rc = 0;

	if (!upd || !upd->fs)
		return -EINVAL;

	if (rdonly && (upd->mountflags & MS_RDONLY))
		return 0;
	if (!rdonly && !(upd->mountflags & MS_RDONLY))
		return 0;

	if (!upd->userspace_only) {
		/* /etc/mtab -- we care about VFS options there */
		const char *o = mnt_fs_get_options(upd->fs);
		char *n = o ? strdup(o) : NULL;

		if (n)
			mnt_optstr_remove_option(&n, rdonly ? "rw" : "ro");
		if (!mnt_optstr_prepend_option(&n, rdonly ? "ro" : "rw", NULL))
			rc = mnt_fs_set_options(upd->fs, n);

		free(n);
	}

	if (rdonly)
		upd->mountflags &= ~MS_RDONLY;
	else
		upd->mountflags |= MS_RDONLY;

	return rc;
}
Ejemplo n.º 2
0
/*
 * Parses one line from {fs,m}tab
 */
static int mnt_parse_table_line(struct libmnt_fs *fs, char *s)
{
	int rc, n = 0;
	char *src, *fstype, *optstr;

	rc = sscanf(s,	UL_SCNsA" "	/* (1) source */
			UL_SCNsA" "	/* (2) target */
			UL_SCNsA" "	/* (3) FS type */
			UL_SCNsA" "	/* (4) options */
			"%n",		/* byte count */

			&src,
			&fs->target,
			&fstype,
			&optstr,
			&n);

	if (rc == 4) {
		unmangle_string(src);
		unmangle_string(fs->target);
		unmangle_string(fstype);
		unmangle_string(optstr);

		rc = __mnt_fs_set_source_ptr(fs, src);
		if (!rc)
			rc = __mnt_fs_set_fstype_ptr(fs, fstype);
		if (!rc)
			rc = mnt_fs_set_options(fs, optstr);
		free(optstr);
	} else {
		DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s));
		rc = -EINVAL;
	}

	if (rc)
		return rc;	/* error */

	fs->passno = fs->freq = 0;
	s = skip_spaces(s + n);
	if (*s) {
		if (next_number(&s, &fs->freq) != 0) {
			if (*s) {
				DBG(TAB, mnt_debug("tab parse error: [freq]"));
				rc = -EINVAL;
			}
		} else if (next_number(&s, &fs->passno) != 0 && *s) {
			DBG(TAB, mnt_debug("tab parse error: [passno]"));
			rc = -EINVAL;
		}
	}

	return rc;
}
Ejemplo n.º 3
0
/*
 * Store mount options to mtab (or /dev/.mount/utab), called from mount.nfs.
 *
 * Note that on systems without /etc/mtab the fs-specific options are not
 * managed by libmount at all. We have to use "mount attributes" that are
 * private for mount.<type> helpers.
 */
static void store_mount_options(struct libmnt_fs *fs, const char *nfs_opts)
{
    char *o = NULL;

    mnt_fs_set_attributes(fs, nfs_opts);	/* for non-mtab systems */

    /* for mtab create a new options list */
    mnt_optstr_append_option(&o, mnt_fs_get_vfs_options(fs), NULL);
    mnt_optstr_append_option(&o, nfs_opts, NULL);
    mnt_optstr_append_option(&o, mnt_fs_get_user_options(fs), NULL);

    mnt_fs_set_options(fs, o);
    free(o);
}
Ejemplo n.º 4
0
static int test_remount(struct libmnt_test *ts, int argc, char *argv[])
{
	struct libmnt_fs *fs = mnt_new_fs();
	int rc;

	if (argc < 3)
		return -1;
	mnt_fs_set_target(fs, argv[1]);
	mnt_fs_set_options(fs, argv[2]);

	rc = update(NULL, fs, MS_REMOUNT);
	mnt_free_fs(fs);
	return rc;
}
Ejemplo n.º 5
0
static int test_add(struct libmnt_test *ts, int argc, char *argv[])
{
	struct libmnt_fs *fs = mnt_new_fs();
	int rc;

	if (argc < 5 || !fs)
		return -1;
	mnt_fs_set_source(fs, argv[1]);
	mnt_fs_set_target(fs, argv[2]);
	mnt_fs_set_fstype(fs, argv[3]);
	mnt_fs_set_options(fs, argv[4]);

	rc = update(NULL, fs, 0);
	mnt_free_fs(fs);
	return rc;
}
Ejemplo n.º 6
0
static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *lc)
{
	struct libmnt_table *tb = NULL;
	int rc = 0;
	struct libmnt_fs *fs;

	assert(upd);
	assert(upd->fs);

	DBG(UPDATE, mnt_debug_h(upd, "%s: modify options", upd->filename));

	fs = upd->fs;

	if (lc)
		rc = mnt_lock_file(lc);
	if (rc)
		return rc;

	tb = __mnt_new_table_from_file(upd->filename,
			upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB);
	if (tb) {
		struct libmnt_fs *cur = mnt_table_find_target(tb,
					mnt_fs_get_target(fs),
					MNT_ITER_BACKWARD);
		if (cur) {
			if (upd->userspace_only)
				rc = mnt_fs_set_attributes(cur,	mnt_fs_get_attributes(fs));
			if (!rc)
				rc = mnt_fs_set_options(cur, mnt_fs_get_options(fs));
			if (!rc)
				rc = update_table(upd, tb);
		}
	}

	if (lc)
		mnt_unlock_file(lc);

	mnt_free_table(tb);
	return rc;
}
Ejemplo n.º 7
0
/*
 * Parses one line from {fs,m}tab
 */
static int mnt_parse_table_line(struct libmnt_fs *fs, char *s)
{
	int rc, n = 0, xrc;
	char *src = NULL, *fstype = NULL, *optstr = NULL;

	rc = sscanf(s,	UL_SCNsA" "	/* (1) source */
			UL_SCNsA" "	/* (2) target */
			UL_SCNsA" "	/* (3) FS type */
			UL_SCNsA" "	/* (4) options */
			"%n",		/* byte count */

			&src,
			&fs->target,
			&fstype,
			&optstr,
			&n);
	xrc = rc;

	if (rc == 3 || rc == 4) {			/* options are optional */
		unmangle_string(src);
		unmangle_string(fs->target);
		unmangle_string(fstype);

		if (optstr && *optstr)
			unmangle_string(optstr);

		/* note that __foo functions does not reallocate the string
		 */
		rc = __mnt_fs_set_source_ptr(fs, src);
		if (!rc) {
			src = NULL;
			rc = __mnt_fs_set_fstype_ptr(fs, fstype);
			if (!rc)
				fstype = NULL;
		}
		if (!rc && optstr)
			rc = mnt_fs_set_options(fs, optstr);
		free(optstr);
		optstr = NULL;
	} else {
		DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s));
		rc = -EINVAL;
	}

	if (rc) {
		free(src);
		free(fstype);
		free(optstr);
		DBG(TAB, mnt_debug("tab parse error: [set vars, rc=%d]\n", rc));
		return rc;	/* error */
	}

	fs->passno = fs->freq = 0;

	if (xrc == 4 && n)
		s = skip_spaces(s + n);
	if (xrc == 4 && *s) {
		if (next_number(&s, &fs->freq) != 0) {
			if (*s) {
				DBG(TAB, mnt_debug("tab parse error: [freq]"));
				rc = -EINVAL;
			}
		} else if (next_number(&s, &fs->passno) != 0 && *s) {
			DBG(TAB, mnt_debug("tab parse error: [passno]"));
			rc = -EINVAL;
		}
	}

	return rc;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
/*
 * Allocates utab entry (upd->fs) for mount/remount. This function should be
 * called *before* mount(2) syscall. The @fs is used as a read-only template.
 *
 * Returns: 0 on success, negative number on error, 1 if utabs update is
 *          unnecessary.
 */
static int utab_new_entry(struct libmnt_update *upd, struct libmnt_fs *fs,
			  unsigned long mountflags)
{
	int rc = 0;
	const char *o = NULL, *a = NULL;
	char *u = NULL;

	assert(fs);
	assert(upd);
	assert(upd->fs == NULL);
	assert(!(mountflags & MS_MOVE));

	DBG(UPDATE, mnt_debug("prepare utab entry"));

	o = mnt_fs_get_user_options(fs);
	a = mnt_fs_get_attributes(fs);
	upd->fs = NULL;

	if (o) {
		/* remove non-mtab options */
		rc = mnt_optstr_get_options(o, &u,
				mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
				MNT_NOMTAB);
		if (rc)
			goto err;
	}

	if (!u && !a) {
		DBG(UPDATE, mnt_debug("utab entry unnecessary (no options)"));
		return 1;
	}

	/* allocate the entry */
	upd->fs = mnt_copy_fs(NULL, fs);
	if (!upd->fs) {
		rc = -ENOMEM;
		goto err;
	}

	rc = mnt_fs_set_options(upd->fs, u);
	if (rc)
		goto err;
	rc = mnt_fs_set_attributes(upd->fs, a);
	if (rc)
		goto err;

	if (!(mountflags & MS_REMOUNT)) {
		rc = set_fs_root(upd, fs, mountflags);
		if (rc)
			goto err;
	}

	free(u);
	DBG(UPDATE, mnt_debug("utab entry OK"));
	return 0;
err:
	free(u);
	mnt_free_fs(upd->fs);
	upd->fs = NULL;
	return rc;
}