mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-25 16:33:15 +00:00
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:
parent
4c2e720a58
commit
5eee6cf40a
178
pkgs/by-name/xa/xar/package.nix
Normal file
178
pkgs/by-name/xa/xar/package.nix
Normal 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 aren’t
|
||||
# picked up by stdenv’s C compiler wrapper (see ccWrapper_addCVars). This
|
||||
# doesn’t 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";
|
||||
};
|
||||
})
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 doesn’t 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_heap’s 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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", ×tr);
|
||||
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", ×tr);
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
};
|
||||
}
|
@ -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 { };
|
||||
|
Loading…
Reference in New Issue
Block a user