xar: 1.6.1 -> 498

This change switches the xar package from unmaintained fork of the
original project to the Apple Open Source tarball. See also
https://repology.org/project/xar/versions

Since the package is essentially rewritten from scratch, we take an
opportunity and move it to pkgs/by-name/xa/xar (formatted with nixfmt).

We also remove Windows from the supported platforms because even before
this change pkgsCross.mingwW64.xar failed with
xar> configure: error: can not detect the size of your system's uid_t type
This commit is contained in:
Ivan Trubach 2024-07-24 21:34:38 +03:00
parent 4c2e720a58
commit 5eee6cf40a
23 changed files with 2436 additions and 94 deletions

View File

@ -0,0 +1,178 @@
{
lib,
stdenv,
fetchFromGitHub,
applyPatches,
autoreconfHook,
nix-update-script,
# Required dependencies.
openssl,
zlib,
libxml2,
# Optional dependencies.
e2fsprogs,
bzip2,
xz, # lzma
# Platform-specific dependencies.
acl,
musl-fts,
# for tests
testers,
python3,
libxslt, # xsltproc
runCommand,
runCommandCC,
makeWrapper,
xar,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "xar";
version = "498";
src = fetchFromGitHub {
owner = "apple-oss-distributions";
repo = "xar";
rev = "xar-${finalAttrs.version}";
hash = "sha256-RyWeR/ZnDBHIZhwzVxETdrTTPQA2VgsLZegRkxX1240=";
};
# Update patch set with
# git clone https://github.com/apple-oss-distributions/xar
# cd xar
# git switch -c nixpkgs
# git am ../pkgs/by-name/xa/xar/patches/*
# # …
# rm -r ../pkgs/by-name/xa/xar/patches
# git format-patch --zero-commit --output-directory ../pkgs/by-name/xa/xar/patches main
patches = lib.filesystem.listFilesRecursive ./patches;
# We do not use or modify files outside of the xar subdirectory.
patchFlags = [ "-p2" ];
sourceRoot = "source/xar";
outputs = [
"out"
"lib"
"dev"
];
strictDeps = true;
nativeBuildInputs = [ autoreconfHook ];
# For some reason libxml2 package headers are in subdirectory and thus arent
# picked up by stdenvs C compiler wrapper (see ccWrapper_addCVars). This
# doesnt really belong here and either should be part of libxml2 package or
# libxml2 in Nixpkgs can just fix their header paths.
env.NIX_CFLAGS_COMPILE = "-isystem ${libxml2.dev}/include/libxml2";
buildInputs =
[
# NB we use OpenSSL instead of CommonCrypto on Darwin.
openssl
zlib
libxml2
bzip2
xz
e2fsprogs
]
++ lib.optional stdenv.hostPlatform.isLinux acl ++ lib.optional stdenv.hostPlatform.isMusl musl-fts;
passthru =
let
patchedSource = applyPatches { inherit (finalAttrs) src patches; };
pythonForTests = python3.withPackages (p: [ p.xattr ]);
in
{
# Tests xar outside of the Nix sandbox (extended attributes are not supported
# in Nix sandbox, e.g. filtered with seccomp on Linux).
#
# Run with
# $ nix run --file . xar.impureTests.integrationTest
# Ensure that all tests are PASSED and none are FAILED or SKIPPED.
impureTests.integrationTest =
runCommand "xar-impure-tests-integration-test"
{
src = patchedSource;
xar = finalAttrs.finalPackage;
xsltproc = lib.getBin libxslt;
pythonInterpreter = pythonForTests.interpreter;
nativeBuildInputs = [ makeWrapper ];
}
''
makeWrapper "$pythonInterpreter" "$out/bin/$name" \
--prefix PATH : "$xar/bin" \
--suffix PATH : "$xsltproc/bin" \
--add-flags -- \
--add-flags "$src/xar/test/run-all.py"
'';
tests = lib.optionalAttrs (stdenv.buildPlatform.canExecute stdenv.hostPlatform) {
version = testers.testVersion {
package = finalAttrs.finalPackage;
version = "1.8dev";
};
integrationTest =
runCommand "xar-tests-integration-test"
{
src = patchedSource;
strictDeps = true;
pythonExecutable = pythonForTests.executable;
nativeBuildInputs = [
finalAttrs.finalPackage
pythonForTests
libxslt
];
}
''
"$pythonExecutable" "$src"/xar/test/run-all.py
touch "$out"
'';
smokeTest =
runCommandCC "xar-tests-smoke-test"
{
src = patchedSource;
strictDeps = true;
nativeBuildInputs = [ finalAttrs.finalPackage ];
buildInputs = [
finalAttrs.finalPackage
openssl
];
}
''
cp "$src"/xar/test/{buffer.c,validate.c} .
"$CC" -lxar -o buffer buffer.c
"$CC" -lxar -lcrypto -o validate validate.c
./buffer validate.c
xar -x -f test.xar
diff validate.c mydir/secondfile
./validate test.xar
touch "$out"
'';
};
updateScript = nix-update-script {
extraArgs = [
"--version-regex"
"xar-(.*)"
];
};
};
meta = {
homepage = "https://github.com/apple-oss-distributions/xar";
description = "An easily extensible archive format";
license = lib.licenses.bsd3;
maintainers =
lib.teams.darwin.members
++ lib.attrValues { inherit (lib.maintainers) copumpkin tie; };
platforms = lib.platforms.unix;
mainProgram = "xar";
};
})

View File

@ -0,0 +1,961 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 12:53:54 +0300
Subject: [PATCH 01/19] Update tests for Python 3 and Nix sandbox
This change updates integration tests for Python 3 and fixes some
assumptions to work under Nix sandbox (in particular, extended
attributes are not allowed).
Also updates xar/test/validate.c for modern OpenSSL versions.
---
xar/test/attr.py | 54 +++++++++++++++++++-------
xar/test/buffer.c | 3 +-
xar/test/checksums.py | 75 +++++++++++++++++++-----------------
xar/test/compression.py | 27 ++++++++-----
xar/test/data.py | 19 +++++----
xar/test/hardlink.py | 12 ++++--
xar/test/heap.py | 27 +++++++------
xar/test/integrity.py | 45 ++++++++++++----------
xar/test/run-all.py | 25 ++++++++++++
xar/test/util.py | 85 ++++++++++++++++++++++++++++++++++++-----
xar/test/validate.c | 32 +++++++++-------
11 files changed, 282 insertions(+), 122 deletions(-)
create mode 100755 xar/test/run-all.py
diff --git a/xar/test/attr.py b/xar/test/attr.py
index adc2c56..c28a4e6 100755
--- a/xar/test/attr.py
+++ b/xar/test/attr.py
@@ -6,6 +6,7 @@ import os
import os.path
import shutil
import subprocess
+import sys
import xattr
import util
@@ -26,20 +27,27 @@ import util
class MissingExtendedAttributeError(AssertionError):
pass
-def _random_big_data(bytes=65536, path="/dev/random"):
+def _random_big_data(bytes=65536):
"""
Returns a random string with the number of bytes requested. Due to xar
implementation details, this should be greater than 4096 (32768 for
compressed heap testing).
"""
- with open(path, "r") as f:
- return f.read(bytes)
+ return os.urandom(bytes)
+
+def _to_bytes(s):
+ if isinstance(s, str):
+ return s.encode("utf-8")
+ return s
def _test_xattr_on_file_with_contents(filename, file_contents, xattrs=[], xar_create_flags=[], xar_extract_flags=[]):
+ file_contents = _to_bytes(file_contents)
+ xattr_prefix = "user." if sys.platform != "darwin" else ""
+ xattrs = [(xattr_prefix + k, _to_bytes(v)) for k, v in xattrs]
try:
# Write file out
- with open(filename, "w") as f:
+ with open(filename, "wb") as f:
f.write(file_contents)
for (key, value) in xattrs:
xattr.setxattr(f, key, value)
@@ -51,14 +59,16 @@ def _test_xattr_on_file_with_contents(filename, file_contents, xattrs=[], xar_cr
with util.directory_created("extracted") as directory:
# Validate resulting xattrs
subprocess.check_call(["xar", "-x", "-C", directory, "-f", path] + xar_extract_flags)
+ extracted_filename = os.path.join(directory, filename)
+ expected_set = {key for key, _ in xattrs}
+ actual_set = set(xattr.listxattr(os.path.join(directory, filename)))
+ for key in expected_set - actual_set:
+ raise MissingExtendedAttributeError("extended attribute \"{n}\" missing after extraction".format(n=key))
for (key, value) in xattrs:
- try:
- assert xattr.getxattr(os.path.join(directory, filename), key) == value, "extended attribute \"{n}\" has incorrect contents after extraction".format(n=key)
- except KeyError:
- raise MissingExtendedAttributeError("extended attribute \"{n}\" missing after extraction".format(n=key))
+ assert xattr.getxattr(extracted_filename, key) == value, "extended attribute \"{n}\" has incorrect contents after extraction".format(n=key)
# Validate file contents
- with open(os.path.join(directory, filename), "r") as f:
+ with open(os.path.join(directory, filename), "rb") as f:
if f.read() != file_contents:
raise MissingExtendedAttributeError("archived file \"{f}\" has has incorrect contents after extraction".format(f=filename))
finally:
@@ -73,36 +83,47 @@ def _test_xattr_on_file_with_contents(filename, file_contents, xattrs=[], xar_cr
# tests are commented out awaiting a day when this might be different.
# def empty_xattr_empty_file(filename):
+# util.skip_if_no_xattrs_support()
# _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "")])
def small_xattr_empty_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "1234")])
def large_xattr_empty_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", _random_big_data(5000))])
# def empty_xattr_small_file(filename):
+# util.skip_if_no_xattrs_support()
# _test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "")])
def small_xattr_small_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "1234")])
def large_xattr_small_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", _random_big_data(4567))])
# def empty_xattr_large_file(filename):
+# util.skip_if_no_xattrs_support()
# _test_xattr_on_file_with_contents(filename, _random_big_data(10000000), xattrs=[("foo", "")])
def small_xattr_large_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, _random_big_data(5000000), xattrs=[("foo", "1234")])
def large_xattr_large_file(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, _random_big_data(9876543), xattrs=[("foo", _random_big_data(6543))])
def multiple_xattrs(filename):
+ util.skip_if_no_xattrs_support()
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "bar"), ("baz", "1234"), ("quux", "more")]) # ("empty", "")
def distribution_create(filename):
+ util.skip_if_no_xattrs_support()
try:
_test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_create_flags=["--distribution"])
except MissingExtendedAttributeError:
@@ -114,6 +135,7 @@ def distribution_create(filename):
# when it can.
# def distribution_extract(filename):
+# util.skip_if_no_xattrs_support()
# try:
# _test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_extract_flags=["--distribution"])
# except MissingExtendedAttributeError:
@@ -128,12 +150,18 @@ TEST_CASES = (small_xattr_empty_file, large_xattr_empty_file,
multiple_xattrs, distribution_create)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case(case.func_name)
- print("PASSED: {f}".format(f=case.func_name))
+ case(func_name)
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
+ except util.TestCaseSkipError as e:
+ print("SKIPPED: {f}: {m}".format(f=func_name, m=e))
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/buffer.c b/xar/test/buffer.c
index a353cef..e4c5639 100644
--- a/xar/test/buffer.c
+++ b/xar/test/buffer.c
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
@@ -50,7 +51,7 @@ int main(int argc, char *argv[])
if( red < sb.st_size )
fprintf(stderr, "Incomplete read\n");
- x = xar_open("/tmp/test.xar", WRITE);
+ x = xar_open("test.xar", WRITE);
if( x == NULL ) {
fprintf(stderr, "Error creating xarchive\n");
exit(6);
diff --git a/xar/test/checksums.py b/xar/test/checksums.py
index 7080d7c..0f39e63 100755
--- a/xar/test/checksums.py
+++ b/xar/test/checksums.py
@@ -2,6 +2,7 @@
from __future__ import print_function
+import contextlib
import hashlib
import os
import os.path
@@ -9,6 +10,7 @@ import re
import shutil
import struct
import subprocess
+import sys
import util
@@ -17,15 +19,21 @@ import util
# Utility Functions
#
+@contextlib.contextmanager
+def _test_archive_created(filename, directory, *args, **kwargs):
+ with util.test_directory_created(directory) as test_directory:
+ with util.archive_created(filename, test_directory, *args, **kwargs) as path:
+ yield path
+
def _get_numeric_value_from_header(archive_name, key):
"""
Dumps the header of the specified xar archive and extracts the header
size from the output, in bytes.
"""
- header = subprocess.check_output(["xar", "--dump-header", "-f", archive_name])
+ header = subprocess.check_output(["xar", "--dump-header", "-f", archive_name], text=True)
for line in header.splitlines():
- matchdata = re.match("^(.+):\s+(.+)$", line) # magic: 0x78617221 (OK)
+ matchdata = re.match(r"^(.+):\s+(.+)$", line) # magic: 0x78617221 (OK)
assert matchdata, "unexpected output from `xar --dump-header`:\n{h}".format(h=header)
if matchdata.groups()[0] == key:
return int(matchdata.groups()[1])
@@ -38,17 +46,14 @@ def _get_toc_size(archive_name):
return _get_numeric_value_from_header(archive_name, "Compressed TOC length")
def _clobber_bytes_at(clobber_range, path):
- with open(path, "r+") as f:
+ with open(path, "rb+") as f:
f.seek(clobber_range[0])
- with open("/dev/random", "r") as r:
- random_bytes = r.read(len(clobber_range))
- f.write(random_bytes)
+ f.write(os.urandom(len(clobber_range)))
def _verify_extraction_failed(filename):
with util.directory_created("extracted") as directory:
try:
- with open("/dev/null", "w") as n:
- returncode = subprocess.call(["xar", "-x", "-C", directory, "-f", filename], stdout=n, stderr=n)
+ returncode = subprocess.call(["xar", "-x", "-C", directory, "-f", filename], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
assert returncode != 0, "xar reported success extracting an archive with a broken TOC"
finally:
if os.path.exists(directory):
@@ -63,7 +68,7 @@ def _verify_header_checksum(filename, algorithm):
header_size = _get_header_size(filename)
toc_length = _get_toc_size(filename)
- with open(filename, "r") as f:
+ with open(filename, "rb") as f:
f.seek(header_size)
h = hashlib.new(algorithm, f.read(toc_length))
computed_digest = h.digest()
@@ -76,23 +81,23 @@ def _verify_header_checksum(filename, algorithm):
#
def default_toc_checksum_validity(filename):
- with util.archive_created(filename, "/bin") as path:
+ with _test_archive_created(filename, "testdir") as path:
_verify_header_checksum(path, "sha1")
def sha1_toc_checksum_validity(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha1") as path:
_verify_header_checksum(path, "sha1")
def sha256_toc_checksum_validity(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha256") as path:
_verify_header_checksum(path, "sha256")
def sha512_toc_checksum_validity(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha512") as path:
_verify_header_checksum(path, "sha512")
def broken_toc_default_checksum(filename):
- with util.archive_created(filename, "/bin") as path:
+ with _test_archive_created(filename, "testdir") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
@@ -101,7 +106,7 @@ def broken_toc_default_checksum(filename):
_verify_extraction_failed(filename)
def broken_toc_sha1_checksum(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha1") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
@@ -110,7 +115,7 @@ def broken_toc_sha1_checksum(filename):
_verify_extraction_failed(filename)
def broken_toc_sha256_checksum(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha256") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
@@ -119,7 +124,7 @@ def broken_toc_sha256_checksum(filename):
_verify_extraction_failed(filename)
def broken_toc_sha512_checksum(filename):
- with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path:
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "sha512") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
@@ -128,7 +133,7 @@ def broken_toc_sha512_checksum(filename):
_verify_extraction_failed(filename)
def broken_heap_default_checksum(filename):
- with util.archive_created(filename, "/bin") as path:
+ with _test_archive_created(filename, "testdir") as path:
# Mess up the archive
toc_start = _get_header_size(path)
toc_size = _get_toc_size(path)
@@ -139,11 +144,11 @@ def broken_heap_default_checksum(filename):
_verify_extraction_failed(filename)
def default_checksum_algorithm(filename):
- with util.archive_created(filename, "/bin") as path:
- header = subprocess.check_output(["xar", "--dump-header", "-f", path])
+ with _test_archive_created(filename, "testdir") as path:
+ header = subprocess.check_output(["xar", "--dump-header", "-f", path], text=True)
found = False
for line in header.splitlines():
- matchdata = re.match("^Checksum algorithm:\s+(\d+)\s+\\((\w+)\\)$", line)
+ matchdata = re.match(r"^Checksum algorithm:\s+(\d+)\s+\((\w+)\)$", line)
if not matchdata:
continue
found = True
@@ -156,7 +161,7 @@ def default_checksum_algorithm(filename):
#
# def invalid_checksum_algorithm(filename):
# try:
-# with util.archive_created(filename, "/bin", "--toc-cksum", "invalid-algorithm") as path:
+# with _test_archive_created(filename, "testdir", "--toc-cksum", "invalid-algorithm") as path:
# raise AssertionError("xar succeeded when it should have failed")
# except subprocess.CalledProcessError:
# pass
@@ -164,17 +169,15 @@ def default_checksum_algorithm(filename):
# It does fail for md5 explicitly, however
def md5_toc_checksum_failure(filename):
try:
- with open("/dev/null", "a") as devnull:
- with util.archive_created(filename, "/bin", "--toc-cksum", "md5", stderr=devnull) as path:
- raise AssertionError("xar succeeded when it should have failed")
+ with _test_archive_created(filename, "testdir", "--toc-cksum", "md5", stderr=subprocess.DEVNULL) as path:
+ raise AssertionError("xar succeeded when it should have failed")
except subprocess.CalledProcessError:
pass
def md5_file_checksum_failure(filename):
try:
- with open("/dev/null", "a") as devnull:
- with util.archive_created(filename, "/bin", "--file-cksum", "md5", stderr=devnull) as path:
- raise AssertionError("xar succeeded when it should have failed")
+ with _test_archive_created(filename, "testdir", "--file-cksum", "md5", stderr=subprocess.DEVNULL) as path:
+ raise AssertionError("xar succeeded when it should have failed")
except subprocess.CalledProcessError:
pass
@@ -185,8 +188,8 @@ def _verify_checksum_algorithm(filename, algorithm):
else:
algorithm = "sha1"
- with util.archive_created(filename, "/bin", *additional_args) as path:
- toc = subprocess.check_output(["xar", "--dump-toc=-", "-f", path])
+ with _test_archive_created(filename, "testdir", *additional_args) as path:
+ toc = subprocess.check_output(["xar", "--dump-toc=-", "-f", path], text=True)
found = False
for line in toc.splitlines():
if '<unarchived-checksum style="{a}">'.format(a=algorithm) in line or '<archived-checksum style="{a}">'.format(a=algorithm) in line:
@@ -214,12 +217,16 @@ TEST_CASES = (default_toc_checksum_validity, sha1_toc_checksum_validity, sha256_
md5_toc_checksum_failure, md5_file_checksum_failure,)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/compression.py b/xar/test/compression.py
index 2b3b2ec..7ed30ca 100755
--- a/xar/test/compression.py
+++ b/xar/test/compression.py
@@ -2,10 +2,10 @@
from __future__ import print_function
-import cStringIO
import os
import os.path
import subprocess
+import sys
import tempfile
import util
@@ -16,10 +16,15 @@ import util
#
def _check_compression(filename, *args, **kwargs):
- with util.archive_created(filename, "/bin", *args, **kwargs) as path:
+ with (
+ util.directory_created("temp") as temp_directory,
+ util.chdir(temp_directory),
+ util.test_directory_created("testdir") as test_directory,
+ util.archive_created(filename, "testdir", *args, **kwargs) as path,
+ ):
with util.directory_created("extracted") as directory:
subprocess.check_call(["xar", "-x", "-f", path, "-C", directory])
- util.assert_identical_directories("/bin", os.path.join(directory, "bin"))
+ util.assert_identical_directories(test_directory, os.path.join(directory, "testdir"))
#
@@ -61,14 +66,18 @@ TEST_CASES = (no_compression, default_compression,
gzip_compression_short, bzip2_compression_short, lzma_compression_short)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
- except util.TestCaseSkipError, e:
- print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))
+ except util.TestCaseSkipError as e:
+ print("SKIPPED: {f}: {m}".format(f=func_name, m=e))
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/data.py b/xar/test/data.py
index a9793f0..f902b78 100755
--- a/xar/test/data.py
+++ b/xar/test/data.py
@@ -6,6 +6,7 @@ import contextlib
import os
import os.path
import subprocess
+import sys
import util
@@ -28,7 +29,7 @@ def _process_toc(archive_path):
subprocess.check_call(["xar", "-f", archive_path, "--dump-toc=data_toc.xml"])
try:
result = subprocess.check_output(["xsltproc", "-o", "-", os.path.realpath(os.path.join(__file__, "..", "data.xsl")), "data_toc.xml"])
- assert result == "", "expected no data offset, but instead found:{o}".format(o=result)
+ assert result == b"", "expected no data offset, but instead found:{o}".format(o=result)
finally:
os.unlink("data_toc.xml")
@@ -90,14 +91,18 @@ TEST_CASES = (zero_length_default_compression, zero_length_no_compression,
mixed_length_gzip_compression, mixed_length_bzip2_compression, mixed_length_lzma_compression)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
- except util.TestCaseSkipError, e:
- print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))
+ except util.TestCaseSkipError as e:
+ print("SKIPPED: {f}: {m}".format(f=func_name, m=e))
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/hardlink.py b/xar/test/hardlink.py
index 5145216..da409d6 100755
--- a/xar/test/hardlink.py
+++ b/xar/test/hardlink.py
@@ -5,6 +5,7 @@ from __future__ import print_function
import os
import os.path
import subprocess
+import sys
import util
@@ -58,12 +59,17 @@ def hard_link_identical_files(filename):
TEST_CASES = (hard_link_in_directory, hard_link_in_cwd, hard_link_identical_files)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
+ failed = True
import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/heap.py b/xar/test/heap.py
index f431c77..727412a 100755
--- a/xar/test/heap.py
+++ b/xar/test/heap.py
@@ -8,6 +8,7 @@ import os.path
import re
import shutil
import subprocess
+import sys
import util
@@ -19,8 +20,8 @@ import util
def _file_offsets_for_archive(path, xsl_path):
subprocess.check_call(["xar", "--dump-toc=heap_toc.xml", "-f", path])
try:
- offsets = subprocess.check_output(["xsltproc", xsl_path, "heap_toc.xml"])
- matches = [re.match("^(.+)\s([^\s]+)$", offset) for offset in offsets.splitlines()]
+ offsets = subprocess.check_output(["xsltproc", xsl_path, "heap_toc.xml"], text=True)
+ matches = [re.match(r"^(.+)\s([^\s]+)$", offset) for offset in offsets.splitlines()]
offsets = [(match.groups()[0], int(match.groups()[1])) for match in matches]
return offsets
finally:
@@ -33,9 +34,8 @@ def _file_offsets_for_archive(path, xsl_path):
XSL_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "heap1.xsl")
def normal_heap(filename):
- with util.directory_created("scratch") as directory:
- shutil.copy("/bin/ls", os.path.join(directory, "ls"))
- shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo"))
+ with util.test_directory_created("scratch") as directory:
+ shutil.copy(os.path.join(directory, "script"), os.path.join(directory, "foo"))
with util.chdir(directory):
with util.archive_created(os.path.join("..", "heap.xar"), ".") as path:
# Verify file offsets are as we expect
@@ -50,9 +50,8 @@ def normal_heap(filename):
subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted])
def coalesce_heap(filename):
- with util.directory_created("scratch") as directory:
- shutil.copy("/bin/ls", os.path.join(directory, "ls"))
- shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo"))
+ with util.test_directory_created("scratch") as directory:
+ shutil.copy(os.path.join(directory, "script"), os.path.join(directory, "foo"))
with util.chdir(directory):
with util.archive_created(os.path.join("..", "heap.xar"), ".", "--coalesce-heap") as path:
# Verify file offsets are as we expect
@@ -67,12 +66,16 @@ def coalesce_heap(filename):
TEST_CASES = (normal_heap, coalesce_heap)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/integrity.py b/xar/test/integrity.py
index c47ac6a..f4d2af7 100755
--- a/xar/test/integrity.py
+++ b/xar/test/integrity.py
@@ -5,6 +5,7 @@ from __future__ import print_function
import os
import os.path
import subprocess
+import sys
import util
@@ -12,9 +13,9 @@ import util
# Utility Functions
#
-def _test_truncation(filename, path_to_be_archived, bytes_to_chop, *args):
- with util.archive_created(filename, path_to_be_archived) as path:
- with open("/dev/null", "w") as bitbucket:
+def _test_truncation(filename, bytes_to_chop, *args):
+ with util.test_directory_created("testdir") as test_directory:
+ with util.archive_created(filename, test_directory) as path:
size = os.stat(path).st_size
while size > 0:
last_size = size
@@ -23,7 +24,7 @@ def _test_truncation(filename, path_to_be_archived, bytes_to_chop, *args):
f.truncate(size)
with util.directory_created("scratch") as directory:
- returncode = subprocess.call(["xar", "-x", "-f", path, "-C", directory], stderr=bitbucket)
+ returncode = subprocess.call(["xar", "-x", "-f", path, "-C", directory], stderr=subprocess.DEVNULL)
assert returncode != 0, "xar claimed to succeed when extracting a truncated archive"
#
@@ -31,42 +32,42 @@ def _test_truncation(filename, path_to_be_archived, bytes_to_chop, *args):
#
def large_uncompressed(filename):
- _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=none")
+ _test_truncation(filename, 1024 * 1024, "--compression=none")
def large_default_compression(filename):
- _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024)
+ _test_truncation(filename, 1024 * 1024)
def large_gzip_compressed(filename):
util.skip_if_no_compression_support("gzip")
- _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=gzip")
+ _test_truncation(filename, 1024 * 1024, "--compression=gzip")
def large_bzip2_compressed(filename):
util.skip_if_no_compression_support("bzip2")
- _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=bzip2")
+ _test_truncation(filename, 1024 * 1024, "--compression=bzip2")
def large_lzma_compressed(filename):
util.skip_if_no_compression_support("lzma")
- _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=lzma")
+ _test_truncation(filename, 1024 * 1024, "--compression=lzma")
# "small" variants use a non-base-2 size to try to catch issues that occur on uneven boundaries
def small_uncompressed(filename):
- _test_truncation(filename, "/bin", 43651, "--compression=none")
+ _test_truncation(filename, 43651, "--compression=none")
def small_default_compression(filename):
- _test_truncation(filename, "/bin", 43651)
+ _test_truncation(filename, 43651)
def small_gzip_compressed(filename):
util.skip_if_no_compression_support("gzip")
- _test_truncation(filename, "/bin", 43651, "--compression=gzip")
+ _test_truncation(filename, 43651, "--compression=gzip")
def small_bzip2_compressed(filename):
util.skip_if_no_compression_support("bzip2")
- _test_truncation(filename, "/bin", 43651, "--compression=bzip2")
+ _test_truncation(filename, 43651, "--compression=bzip2")
def small_lzma_compressed(filename):
util.skip_if_no_compression_support("lzma")
- _test_truncation(filename, "/bin", 43651, "--compression=lzma")
+ _test_truncation(filename, 43651, "--compression=lzma")
TEST_CASES = (large_uncompressed, large_default_compression,
@@ -75,14 +76,18 @@ TEST_CASES = (large_uncompressed, large_default_compression,
small_gzip_compressed, small_bzip2_compressed, small_lzma_compressed)
if __name__ == "__main__":
+ failed = False
for case in TEST_CASES:
+ func_name = case.__name__
try:
- case("{f}.xar".format(f=case.func_name))
- print("PASSED: {f}".format(f=case.func_name))
+ case("{f}.xar".format(f=func_name))
+ print("PASSED: {f}".format(f=func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
- import sys, os
- print("FAILED: {f}".format(f=case.func_name))
+ failed = True
+ print("FAILED: {f}".format(f=func_name))
sys.excepthook(*sys.exc_info())
print("")
- except util.TestCaseSkipError, e:
- print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))
+ except util.TestCaseSkipError as e:
+ print("SKIPPED: {f}: {m}".format(f=func_name, m=e))
+ if failed:
+ sys.exit(1)
diff --git a/xar/test/run-all.py b/xar/test/run-all.py
new file mode 100755
index 0000000..05e3054
--- /dev/null
+++ b/xar/test/run-all.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import os.path
+import subprocess
+import sys
+
+test_suites = [
+ "attr.py",
+ "checksums.py",
+ "compression.py",
+ "data.py",
+ "hardlink.py",
+ "heap.py",
+ "integrity.py",
+]
+
+test_path = os.path.dirname(__file__)
+
+failed = False
+for suite in test_suites:
+ p = subprocess.run([sys.executable, "--", os.path.join(test_path, suite)])
+ if p.returncode:
+ failed = True
+if failed:
+ sys.exit(1)
diff --git a/xar/test/util.py b/xar/test/util.py
index da79925..423dd3c 100644
--- a/xar/test/util.py
+++ b/xar/test/util.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
import contextlib
+import errno
+import functools
import hashlib
import os
import os.path
@@ -13,16 +15,65 @@ import xattr
class TestCaseSkipError(Exception):
pass
+@functools.cache
+def _check_xattrs_supported():
+ """
+ Returns True if the filesystem supports extended attributes.
+ """
+ with directory_created("empty") as directory:
+ try:
+ xattr.setxattr(directory, "user.xattrcheck", b"supported")
+ return True
+ except OSError as e:
+ if e.errno != errno.ENOTSUP:
+ raise
+ return False
+
+def skip_if_no_xattrs_support():
+ """
+ Raises TestCaseSkipError if the the filesystem does not support extended
+ attributes.
+ """
+ if not _check_xattrs_supported():
+ raise TestCaseSkipError("filesystem does not support extended attributes")
+
+@functools.cache
+def _check_compression_supported(type):
+ """
+ Returns True if xar has support for the given compression type compiled
+ in. This function performs a runtime check that tries to compress data
+ with the given compression type and looks for a known error string. It
+ ignores all other errors.
+ """
+ supported = True
+ with directory_created("empty") as directory:
+ archive_path = f"{type}_compression_check.xar"
+ try:
+ return f"{type} support not compiled in." not in subprocess.run(
+ [
+ "xar",
+ "-c",
+ "-f",
+ archive_path,
+ "--compression=" + type,
+ directory,
+ ],
+ stdout=subprocess.PIPE,
+ text=True,
+ ).stdout
+ except:
+ # Assume that this compression type is supported.
+ pass
+ finally:
+ if os.path.exists(archive_path):
+ os.unlink(archive_path)
+ return supported
+
def skip_if_no_compression_support(type):
"""
- Raises TestCaseSkipError if the type is "lzma" and the test is running on
- darwin (OS X). In the future, we should add a hidden debugging flag to xar
- to determine valid compression types. This will skip incorrectly if a
- custom xar is used on OS X, or if a custom xar on another platform is
- built without bzip2 or lzma.
-
+ Raises TestCaseSkipError if the compression type is not compiled in.
"""
- if sys.platform == "darwin" and type == "lzma":
+ if not _check_compression_supported(type):
raise TestCaseSkipError("{t} support not compiled in".format(t=type))
@contextlib.contextmanager
@@ -43,6 +94,22 @@ def directory_created(directory_path):
if os.path.exists(directory_path):
shutil.rmtree(directory_path)
+@contextlib.contextmanager
+def test_directory_created(directory_path):
+ """
+ Like directory_created, but populates the directory with test files.
+ """
+ with directory_created(directory_path) as directory:
+ with open(os.path.join(directory, "script"), "w+", opener=lambda path, flags: os.open(path, flags, 0o750)) as f:
+ f.write("#!/bin/sh\necho hello world")
+ with open(os.path.join(directory, "random_1kb"), "wb+") as f:
+ f.write(os.urandom(1000))
+ with open(os.path.join(directory, "random_4kib"), "wb+") as f:
+ f.write(os.urandom(4096))
+ with open(os.path.join(directory, "random_1mb"), "wb+") as f:
+ f.write(os.urandom(9999999))
+ yield directory
+
@contextlib.contextmanager
def archive_created(archive_path, content_path, *extra_args, **extra_kwargs):
"""
@@ -68,7 +135,7 @@ def archive_created(archive_path, content_path, *extra_args, **extra_kwargs):
HASH_CHUNK_SIZE = 32768
def _md5_path(path):
- with open(path, "r") as f:
+ with open(path, "rb") as f:
h = hashlib.md5()
while True:
last = f.read(HASH_CHUNK_SIZE)
@@ -122,7 +189,7 @@ def assert_identical_directories(path1, path2):
# Sizes and the like
assert stat1.st_size == stat2.st_size, "size mismatch for \"{e1}\" ({s1}) and \"{e2}\" ({s2})".format(e1=entry1, s1=stat1.st_size, e2=entry2, s2=stat2.st_size)
- assert stat1.st_mtime == stat2.st_mtime, "mtime mismatch for \"{e1}\" and \"{e2}\"".format(e1=entry1, e2=entry2)
+ assert int(stat1.st_mtime) == int(stat2.st_mtime), "mtime mismatch for \"{e1}\" and \"{e2}\"".format(e1=entry1, e2=entry2)
assert _md5_path(entry1) == _md5_path(entry2), "md5 hash mismatch for \"{e1}\" and \"{e2}\"".format(e1=entry1, e2=entry2)
if os.path.isdir(entry1):
assert_identical_directories(entry1, entry2)
diff --git a/xar/test/validate.c b/xar/test/validate.c
index dfe69eb..a5fbe37 100644
--- a/xar/test/validate.c
+++ b/xar/test/validate.c
@@ -16,37 +16,40 @@
off_t HeapOff = 0;
-static char* xar_format_md5(const unsigned char* m) {
+static char* xar_format_sha1(const unsigned char* m) {
char* result = NULL;
asprintf(&result,
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
"%02x%02x%02x%02x",
m[0], m[1], m[2], m[3],
m[4], m[5], m[6], m[7],
m[8], m[9], m[10], m[11],
- m[12], m[13], m[14], m[15]);
+ m[12], m[13], m[14], m[15],
+ m[16], m[17], m[18], m[19]);
return result;
}
void heap_check(int fd, const char *name, const char *prop, off_t offset, off_t length, const char *csum) {
char *buf;
- EVP_MD_CTX ctx;
+ EVP_MD_CTX *ctx;
const EVP_MD *md;
- unsigned char md5str[EVP_MAX_MD_SIZE];
+ unsigned char sha1str[EVP_MAX_MD_SIZE];
unsigned int len;
ssize_t r;
- char *formattedmd5;
+ char *formattedsha1;
fprintf(stderr, "Heap checking %s %s at offset: %" PRIu64 "\n", name, prop, HeapOff+offset);
OpenSSL_add_all_digests();
- md = EVP_get_digestbyname("md5");
+ md = EVP_get_digestbyname("sha1");
if( md == NULL ) {
- fprintf(stderr, "No md5 digest in openssl\n");
+ fprintf(stderr, "No sha1 digest in openssl\n");
exit(1);
}
- EVP_DigestInit(&ctx, md);
+ ctx = EVP_MD_CTX_create();
+ EVP_DigestInit(ctx, md);
buf = malloc(length);
if( !buf ) {
@@ -65,14 +68,15 @@ void heap_check(int fd, const char *name, const char *prop, off_t offset, off_t
fprintf(stderr, "Error reading from the heap\n");
exit(1);
}
- EVP_DigestUpdate(&ctx, buf, length);
- EVP_DigestFinal(&ctx, md5str, &len);
+ EVP_DigestUpdate(ctx, buf, length);
+ EVP_DigestFinal(ctx, sha1str, &len);
+ EVP_MD_CTX_destroy(ctx);
- formattedmd5 = xar_format_md5(md5str);
- if( strcmp(formattedmd5, csum) != 0 ) {
- fprintf(stderr, "%s %s checksum does not match\n", name, prop);
+ formattedsha1 = xar_format_sha1(sha1str);
+ if( strcmp(formattedsha1, csum) != 0 ) {
+ fprintf(stderr, "%s %s checksum does not match (got %s but expected %s)\n", name, prop, formattedsha1, csum);
}
- free(formattedmd5);
+ free(formattedsha1);
free(buf);
}
--
2.44.1

View File

@ -0,0 +1,153 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 16:34:17 +0300
Subject: [PATCH 02/19] Update for modern liblzma5 versions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This change updates liblzma usage for modern xz versions (≥ 5, that is,
released less than a decade ago).
It also fixes missing realloc buffer calls that were supposed to be
there but were lost in xar-420 (and Apple does not ship xar with LZMA
support so nobody noticed). See also the offending commit:
https://github.com/apple-oss-distributions/xar/commit/2426082efec74e9ed545cc4f5812ad16322bdf2c
---
xar/lib/lzmaxar.c | 65 ++++++++---------------------------------------
1 file changed, 10 insertions(+), 55 deletions(-)
diff --git a/xar/lib/lzmaxar.c b/xar/lib/lzmaxar.c
index ba9c868..8dcb484 100644
--- a/xar/lib/lzmaxar.c
+++ b/xar/lib/lzmaxar.c
@@ -54,27 +54,12 @@
#ifdef HAVE_LIBLZMA
-#ifndef UINT32_C
-#define UINT32_C(v) (v ## U) /* from <stdint.h> normally */
-#endif
-#ifndef LZMA_VERSION
-#define LZMA_VERSION UINT32_C(40420000) /* = 4.42.0alpha6 */
-#endif
-
struct _lzma_context{
uint8_t lzmacompressed;
lzma_stream lzma;
- lzma_options_stream options;
- lzma_allocator allocator;
-#if LZMA_VERSION < 40420010U
- lzma_memory_limitter *limit;
-#else
- lzma_memlimit *limit;
-#endif
};
#define preset_level 7
-#define memory_limit 93*1024*1024 /* 1=1M, 5=24M, 6=39M, 7=93M, 8=185M, 9=369M */
#define LZMA_CONTEXT(x) ((struct _lzma_context *)(*x))
#endif
@@ -116,9 +101,7 @@ int xar_lzma_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t
if( !opt ) return 0;
if( strcmp(opt, "application/x-lzma") != 0 ) return 0;
- lzma_init_decoder();
- LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR;
- r = lzma_stream_decoder(&LZMA_CONTEXT(context)->lzma, NULL, NULL);
+ r = lzma_stream_decoder(&LZMA_CONTEXT(context)->lzma, UINT64_MAX, LZMA_CONCATENATED);
if( (r != LZMA_OK) ) {
xar_err_new(x);
xar_err_set_file(x, f);
@@ -194,11 +177,6 @@ int xar_lzma_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
if( LZMA_CONTEXT(context)->lzmacompressed){
lzma_end(&LZMA_CONTEXT(context)->lzma);
-#if LZMA_VERSION < 40420010U
- lzma_memory_limitter_end(LZMA_CONTEXT(context)->limit, 1);
-#else
- lzma_memlimit_end(LZMA_CONTEXT(context)->limit, 1);
-#endif
tmpp = xar_prop_pset(f, p, "encoding", NULL);
if( tmpp )
@@ -222,7 +200,7 @@ int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_
/* on first run, we init the context and check the compression type */
if( !LZMA_CONTEXT(context) ) {
- int level = preset_level;
+ uint32_t level = preset_level;
*context = calloc(1,sizeof(struct _lzma_context));
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
@@ -243,35 +221,7 @@ int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_
}
}
- lzma_init_encoder();
- LZMA_CONTEXT(context)->options.check = LZMA_CHECK_CRC64;
- LZMA_CONTEXT(context)->options.has_crc32 = 1; /* true */
- LZMA_CONTEXT(context)->options.alignment = 0;
-#if defined (__ppc__) || defined (powerpc) || defined (__ppc64__)
- LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_POWERPC;
-#elif defined (__i386__) || defined (__amd64__) || defined(__x86_64__)
- LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_X86;
-#else
- LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_COPY;
-#endif
- LZMA_CONTEXT(context)->options.filters[0].options = NULL;
- LZMA_CONTEXT(context)->options.filters[1].id = LZMA_FILTER_LZMA;
- LZMA_CONTEXT(context)->options.filters[1].options = (lzma_options_lzma *)(lzma_preset_lzma + level - 1);
- /* Terminate the filter options array. */
- LZMA_CONTEXT(context)->options.filters[2].id = UINT64_MAX;
- LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR;
-#if LZMA_VERSION < 40420010U
- LZMA_CONTEXT(context)->limit = lzma_memory_limitter_create(memory_limit);
- LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memory_alloc;
- LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memory_free;
-#else
- LZMA_CONTEXT(context)->limit = lzma_memlimit_create(memory_limit);
- LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memlimit_alloc;
- LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memlimit_free;
-#endif
- LZMA_CONTEXT(context)->allocator.opaque = LZMA_CONTEXT(context)->limit;
- LZMA_CONTEXT(context)->lzma.allocator = &LZMA_CONTEXT(context)->allocator;
- r = lzma_stream_encoder_single(&LZMA_CONTEXT(context)->lzma, &(LZMA_CONTEXT(context)->options));
+ r = lzma_easy_encoder(&LZMA_CONTEXT(context)->lzma, level, LZMA_CHECK_CRC64);
if( (r != LZMA_OK) ) {
xar_err_new(x);
xar_err_set_file(x, f);
@@ -279,6 +229,7 @@ int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
+
LZMA_CONTEXT(context)->lzmacompressed = 1;
if( *inlen == 0 )
return 0;
@@ -303,7 +254,8 @@ int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
-
+
+ out = realloc(out, outlen);
if( out == NULL ) abort();
LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset;
@@ -318,7 +270,10 @@ int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_
if (newlen > outlen)
outlen = newlen;
else
- abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ if( out == NULL ) abort();
+ abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
+
+ out = realloc(out, outlen);
+ if( out == NULL ) abort();
LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset;
LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset;
--
2.44.1

View File

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 18:25:48 +0300
Subject: [PATCH 03/19] Fix undefined EXT2_ECOMPR_FL for e2fsprogs
See https://github.com/mackyle/xar/issues/10
---
xar/lib/ext2.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/xar/lib/ext2.c b/xar/lib/ext2.c
index 767891a..2380846 100644
--- a/xar/lib/ext2.c
+++ b/xar/lib/ext2.c
@@ -139,8 +139,10 @@ int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *bu
if(! (flags & ~EXT2_NOCOMPR_FL) )
x_addprop(f, "NoCompBlock");
#endif
+#ifdef EXT2_ECOMPR_FL
if(! (flags & ~EXT2_ECOMPR_FL) )
x_addprop(f, "CompError");
+#endif
if(! (flags & ~EXT2_BTREE_FL) )
x_addprop(f, "BTree");
if(! (flags & ~EXT2_INDEX_FL) )
@@ -225,8 +227,10 @@ int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer,
if( e2prop_get(f, "NoCompBlock", (char **)&tmp) == 0 )
flags |= EXT2_NOCOMPR_FL ;
#endif
+#ifdef EXT2_ECOMPR_FL
if( e2prop_get(f, "CompError", (char **)&tmp) == 0 )
flags |= EXT2_ECOMPR_FL ;
+#endif
if( e2prop_get(f, "BTree", (char **)&tmp) == 0 )
flags |= EXT2_BTREE_FL ;
if( e2prop_get(f, "HashIndexed", (char **)&tmp) == 0 )
--
2.44.1

View File

@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fabian Groffen <grobian@gentoo.org>
Date: Tue, 1 Jan 2019 18:00:08 +0100
Subject: [PATCH 04/19] Fix compatibility with openssl-1.0
Patch-Source: https://github.com/gentoo/gentoo/blob/dce914f2bbf52360f45c90d877857df3c4c2a353/app-arch/xar/files/xar-1.8-openssl-1.1.patch
--
lib/hash.c: fix compilation with OpenSSL-1.1+
EVP_MD_CTX has become an anonymous struct now, so can't allocate size
for it anymore.
---
xar/lib/hash.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/xar/lib/hash.c b/xar/lib/hash.c
index 66876ad..cb4f6cf 100644
--- a/xar/lib/hash.c
+++ b/xar/lib/hash.c
@@ -97,7 +97,7 @@ struct __xar_hash_t {
#ifdef __APPLE__
CCDigestRef digest;
#else
- EVP_MD_CTX digest;
+ EVP_MD_CTX *digest;
const EVP_MD *type;
#endif
unsigned int length;
@@ -118,7 +118,8 @@ xar_hash_t xar_hash_new(const char *digest_name, void *context) {
#else
OpenSSL_add_all_digests();
HASH_CTX(hash)->type = EVP_get_digestbyname(digest_name);
- EVP_DigestInit(&HASH_CTX(hash)->digest, HASH_CTX(hash)->type);
+ HASH_CTX(hash)->digest = EVP_MD_CTX_create();
+ EVP_DigestInit(HASH_CTX(hash)->digest, HASH_CTX(hash)->type);
#endif
HASH_CTX(hash)->digest_name = strdup(digest_name);
@@ -138,7 +139,7 @@ void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte) {
#ifdef __APPLE__
CCDigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte);
#else
- EVP_DigestUpdate(&HASH_CTX(hash)->digest, buffer, nbyte);
+ EVP_DigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte);
#endif
}
@@ -155,7 +156,8 @@ void *xar_hash_finish(xar_hash_t hash, size_t *nbyte) {
CCDigestFinal(HASH_CTX(hash)->digest, buffer);
CCDigestDestroy(HASH_CTX(hash)->digest);
#else
- EVP_DigestFinal(&HASH_CTX(hash)->digest, buffer, &HASH_CTX(hash)->length);
+ EVP_DigestFinal(HASH_CTX(hash)->digest, buffer, &HASH_CTX(hash)->length);
+ EVP_MD_CTX_destroy(HASH_CTX(hash)->digest);
#endif
*nbyte = HASH_CTX(hash)->length;
--
2.44.1

View File

@ -0,0 +1,123 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net>
Date: Sat, 2 Mar 2024 01:25:52 +0100
Subject: [PATCH 05/19] Fix configure.ac for Linux headers
Patch-Source: https://github.com/gentoo/gentoo/blob/dce914f2bbf52360f45c90d877857df3c4c2a353/app-arch/xar/files/xar-1.8.0.0.452-linux.patch
---
xar/configure.ac | 19 +++++++++++++++++--
xar/include/config.h.in | 3 +++
xar/lib/util.c | 15 +++++++++++++++
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/xar/configure.ac b/xar/configure.ac
index 3a36f42..26d41a5 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -183,7 +183,7 @@ AC_SUBST([enable_autogen])
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/acl.h>], [acl_t a], [AC_DEFINE([HAVE_SYS_ACL_H],[1], [define if you have sys/acl.h and it has a working acl_t type])])
-AC_CHECK_HEADERS(ext2fs/ext2_fs.h sys/statfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h)
+AC_CHECK_HEADERS(ext2fs/ext2_fs.h sys/statfs.h sys/vfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h)
AC_CHECK_FUNCS(lgetxattr)
AC_CHECK_FUNCS(lsetxattr)
AC_CHECK_FUNCS(getxattr)
@@ -199,7 +199,22 @@ AC_CHECK_FUNCS(strmode)
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[#include <sys/types.h>
#include <sys/param.h>
-#include <sys/mount.h>])
+#include <sys/mount.h>
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif])
+AC_CHECK_MEMBERS([struct statfs.f_iosize],,,[#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif])
+AC_CHECK_MEMBERS([struct statfs.f_bsize],,,[#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif])
AC_CHECK_MEMBERS([struct statvfs.f_fstypename],,,[#include <sys/statvfs.h>])
AC_CHECK_MEMBERS([struct stat.st_flags])
diff --git a/xar/include/config.h.in b/xar/include/config.h.in
index 2bb997b..16c72d3 100644
--- a/xar/include/config.h.in
+++ b/xar/include/config.h.in
@@ -1,4 +1,5 @@
#undef HAVE_SYS_STATFS_H
+#undef HAVE_SYS_VFS_H
#undef HAVE_SYS_XATTR_H
#undef HAVE_SYS_EXTATTR_H
#undef HAVE_SYS_PARAM_H
@@ -15,6 +16,8 @@
#undef HAVE_STRUCT_STAT_ST_FLAGS
#undef HAVE_STRUCT_STATVFS_F_FSTYPENAME
#undef HAVE_STRUCT_STATFS_F_FSTYPENAME
+#undef HAVE_STRUCT_STATFS_F_IOSIZE
+#undef HAVE_STRUCT_STATFS_F_BSIZE
#undef HAVE_SYS_ACL_H
#undef HAVE_LIBUTIL_H
#undef HAVE_LIBPTHREAD
diff --git a/xar/lib/util.c b/xar/lib/util.c
index 0ea661a..1db2daa 100644
--- a/xar/lib/util.c
+++ b/xar/lib/util.c
@@ -35,11 +35,16 @@
* Christopher Ryan <ryanc@apple.com>
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/param.h>
+#ifdef HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
@@ -583,6 +588,14 @@ char *xar_get_mtime(xar_t x, xar_file_t f) {
return tmp;
}
+#ifndef HAVE_STRUCT_STATFS_F_IOSIZE
+# ifdef HAVE_STRUCT_STATFS_F_BSIZE
+# define f_iosize f_bsize
+# else
+# error need a field to get optimal transfer block size
+# endif
+#endif
+
size_t xar_optimal_io_size_at_path(const char *path)
{
// Start at 1MiB
@@ -599,6 +612,7 @@ size_t xar_optimal_io_size_at_path(const char *path)
fs_iosize = optimal_rsize;
}
+#ifdef MNT_LOCAL
// If we're a remote filesystem, never let us go below the optimal size above of 1MiB
// NFS is horrible and lies that the optimal size is 512 bytes.
// Whereas SMB in my testing returns 7MiBs (far more practicle)
@@ -611,6 +625,7 @@ size_t xar_optimal_io_size_at_path(const char *path)
}
}
else
+#endif
{
optimal_rsize = fs_iosize;
}
--
2.44.1

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 18:38:10 +0300
Subject: [PATCH 06/19] Fix more non-Darwin stuff
---
xar/include/xar.h.in | 1 +
xar/lib/linuxattr.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/xar/include/xar.h.in b/xar/include/xar.h.in
index 9c93798..3d24b4f 100644
--- a/xar/include/xar.h.in
+++ b/xar/include/xar.h.in
@@ -52,6 +52,7 @@ extern "C" {
#import <os/availability.h>
#else
#define API_DEPRECATED(...)
+#define API_AVAILABLE(...)
#endif
#pragma pack(4)
diff --git a/xar/lib/linuxattr.c b/xar/lib/linuxattr.c
index 0fec2bb..58ee6a8 100644
--- a/xar/lib/linuxattr.c
+++ b/xar/lib/linuxattr.c
@@ -226,7 +226,7 @@ int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buf
if( statfs(file, &sfs) != 0 ) {
char *tmp, *bname;
tmp = strdup(file);
- bname = safe_dirname(tmp);
+ bname = xar_safe_dirname(tmp);
statfs(bname, &sfs);
free(tmp);
free(bname);
--
2.44.1

View File

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fabian Groffen <grobian@gentoo.org>
Date: Sat, 16 Jul 2022 21:34:13 +0200
Subject: [PATCH 07/19] replace initialized constant with #define statement
GCC doesn't like this:
filetree.c:744:9: error: variable-sized object may not be initialized
Since there's nothing changing at runtime at all, just make the compiler
see it's always going to be 1.
Patch-Source: https://github.com/gentoo/gentoo/blob/dce914f2bbf52360f45c90d877857df3c4c2a353/app-arch/xar/files/xar-1.8.0.0.487-variable-sized-object.patch
---
xar/lib/filetree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xar/lib/filetree.c b/xar/lib/filetree.c
index f31682a..9c30c03 100644
--- a/xar/lib/filetree.c
+++ b/xar/lib/filetree.c
@@ -752,7 +752,7 @@ int xar_file_equals_file(xar_file_t f1, xar_file_t f2)
size_t fspath1_size = 0, fspath2_size = 0;
size_t ns1_size = 0, ns2_size = 0;
const struct __xar_file_t * child1 = NULL, * child2 = NULL;
- const uint keys_to_ignore_count = 1;
+#define keys_to_ignore_count 1
char * keys_to_ignore[keys_to_ignore_count] = { "id" }; // ID is allowed ot mismatch
// If the two pointers match, call it the same.
--
2.44.1

View File

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 18:43:38 +0300
Subject: [PATCH 08/19] Fix configure.ac not finding $AR with target prefix
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes AR and RANLIB with target prefix (if not set to absolute paths).
Looks like AC_PATH_PROG doesnt perform PATH lookups when user overrides
the program via environment variable but sets the value to program name
instead of absolute path.
Note that LD seems to be unused so we remove it.
---
xar/configure.ac | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/xar/configure.ac b/xar/configure.ac
index 26d41a5..3d8e5de 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -86,9 +86,8 @@ fi
AC_PROG_CPP
AC_PROG_INSTALL
-AC_PATH_PROG([LD], [ld], , [$PATH])
-AC_PATH_PROG([AR], [ar], , [$PATH])
-AC_PATH_PROG([RANLIB], [ranlib], , [$PATH])
+AC_PROG_AR
+AC_PROG_RANLIB
AC_PATH_PROG([AUTOCONF], [autoconf], , [$PATH])
dnl Some libtool envy
--
2.44.1

View File

@ -1,18 +1,18 @@
From a14be07c0aae3bf6f732d1ca5f625ba375702121 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Childs <andrew.childs@bibo.com.ph>
Date: Sun, 15 Nov 2020 19:12:33 +0900
Subject: [PATCH 1/2] Add useless descriptions to AC_DEFINE
Subject: [PATCH 09/19] Add useless descriptions to AC_DEFINE
Removes autoheader warnings.
Removes autoheader warnings from autoreconfHook.
---
configure.ac | 42 +++++++++++++++++++++---------------------
1 file changed, 21 insertions(+), 21 deletions(-)
xar/configure.ac | 46 +++++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/configure.ac b/configure.ac
index 812b5ff..358ab89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -210,48 +210,48 @@ AC_CHECK_MEMBERS([struct stat.st_flags])
diff --git a/xar/configure.ac b/xar/configure.ac
index 3d8e5de..0cc04dd 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -219,48 +219,48 @@ AC_CHECK_MEMBERS([struct stat.st_flags])
AC_CHECK_SIZEOF(uid_t)
if test $ac_cv_sizeof_uid_t = "4"; then
@ -81,7 +81,7 @@ index 812b5ff..358ab89 100644
else
AC_ERROR(can not detect the size of your system's dev_t type)
fi
@@ -261,7 +261,7 @@ AC_CHECK_LIB(acl, acl_get_file)
@@ -270,7 +270,7 @@ AC_CHECK_LIB(acl, acl_get_file)
dnl Check for paths
AC_PREFIX_DEFAULT(/usr/local)
@ -90,6 +90,24 @@ index 812b5ff..358ab89 100644
dnl
dnl Configure libxml2.
@@ -350,7 +350,7 @@ have_libbz2="1"
AC_CHECK_HEADERS([bzlib.h], , [have_libbz2="0"])
AC_CHECK_LIB([bz2], [BZ2_bzCompress], , [have_libbz2="0"])
if test "x${have_libbz2}" = "x1" ; then
- AC_DEFINE([HAVE_LIBBZ2])
+ AC_DEFINE([HAVE_LIBBZ2], [], [HAVE_LIBBZ2])
fi
dnl
@@ -360,7 +360,7 @@ have_libpthread="1"
AC_CHECK_HEADERS([pthread.h], , [have_pthread="0"])
AC_CHECK_LIB([pthread], [pthread_mutex_lock], , [have_pthread="0"])
if test "x${have_pthread}" = "x1" ; then
- AC_DEFINE([HAVE_PTHREAD])
+ AC_DEFINE([HAVE_PTHREAD], [], [HAVE_PTHREAD])
fi
dnl
--
2.28.0
2.44.1

View File

@ -1,21 +1,31 @@
From 276833851657c85651c053ee16b8e1a8dc768a50 Mon Sep 17 00:00:00 2001
From: Andrew Childs <andrew.childs@bibo.com.ph>
Date: Sun, 15 Nov 2020 19:12:56 +0900
Subject: [PATCH 2/2] Use pkg-config for libxml2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 18:58:14 +0300
Subject: [PATCH 10/19] Update configure.ac for openssl, libxml2, liblzma and
musl-fts
Simplifies libxml2 detection, adds detection for liblzma (from xz),
openssl and fts (for musl libc).
---
configure.ac | 66 +++++++++-------------------------------------------
1 file changed, 11 insertions(+), 55 deletions(-)
xar/configure.ac | 83 +++++++++++++++++-------------------------------
1 file changed, 30 insertions(+), 53 deletions(-)
diff --git a/configure.ac b/configure.ac
index 358ab89..984a694 100644
--- a/configure.ac
+++ b/configure.ac
@@ -268,61 +268,17 @@ dnl Configure libxml2.
dnl
LIBXML2_VERSION_MIN=2.6.11
diff --git a/xar/configure.ac b/xar/configure.ac
index 0cc04dd..e466ee0 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -272,63 +272,14 @@ AC_PREFIX_DEFAULT(/usr/local)
-have_libxml2="1"
AC_CHECK_FUNC([asprintf], AC_DEFINE([HAVE_ASPRINTF], [], [HAVE_ASPRINTF]))
+AC_SEARCH_LIBS([fts_close], [fts])
+
dnl
dnl Configure libxml2.
dnl
-LIBXML2_VERSION_MIN=2.6.11
-
have_libxml2="1"
-
-AC_ARG_WITH([xml2-config], [ --with-xml2-config libxml2 config program],
-if test "x${with_xml2_config}" = "xno" ; then
@ -67,23 +77,51 @@ index 358ab89..984a694 100644
- dnl Final sanity check, to make sure that xmlwriter is present.
- AC_CHECK_HEADER([libxml/xmlwriter.h], , [have_libxml2="0"])
-fi
-if test "x${have_libxml2}" = "x0" ; then
- AC_MSG_ERROR([Cannot build without libxml2])
-fi
+PKG_PROG_PKG_CONFIG
+
+PKG_CHECK_MODULES(LIBXML2_PKGCONFIG, [libxml-2.0 >= ${LIBXML2_VERSION_MIN}],
+ [
+ have_libxml2=1
+ CPPFLAGS="${CPPFLAGS} ${LIBXML2_PKGCONFIG_CFLAGS}"
+ LIBS="${LIBS} ${LIBXML2_PKGCONFIG_LIBS}"
+ ],
+ [
+ have_libxml2=0
+ ])
+AC_CHECK_HEADERS([libxml/xmlwriter.h], , [have_libxml2="0"])
+AC_CHECK_LIB([xml2], [xmlInitParser], , [have_libxml2="0"])
if test "x${have_libxml2}" = "x0" ; then
AC_MSG_ERROR([Cannot build without libxml2])
fi
@@ -343,6 +294,22 @@ if test "x${have_libz}" = "x0" ; then
AC_MSG_ERROR([Cannot build without libz])
fi
+dnl
+dnl Configure openssl.
+dnl
+have_openssl="1"
+AC_CHECK_HEADERS([openssl/evp.h], , [have_openssl="0"])
+AC_CHECK_LIB([crypto], [OPENSSL_config], , [have_openssl="0"])
+if test "x${have_openssl}" = "x0" ; then
+ case "${host}" in
+ *-*-darwin*)
+ ;;
+ *)
+ AC_MSG_ERROR([Cannot build without OpenSSL for non-Darwin host])
+ ;;
+ esac
+fi
+
dnl
dnl Configure libbz2.
dnl
@@ -353,6 +320,16 @@ if test "x${have_libbz2}" = "x1" ; then
AC_DEFINE([HAVE_LIBBZ2], [], [HAVE_LIBBZ2])
fi
+dnl
+dnl Configure liblzma.
+dnl
+have_liblzma="1"
+AC_CHECK_HEADERS([lzma.h], , [have_liblzma="0"])
+AC_CHECK_LIB([lzma], [lzma_stream_decoder], , [have_liblzma="0"])
+if test "x${have_liblzma}" = "x1" ; then
+ AC_DEFINE([HAVE_LIBLZMA], [], [HAVE_LIBLZMA])
+fi
+
dnl
dnl Configure libpthread.
dnl
dnl Configure libcrypto (part of OpenSSL).
--
2.28.0
2.44.1

View File

@ -0,0 +1,104 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 19:10:46 +0300
Subject: [PATCH 11/19] Fix missing includes and silence string format warnings
Based on patch from Gentoo; see
https://gitweb.gentoo.org/repo/gentoo.git/plain/app-arch/xar/files/xar-1.8.0.0.498-impl-decls.patch?id=cc91eb0f86043ae92c10cce55b326244bed3f061
---
xar/lib/Makefile.inc.in | 1 +
xar/lib/darwinattr.c | 1 +
xar/lib/ea.c | 3 ++-
xar/lib/ext2.c | 1 +
xar/lib/util.c | 1 +
xar/src/xar_internal.h | 4 ----
6 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/xar/lib/Makefile.inc.in b/xar/lib/Makefile.inc.in
index c046b25..d5e9003 100644
--- a/xar/lib/Makefile.inc.in
+++ b/xar/lib/Makefile.inc.in
@@ -127,6 +127,7 @@ lib_distclean :
CPPFLAGS := -I@objroot@include $(CPPFLAGS)
CPPFLAGS := -I@srcroot@include $(CPPFLAGS)
+CPPFLAGS := -I@srcroot@lib $(CPPFLAGS)
#
# Build rules.
diff --git a/xar/lib/darwinattr.c b/xar/lib/darwinattr.c
index 4938965..18302b0 100644
--- a/xar/lib/darwinattr.c
+++ b/xar/lib/darwinattr.c
@@ -37,6 +37,7 @@
#include "config.h"
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
diff --git a/xar/lib/ea.c b/xar/lib/ea.c
index 1bb8e27..fa1d06a 100644
--- a/xar/lib/ea.c
+++ b/xar/lib/ea.c
@@ -29,6 +29,7 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
+#include <inttypes.h> /* for PRId64 */
#include <string.h>
#include <assert.h>
#include <libgen.h>
@@ -67,7 +68,7 @@ xar_ea_t xar_ea_new(xar_file_t f, const char *name)
xar_prop_setvalue(XAR_EA(ret)->prop, NULL);
XAR_PROP(XAR_EA(ret)->prop)->attrs = xar_attr_new();
XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->key = strdup("id");
- asprintf((char **)&XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->value, "%lld", XAR_FILE(f)->nexteaid++);
+ asprintf((char **)&XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->value, "%"PRId64, XAR_FILE(f)->nexteaid++);
xar_prop_pset(f, XAR_EA(ret)->prop, "name", name);
diff --git a/xar/lib/ext2.c b/xar/lib/ext2.c
index 2380846..b4ca1b0 100644
--- a/xar/lib/ext2.c
+++ b/xar/lib/ext2.c
@@ -41,6 +41,7 @@
#include "asprintf.h"
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include "xar.h"
#include "arcmod.h"
diff --git a/xar/lib/util.c b/xar/lib/util.c
index 1db2daa..ac0b822 100644
--- a/xar/lib/util.c
+++ b/xar/lib/util.c
@@ -38,6 +38,7 @@
#include "config.h"
#include <stdio.h>
+#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/mount.h>
diff --git a/xar/src/xar_internal.h b/xar/src/xar_internal.h
index b78745c..2e6199e 100644
--- a/xar/src/xar_internal.h
+++ b/xar/src/xar_internal.h
@@ -8,11 +8,7 @@
#ifndef _XAR_INTERNAL_H_
#define _XAR_INTERNAL_H_
-#ifdef XARSIG_BUILDING_WITH_XAR
#include "xar.h"
-#else
-#include <xar/xar.h>
-#endif // XARSIG_BUILDING_WITH_XAR
// Undeprecate these for internal usage
xar_t xar_open(const char *file, int32_t flags) API_AVAILABLE(macos(10.4));
--
2.44.1

View File

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 19:26:14 +0300
Subject: [PATCH 12/19] Fix char signedness for ARM and PowerPC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use signed char explicitly for ARM and PowerPC (defaults to unsigned).
Otherwise -1 integer literal is helpfully converted to char 255…
Derives from https://gitweb.gentoo.org/repo/gentoo.git/plain/app-arch/xar/files/xar-1.8-arm-ppc.patch?id=cc91eb0f86043ae92c10cce55b326244bed3f061
---
xar/lib/b64.c | 2 +-
xar/src/xar.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/xar/lib/b64.c b/xar/lib/b64.c
index 6361acd..4ffc34c 100644
--- a/xar/lib/b64.c
+++ b/xar/lib/b64.c
@@ -59,7 +59,7 @@ typedef enum _B64CommandCodes {
B64_IgnorableCharacter = -1
} B64CommandCodes;
-static char b64revtb[256] = {
+static signed char b64revtb[256] = {
-3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*0-15*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16-31*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /*32-47*/
diff --git a/xar/src/xar.c b/xar/src/xar.c
index 9977e8a..1bceb63 100644
--- a/xar/src/xar.c
+++ b/xar/src/xar.c
@@ -910,7 +910,7 @@ static void print_version() {
int main(int argc, char *argv[]) {
int ret;
char *filename = NULL;
- char command = 0, c;
+ signed char command = 0, c;
char **args;
const char *tocfile = NULL;
int arglen, i, err;
--
2.44.1

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 19:28:09 +0300
Subject: [PATCH 13/19] Enable extended attributes for btrfs
---
xar/lib/linuxattr.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/xar/lib/linuxattr.c b/xar/lib/linuxattr.c
index 58ee6a8..496dd82 100644
--- a/xar/lib/linuxattr.c
+++ b/xar/lib/linuxattr.c
@@ -80,6 +80,10 @@
#define XFS_SUPER_MAGIC 0x58465342
#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__)
struct _linuxattr_context{
@@ -175,6 +179,7 @@ TRYAGAIN:
case JFS_SUPER_MAGIC: fsname = "jfs" ; break;
case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break;
case XFS_SUPER_MAGIC: fsname = "xfs" ; break;
+ case BTRFS_SUPER_MAGIC: fsname = "btrfs" ; break;
default: retval=0; goto BAIL;
};
@@ -236,6 +241,7 @@ int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buf
case JFS_SUPER_MAGIC: fsname = "jfs" ; break;
case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break;
case XFS_SUPER_MAGIC: fsname = "xfs" ; break;
+ case BTRFS_SUPER_MAGIC:fsname = "btrfs" ; break;
};
for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) {
--
2.44.1

View File

@ -0,0 +1,123 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 20:46:31 +0300
Subject: [PATCH 14/19] Fix segfault when copying xattr buffers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
xar_linuxattr_read allocates an internal buffer and incrementally copies
the data to xar_attrcopy_to_heaps inbuf. This change fixes the offset
handling by rewriting xar_linuxattr_read function from scratch (with an
arguably cleaner implementation).
---
xar/lib/linuxattr.c | 68 +++++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 27 deletions(-)
diff --git a/xar/lib/linuxattr.c b/xar/lib/linuxattr.c
index 496dd82..30c85c2 100644
--- a/xar/lib/linuxattr.c
+++ b/xar/lib/linuxattr.c
@@ -97,39 +97,50 @@ struct _linuxattr_context{
#define LINUXATTR_CONTEXT(x) ((struct _linuxattr_context *)(x))
-int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len, void *context) {
-
- if( !LINUXATTR_CONTEXT(context)->buf ) {
- int r;
- LINUXATTR_CONTEXT(context)->bufsz = 1024;
+int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void *inbuf, size_t len, void *context) {
+ void *buf;
+ int bufsz, off, ret;
+ int r;
+
+ buf = LINUXATTR_CONTEXT(context)->buf;
+ bufsz = LINUXATTR_CONTEXT(context)->bufsz;
+ off = LINUXATTR_CONTEXT(context)->off;
+
+ if (buf == NULL) {
+ bufsz = 1024;
AGAIN2:
- LINUXATTR_CONTEXT(context)->buf = malloc(LINUXATTR_CONTEXT(context)->bufsz);
- if(!LINUXATTR_CONTEXT(context)->buf)
- goto AGAIN2;
- memset(LINUXATTR_CONTEXT(context)->buf, 0, LINUXATTR_CONTEXT(context)->bufsz);
- r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, LINUXATTR_CONTEXT(context)->buf, LINUXATTR_CONTEXT(context)->bufsz);
- if( r < 0 ) {
- switch(errno) {
- case ERANGE: LINUXATTR_CONTEXT(context)->bufsz *= 2; free(LINUXATTR_CONTEXT(context)->buf); goto AGAIN2;
- case ENOTSUP: free(LINUXATTR_CONTEXT(context)->buf); return 0;
- default: break;
+ buf = malloc(bufsz);
+ if (!buf) {
+ return -1;
+ }
+ memset(buf, 0, bufsz);
+ r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, buf, bufsz);
+ if (r < 0) {
+ free(buf);
+ switch (errno) {
+ case ERANGE:
+ bufsz *= 2;
+ goto AGAIN2;
+ case ENOTSUP:
+ return 0;
};
return -1;
}
+ LINUXATTR_CONTEXT(context)->buf = buf;
LINUXATTR_CONTEXT(context)->bufsz = r;
+ bufsz = r;
}
- if( (LINUXATTR_CONTEXT(context)->bufsz-LINUXATTR_CONTEXT(context)->off) <= len ) {
- int32_t ret;
- ret = LINUXATTR_CONTEXT(context)->bufsz - LINUXATTR_CONTEXT(context)->off;
- memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, ret);
- LINUXATTR_CONTEXT(context)->off += ret;
- return(ret);
- } else {
- memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, len);
- LINUXATTR_CONTEXT(context)->buf = ((char *)LINUXATTR_CONTEXT(context)->buf) + len;
- return len;
+ ret = bufsz - off;
+ if (ret <= len) {
+ memcpy(inbuf, ((char *)buf) + off, ret);
+ LINUXATTR_CONTEXT(context)->off = bufsz;
+ return ret;
}
+
+ memcpy(inbuf, ((char *)buf) + off, len);
+ LINUXATTR_CONTEXT(context)->off += len;
+ return len;
}
int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
@@ -185,6 +196,7 @@ TRYAGAIN:
for( i=buf; (i-buf) < ret; i += strlen(i)+1 ) {
xar_ea_t e;
+ int rc;
context.bufsz = 0;
context.off = 0;
@@ -194,11 +206,13 @@ TRYAGAIN:
xar_ea_pset(f, e, "fstype", fsname);
context.attrname = i;
context.ea = e;
- if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read,&context) < 0) {
+ rc = XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read, &context);
+ if (context.buf != NULL)
+ free(context.buf);
+ if (rc < 0) {
retval = -1;
goto BAIL;
}
- free(context.buf);
context.attrname = NULL;
}
--
2.44.1

View File

@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 21:04:20 +0300
Subject: [PATCH 15/19] Fix segfault in xar_attrcopy_from_heap
Fixes a nasty segfault crash when extracting files with extended
attributes (and perhaps in other cases).
xar_attrcopy_from_heap (in lib/io.c) must not assume that context is
convertible to DATA_CONTEXT. Without this change, it calls the callback
from the provided context as if it was DATA_CONTEXT, but the context can
actually be other types, e.g. LINUXATTR_CONTEXT.
---
xar/lib/data.c | 9 ++++++++-
xar/lib/io.c | 3 ---
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/xar/lib/data.c b/xar/lib/data.c
index dcb5783..cfb3d58 100644
--- a/xar/lib/data.c
+++ b/xar/lib/data.c
@@ -245,6 +245,13 @@ int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file, char *buffer,
return retval;
}
+static int xar_data_verify_callback(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) {
+ DATA_CONTEXT(context)->total += bsize;
+ if (DATA_CONTEXT(context)->progress)
+ DATA_CONTEXT(context)->progress(x, f, DATA_CONTEXT(context)->total);
+ return 0;
+}
+
int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p)
{
const char *opt;
@@ -269,5 +276,5 @@ int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p)
if (!tmpp) // It appears that xar can have truely empty files, aka, no data. We should just fail to verify these files.
return 0; // After all, the checksum of blank is meaningless. So, failing to do so will cause a crash.
- return XAR(x)->attrcopy_from_heap(x, f, tmpp, NULL , (void *)(&context));
+ return XAR(x)->attrcopy_from_heap(x, f, tmpp, xar_data_verify_callback, (void *)(&context));
}
diff --git a/xar/lib/io.c b/xar/lib/io.c
index fb9a72e..64c69af 100644
--- a/xar/lib/io.c
+++ b/xar/lib/io.c
@@ -529,9 +529,6 @@ int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, xar_prop_t p, write_callba
readsofar += bsize;
- if (DATA_CONTEXT(context)->progress)
- DATA_CONTEXT(context)->progress(x, f, readsofar);
-
bsize = def_bsize;
}
--
2.44.1

View File

@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sun, 28 Jul 2024 12:00:01 +0300
Subject: [PATCH 16/19] Do not set property for empty ACL
On Linux, acl_get_file helpfully converts file mode bits to ACL if no
extended attribute is set. See
https://git.savannah.nongnu.org/cgit/acl.git/tree/libacl/acl_get_file.c?id=d9bb1759d4dad2f28a6dcc8c1742ff75d16dd10d#n83
At the same time, Nix sandbox does not filter getxattr syscalls to
return ENOTSUP, but does filter setxattr. So we are in a intricate
situation where acl library thinks that EAs/ACLs are supported and
returns meaningful values for reads, so xar archives files with acl
property, but extraction fails because of the syscall filter.
As a workaround, we add acl_extended_file check that actually returns
whether the file is associated with ACLs (internally represented as
extended attributes).
---
xar/configure.ac | 5 ++---
xar/include/config.h.in | 2 ++
xar/lib/stat.c | 9 +++++++++
3 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/xar/configure.ac b/xar/configure.ac
index e466ee0..c3d9ff7 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -180,9 +180,8 @@ fi
)
AC_SUBST([enable_autogen])
-AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/acl.h>], [acl_t a], [AC_DEFINE([HAVE_SYS_ACL_H],[1], [define if you have sys/acl.h and it has a working acl_t type])])
-AC_CHECK_HEADERS(ext2fs/ext2_fs.h sys/statfs.h sys/vfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h)
+AC_CHECK_HEADERS(sys/acl.h acl/libacl.h ext2fs/ext2_fs.h sys/statfs.h sys/vfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h)
+AC_CHECK_DECLS([acl_extended_file], [], [], [[#include <acl/libacl.h>]])
AC_CHECK_FUNCS(lgetxattr)
AC_CHECK_FUNCS(lsetxattr)
AC_CHECK_FUNCS(getxattr)
diff --git a/xar/include/config.h.in b/xar/include/config.h.in
index 16c72d3..779f5aa 100644
--- a/xar/include/config.h.in
+++ b/xar/include/config.h.in
@@ -3,6 +3,7 @@
#undef HAVE_SYS_XATTR_H
#undef HAVE_SYS_EXTATTR_H
#undef HAVE_SYS_PARAM_H
+#undef HAVE_DECL_ACL_EXTENDED_FILE
#undef HAVE_LGETXATTR
#undef HAVE_LSETXATTR
#undef HAVE_GETXATTR
@@ -12,6 +13,7 @@
#undef HAVE_CHFLAGS
#undef HAVE_STATVFS
#undef HAVE_STATFS
+#undef HAVE_ACL_LIBACL_H
#undef HAVE_EXT2FS_EXT2_FS_H
#undef HAVE_STRUCT_STAT_ST_FLAGS
#undef HAVE_STRUCT_STATVFS_F_FSTYPENAME
diff --git a/xar/lib/stat.c b/xar/lib/stat.c
index b0cce7c..81771dc 100644
--- a/xar/lib/stat.c
+++ b/xar/lib/stat.c
@@ -66,6 +66,9 @@
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#ifdef HAVE_ACL_LIBACL_H
+#include <acl/libacl.h>
+#endif
#include "xar.h"
#include "arcmod.h"
#include "archive.h"
@@ -131,6 +134,12 @@ static int32_t aacls(xar_t x, xar_file_t f, const char *file) {
if( !xar_check_prop(x, "acl") )
return 0;
+#ifdef HAVE_DECL_ACL_EXTENDED_FILE
+ /* Do nothing if the file is not associated with ACL. */
+ if( !acl_extended_file(file) )
+ return 0;
+#endif
+
a = acl_get_file(file, ACL_TYPE_DEFAULT);
if( a ) {
char *t;
--
2.44.1

View File

@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Tue, 30 Jul 2024 16:06:57 +0300
Subject: [PATCH 17/19] Fix time format for musl
Directive %F is not supported in musl (until recent versions).
https://git.musl-libc.org/cgit/musl/commit/src/time/strptime.c?id=fced99e93daeefb0192fd16304f978d4401d1d77
Avoid using it for str[fp]time.
---
xar/lib/stat.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/xar/lib/stat.c b/xar/lib/stat.c
index 81771dc..d71a613 100644
--- a/xar/lib/stat.c
+++ b/xar/lib/stat.c
@@ -82,6 +82,8 @@
#define LLONG_MAX LONG_LONG_MAX
#endif
+static const char time_format[] = "%Y-%m-%dT%H:%M:%SZ";
+
static struct {
const char *name;
mode_t type;
@@ -513,24 +515,21 @@ int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *bu
if( xar_check_prop(x, "atime") ) {
gmtime_r(&XAR(x)->sbcache.st_atime, &t);
memset(time, 0, sizeof(time));
- strftime(time, sizeof(time), "%FT%T", &t);
- strcat(time, "Z");
+ strftime(time, sizeof(time), time_format, &t);
xar_prop_set(f, "atime", time);
}
if( xar_check_prop(x, "mtime") ) {
gmtime_r(&XAR(x)->sbcache.st_mtime, &t);
memset(time, 0, sizeof(time));
- strftime(time, sizeof(time), "%FT%T", &t);
- strcat(time, "Z");
+ strftime(time, sizeof(time), time_format, &t);
xar_prop_set(f, "mtime", time);
}
if( xar_check_prop(x, "ctime") ) {
gmtime_r(&XAR(x)->sbcache.st_ctime, &t);
memset(time, 0, sizeof(time));
- strftime(time, sizeof(time), "%FT%T", &t);
- strcat(time, "Z");
+ strftime(time, sizeof(time), time_format, &t);
xar_prop_set(f, "ctime", time);
}
@@ -680,7 +679,7 @@ int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size
xar_prop_get(f, "atime", &timestr);
if( timestr ) {
memset(&t, 0, sizeof(t));
- strptime(timestr, "%FT%T", &t);
+ strptime(timestr, time_format, &t);
tv[ATIME].tv_sec = timegm(&t);
} else {
tv[ATIME].tv_sec = time(NULL);
@@ -689,7 +688,7 @@ int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size
xar_prop_get(f, "mtime", &timestr);
if( timestr ) {
memset(&t, 0, sizeof(t));
- strptime(timestr, "%FT%T", &t);
+ strptime(timestr, time_format, &t);
tv[MTIME].tv_sec = timegm(&t);
} else {
tv[MTIME].tv_sec = time(NULL);
--
2.44.1

View File

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Tue, 30 Jul 2024 17:29:06 +0300
Subject: [PATCH 18/19] Replace memcpy with memmove for musl
---
xar/lib/io.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xar/lib/io.c b/xar/lib/io.c
index 64c69af..c962c4b 100644
--- a/xar/lib/io.c
+++ b/xar/lib/io.c
@@ -650,7 +650,7 @@ static int32_t flush_stream(xar_stream *stream) {
state->pending_buf = NULL;
} else if( state->pending_buf_size > len ) {
state->pending_buf_size -= len;
- memcpy(state->pending_buf, state->pending_buf + len, state->pending_buf_size);
+ memmove(state->pending_buf, state->pending_buf + len, state->pending_buf_size);
}
}
--
2.44.1

View File

@ -0,0 +1,150 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 24 Aug 2024 10:44:09 +0300
Subject: [PATCH 19/19] Prefer OpenSSL over CommonCrypto if available
In Nixpkgs, we always have OpenSSL input available, so it makes sense to
prefer it over the CommonCrypto library.
See https://github.com/NixOS/nixpkgs/pull/329721#discussion_r1713492113
---
xar/configure.ac | 5 ++++-
xar/include/config.h.in | 1 +
xar/lib/archive.h | 6 ------
xar/lib/hash.c | 20 +++++++++++---------
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/xar/configure.ac b/xar/configure.ac
index c3d9ff7..f7626bf 100644
--- a/xar/configure.ac
+++ b/xar/configure.ac
@@ -299,9 +299,12 @@ dnl
have_openssl="1"
AC_CHECK_HEADERS([openssl/evp.h], , [have_openssl="0"])
AC_CHECK_LIB([crypto], [OPENSSL_config], , [have_openssl="0"])
-if test "x${have_openssl}" = "x0" ; then
+if test "x${have_openssl}" = "x1" ; then
+ AC_DEFINE([HAVE_OPENSSL], [], [HAVE_OPENSSL])
+else
case "${host}" in
*-*-darwin*)
+ # Darwin uses CommonCrypto if OpenSSL is not available.
;;
*)
AC_MSG_ERROR([Cannot build without OpenSSL for non-Darwin host])
diff --git a/xar/include/config.h.in b/xar/include/config.h.in
index 779f5aa..dd44002 100644
--- a/xar/include/config.h.in
+++ b/xar/include/config.h.in
@@ -24,6 +24,7 @@
#undef HAVE_LIBUTIL_H
#undef HAVE_LIBPTHREAD
#undef HAVE_ASPRINTF
+#undef HAVE_OPENSSL
#undef HAVE_LIBBZ2
#undef HAVE_LIBLZMA
#undef HAVE_LCHOWN
diff --git a/xar/lib/archive.h b/xar/lib/archive.h
index f926245..8743120 100644
--- a/xar/lib/archive.h
+++ b/xar/lib/archive.h
@@ -40,12 +40,6 @@
#define _XAR_ARCHIVE_H_
#include <zlib.h>
#include <libxml/hash.h>
-#ifdef __APPLE__
-#include <CommonCrypto/CommonDigest.h>
-#include <CommonCrypto/CommonDigestSPI.h>
-#else
-#include <openssl/evp.h>
-#endif
#include <sys/types.h>
#include <sys/stat.h>
#include "xar.h"
diff --git a/xar/lib/hash.c b/xar/lib/hash.c
index cb4f6cf..b99eca9 100644
--- a/xar/lib/hash.c
+++ b/xar/lib/hash.c
@@ -41,7 +41,10 @@
#include <string.h>
#include <sys/types.h>
#include <zlib.h>
-#ifdef __APPLE__
+
+#include "config.h"
+
+#if !defined(HAVE_OPENSSL)
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
#else
@@ -50,7 +53,6 @@
#include "xar.h"
#include "hash.h"
-#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
@@ -58,7 +60,7 @@
#pragma mark Hash Wrapper Object
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
CCDigestRef digestRef_from_name(const char* name, unsigned int *outHashSize) {
CCDigestRef result = NULL;
@@ -88,13 +90,13 @@ CCDigestRef digestRef_from_name(const char* name, unsigned int *outHashSize) {
return result;
}
-#endif // __APPLE__
+#endif // !defined(HAVE_OPENSSL)
struct __xar_hash_t {
const char *digest_name;
void *context;
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
CCDigestRef digest;
#else
EVP_MD_CTX *digest;
@@ -113,7 +115,7 @@ xar_hash_t xar_hash_new(const char *digest_name, void *context) {
if( context )
HASH_CTX(hash)->context = context;
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
HASH_CTX(hash)->digest = digestRef_from_name(digest_name, &HASH_CTX(hash)->length);
#else
OpenSSL_add_all_digests();
@@ -136,7 +138,7 @@ const char *xar_hash_get_digest_name(xar_hash_t hash) {
}
void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte) {
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
CCDigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte);
#else
EVP_DigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte);
@@ -144,7 +146,7 @@ void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte) {
}
void *xar_hash_finish(xar_hash_t hash, size_t *nbyte) {
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
void *buffer = calloc(1, CC_SHA512_DIGEST_LENGTH); // current biggest digest size This is what OpenSSL uses
#else
void *buffer = calloc(1, EVP_MAX_MD_SIZE);
@@ -152,7 +154,7 @@ void *xar_hash_finish(xar_hash_t hash, size_t *nbyte) {
if( ! buffer )
return NULL;
-#ifdef __APPLE__
+#if !defined(HAVE_OPENSSL)
CCDigestFinal(HASH_CTX(hash)->digest, buffer);
CCDigestDestroy(HASH_CTX(hash)->digest);
#else
--
2.44.1

View File

@ -2331,7 +2331,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
openpam
openssl.out
patch
xar
xar.lib
xz.bin
xz.out
zlib.dev

View File

@ -1,49 +0,0 @@
{ lib, stdenv, fetchurl, pkg-config, libxml2, xz, openssl, zlib, bzip2, fts, autoreconfHook }:
stdenv.mkDerivation rec {
version = "1.6.1";
pname = "xar";
src = fetchurl {
url = "https://github.com/downloads/mackyle/xar/${pname}-${version}.tar.gz";
sha256 = "0ghmsbs6xwg1092v7pjcibmk5wkyifwxw6ygp08gfz25d2chhipf";
};
nativeBuildInputs = [ autoreconfHook pkg-config ];
buildInputs = [ libxml2 xz openssl zlib bzip2 fts ];
patches = [
./0001-Add-useless-descriptions-to-AC_DEFINE.patch
./0002-Use-pkg-config-for-libxml2.patch
];
postPatch = ''
substituteInPlace configure.ac \
--replace 'OpenSSL_add_all_ciphers' 'OPENSSL_init_crypto' \
--replace 'openssl/evp.h' 'openssl/crypto.h'
'';
configureFlags = lib.optional (fts != null) "LDFLAGS=-lfts";
meta = {
homepage = "https://mackyle.github.io/xar/";
description = "Extensible Archiver";
longDescription =
'' The XAR project aims to provide an easily extensible archive format.
Important design decisions include an easily extensible XML table of
contents for random access to archived files, storing the toc at the
beginning of the archive to allow for efficient handling of streamed
archives, the ability to handle files of arbitrarily large sizes, the
ability to choose independent encodings for individual files in the
archive, the ability to store checksums for individual files in both
compressed and uncompressed form, and the ability to query the table
of content's rich meta-data.
'';
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [ copumpkin ];
platforms = lib.platforms.all;
mainProgram = "xar";
};
}

View File

@ -14082,8 +14082,6 @@ with pkgs;
vul = callPackage ../applications/misc/vul { };
xar = callPackage ../tools/compression/xar { };
xarchive = callPackage ../tools/archivers/xarchive { };
xarchiver = callPackage ../tools/archivers/xarchiver { };