forked from Mirror/pmbootstrap
While at it, also remove unnecessary "#!/usr/bin/env python3" in files that only get imported, and adjust other empty/comment lines in the beginnings of the files for consistency. This makes files easier to read, and makes the pmbootstrap codebase more consistent with the build.postmarketos.org codebase.
103 lines
3.9 KiB
Python
103 lines
3.9 KiB
Python
# Copyright 2020 Oliver Smith
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
import glob
|
|
import logging
|
|
import os
|
|
import pmb.config
|
|
import pmb.parse
|
|
import pmb.helpers.mount
|
|
|
|
|
|
def create_device_nodes(args, suffix):
|
|
"""
|
|
Create device nodes for null, zero, full, random, urandom in the chroot.
|
|
"""
|
|
try:
|
|
chroot = args.work + "/chroot_" + suffix
|
|
|
|
# Create all device nodes as specified in the config
|
|
for dev in pmb.config.chroot_device_nodes:
|
|
path = chroot + "/dev/" + str(dev[4])
|
|
if not os.path.exists(path):
|
|
pmb.helpers.run.root(args, ["mknod",
|
|
"-m", str(dev[0]), # permissions
|
|
path, # name
|
|
str(dev[1]), # type
|
|
str(dev[2]), # major
|
|
str(dev[3]), # minor
|
|
])
|
|
|
|
# Verify major and minor numbers of created nodes
|
|
for dev in pmb.config.chroot_device_nodes:
|
|
path = chroot + "/dev/" + str(dev[4])
|
|
stat_result = os.stat(path)
|
|
rdev = stat_result.st_rdev
|
|
assert os.major(rdev) == dev[2], "Wrong major in " + path
|
|
assert os.minor(rdev) == dev[3], "Wrong minor in " + path
|
|
|
|
# Verify /dev/zero reading and writing
|
|
path = chroot + "/dev/zero"
|
|
with open(path, "r+b", 0) as handle:
|
|
assert handle.write(bytes([0xff])), "Write failed for " + path
|
|
assert handle.read(1) == bytes([0x00]), "Read failed for " + path
|
|
|
|
# On failure: Show filesystem-related error
|
|
except Exception as e:
|
|
logging.info(str(e) + "!")
|
|
raise RuntimeError("Failed to create device nodes in the '" +
|
|
suffix + "' chroot.")
|
|
|
|
|
|
def mount_dev_tmpfs(args, suffix="native"):
|
|
"""
|
|
Mount tmpfs inside the chroot's dev folder to make sure we can create
|
|
device nodes, even if the filesystem of the work folder does not support
|
|
it.
|
|
"""
|
|
# Do nothing when it is already mounted
|
|
dev = args.work + "/chroot_" + suffix + "/dev"
|
|
if pmb.helpers.mount.ismount(dev):
|
|
return
|
|
|
|
# Create the $chroot/dev folder and mount tmpfs there
|
|
pmb.helpers.run.root(args, ["mkdir", "-p", dev])
|
|
pmb.helpers.run.root(args, ["mount", "-t", "tmpfs",
|
|
"-o", "size=1M,noexec,dev",
|
|
"tmpfs", dev])
|
|
|
|
# Create pts, shm folders and device nodes
|
|
pmb.helpers.run.root(args, ["mkdir", "-p", dev + "/pts", dev + "/shm"])
|
|
pmb.helpers.run.root(args, ["mount", "-t", "tmpfs",
|
|
"-o", "nodev,nosuid,noexec",
|
|
"tmpfs", dev + "/shm"])
|
|
create_device_nodes(args, suffix)
|
|
|
|
|
|
def mount(args, suffix="native"):
|
|
# Mount tmpfs as the chroot's /dev
|
|
mount_dev_tmpfs(args, suffix)
|
|
|
|
# Get all mountpoints
|
|
arch = pmb.parse.arch.from_chroot_suffix(args, suffix)
|
|
mountpoints = {}
|
|
for source, target in pmb.config.chroot_mount_bind.items():
|
|
source = source.replace("$WORK", args.work)
|
|
source = source.replace("$ARCH", arch)
|
|
mountpoints[source] = target
|
|
|
|
# Mount if necessary
|
|
for source, target in mountpoints.items():
|
|
target_full = args.work + "/chroot_" + suffix + target
|
|
pmb.helpers.mount.bind(args, source, target_full)
|
|
|
|
|
|
def mount_native_into_foreign(args, suffix):
|
|
source = args.work + "/chroot_native"
|
|
target = args.work + "/chroot_" + suffix + "/native"
|
|
pmb.helpers.mount.bind(args, source, target)
|
|
|
|
musl = os.path.basename(glob.glob(source + "/lib/ld-musl-*.so.1")[0])
|
|
musl_link = args.work + "/chroot_" + suffix + "/lib/" + musl
|
|
if not os.path.lexists(musl_link):
|
|
pmb.helpers.run.root(args, ["ln", "-s", "/native/lib/" + musl,
|
|
musl_link])
|