summaryrefslogtreecommitdiffstats
path: root/shlibs/mount/src/context.c
diff options
context:
space:
mode:
authorKarel Zak2010-10-04 13:37:33 +0200
committerKarel Zak2011-01-03 12:28:44 +0100
commit1bb1d80b3e3512a4664cb9895c95f29a900f8aba (patch)
tree809c0338ce8ea4c6567b1fd41fff1020d2761f11 /shlibs/mount/src/context.c
parentlibmount: cleanup helpers support (diff)
downloadkernel-qcow2-util-linux-1bb1d80b3e3512a4664cb9895c95f29a900f8aba.tar.gz
kernel-qcow2-util-linux-1bb1d80b3e3512a4664cb9895c95f29a900f8aba.tar.xz
kernel-qcow2-util-linux-1bb1d80b3e3512a4664cb9895c95f29a900f8aba.zip
libmount: split context.c
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount/src/context.c')
-rw-r--r--shlibs/mount/src/context.c906
1 files changed, 73 insertions, 833 deletions
diff --git a/shlibs/mount/src/context.c b/shlibs/mount/src/context.c
index 2102be539..07a72c2d3 100644
--- a/shlibs/mount/src/context.c
+++ b/shlibs/mount/src/context.c
@@ -13,87 +13,9 @@
#include <string.h>
#include <errno.h>
-#include <sys/wait.h>
-#include <sys/mount.h>
-
-#ifdef HAVE_LIBSELINUX
-#include <selinux/selinux.h>
-#include <selinux/context.h>
-#endif
-
#include "c.h"
#include "mountP.h"
-/*
- * Mount context -- high-level API
- */
-struct _mnt_context
-{
- int action; /* MNT_ACT_{MOUNT,UMOUNT} */
-
- int restricted; /* root or not? */
-
- char *fstype_pattern; /* for mnt_match_fstype() */
- char *optstr_pattern; /* for mnt_match_options() */
-
- char *spec; /* unresolved source OR target */
- mnt_fs *fs; /* filesystem description (type, mountpopint, device, ...) */
-
- mnt_tab *fstab; /* fstab (or mtab for some remounts) entires */
- mnt_tab *mtab; /* mtab entries */
- int optsmode; /* fstab optstr mode MNT_OPTSMODE_{AUTO,FORCE,IGNORE} */
-
- unsigned long mountflags; /* final mount(2) flags */
- const void *mountdata; /* final mount(2) data, string or binary data */
-
- unsigned long user_mountflags; /* MNT_MS_* (loop=, user=, ...) */
-
- mnt_update *update; /* mtab update */
- mnt_cache *cache; /* paths cache */
-
- int flags; /* private context flags */
- int ambi; /* libblkid returns ambivalent result */
-
- char *helper; /* name of the used /sbin/[u]mount.<type> helper */
- int helper_status; /* helper wait(2) status */
-
- char *orig_user; /* original (non-fixed) user= option */
-
- int syscall_errno; /* mount(2) or umount(2) error */
-};
-
-/* flags */
-#define MNT_FL_NOMTAB (1 << 1)
-#define MNT_FL_FAKE (1 << 2)
-#define MNT_FL_SLOPPY (1 << 3)
-#define MNT_FL_VERBOSE (1 << 4)
-#define MNT_FL_NOHELPERS (1 << 5)
-#define MNT_FL_LOOPDEL (1 << 6)
-#define MNT_FL_LAZY (1 << 7)
-#define MNT_FL_FORCE (1 << 8)
-#define MNT_FL_NOCANONICALIZE (1 << 9)
-#define MNT_FL_NOLOCK (1 << 10) /* don't lock mtab file */
-
-#define MNT_FL_EXTERN_FS (1 << 15) /* cxt->fs is not private */
-#define MNT_FL_EXTERN_FSTAB (1 << 16) /* cxt->fstab is not private */
-#define MNT_FL_EXTERN_CACHE (1 << 17) /* cxt->cache is not private */
-
-#define MNT_FL_MOUNTDATA (1 << 20)
-#define MNT_FL_FSTAB_APPLIED (1 << 21)
-#define MNT_FL_MOUNTFLAGS_MERGED (1 << 22) /* MS_* flags was read from optstr */
-#define MNT_FL_SAVED_USER (1 << 23)
-
-/* default flags */
-#define MNT_FL_DEFAULT 0
-
-/* mode for mount options from fstab */
-enum {
- MNT_OPTSMODE_AUTO = 0, /* use options if source or target are not defined */
- MNT_OPTSMODE_IGNORE, /* never use mount options from fstab */
- MNT_OPTSMODE_FORCE, /* always use mount options from fstab */
- MNT_OPTSMODE_MTABFORCE, /* for MS_REMOUNT use always options mountinfo/mtab */
-};
-
/**
* mnt_new_context:
*
@@ -212,7 +134,7 @@ int mnt_reset_context(mnt_context *cxt)
return 0;
}
-static int mnt_context_set_flag(mnt_context *cxt, int flag, int enable)
+static int set_flag(mnt_context *cxt, int flag, int enable)
{
if (!cxt)
return -EINVAL;
@@ -223,17 +145,6 @@ static int mnt_context_set_flag(mnt_context *cxt, int flag, int enable)
return 0;
}
-static mnt_fs *mnt_context_get_fs(mnt_context *cxt)
-{
- if (!cxt)
- return NULL;
- if (!cxt->fs) {
- cxt->fs = mnt_new_fs();
- cxt->flags &= ~MNT_FL_EXTERN_FS;
- }
- return cxt->fs;
-}
-
/**
* mnt_context_is_restricted:
* @cxt: mount context
@@ -292,7 +203,7 @@ int mnt_context_set_optsmode(mnt_context *cxt, int mode)
*/
int mnt_context_disable_canonicalize(mnt_context *cxt, int disable)
{
- return mnt_context_set_flag(cxt, MNT_FL_NOCANONICALIZE, disable);
+ return set_flag(cxt, MNT_FL_NOCANONICALIZE, disable);
}
/**
@@ -306,7 +217,7 @@ int mnt_context_disable_canonicalize(mnt_context *cxt, int disable)
*/
int mnt_context_enable_lazy(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_LAZY, enable);
+ return set_flag(cxt, MNT_FL_LAZY, enable);
}
/**
@@ -320,7 +231,7 @@ int mnt_context_enable_lazy(mnt_context *cxt, int enable)
*/
int mnt_context_disable_helpers(mnt_context *cxt, int disable)
{
- return mnt_context_set_flag(cxt, MNT_FL_NOHELPERS, disable);
+ return set_flag(cxt, MNT_FL_NOHELPERS, disable);
}
/**
@@ -334,7 +245,7 @@ int mnt_context_disable_helpers(mnt_context *cxt, int disable)
*/
int mnt_context_enable_sloppy(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_SLOPPY, enable);
+ return set_flag(cxt, MNT_FL_SLOPPY, enable);
}
/**
@@ -348,7 +259,7 @@ int mnt_context_enable_sloppy(mnt_context *cxt, int enable)
*/
int mnt_context_enable_fake(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_FAKE, enable);
+ return set_flag(cxt, MNT_FL_FAKE, enable);
}
/**
@@ -362,7 +273,7 @@ int mnt_context_enable_fake(mnt_context *cxt, int enable)
*/
int mnt_context_disable_mtab(mnt_context *cxt, int disable)
{
- return mnt_context_set_flag(cxt, MNT_FL_NOMTAB, disable);
+ return set_flag(cxt, MNT_FL_NOMTAB, disable);
}
/**
@@ -376,7 +287,7 @@ int mnt_context_disable_mtab(mnt_context *cxt, int disable)
*/
int mnt_context_disable_lock(mnt_context *cxt, int disable)
{
- return mnt_context_set_flag(cxt, MNT_FL_NOLOCK, disable);
+ return set_flag(cxt, MNT_FL_NOLOCK, disable);
}
/**
@@ -390,7 +301,7 @@ int mnt_context_disable_lock(mnt_context *cxt, int disable)
*/
int mnt_context_enable_force(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_FORCE, enable);
+ return set_flag(cxt, MNT_FL_FORCE, enable);
}
/**
@@ -398,13 +309,13 @@ int mnt_context_enable_force(mnt_context *cxt, int enable)
* @cxt: mount context
* @enable: TRUE or FALSE
*
- * Enable/disable verbose output.
+ * Enable/disable verbose output (see also mnt_context_mount_strerror()).
*
* Returns: 0 on success, negative number in case of error.
*/
int mnt_context_enable_verbose(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_VERBOSE, enable);
+ return set_flag(cxt, MNT_FL_VERBOSE, enable);
}
/**
@@ -418,7 +329,7 @@ int mnt_context_enable_verbose(mnt_context *cxt, int enable)
*/
int mnt_context_enable_loopdel(mnt_context *cxt, int enable)
{
- return mnt_context_set_flag(cxt, MNT_FL_LOOPDEL, enable);
+ return set_flag(cxt, MNT_FL_LOOPDEL, enable);
}
/**
@@ -464,11 +375,22 @@ int mnt_context_set_fs(mnt_context *cxt, mnt_fs *fs)
if (!(cxt->flags & MNT_FL_EXTERN_FS))
mnt_free_fs(cxt->fs);
- mnt_context_set_flag(cxt, MNT_FL_EXTERN_FS, fs != NULL);
+ set_flag(cxt, MNT_FL_EXTERN_FS, fs != NULL);
cxt->fs = fs;
return 0;
}
+mnt_fs *mnt_context_get_fs(mnt_context *cxt)
+{
+ if (!cxt)
+ return NULL;
+ if (!cxt->fs) {
+ cxt->fs = mnt_new_fs();
+ cxt->flags &= ~MNT_FL_EXTERN_FS;
+ }
+ return cxt->fs;
+}
+
/**
* mnt_context_set_source:
* @cxt: mount context
@@ -606,7 +528,7 @@ int mnt_context_set_fstab(mnt_context *cxt, mnt_tab *tb)
if (!(cxt->flags & MNT_FL_EXTERN_FSTAB))
mnt_free_tab(cxt->fstab);
- mnt_context_set_flag(cxt, MNT_FL_EXTERN_FSTAB, tb != NULL);
+ set_flag(cxt, MNT_FL_EXTERN_FSTAB, tb != NULL);
cxt->fstab = tb;
return 0;
}
@@ -632,12 +554,20 @@ int mnt_context_set_cache(mnt_context *cxt, mnt_cache *cache)
if (!(cxt->flags & MNT_FL_EXTERN_CACHE))
mnt_free_cache(cxt->cache);
- mnt_context_set_flag(cxt, MNT_FL_EXTERN_CACHE, cache != NULL);
+ set_flag(cxt, MNT_FL_EXTERN_CACHE, cache != NULL);
cxt->cache = cache;
return 0;
}
-static mnt_cache *mnt_context_get_cache(mnt_context *cxt)
+/**
+ * mnt_context_get_cache
+ * @cxt: mount context
+ *
+ * See also mnt_context_set_cache().
+ *
+ * Returns: pointer to cache or NULL if canonicalization is disabled.
+ */
+mnt_cache *mnt_context_get_cache(mnt_context *cxt)
{
if (!cxt || (cxt->flags & MNT_FL_NOCANONICALIZE))
return NULL;
@@ -652,6 +582,33 @@ static mnt_cache *mnt_context_get_cache(mnt_context *cxt)
}
/**
+ * mnt_context_get_lock:
+ * @cxt: mount context
+ *
+ * The lock is available after mnt_context_prepare_mount() or
+ * mnt_context_prepare_umount().
+ *
+ * The application that uses libmount context does not have to care about
+ * mtab locking, but with a small exceptions: the application has to be able to
+ * remove the lock file when interrupted by signal. It means that properly written
+ * mount(8)-like application has to call mnt_unlock_file() from a signal handler.
+ *
+ * See also mnt_unlock_file(), mnt_context_disable_lock() and
+ * mnt_context_disable_mtab().
+ *
+ * It's not error if this function returns NULL (it usually means that the
+ * context is not prepared yet, or mtab update is unnecessary).
+ *
+ * Returns: pointer to lock struct.
+ */
+mnt_lock *mnt_context_get_lock(mnt_context *cxt)
+{
+ if (!cxt || !cxt->update || (cxt->flags & (MNT_FL_NOMTAB | MNT_FL_NOLOCK)))
+ return NULL;
+ return mnt_update_get_lock(cxt->update);
+}
+
+/**
* mnt_context_set_mountflags:
* @cxt: mount context
* @flags: mount(2) flags (MS_* flags)
@@ -704,17 +661,6 @@ int mnt_context_get_mountflags(mnt_context *cxt, unsigned long *flags)
return rc;
}
-static int mnt_context_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;
-}
-
/**
* mnt_context_set_userspace_mountflags:
* @cxt: mount context
@@ -759,7 +705,7 @@ int mnt_context_get_userspace_mountflags(mnt_context *cxt, unsigned long *flags)
return rc;
}
-static int mnt_context_is_loop(mnt_context *cxt)
+static int is_loop(mnt_context *cxt)
{
unsigned long fl = 0;
@@ -774,7 +720,6 @@ static int mnt_context_is_loop(mnt_context *cxt)
return 0;
}
-
/**
* mnt_context_set_mountdata:
* @cxt: mount context
@@ -798,322 +743,10 @@ int mnt_context_set_mountdata(mnt_context *cxt, void *data)
return 0;
}
-static int mnt_context_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);
- else if (cxt->spec) {
- fs = mnt_tab_find_source(tb, cxt->spec, MNT_ITER_FORWARD);
-
- if (!fs && (strncmp(cxt->spec, "LABEL=", 6) ||
- strncmp(cxt->spec, "UUID=", 5)))
- fs = mnt_tab_find_target(tb, cxt->spec, 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->spec && !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, spec=%s)",
- src, tgt, cxt->spec));
-
- /* 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 = mnt_context_apply_tab(cxt, cxt->fstab);
-
- /* try mtab */
- if (rc || (cxt->optsmode == MNT_OPTSMODE_MTABFORCE &&
- mnt_context_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 = mnt_context_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;
-}
-
-/*
- * this has to be called after mnt_context_evaluate_permissions()
- */
-static int mnt_context_fix_optstr(mnt_context *cxt)
-{
- int rc = 0, rem_se = 0;
- char *next, **optstr;
- char *name, *val;
- size_t namesz, valsz;
-
- if (!cxt)
- return -EINVAL;
- if (!cxt->fs)
- return 0;
-
- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
-
- /*
- * we directly work with optstr pointer here
- */
- optstr = &cxt->fs->optstr;
- if (!optstr)
- return 0;
-
- /* The propagation flags should not be used together with any other flags */
- if (cxt->mountflags & MS_PROPAGATION)
- cxt->mountflags &= MS_PROPAGATION;
-
- if (!mnt_optstr_get_option(*optstr, "user", &val, &valsz)) {
- if (val) {
- cxt->orig_user = strndup(val, valsz);
- if (!cxt->orig_user) {
- rc = -ENOMEM;
- goto done;
- }
- }
- cxt->flags |= MNT_FL_SAVED_USER;
- }
-
- /*
- * Sync mount options with mount flags
- */
- rc = mnt_optstr_apply_flags(optstr, cxt->mountflags,
- mnt_get_builtin_optmap(MNT_LINUX_MAP));
- if (rc)
- goto done;
-
- rc = mnt_optstr_apply_flags(optstr, cxt->user_mountflags,
- mnt_get_builtin_optmap(MNT_USERSPACE_MAP));
- if (rc)
- goto done;
-
- next = *optstr;
-
-#ifdef HAVE_LIBSELINUX
- rem_se = (cxt->mountflags & MS_REMOUNT) || !is_selinux_enabled();
-#endif
- DBG(CXT, mnt_debug_h(cxt, "fixing mount options: '%s'", *optstr));
-
- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
-
- if (namesz == 3 && !strncmp(name, "uid", 3))
- rc = mnt_optstr_fix_uid(optstr, val, valsz, &next);
- else if (namesz == 3 && !strncmp(name, "gid", 3))
- rc = mnt_optstr_fix_gid(optstr, val, valsz, &next);
-#ifdef HAVE_LIBSELINUX
- else if (namesz >= 7 && (!strncmp(name, "context", 7) ||
- !strncmp(name, "fscontext", 9) ||
- !strncmp(name, "defcontext", 10) ||
- !strncmp(name, "rootcontext", 11))) {
- if (rem_se) {
- /* remove context= option */
- next = name;
- rc = mnt_optstr_remove_option_at(optstr,
- name, val + valsz);
- } else
- rc = mnt_optstr_fix_secontext(optstr,
- val, valsz, &next);
- }
-#endif
- else if (namesz == 4 && (cxt->user_mountflags && MNT_MS_USER) &&
- !strncmp(name, "user", 4)) {
-
- rc = mnt_optstr_fix_user(optstr,
- val ? val : name + namesz,
- valsz, &next);
- }
- if (rc)
- goto done;
- }
-
-done:
- __mnt_fs_set_optstr_ptr(cxt->fs, *optstr, TRUE);
- DBG(CXT, mnt_debug_h(cxt, "fixed options [rc=%d]: '%s'", rc, *optstr));
- return rc;
-}
-
-/*
- * Converts already evalulated and fixed options to the form that is comaptible
- * with /sbin/mount.<type> helpers.
- *
- * Retursn newly allocated string.
- */
-static int mnt_context_get_helper_optstr(mnt_context *cxt, char **optstr)
-{
- const char *o;
- int rc = 0;
-
- assert(cxt);
- assert(cxt->fs);
- assert(optstr);
-
- *optstr = NULL;
- o = mnt_fs_get_optstr(cxt->fs);
-
- if (o)
- rc = mnt_optstr_append_option(optstr, o, NULL);
- if (!rc && (cxt->flags & MNT_FL_SAVED_USER))
- rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user);
- if (rc) {
- free(*optstr);
- *optstr = NULL;
- }
- return rc;
-}
-
-
/*
- * this has to be called before mnt_context_fix_optstr()
+ * Translates LABEL/UUID/path to mountable path
*/
-static int mnt_context_evaluate_permissions(mnt_context *cxt)
-{
- unsigned long u_flags;
- const char *srcpath;
-
- if (!cxt)
- return -EINVAL;
- if (!cxt->fs)
- return 0;
-
- mnt_context_get_userspace_mountflags(cxt, &u_flags);
-
- if (!mnt_context_is_restricted(cxt)) {
- /*
- * superuser mount
- */
- cxt->user_mountflags &= ~MNT_MS_OWNER;
- cxt->user_mountflags &= ~MNT_MS_GROUP;
- cxt->user_mountflags &= ~MNT_MS_USER;
- cxt->user_mountflags &= ~MNT_MS_USERS;
- } else {
- /*
- * user mount
- */
- if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP))
- cxt->mountflags |= MS_OWNERSECURE;
-
- if (u_flags & (MNT_MS_USER | MNT_MS_USERS))
- cxt->mountflags |= MS_SECURE;
-
- srcpath = mnt_fs_get_srcpath(cxt->fs);
- if (!srcpath)
- return -EINVAL;
-
- /*
- * MS_OWNER: Allow owners to mount when fstab contains the
- * owner option. Note that this should never be used in a high
- * security environment, but may be useful to give people at
- * the console the possibility of mounting a floppy. MS_GROUP:
- * Allow members of device group to mount. (Martin Dickopp)
- */
- if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) {
- struct stat sb;
-
- if (strncmp(srcpath, "/dev/", 5) == 0 &&
- stat(srcpath, &sb) == 0 &&
- (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) ||
- ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid))))
-
- cxt->user_mountflags |= MNT_MS_USER;
- }
-
- if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) {
- DBG(CXT, mnt_debug_h(cxt, "permissions evaluation ends with -EPERMS"));
- return -EPERM;
- }
- }
-
- return 0;
-}
-
-static int mnt_context_prepare_srcpath(mnt_context *cxt)
+int mnt_context_prepare_srcpath(mnt_context *cxt)
{
const char *path = NULL, *type;
mnt_cache *cache;
@@ -1168,7 +801,7 @@ static int mnt_context_prepare_srcpath(mnt_context *cxt)
/*
* Initialize loop device
*/
- if (mnt_context_is_loop(cxt) &&
+ if (is_loop(cxt) &&
!(cxt->mountflags & (MS_BIND | MS_MOVE |
MS_PROPAGATION | MS_REMOUNT))) {
; /* TODO */
@@ -1178,7 +811,7 @@ static int mnt_context_prepare_srcpath(mnt_context *cxt)
return 0;
}
-static int mnt_context_guess_fstype(mnt_context *cxt)
+int mnt_context_guess_fstype(mnt_context *cxt)
{
char *type;
const char *dev;
@@ -1232,26 +865,6 @@ err:
return rc;
}
-static int mnt_context_merge_mountflags(mnt_context *cxt)
-{
- unsigned long fl = 0;
- int rc;
-
- rc = mnt_context_get_mountflags(cxt, &fl);
- if (rc)
- return rc;
- cxt->mountflags = fl;
-
- fl = 0;
- rc = mnt_context_get_userspace_mountflags(cxt, &fl);
- if (rc)
- return rc;
- cxt->user_mountflags = fl;
-
- cxt->flags |= MNT_FL_MOUNTFLAGS_MERGED;
- return 0;
-}
-
/*
* The default is to use fstype from cxt->fs, this could be overwritten by
* @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
@@ -1259,17 +872,15 @@ static int mnt_context_merge_mountflags(mnt_context *cxt)
* Returns: 0 on success or negative number in case of error. Note that success
* does not mean that there is any usable helper, you have to check cxt->helper.
*/
-static int mnt_context_prepare_helper(mnt_context *cxt, int act, const char *type)
+int mnt_context_prepare_helper(mnt_context *cxt, const char *name,
+ const char *type)
{
char search_path[] = FS_SEARCH_PATH; /* from config.h */
char *p = NULL, *path;
- const char *name;
assert(cxt);
assert(cxt->fs);
- name = MNT_ACT_MOUNT ? "mount" : "umount";
-
if (!type)
type = mnt_fs_get_fstype(cxt->fs);
@@ -1313,7 +924,10 @@ static int mnt_context_prepare_helper(mnt_context *cxt, int act, const char *typ
return 0;
}
-static int mnt_context_prepare_update(mnt_context *cxt, int act)
+/*
+ * Prepare /etc/mtab or /var/run/mount/mountinfo update
+ */
+int mnt_context_prepare_update(mnt_context *cxt, int act)
{
int rc;
@@ -1346,377 +960,3 @@ static int mnt_context_prepare_update(mnt_context *cxt, int act)
return rc;
}
-/**
- * mnt_context_get_lock:
- * @cxt: mount context
- *
- * The lock is available after mnt_context_prepare_mount() or
- * mnt_context_prepare_umount().
- *
- * The application that uses libmount context does not have to care about
- * mtab locking, but with a small exceptions: the application has to be able to
- * remove the lock file when interrupted by signal. It means that properly written
- * mount(8)-like application has to call mnt_unlock_file() from a signal handler.
- *
- * See also mnt_unlock_file(), mnt_context_disable_lock() and
- * mnt_context_disable_mtab().
- *
- * It's not error if this function returns NULL (it usually means that the
- * context is not prepared yet, or mtab update is unnecessary).
- *
- * Returns: pointer to lock struct.
- */
-mnt_lock *mnt_context_get_lock(mnt_context *cxt)
-{
- if (!cxt || !cxt->update || (cxt->flags & (MNT_FL_NOMTAB | MNT_FL_NOLOCK)))
- return NULL;
- return mnt_update_get_lock(cxt->update);
-}
-
-/**
- * mnt_context_prepare_mount:
- * @cxt: mount context
- *
- * This function:
- * - read information from fstab (if necessary)
- * - cleanup mount options
- * - check premissions
- * - prepare device (e.g. loop device)
- * - detect FS type (if necessary)
- * - generate mount flags and mount data (if not set yet)
- * - prepare for mtab update (if necessary)
- *
- * It's strongly recommended to use this function before mnt_context_mount_fs().
- *
- * Returns: 0 on success, and negative number in case of error.
- */
-int mnt_context_prepare_mount(mnt_context *cxt)
-{
- int rc = 0;
-
- if (!cxt)
- return -EINVAL;
-
- if (!cxt->spec && !(cxt->fs && (mnt_fs_get_source(cxt->fs) ||
- mnt_fs_get_target(cxt->fs))))
- return -EINVAL;
-
- rc = mnt_context_apply_fstab(cxt);
- if (!rc)
- rc = mnt_context_merge_mountflags(cxt);
- if (!rc)
- rc = mnt_context_evaluate_permissions(cxt);
- if (!rc)
- rc = mnt_context_fix_optstr(cxt);
- if (!rc)
- rc = mnt_context_prepare_srcpath(cxt);
- if (!rc)
- rc = mnt_context_guess_fstype(cxt);
- if (!rc)
- rc = mnt_context_prepare_helper(cxt, MNT_ACT_MOUNT, NULL);
- if (!rc)
- rc = mnt_context_prepare_update(cxt, MNT_ACT_MOUNT);
-
- if (!rc) {
- DBG(CXT, mnt_debug_h(cxt, "sucessfully prepared"));
- return 0;
- }
-
- DBG(CXT, mnt_debug_h(cxt, "prepare failed"));
- return rc;
-}
-
-static int exec_mount_helper(mnt_context *cxt)
-{
- char *o = NULL;
- int rc;
-
- assert(cxt);
- assert(cxt->fs);
- assert(cxt->helper);
-
- rc = mnt_context_get_helper_optstr(cxt, &o);
- if (rc)
- goto done;
-
- 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 */
-
- if (cxt->flags & MNT_FL_SLOPPY)
- args[i++] = "-s"; /* 4 */
- if (cxt->flags & MNT_FL_FAKE)
- args[i++] = "-f"; /* 5 */
- if (cxt->flags & MNT_FL_NOMTAB)
- args[i++] = "-n"; /* 6 */
- if (cxt->flags & MNT_FL_VERBOSE)
- 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
- i = 0;
- 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));
- rc = 0;
- break;
- }
-
- case -1:
- rc = -errno;
- DBG(CXT, mnt_debug_h(cxt, "fork() failed"));
- break;
- }
-
-done:
- free(o);
- return rc;
-}
-
-/*
- * The default is to use fstype from cxt->fs, this could be overwritten by
- * @try_type argument.
- */
-static int mnt_context_do_mount(mnt_context *cxt, const char *try_type)
-{
- int rc;
- const char *src, *target, *type;
- unsigned long flags;
-
- assert(cxt);
- assert(cxt->fs);
-
- if (try_type && !cxt->helper) {
- rc = mnt_context_prepare_helper(cxt, MNT_ACT_MOUNT, try_type);
- if (!rc)
- return rc;
- }
- if (cxt->helper)
- return exec_mount_helper(cxt);
-
- type = try_type ? : mnt_fs_get_fstype(cxt->fs);
-
- flags = cxt->mountflags;
- src = mnt_fs_get_srcpath(cxt->fs);
- target = mnt_fs_get_target(cxt->fs);
-
- if (!src || !target)
- return -EINVAL;
-
- if (!(flags & MS_MGC_MSK))
- flags |= MS_MGC_VAL;
-
- DBG(CXT, mnt_debug_h(cxt, "calling mount(2) "
- "[source=%s, target=%s, type=%s, "
- " mountflags=%08lx, mountdata=%s]",
- src, target, type,
- flags, cxt->mountdata ? "yes" : "<none>"));
-
- if (mount(src, target, type, flags, cxt->mountdata)) {
- cxt->syscall_errno = errno;
- DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d]",
- cxt->syscall_errno));
- return -cxt->syscall_errno;
- }
-
- DBG(CXT, mnt_debug_h(cxt, "mount(2) success"));
- return 0;
-}
-
-/**
- * mnt_context_mount_fs:
- * @cxt: mount context
- *
- * Mount filesystem by mount(2) or fork()+exec(/sbin/mount.<type>).
- *
- * See also mnt_context_disable_helpers().
- *
- * Returns: 0 on success, and negative number in case of error.
- */
-int mnt_context_mount_fs(mnt_context *cxt)
-{
- int rc = -EINVAL;
- const char *type;
-
- if (!cxt || !cxt->fs || (cxt->fs->flags & MNT_FS_SWAP))
- return -EINVAL;
-
- if (!(cxt->flags & MNT_FL_MOUNTDATA))
- cxt->mountdata = (char *) mnt_fs_get_fs_optstr(cxt->fs);
-
- type = mnt_fs_get_fstype(cxt->fs);
-
- if (type && !strchr(type, ',')) {
- rc = mnt_context_do_mount(cxt, NULL);
- if (rc)
- return rc;
- }
-
- /* TODO: try all filesystems from comma separated list of types */
-
- /* TODO: try all filesystems from /proc/filesystems and /etc/filesystems */
-
- return rc;
-}
-
-/**
- * mnt_context_post_mount:
- * @cxt: mount context
- *
- * Updates mtab, etc. This function should be always called after
- * mnt_context_do_mount().
- *
- * Returns: 0 on success, and negative number in case of error.
- */
-int mnt_context_post_mount(mnt_context *cxt)
-{
- int rc = 0;
-
- if (!cxt)
- return -EINVAL;
- /*
- * Update /etc/mtab or /var/run/mount/mountinfo
- */
- if (!cxt->syscall_errno && !cxt->helper &&
- !(cxt->flags & MNT_FL_NOMTAB) &&
- cxt->update && !mnt_update_is_pointless(cxt->update)) {
-
- /* TODO: if mtab update is expected then checkif the target is really
- * mounted read-write to avoid 'ro' in mtab and 'rw' in /proc/mounts.
- */
- rc = mnt_update_file(cxt->update);
- }
-
- return rc;
-}
-
-/**
- * mnt_context_get_mount_error:
- * @cxt: mount context
- * @buf: buffer for error message
- * @bufsiz: size of buffer
- *
- * Generates human readable error message for failed mnt_context_mount_fs().
- *
- * Returns: 0 on success, and negative number in case of error.
- */
-int mnt_context_get_mount_error(mnt_context *cxt, char *buf, size_t bufsiz)
-{
- /* TODO: based on cxt->syscall_errno or cxt->helper_status */
- return 0;
-}
-
-#ifdef TEST_PROGRAM
-
-mnt_lock *lock;
-
-static void lock_fallback(void)
-{
- if (lock) {
- mnt_unlock_file(lock);
- mnt_free_lock(lock);
- }
-}
-
-int test_mount(struct mtest *ts, int argc, char *argv[])
-{
- int idx = 1, rc = 0;
- mnt_context *cxt;
-
- if (argc < 2)
- return -EINVAL;
-
- cxt = mnt_new_context();
- if (!cxt)
- return -ENOMEM;
-
- if (!strcmp(argv[idx], "-o")) {
- mnt_context_set_optstr(cxt, argv[idx + 1]);
- idx += 2;
- }
- if (!strcmp(argv[idx], "-t")) {
- /* TODO: use mnt_context_set_fstype_pattern() */
- mnt_context_set_fstype(cxt, argv[idx + 1]);
- idx += 2;
- }
-
- if (argc == idx + 1)
- /* mount <spec> */
- mnt_context_set_spec(cxt, argv[idx++]);
-
- else if (argc == idx + 2) {
- /* mount <device> <mountpoint> */
- mnt_context_set_source(cxt, argv[idx++]);
- mnt_context_set_target(cxt, argv[idx++]);
- }
-
- rc = mnt_context_prepare_mount(cxt);
- if (rc)
- printf("failed to prepare mount\n");
- else {
- lock = mnt_context_get_lock(cxt);
- if (lock)
- atexit(lock_fallback);
-
- rc = mnt_context_mount_fs(cxt);
- if (rc)
- printf("failed to mount\n");
- else {
- printf("successfully mounted");
- rc = mnt_context_post_mount(cxt);
- if (rc)
- printf("mtab update failed\n");
- }
- }
-
- mnt_free_context(cxt);
- return rc;
-}
-
-int main(int argc, char *argv[])
-{
- struct mtest tss[] = {
- { "--mount", test_mount, "[-o <opts>] [-t <type>] <spec> | <src> <target>" },
- { NULL }
- };
-
- return mnt_run_test(tss, argc, argv);
-}
-
-#endif /* TEST_PROGRAM */