1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2025 Zhaofeng Li
5 * All rights reserved.
6 */
7 #include "test.h"
8
DEFINE_TEST(test_read_format_tar_mac_metadata)9 DEFINE_TEST(test_read_format_tar_mac_metadata)
10 {
11 /*
12 This test tar file is crafted with two files in a specific order:
13
14 1. A ._-prefixed file with pax header containing the path attribute.
15 2. A file with a pax header but without the path attribute.
16
17 It's designed to trigger the case encountered in:
18 <https://github.com/libarchive/libarchive/pull/2636>
19
20 GNU tar is required to reproduce this tar file:
21
22 ```sh
23 NAME1="._101_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
24 NAME2="goodname"
25 OUT="test_read_format_tar_mac_metadata_1.tar"
26
27 echo "content of badname" >"${NAME1}"
28 echo "content of goodname" >"${NAME2}"
29
30 rm -f "${OUT}"
31 gnutar \
32 --mtime="@0" \
33 --owner=0 --group=0 --numeric-owner \
34 --pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0,foo:=bar \
35 --format=pax \
36 -cf "${OUT}" \
37 "${NAME1}" \
38 "${NAME2}"
39 uuencode "${OUT}" "${OUT}" >"${OUT}.uu"
40
41 sha256sum "${OUT}"
42 sha256sum "${OUT}.uu"
43 ```
44 */
45 const char *refname = "test_read_format_tar_mac_metadata_1.tar";
46 char *p;
47 size_t s;
48 struct archive *a;
49 struct archive_entry *ae;
50
51 /*
52 * This is not a valid AppleDouble metadata file. It is merely to test that
53 * the correct bytes are read.
54 */
55 const unsigned char appledouble[] = {
56 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62,
57 0x61, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x0a
58 };
59
60 extract_reference_file(refname);
61 p = slurpfile(&s, "%s", refname);
62
63 assert((a = archive_read_new()) != NULL);
64 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_tar(a));
65 assertEqualIntA(a, ARCHIVE_OK, archive_read_set_option(a, "tar", "mac-ext", "1"));
66 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
67
68 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
69
70 /* Correct name and metadata bytes */
71 assertEqualString("goodname", archive_entry_pathname(ae));
72
73 const void *metadata = archive_entry_mac_metadata(ae, &s);
74 if (assert(metadata != NULL)) {
75 assertEqualMem(metadata, appledouble,
76 sizeof(appledouble));
77 }
78
79 /* ... and nothing else */
80 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
81 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
82 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
83
84 free(p);
85 }
86