mirror of
https://github.com/BigfootACA/arch-image-builder.git
synced 2024-11-11 08:37:54 +08:00
108 lines
2.9 KiB
Python
108 lines
2.9 KiB
Python
import os
|
|
from logging import getLogger
|
|
from builder.lib.context import ArchBuilderContext
|
|
from builder.lib.mount import MountTab, MountPoint
|
|
log = getLogger(__name__)
|
|
|
|
|
|
def init_rootfs(ctx: ArchBuilderContext):
|
|
"""
|
|
Initialize Arch Linux rootfs
|
|
"""
|
|
path = ctx.get_rootfs()
|
|
def mkdir(mode, *names):
|
|
real = os.path.join(path, *names)
|
|
if not os.path.exists(real):
|
|
log.debug(f"create folder {real} with {mode:04o}")
|
|
os.makedirs(real, mode=mode)
|
|
log.debug(f"initializing rootfs folders at {path}")
|
|
mkdir(0o0755, path)
|
|
mkdir(0o0755, "dev")
|
|
mkdir(0o0555, "proc")
|
|
mkdir(0o0755, "run")
|
|
mkdir(0o0555, "sys")
|
|
mkdir(0o0755, "var", "lib", "pacman")
|
|
mkdir(0o0755, "etc", "pacman.d")
|
|
log.info(f"initialized rootfs folders at {path}")
|
|
|
|
|
|
def undo_mounts(ctx: ArchBuilderContext):
|
|
"""
|
|
Clean up mount points
|
|
"""
|
|
if len(ctx.mounted) <= 0: return
|
|
log.debug("undo mount points")
|
|
ctx.chroot = False
|
|
while len(ctx.mounted) > 0:
|
|
unmounted = 0
|
|
for mount in ctx.mounted.copy():
|
|
try:
|
|
mount.umount()
|
|
ctx.mounted.remove(mount)
|
|
unmounted += 1
|
|
except:
|
|
pass
|
|
if unmounted == 0:
|
|
raise RuntimeError("failed to umount all")
|
|
mnts = MountTab.parse_mounts()
|
|
if any(mnts.find_folder(ctx.work)):
|
|
raise RuntimeError("mount points not cleanup")
|
|
|
|
|
|
def do_mount(
|
|
ctx: ArchBuilderContext,
|
|
source: str,
|
|
target: str,
|
|
fstype: str,
|
|
options: str
|
|
):
|
|
"""
|
|
Add a mount point
|
|
"""
|
|
mnt = MountPoint()
|
|
mnt.source = source
|
|
mnt.target = target
|
|
mnt.fstype = fstype
|
|
mnt.options = options
|
|
mnt.mount()
|
|
ctx.mounted.insert(0, mnt)
|
|
|
|
|
|
def init_mount(ctx: ArchBuilderContext):
|
|
"""
|
|
Setup mount points for rootfs
|
|
"""
|
|
root = ctx.get_rootfs()
|
|
def symlink(target, *names):
|
|
real = os.path.join(root, *names)
|
|
if not os.path.exists(real):
|
|
log.debug(f"create symlink {real} -> {target}")
|
|
os.symlink(target, real)
|
|
def root_mount(source, target, fstype, options):
|
|
real = os.path.realpath(os.path.join(root, target))
|
|
do_mount(ctx, source, real, fstype, options)
|
|
try:
|
|
# ensure mount point is clean
|
|
mnts = MountTab.parse_mounts()
|
|
if any(mnts.find_folder(ctx.work)):
|
|
raise RuntimeError("mount points not cleanup")
|
|
|
|
root_mount("proc", "proc", "proc", "nosuid,noexec,nodev")
|
|
root_mount("sys", "sys", "sysfs", "nosuid,noexec,nodev,ro")
|
|
root_mount("dev", "dev", "devtmpfs", "mode=0755,nosuid")
|
|
root_mount("pts", "dev/pts", "devpts", "mode=0620,gid=5,nosuid,noexec")
|
|
root_mount("shm", "dev/shm", "tmpfs", "mode=1777,nosuid,nodev")
|
|
root_mount("run", "run", "tmpfs", "nosuid,nodev,mode=0755")
|
|
root_mount("tmp", "tmp", "tmpfs", "mode=1777,strictatime,nodev,nosuid")
|
|
|
|
# symbolic links for some script tools (e.g. mkinitcpio)
|
|
symlink("/proc/self/fd", "dev", "fd")
|
|
symlink("/proc/self/fd/0", "dev", "stdin")
|
|
symlink("/proc/self/fd/1", "dev", "stdout")
|
|
symlink("/proc/self/fd/2", "dev", "stderr")
|
|
ctx.chroot = True
|
|
except:
|
|
log.error("failed to initialize mount points")
|
|
undo_mounts(ctx)
|
|
raise
|