예제 #1
0
/*
 * This function uses @uf to found corresponding record in @tb, then the record
 * from @tb is updated (user specific mount options are added).
 *
 * Note that @uf must contain only user specific mount options instead of
 * VFS options (note that FS options are ignored).
 *
 * Returns modified filesystem (from @tb) or NULL.
 */
static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct libmnt_fs *uf)
{
	struct libmnt_fs *fs;
	struct libmnt_iter itr;
	const char *optstr, *src, *target, *root, *attrs;

	assert(tb);
	assert(uf);
	if (!tb || !uf)
		return NULL;

	DBG(TAB, mnt_debug_h(tb, "merging user fs"));

	src = mnt_fs_get_srcpath(uf);
	target = mnt_fs_get_target(uf);
	optstr = mnt_fs_get_user_options(uf);
	attrs = mnt_fs_get_attributes(uf);
	root = mnt_fs_get_root(uf);

	if (!src || !target || !root || (!attrs && !optstr))
		return NULL;

	mnt_reset_iter(&itr, MNT_ITER_BACKWARD);

	while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
		const char *s = mnt_fs_get_srcpath(fs),
			   *t = mnt_fs_get_target(fs),
			   *r = mnt_fs_get_root(fs);

		if (fs->flags & MNT_FS_MERGED)
			continue;

		if (s && t && r && !strcmp(t, target) &&
		    !strcmp(s, src) && !strcmp(r, root))
			break;
	}

	if (fs) {
		DBG(TAB, mnt_debug_h(tb, "found fs -- appending user optstr"));
		mnt_fs_append_options(fs, optstr);
		mnt_fs_append_attributes(fs, attrs);
		mnt_fs_set_bindsrc(fs, mnt_fs_get_bindsrc(uf));
		fs->flags |= MNT_FS_MERGED;

		DBG(TAB, mnt_debug_h(tb, "found fs:"));
		DBG(TAB, mnt_fs_print_debug(fs, stderr));
	}
	return fs;
}
예제 #2
0
/**
 * mnt_update_table:
 * @upd: update
 * @lc: lock or NULL
 *
 * High-level API to update /etc/mtab (or private /run/mount/utab file).
 *
 * The @lc lock is optional and will be created if necessary. Note that
 * the automatically created lock blocks all signals.
 *
 * See also mnt_lock_block_signals() and mnt_context_get_lock().
 *
 * Returns: 0 on success, negative number on error.
 */
int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
{
	struct libmnt_lock *lc0 = lc;
	int rc = -EINVAL;

	assert(upd);

	if (!upd->filename || !upd)
		return -EINVAL;
	if (!upd->ready)
		return 0;

	DBG(UPDATE, mnt_debug_h(upd, "%s: update tab", upd->filename));
	if (upd->fs) {
		DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr));
	}
	if (!lc) {
		lc = mnt_new_lock(upd->filename, 0);
		if (lc)
			mnt_lock_block_signals(lc, TRUE);
	}
	if (lc && upd->userspace_only)
		mnt_lock_use_simplelock(lc, TRUE);	/* use flock */

	if (!upd->fs && upd->target)
		rc = update_remove_entry(upd, lc);	/* umount */
	else if (upd->mountflags & MS_MOVE)
		rc = update_modify_target(upd, lc);	/* move */
	else if (upd->mountflags & MS_REMOUNT)
		rc = update_modify_options(upd, lc);	/* remount */
	else if (upd->fs)
		rc = update_add_entry(upd, lc);	/* mount */

	upd->ready = FALSE;
	DBG(UPDATE, mnt_debug_h(upd, "%s: update tab: done [rc=%d]",
				upd->filename, rc));
	if (lc != lc0)
		 mnt_free_lock(lc);
	return rc;
}
예제 #3
0
/**
 * mnt_update_set_fs:
 * @upd: update handler
 * @mountflags: MS_* flags
 * @target: umount target, must be NULL for mount
 * @fs: mount filesystem description, must be NULL for umount
 *
 * Returns: <0 in case on error, 0 on success, 1 if update is unnecessary.
 */
int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags,
		      const char *target, struct libmnt_fs *fs)
{
	int rc;

	assert(upd);
	assert(target || fs);

	if (!upd)
		return -EINVAL;
	if ((mountflags & MS_MOVE) && (!fs || !mnt_fs_get_srcpath(fs)))
		return -EINVAL;
	if (target && fs)
		return -EINVAL;

	DBG(UPDATE, mnt_debug_h(upd,
			"reseting FS [fs=0x%p, target=%s, flags=0x%08lx]",
			fs, target, mountflags));
	if (fs) {
		DBG(UPDATE, mnt_debug_h(upd, "FS template:"));
		DBG(UPDATE, mnt_fs_print_debug(fs, stderr));
	}

	mnt_free_fs(upd->fs);
	free(upd->target);
	upd->ready = FALSE;
	upd->fs = NULL;
	upd->target = NULL;
	upd->mountflags = 0;

	if (mountflags & MS_PROPAGATION)
		return 1;

	upd->mountflags = mountflags;

	rc = mnt_update_set_filename(upd, NULL, 0);
	if (rc) {
		DBG(UPDATE, mnt_debug_h(upd, "no writable file available [rc=%d]", rc));
		return rc;	/* error or no file available (rc = 1) */
	}
	if (target) {
		upd->target = strdup(target);
		if (!upd->target)
			return -ENOMEM;

	} else if (fs) {
		if (upd->userspace_only && !(mountflags & MS_MOVE)) {
			int rc = utab_new_entry(upd, fs, mountflags);
			if (rc)
				return rc;
		} else {
			upd->fs = mnt_copy_mtab_fs(fs);
			if (!upd->fs)
				return -ENOMEM;

		}
	}


	DBG(UPDATE, mnt_debug_h(upd, "ready"));
	upd->ready = TRUE;
	return 0;
}