#include <stdarg.h>
#include <sys/wait.h>
+#include "mount-api-utils.h"
+
/**
* mnt_new_context:
*
return 0;
}
+#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
+int mnt_context_open_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg)
+{
+ unsigned long oflg = OPEN_TREE_CLOEXEC;
+ int rc = 0, fd = -1;
+
+ if (mflg == (unsigned long) -1) {
+ rc = mnt_optlist_get_flags(cxt->optlist, &mflg, cxt->map_linux, 0);
+ if (rc)
+ return rc;
+ }
+ if (!path) {
+ path = mnt_fs_get_target(cxt->fs);
+ if (!path)
+ return -EINVAL;
+ }
+
+ /* Classic -oremount,bind,ro is not bind operation, it's just
+ * VFS flags update only */
+ if ((mflg & MS_BIND) && !(mflg & MS_REMOUNT)) {
+ oflg |= OPEN_TREE_CLONE;
+
+ if (mnt_optlist_is_rbind(cxt->optlist))
+ oflg |= AT_RECURSIVE;
+ }
+
+ if (cxt->force_clone)
+ oflg |= OPEN_TREE_CLONE;
+
+ DBG(CXT, ul_debugobj(cxt, "open_tree(path=%s%s%s)", path,
+ oflg & OPEN_TREE_CLONE ? " clone" : "",
+ oflg & AT_RECURSIVE ? " recursive" : ""));
+ fd = open_tree(AT_FDCWD, path, oflg);
+ mnt_context_syscall_save_status(cxt, "open_tree", fd >= 0);
+
+ return fd;
+}
+#endif
+
/*
* Translates LABEL/UUID/path to mountable path
*/
return api->fd_fs;
}
-static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg)
-{
- unsigned long oflg = OPEN_TREE_CLOEXEC;
- int rc = 0, fd = -1;
-
- if (mflg == (unsigned long) -1) {
- rc = mnt_optlist_get_flags(cxt->optlist, &mflg, cxt->map_linux, 0);
- if (rc)
- return rc;
- }
- if (!path) {
- path = mnt_fs_get_target(cxt->fs);
- if (!path)
- return -EINVAL;
- }
-
- /* Classic -oremount,bind,ro is not bind operation, it's just
- * VFS flags update only */
- if ((mflg & MS_BIND) && !(mflg & MS_REMOUNT)) {
- oflg |= OPEN_TREE_CLONE;
-
- if (mnt_optlist_is_rbind(cxt->optlist))
- oflg |= AT_RECURSIVE;
- }
-
- if (cxt->force_clone)
- oflg |= OPEN_TREE_CLONE;
-
- DBG(HOOK, ul_debug("open_tree(path=%s%s%s)", path,
- oflg & OPEN_TREE_CLONE ? " clone" : "",
- oflg & AT_RECURSIVE ? " recursive" : ""));
- fd = open_tree(AT_FDCWD, path, oflg);
- hookset_set_syscall_status(cxt, "open_tree", fd >= 0);
-
- return fd;
-}
-
static int hook_create_mount(struct libmnt_context *cxt,
const struct libmnt_hookset *hs,
void *data __attribute__((__unused__)))
/* fallback only; necessary when init_sysapi() during preparation
* cannot open the tree -- for example when we call /sbin/mount.<type> */
if (api->fd_tree < 0 && mnt_fs_get_target(cxt->fs)) {
- rc = api->fd_tree = open_mount_tree(cxt, NULL, (unsigned long) -1);
+ rc = api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
if (rc < 0)
return rc;
rc = 0;
/* fallback only; necessary when init_sysapi() during preparation
* cannot open the tree -- for example when we call /sbin/mount.<type> */
if (api->fd_tree < 0 && mnt_fs_get_target(cxt->fs)) {
- rc = api->fd_tree = open_mount_tree(cxt, NULL, (unsigned long) -1);
+ rc = api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
if (rc < 0)
goto done;
rc = 0;
return -ENOMEM;
if (path) {
- api->fd_tree = open_mount_tree(cxt, path, flags);
+ api->fd_tree = mnt_context_open_tree(cxt, path, flags);
if (api->fd_tree < 0)
goto fail;
static int do_mount_subdir(
struct libmnt_context *cxt,
struct hookset_data *hsd,
- const char *root,
- const char *target)
+ const char *root)
{
int rc = 0;
const char *subdir = hsd->subdir;
+ const char *target;
#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
- struct libmnt_sysapi *api;
+ struct libmnt_sysapi *api = mnt_context_get_sysapi(cxt);
+
+ /* fallback only; necessary when hook_mount.c during preparation
+ * cannot open the tree -- for example when we call /sbin/mount.<type> */
+ if (api && api->fd_tree < 0) {
+ api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
+ if (api->fd_tree < 0)
+ return api->fd_tree;
+ }
+#endif
+ /* reset to the original mountpoint */
+ mnt_fs_set_target(cxt->fs, hsd->org_target);
+ target = mnt_fs_get_target(cxt->fs);
- api = mnt_context_get_sysapi(cxt);
- if (api) {
+#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
+ if (api && api->fd_tree >= 0) {
/* FD based way - unfortunately, it's impossible to open
* sub-directory on not-yet attached mount. It means
* hook_mount.c attaches FS to temporary directory, and we
*/
int fd;
- DBG(HOOK, ul_debug("attach subdir %s", subdir));
+ DBG(HOOK, ul_debug("attach subdir '%s'", subdir));
fd = open_tree(api->fd_tree, subdir,
OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
mnt_context_syscall_save_status(cxt, "open_tree", fd >= 0);
if (!hsd || !hsd->subdir)
return 0;
- /* reset to the original mountpoint */
- mnt_fs_set_target(cxt->fs, hsd->org_target);
-
/* bind subdir to the real target, umount temporary target */
- rc = do_mount_subdir(cxt, hsd,
- MNT_PATH_TMPTGT,
- mnt_fs_get_target(cxt->fs));
+ rc = do_mount_subdir(cxt, hsd, MNT_PATH_TMPTGT);
if (rc)
return rc;
{
return mnt_context_get_hookset_data(cxt, &hookset_mount);
}
+
+int mnt_context_open_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg);
+
#endif
#endif /* _LIBMOUNT_PRIVATE_H */