From: Martin Matuska Date: Tue, 3 Dec 2019 00:09:42 +0000 (+0100) Subject: Add the "xattrhdr" option to pax write options. X-Git-Tag: v3.4.1~7^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F1288%2Fhead;p=thirdparty%2Flibarchive.git Add the "xattrhdr" option to pax write options. This allows us to control whether "SCHILY.xattr", "LIBARCHIVE.xattr" or both headers (default) are written when storing extended attributes. Document "hdrcharset" option for pax. --- diff --git a/Makefile.am b/Makefile.am index 6816eb532..6d864fb66 100644 --- a/Makefile.am +++ b/Makefile.am @@ -429,6 +429,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_open_file.c \ libarchive/test/test_open_filename.c \ libarchive/test/test_pax_filename_encoding.c \ + libarchive/test/test_pax_xattr_header.c \ libarchive/test/test_read_data_large.c \ libarchive/test/test_read_disk.c \ libarchive/test/test_read_disk_directory_traversals.c \ @@ -702,6 +703,9 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_fuzz.lzh.uu \ libarchive/test/test_fuzz_1.iso.Z.uu \ libarchive/test/test_pax_filename_encoding.tar.uu \ + libarchive/test/test_pax_xattr_header_all.tar.uu \ + libarchive/test/test_pax_xattr_header_libarchive.tar.uu \ + libarchive/test/test_pax_xattr_header_schily.tar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu \ diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index cf2a1f959..7c5e63bb3 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -199,6 +199,28 @@ archive_write_pax_options(struct archive_write *a, const char *key, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "pax: invalid charset name"); return (ret); + } else if (strcmp(key, "xattrheader") == 0) { + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: xattrheader requires a value"); + } else if (strcmp(val, "ALL") == 0 || + strcmp(val, "all") == 0) { + pax->flags |= WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR; + ret = ARCHIVE_OK; + } else if (strcmp(val, "SCHILY") == 0 || + strcmp(val, "schily") == 0) { + pax->flags |= WRITE_SCHILY_XATTR; + pax->flags &= ~WRITE_LIBARCHIVE_XATTR; + ret = ARCHIVE_OK; + } else if (strcmp(val, "LIBARCHIVE") == 0 || + strcmp(val, "libarchive") == 0) { + pax->flags |= WRITE_LIBARCHIVE_XATTR; + pax->flags &= ~WRITE_SCHILY_XATTR; + ret = ARCHIVE_OK; + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "pax: invalid xattr header name"); + return (ret); } /* Note: The "warn" return is just to inform the options diff --git a/libarchive/archive_write_set_options.3 b/libarchive/archive_write_set_options.3 index a9f70a664..09eb95ea5 100644 --- a/libarchive/archive_write_set_options.3 +++ b/libarchive/archive_write_set_options.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 27, 2019 +.Dd December 3, 2019 .Dt ARCHIVE_WRITE_OPTIONS 3 .Os .Sh NAME @@ -404,6 +404,32 @@ Specifies a filename that should not be compressed when using This option can be provided multiple times to suppress compression on many files. .El +.It Format pax +.Bl -tag -compact -width indent +.It Cm hdrcharset +This sets the character set used for filenames, uname and gname. +The value is one of +.Dq BINARY +or +.Dq UTF-8 . +With +.Dq BINARY +there is no character conversion, with +.Dq UTF-8 +names are converted to UTF-8. +.It Cm xattrheader +When storing extended attributes, this option configures which +headers should be written. The value is one of +.Dq all , +.Dq LIBARCHIVE , +or +.Dq SCHILY . +By default, both +.Dq LIBARCHIVE.xattr +and +.Dq SCHILY.xattr +headers are written. +.El .It Format 7zip .Bl -tag -compact -width indent .It Cm compression diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index b25892565..0822e591d 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -82,6 +82,7 @@ IF(ENABLE_TEST) test_open_file.c test_open_filename.c test_pax_filename_encoding.c + test_pax_xattr_header.c test_read_data_large.c test_read_disk.c test_read_disk_directory_traversals.c diff --git a/libarchive/test/test_pax_xattr_header.c b/libarchive/test/test_pax_xattr_header.c new file mode 100644 index 000000000..d0394aa09 --- /dev/null +++ b/libarchive/test/test_pax_xattr_header.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2019 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +static struct archive_entry* +create_archive_entry(void) { + struct archive_entry *ae; + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 20); + archive_entry_set_ctime(ae, 4, 40); + archive_entry_set_mtime(ae, 5, 50); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + archive_entry_set_nlink(ae, 2); + archive_entry_set_size(ae, 8); + archive_entry_xattr_add_entry(ae, "user.data1", "ABCDEFG", 7); + archive_entry_xattr_add_entry(ae, "user.data2", "XYZ", 3); + + return (ae); +} + +DEFINE_TEST(test_pax_xattr_header) +{ + static const char *reffiles[] = { + "test_pax_xattr_header_all.tar", + "test_pax_xattr_header_libarchive.tar", + "test_pax_xattr_header_schily.tar", + NULL + }; + struct archive *a; + struct archive_entry *ae; + + extract_reference_files(reffiles); + + /* First archive, no options */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualInt(0, + archive_write_open_filename(a, "test1.tar")); + ae = create_archive_entry(); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assertEqualFile("test1.tar","test_pax_xattr_header_all.tar"); + + /* Second archive, xattrheader=SCHILY */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_set_options(a, + "xattrheader=SCHILY")); + assertEqualInt(0, + archive_write_open_filename(a, "test2.tar")); + + ae = create_archive_entry(); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assertEqualFile("test2.tar","test_pax_xattr_header_schily.tar"); + + /* Third archive, xattrheader=LIBARCHIVE */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_set_options(a, + "xattrheader=LIBARCHIVE")); + assertEqualInt(0, + archive_write_open_filename(a, "test3.tar")); + + ae = create_archive_entry(); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assertEqualFile("test3.tar","test_pax_xattr_header_libarchive.tar"); + + /* Fourth archive, xattrheader=ALL */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, 0, archive_write_set_format_pax(a)); + assertEqualIntA(a, 0, archive_write_add_filter_none(a)); + assertEqualIntA(a, 0, archive_write_set_options(a, "xattrheader=ALL")); + assertEqualInt(0, + archive_write_open_filename(a, "test4.tar")); + + ae = create_archive_entry(); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + + assertEqualFile("test4.tar","test_pax_xattr_header_all.tar"); +} diff --git a/libarchive/test/test_pax_xattr_header_all.tar.uu b/libarchive/test/test_pax_xattr_header_all.tar.uu new file mode 100644 index 000000000..086428e71 --- /dev/null +++ b/libarchive/test/test_pax_xattr_header_all.tar.uu @@ -0,0 +1,72 @@ +begin 644 test_pax_xattr_header_all.tar +M4&%X2&5A9&5R+V9I;&4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U