From 1bb1d80b3e3512a4664cb9895c95f29a900f8aba Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 4 Oct 2010 13:37:33 +0200 Subject: libmount: split context.c Signed-off-by: Karel Zak --- shlibs/mount/src/context.c | 906 ++++----------------------------------------- 1 file changed, 73 insertions(+), 833 deletions(-) (limited to 'shlibs/mount/src/context.c') 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 #include -#include -#include - -#ifdef HAVE_LIBSELINUX -#include -#include -#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. 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; @@ -651,6 +581,33 @@ static mnt_cache *mnt_context_get_cache(mnt_context *cxt) return cxt->cache; } +/** + * 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 @@ -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. 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" : "")); - - 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.). - * - * 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 */ - mnt_context_set_spec(cxt, argv[idx++]); - - else if (argc == idx + 2) { - /* mount */ - 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 ] [-t ] | " }, - { NULL } - }; - - return mnt_run_test(tss, argc, argv); -} - -#endif /* TEST_PROGRAM */ -- cgit v1.2.3-55-g7522