From 000330e11538b0d85ee932fc27b42f199a1fa966 Mon Sep 17 00:00:00 2001 From: Eero Kelly Date: Thu, 6 Aug 2026 22:45:23 +0000 Subject: [PATCH 1/2] Use a tar lib instead of shelling out in fs build --- .../build_container_filesystem_tar.py | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/toolchains/sysimage/build_container_filesystem_tar.py b/toolchains/sysimage/build_container_filesystem_tar.py index 26fab6ad33f3..2c34b41dacb4 100755 --- a/toolchains/sysimage/build_container_filesystem_tar.py +++ b/toolchains/sysimage/build_container_filesystem_tar.py @@ -6,6 +6,8 @@ import argparse import os import shutil +import subprocess +import tarfile import tempfile import uuid from dataclasses import dataclass @@ -105,22 +107,27 @@ def export_container_filesystem(image_tag: str, destination_tar_filename: str): Export the filesystem from an image. Creates container - but does not start it, avoiding timestamp and other determinism issues. """ - # tempfile cleanup is handled by proc_wrapper.sh - tempdir = tempfile.mkdtemp() - tar_file = tempdir + "/temp.tar" - fakeroot_statefile = tempdir + "/fakeroot.state" - tar_dir = tempdir + "/tar" - container_name = image_tag + "_container" storage_args = get_storage_dir_args() invoke.run(f"podman {storage_args} create --name {container_name} {image_tag}") - invoke.run(f"podman {storage_args} export -o {tar_file} {container_name}") - invoke.run(f"mkdir -p {tar_dir}") - invoke.run(f"fakeroot -s {fakeroot_statefile} tar xpf {tar_file} --same-owner --numeric-owner -C {tar_dir}") - invoke.run( - f"fakeroot -i {fakeroot_statefile} tar cf {destination_tar_filename} --mtime='UTC 1970-01-01 00:00:00' --numeric-owner --sort=name --exclude='run/*' -C {tar_dir} $(ls -A {tar_dir})" - ) + + with subprocess.Popen(f"podman {storage_args} export {container_name}", stdout=subprocess.PIPE, shell=True) as proc: + with tarfile.open(fileobj=proc.stdout, mode="r|") as source, tarfile.open( + destination_tar_filename, "w|", format=tarfile.GNU_FORMAT + ) as destination: + for member in source: + if member.name.startswith("run/"): + continue + + if member.islnk() and member.linkname.startswith("run/"): + raise RuntimeError(f"{member.name} is a hard link to `/run`, which is stripped out of the image") + + data = source.extractfile(member) if member.isfile() else None + destination.addfile(member.replace(mtime=0, uname="", gname="", deep=False), data) + + if proc.returncode != 0: + raise RuntimeError(f"podman export failed (exit {proc.returncode})") def resolve_file_args(context_dir: str, file_build_args: List[str]) -> List[str]: From d478d4237b69d8a04a3d4a9b51a97f56c6f615da Mon Sep 17 00:00:00 2001 From: Eero Kelly Date: Thu, 13 Aug 2026 18:40:12 +0000 Subject: [PATCH 2/2] Trigger CI