]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Support decompressing tar archives
authorMichael Ferrari <nekkodroid404@gmail.com>
Mon, 1 Jul 2024 09:10:36 +0000 (11:10 +0200)
committerMichael Ferrari <nekkodroid404@gmail.com>
Mon, 1 Jul 2024 09:10:36 +0000 (11:10 +0200)
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.

mkosi/__init__.py
mkosi/archive.py

index 8258a922b3bafcb0d9fbb0c89c977eaf6ee08a6d..6cf29d99bcc81fa36e61f3f0be2035f89383861e 100644 (file)
@@ -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(
index 077d02e47247df17cc2393aea5ceba85c1188096..911e15e6fd628fa4e358f518e661fa3731081f2b 100644 (file)
@@ -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(