/* * The default is to use fstype from cxt->fs, this could be overwritten by * @try_type argument. * * Returns: 0 on success, * >0 in case of mount(2) error (returns syscall errno), * <0 in case of other errors. */ static int do_mount(struct libmnt_context *cxt, const char *try_type) { int rc = 0; const char *src, *target, *type; unsigned long flags; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); if (try_type && !cxt->helper) { rc = mnt_context_prepare_helper(cxt, "mount", try_type); if (!rc) return rc; } if (cxt->helper) return exec_helper(cxt); flags = cxt->mountflags; src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!src || !target) return -EINVAL; type = try_type ? : mnt_fs_get_fstype(cxt->fs); if (!(flags & MS_MGC_MSK)) flags |= MS_MGC_VAL; DBG(CXT, mnt_debug_h(cxt, "%smount(2) " "[source=%s, target=%s, type=%s, " " mountflags=0x%08lx, mountdata=%s]", (cxt->flags & MNT_FL_FAKE) ? "(FAKE) " : "", src, target, type, flags, cxt->mountdata ? "yes" : "<none>")); if (cxt->flags & MNT_FL_FAKE) cxt->syscall_status = 0; else { if (mount(src, target, type, flags, cxt->mountdata)) { cxt->syscall_status = -errno; DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]", -cxt->syscall_status)); return -cxt->syscall_status; } DBG(CXT, mnt_debug_h(cxt, "mount(2) success")); cxt->syscall_status = 0; } if (try_type && cxt->update) { struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); if (fs) rc = mnt_fs_set_fstype(fs, try_type); } return rc; }
static int do_umount(struct libmnt_context *cxt) { int rc = 0, flags = 0; const char *src, *target; char *tgtbuf = NULL; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); assert(cxt->syscall_status == 1); if (cxt->helper) return exec_helper(cxt); src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!target) return -EINVAL; DBG(CXT, mnt_debug_h(cxt, "do umount")); if (cxt->restricted && !mnt_context_is_fake(cxt)) { /* * extra paranoia for non-root users * -- chdir to the parent of the mountpoint and use NOFOLLOW * flag to avoid races and symlink attacks. */ if (umount_nofollow_support()) flags |= UMOUNT_NOFOLLOW; rc = mnt_chdir_to_parent(target, &tgtbuf); if (rc) return rc; target = tgtbuf; } if (mnt_context_is_lazy(cxt)) flags |= MNT_DETACH; else if (mnt_context_is_force(cxt)) flags |= MNT_FORCE; DBG(CXT, mnt_debug_h(cxt, "umount(2) [target='%s', flags=0x%08x]%s", target, flags, mnt_context_is_fake(cxt) ? " (FAKE)" : "")); if (mnt_context_is_fake(cxt)) rc = 0; else { rc = flags ? umount2(target, flags) : umount(target); if (rc < 0) cxt->syscall_status = -errno; free(tgtbuf); } /* * try remount read-only */ if (rc < 0 && cxt->syscall_status == -EBUSY && mnt_context_is_rdonly_umount(cxt) && src) { mnt_context_set_mflags(cxt, (cxt->mountflags | MS_REMOUNT | MS_RDONLY)); mnt_context_enable_loopdel(cxt, FALSE); DBG(CXT, mnt_debug_h(cxt, "umount(2) failed [errno=%d] -- trying to remount read-only", -cxt->syscall_status)); rc = mount(src, mnt_fs_get_target(cxt->fs), NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); if (rc < 0) { cxt->syscall_status = -errno; DBG(CXT, mnt_debug_h(cxt, "read-only re-mount(2) failed [errno=%d]", -cxt->syscall_status)); return -cxt->syscall_status; } cxt->syscall_status = 0; DBG(CXT, mnt_debug_h(cxt, "read-only re-mount(2) success")); return 0; } if (rc < 0) { DBG(CXT, mnt_debug_h(cxt, "umount(2) failed [errno=%d]", -cxt->syscall_status)); return -cxt->syscall_status; } cxt->syscall_status = 0; DBG(CXT, mnt_debug_h(cxt, "umount(2) success")); return 0; }
/* * The default is to use fstype from cxt->fs, this could be overwritten by * @try_type argument. * * Returns: 0 on success, * >0 in case of mount(2) error (returns syscall errno), * <0 in case of other errors. */ static int do_mount(struct libmnt_context *cxt, const char *try_type) { int rc = 0; const char *src, *target, *type; unsigned long flags; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); if (try_type && !cxt->helper) { rc = mnt_context_prepare_helper(cxt, "mount", try_type); if (rc) return rc; } if (cxt->helper) return exec_helper(cxt); flags = cxt->mountflags; src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!target) return -EINVAL; if (!src) { /* unnecessary, should be already resolved in * mnt_context_prepare_srcpath(), but for sure... */ DBG(CXT, mnt_debug_h(cxt, "WARNING: source is NULL -- using \"none\"!")); src = "none"; } type = try_type ? : mnt_fs_get_fstype(cxt->fs); if (!(flags & MS_MGC_MSK)) flags |= MS_MGC_VAL; DBG(CXT, mnt_debug_h(cxt, "%smount(2) " "[source=%s, target=%s, type=%s, " " mountflags=0x%08lx, mountdata=%s]", mnt_context_is_fake(cxt) ? "(FAKE) " : "", src, target, type, flags, cxt->mountdata ? "yes" : "<none>")); if (mnt_context_is_fake(cxt)) cxt->syscall_status = 0; else { if (mount(src, target, type, flags, cxt->mountdata)) { cxt->syscall_status = -errno; DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]", -cxt->syscall_status)); return -cxt->syscall_status; } DBG(CXT, mnt_debug_h(cxt, "mount(2) success")); cxt->syscall_status = 0; } if (try_type && cxt->update) { struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); if (fs) rc = mnt_fs_set_fstype(fs, try_type); } return rc; }