From: Michael Ferrari Date: Mon, 1 Jul 2024 09:10:36 +0000 (+0200) Subject: Support decompressing tar archives X-Git-Tag: v24~75^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dcd1f289c1ebef4133db54c91edaaf0aadb0af81;p=thirdparty%2Fmkosi.git Support decompressing tar archives This switches `extract_tar` to read the file itself instead of from stdin to be able to auto-detect the compression method used. BSD tar can auto-detect and decompress from stdin, but GNU tar only auto-detects the compression method and notifies the user, but refuses to run when not explicitly specifying the format on the command line. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 8258a922b..6cf29d99b 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -25,7 +25,7 @@ from contextlib import AbstractContextManager from pathlib import Path from typing import Optional, Union, cast -from mkosi.archive import extract_tar, make_cpio, make_tar +from mkosi.archive import can_extract_tar, extract_tar, make_cpio, make_tar from mkosi.burn import run_burn from mkosi.config import ( Args, @@ -104,7 +104,7 @@ def mount_base_trees(context: Context) -> Iterator[None]: if path.is_dir(): bases += [path] - elif path.suffix == ".tar": + elif can_extract_tar(path): extract_tar(path, d, sandbox=context.sandbox) bases += [d] elif path.suffix == ".raw": @@ -1575,7 +1575,7 @@ def install_tree( if src.is_dir() or (src.is_file() and target): copy() - elif src.suffix == ".tar": + elif can_extract_tar(src): extract_tar(src, t, sandbox=config.sandbox) elif src.suffix == ".raw": run( diff --git a/mkosi/archive.py b/mkosi/archive.py index 077d02e47..911e15e6f 100644 --- a/mkosi/archive.py +++ b/mkosi/archive.py @@ -50,6 +50,10 @@ def make_tar(src: Path, dst: Path, *, sandbox: SandboxProtocol = nosandbox) -> N ) +def can_extract_tar(src: Path) -> bool: + return ".tar" in src.suffixes[-2:] + + def extract_tar( src: Path, dst: Path, @@ -63,31 +67,29 @@ def extract_tar( with umask(~0o755): dst.mkdir(exist_ok=True) - with src.open("rb") as f: - run( - [ - "tar", - "--extract", - "--file", "-", - "--directory", dst, - "--keep-directory-symlink", - "--no-overwrite-dir", - "--same-permissions", - "--same-owner" if (dst / "etc/passwd").exists() else "--numeric-owner", - "--same-order", - "--acls", - "--selinux", - "--xattrs", - "--force-local", - *tar_exclude_apivfs_tmp(), - ], - stdin=f, - sandbox=sandbox( - binary="tar", - # Make sure tar uses user/group information from the root directory instead of the host. - mounts=[Mount(src, src, ro=True), Mount(dst, dst), *finalize_passwd_mounts(dst)] - ), - ) + run( + [ + "tar", + "--extract", + "--file", src, + "--directory", dst, + "--keep-directory-symlink", + "--no-overwrite-dir", + "--same-permissions", + "--same-owner" if (dst / "etc/passwd").exists() else "--numeric-owner", + "--same-order", + "--acls", + "--selinux", + "--xattrs", + "--force-local", + *tar_exclude_apivfs_tmp(), + ], + sandbox=sandbox( + binary="tar", + # Make sure tar uses user/group information from the root directory instead of the host. + mounts=[Mount(src, src, ro=True), Mount(dst, dst), *finalize_passwd_mounts(dst)] + ), + ) def make_cpio(