From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 4CAD313835B for ; Wed, 27 May 2020 06:20:34 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 687CEE0999; Wed, 27 May 2020 06:20:33 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 39BDDE0999 for ; Wed, 27 May 2020 06:20:33 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 639A334EF2A for ; Wed, 27 May 2020 06:20:30 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 2D9D126E for ; Wed, 27 May 2020 06:20:04 +0000 (UTC) From: "Matt Turner" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Matt Turner" Message-ID: <1590098861.b11d30977dd90954357722f488e37ad3cd257ff4.mattst88@gentoo> Subject: [gentoo-commits] proj/catalyst:wip/mattst88 commit in: catalyst/base/, catalyst/ X-VCS-Repository: proj/catalyst X-VCS-Files: catalyst/base/stagebase.py catalyst/mount.py X-VCS-Directories: catalyst/ catalyst/base/ X-VCS-Committer: mattst88 X-VCS-Committer-Name: Matt Turner X-VCS-Revision: b11d30977dd90954357722f488e37ad3cd257ff4 X-VCS-Branch: wip/mattst88 Date: Wed, 27 May 2020 06:20:04 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 600c1704-fb77-4ae9-8739-fac43231ec50 X-Archives-Hash: 35db147ff930dbc2fd4a789d0bc0b3c3 commit: b11d30977dd90954357722f488e37ad3cd257ff4 Author: Matt Turner gentoo org> AuthorDate: Sat May 16 21:44:37 2020 +0000 Commit: Matt Turner gentoo org> CommitDate: Thu May 21 22:07:41 2020 +0000 URL: https://gitweb.gentoo.org/proj/catalyst.git/commit/?id=b11d3097 catalyst: Add and use support API for handling mounts Handle the mounts/unmounts in all in process rather than shelling out (pun intended!) to an external program. Signed-off-by: Matt Turner gentoo.org> catalyst/base/stagebase.py | 28 ++++++++++++++++++---------- catalyst/mount.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/catalyst/base/stagebase.py b/catalyst/base/stagebase.py index 00efd252..aa5cafd0 100644 --- a/catalyst/base/stagebase.py +++ b/catalyst/base/stagebase.py @@ -15,6 +15,7 @@ from DeComp.compress import CompressMap from catalyst import log from catalyst.defaults import (confdefaults, MOUNT_DEFAULTS, PORT_LOGDIR_CLEAN) +from catalyst.mount import MS, mount, umount from catalyst.support import (CatalystError, file_locate, normpath, cmd, read_makeconf, ismount, file_check) from catalyst.base.targetbase import TargetBase @@ -847,7 +848,9 @@ class StageBase(TargetBase, ClearBase, GenBase): source = str(self.mount[x]['source']) target = self.settings['chroot_path'] + str(self.mount[x]['target']) - mount = ['mount'] + filesystem = '' + flags = MS.NONE + options = '' log.debug('bind %s: "%s" -> "%s"', x, source, target) @@ -855,18 +858,19 @@ class StageBase(TargetBase, ClearBase, GenBase): if 'var_tmpfs_portage' not in self.settings: continue - mount += ['-t', 'tmpfs', '-o', - f"size={self.settings['var_tmpfs_portage']}G"] + filesystem = 'tmpfs' + options = f"size={self.settings['var_tmpfs_portage']}G" elif source == 'tmpfs': - mount += ['-t', 'tmpfs'] + filesystem = 'tmpfs' elif source == 'shm': - mount += ['-t', 'tmpfs', '-o', 'noexec,nosuid,nodev'] + filesystem = 'tmpfs' + flags = MS.NOEXEC | MS.NOSUID | MS.NODEV else: source_path = Path(self.mount[x]['source']) if source_path.suffix == '.sqfs': - mount += ['-o', 'ro'] + flags = MS.RDONLY else: - mount.append('--bind') + flags = MS.BIND # We may need to create the source of the bind mount. E.g., in the # case of an empty package cache we must create the directory that @@ -875,7 +879,11 @@ class StageBase(TargetBase, ClearBase, GenBase): Path(target).mkdir(mode=0o755, parents=True, exist_ok=True) - cmd(mount + [source, target], env=self.env, fail_func=self.unbind) + try: + mount(source, target, filesystem, flags, options) + except OSError as e: + self.unbind() + raise CatalystError def unbind(self): ouch = 0 @@ -893,7 +901,7 @@ class StageBase(TargetBase, ClearBase, GenBase): continue try: - cmd(['umount', target], env=self.env) + umount(target) except CatalystError: log.warning('First attempt to unmount failed: %s', target) log.warning('Killing any pids still running in the chroot') @@ -901,7 +909,7 @@ class StageBase(TargetBase, ClearBase, GenBase): self.kill_chroot_pids() try: - cmd(['umount', target], env=self.env) + umount(target) except CatalystError: ouch = 1 log.warning("Couldn't umount bind mount: %s", target) diff --git a/catalyst/mount.py b/catalyst/mount.py new file mode 100644 index 00000000..58b953fc --- /dev/null +++ b/catalyst/mount.py @@ -0,0 +1,32 @@ +import ctypes +import ctypes.util +import enum +import os + +libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) +libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p) +libc.umount.argtypes = (ctypes.c_char_p) + +class MS(enum.IntFlag): + NONE = 0x0 + RDONLY = 0x1 + NOSUID = 0x2 + NODEV = 0x4 + NOEXEC = 0x8 + BIND = 0x1000 + +def mount(source: str, target: str, fs: str, flags: MS = MS.NONE, options: str = '') -> None: + ret = libc.mount(source.encode(), target.encode(), fs.encode(), flags, + options.encode()) + if ret < 0: + errno = ctypes.get_errno() + raise OSError(errno, + f"Error mounting {source} ({fs}) on {target} with options" + f" {options}': {os.strerror(errno)}") + +def umount(target: str) -> None: + ret = libc.umount(target.encode()) + if ret < 0: + errno = ctypes.get_errno() + raise OSError(errno, + f"Error unmounting {target}': {os.strerror(errno)}"