Merge pull request #3242 from datauwu/zip-basic-support-0x000d

zip: read PKWARE Unix extra field metadata
(cherry picked from commit f7965ac947)
This commit is contained in:
Tim Kientzle authored and Martin Matuska committed 2026-07-26 20:17:39 +02:00
1 parent 69e9ab7548
commit 3de8f12efd
4 files changed
+88

No files matched your search

+1
View File
@@ -1126,6 +1126,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_zip_padded1.zip.uu \
libarchive/test/test_read_format_zip_padded2.zip.uu \
libarchive/test/test_read_format_zip_padded3.zip.uu \
libarchive/test/test_read_format_zip_pkware_unix.zip.uu \
libarchive/test/test_read_format_zip_ppmd8.zipx.uu \
libarchive/test/test_read_format_zip_ppmd8_aes256_streaming.zipx.uu \
libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu \
@@ -756,6 +756,22 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
* on which file starts, but we don't handle
* multi-volume Zip files. */
break;
case 0x000d:
/* PKWARE Unix Extra Field fixed metadata. */
if (datasize >= 12) {
zip_entry->atime = archive_le32dec(p + offset);
zip_entry->mtime =
archive_le32dec(p + offset + 4);
zip_entry->uid =
archive_le16dec(p + offset + 8);
zip_entry->gid =
archive_le16dec(p + offset + 10);
/*
* APPNOTE.TXT also defines additional data after
* this fixed metadata, depending on file type.
*/
}
break;
#ifdef DEBUG
case 0x0017:
{
+64
View File
@@ -271,6 +271,69 @@ test_info_zip_ux(void)
free(p);
}
/*
* Read PKWARE Unix Extra Field 0x000d.
*/
static void
verify_pkware_unix(struct archive *a, int seek_checks)
{
struct archive_entry *ae;
char buff[8];
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("file1", archive_entry_pathname(ae));
assertEqualInt(1300668680, archive_entry_mtime(ae));
assertEqualInt(1300668670, archive_entry_atime(ae));
assertEqualInt(6, archive_entry_size(ae));
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
if (seek_checks)
assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
failure("zip reader should read PKWARE Unix Extra Field");
assertEqualInt(1001, archive_entry_uid(ae));
assertEqualInt(1002, archive_entry_gid(ae));
assertEqualInt(6, archive_read_data(a, buff, sizeof(buff)));
assertEqualMem(buff, "hello\n", 6);
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
/* Verify the number of files read. */
failure("the archive file has just one file");
assertEqualInt(1, archive_file_count(a));
assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
static void
test_pkware_unix(void)
{
const char *refname = "test_read_format_zip_pkware_unix.zip";
struct archive *a;
char *p;
size_t s;
extract_reference_file(refname);
/* Verify with seeking reader. */
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_filename(a, refname, 10240));
verify_pkware_unix(a, 1);
/* Verify with streaming reader. */
p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
verify_pkware_unix(a, 0);
free(p);
}
/*
* Verify that test_read_extract correctly works with
* Zip entries that use length-at-end.
@@ -377,6 +440,7 @@ DEFINE_TEST(test_read_format_zip)
{
test_basic();
test_info_zip_ux();
test_pkware_unix();
test_extract_length_at_end();
test_symlink();
}
@@ -0,0 +1,7 @@
begin 644 test_read_format_zip_pkware_unix.zip
M4$L#!!0 =3X@,#HV!@ 8 % ! 9FEL93$- P _J"&30BA
MADWI ^H#:&5L;&\*4$L! A0#% !U/B P.C8& !@ 4 $```
M *2! &9I;&4Q#0 , /Z@ADT(H89-Z0/J U!+!08 0 !
+ $, Y````````
`
end