From f63173b2202c9ce3c7a973a14e6b0dfb26c0c564 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 4 Oct 2010 14:09:55 +0200 Subject: libmount: allows to swap source and target Signed-off-by: Karel Zak --- shlibs/mount/src/context.c | 168 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 144 insertions(+), 24 deletions(-) (limited to 'shlibs/mount/src/context.c') diff --git a/shlibs/mount/src/context.c b/shlibs/mount/src/context.c index 07a72c2d3..1d3c76a75 100644 --- a/shlibs/mount/src/context.c +++ b/shlibs/mount/src/context.c @@ -57,7 +57,6 @@ void mnt_free_context(mnt_context *cxt) free(cxt->fstype_pattern); free(cxt->optstr_pattern); - free(cxt->spec); free(cxt->helper); free(cxt->orig_user); @@ -113,11 +112,9 @@ int mnt_reset_context(mnt_context *cxt) cxt->fs = NULL; cxt->mtab = NULL; - free(cxt->spec); free(cxt->helper); free(cxt->orig_user); - cxt->spec = NULL; cxt->helper = NULL; cxt->mountflags = 0; @@ -332,27 +329,6 @@ int mnt_context_enable_loopdel(mnt_context *cxt, int enable) return set_flag(cxt, MNT_FL_LOOPDEL, enable); } -/** - * mnt_context_set_spec: - * @cxt: mount context - * @spec: unresolved source (device, label, uuid, ...) or target (mountpoint) - * - * Returns: 0 on success, negative number in case of error. - */ -int mnt_context_set_spec(mnt_context *cxt, const char *spec) -{ - char *p; - - if (!cxt) - return -EINVAL; - p = strdup(spec); - if (!p) - return -ENOMEM; - free(cxt->spec); - cxt->spec = p; - return 0; -} - /** * mnt_context_set_fs: * @cxt: mount context @@ -960,3 +936,147 @@ int mnt_context_prepare_update(mnt_context *cxt, int act) return rc; } +static int is_remount(mnt_context *cxt) +{ + unsigned long fl = 0; + + if (cxt->mountflags & MS_REMOUNT) + return 1; + if (!mnt_context_get_mountflags(cxt, &fl) && (fl & MS_REMOUNT)) + return 1; + return 0; +} + +static int apply_tab(mnt_context *cxt, mnt_tab *tb) +{ + mnt_fs *fs = NULL; + const char *src = NULL, *tgt = NULL; + int rc; + + if (!cxt->fs) + return -EINVAL; + + src = mnt_fs_get_source(cxt->fs); + tgt = mnt_fs_get_target(cxt->fs); + + if (tgt && src) + ; /* TODO: search pair for MNT_OPTSMODE_FORCE */ + else { + if (src) + fs = mnt_tab_find_source(tb, src, MNT_ITER_FORWARD); + else if (tgt) + fs = mnt_tab_find_target(tb, tgt, MNT_ITER_FORWARD); + + if (!fs) { + /* swap source and target (if @src is not LABEL/UUID), + * for example in + * + * mount /foo/bar + * + * the path could be a mountpoint as well as source (for + * example bind mount, symlink to device, ...). + */ + if (src && !mnt_fs_get_tag(cxt->fs, NULL, NULL)) + fs = mnt_tab_find_target(tb, src, + MNT_ITER_FORWARD); + if (!fs && tgt) + fs = mnt_tab_find_source(tb, tgt, + MNT_ITER_FORWARD); + } + } + + if (!fs) + return -EINVAL; + + DBG(CXT, mnt_debug_h(cxt, "apply entry:")); + DBG(CXT, mnt_fs_print_debug(fs, stderr)); + + /* copy from fstab to our FS description + */ + rc = mnt_fs_set_source(cxt->fs, mnt_fs_get_source(fs)); + if (!rc) + rc = mnt_fs_set_target(cxt->fs, mnt_fs_get_target(fs)); + + if (!rc && !mnt_fs_get_fstype(cxt->fs)) + rc = mnt_fs_set_fstype(cxt->fs, mnt_fs_get_fstype(fs)); + + if (!rc && cxt->optsmode != MNT_OPTSMODE_IGNORE) + rc = mnt_fs_prepend_optstr(cxt->fs, mnt_fs_get_optstr(fs)); + + if (!rc) + cxt->flags |= MNT_FL_FSTAB_APPLIED; + + return rc; +} + +int mnt_context_apply_fstab(mnt_context *cxt) +{ + int rc; + mnt_cache *cache; + const char *src = NULL, *tgt = NULL; + + if (!cxt || !cxt->fs) + return -EINVAL; + + if (cxt->flags & MNT_FL_FSTAB_APPLIED) + return 0; + + if (cxt->fs) { + src = mnt_fs_get_source(cxt->fs); + tgt = mnt_fs_get_target(cxt->fs); + } + + /* fstab is not required if source and target are specified */ + if (src && tgt && !(cxt->optsmode == MNT_OPTSMODE_FORCE || + cxt->optsmode == MNT_OPTSMODE_MTABFORCE)) + return 0; + + DBG(CXT, mnt_debug_h(cxt, + "trying to apply fstab (src=%s, target=%s)", src, tgt)); + + /* initialize fstab */ + if (!cxt->fstab) { + cxt->fstab = mnt_new_tab(); + if (!cxt->fstab) + goto errnomem; + cxt->flags &= ~MNT_FL_EXTERN_FSTAB; + rc = mnt_tab_parse_fstab(cxt->fstab); + if (rc) + goto err; + } + + cache = mnt_context_get_cache(cxt); /* NULL if MNT_FL_NOCANONICALIZE is enabled */ + + /* never touch an external fstab */ + if (!(cxt->flags & MNT_FL_EXTERN_FSTAB)) + mnt_tab_set_cache(cxt->fstab, cache); + + /* let's initialize cxt->fs */ + mnt_context_get_fs(cxt); + + /* try fstab */ + rc = apply_tab(cxt, cxt->fstab); + + /* try mtab */ + if (rc || (cxt->optsmode == MNT_OPTSMODE_MTABFORCE && is_remount(cxt))) { + + cxt->mtab = mnt_new_tab(); + if (!cxt->mtab) + goto errnomem; + rc = mnt_tab_parse_mtab(cxt->mtab); + if (rc) + goto err; + + mnt_tab_set_cache(cxt->mtab, cache); + rc = apply_tab(cxt, cxt->mtab); + if (rc) + goto err; + } + return 0; + +errnomem: + rc = ENOMEM; +err: + DBG(CXT, mnt_debug_h(cxt, "failed to found entry in fstab/mtab")); + return rc; +} -- cgit v1.2.3-55-g7522