summaryrefslogtreecommitdiff
path: root/archivers/libarchive
diff options
context:
space:
mode:
authorjoerg <joerg@pkgsrc.org>2017-08-01 22:21:11 +0000
committerjoerg <joerg@pkgsrc.org>2017-08-01 22:21:11 +0000
commit941762f14ba6415727cdda4c6039ad103c34a479 (patch)
tree80fe5b627eb5287dbe256d01cff629b4ed088ba6 /archivers/libarchive
parent2d98c0c6588efc6b806de1afa47764b89358e2ba (diff)
downloadpkgsrc-941762f14ba6415727cdda4c6039ad103c34a479.tar.gz
Import libarchive-3.3.2 + 9de5f3 + f9dacbf:
- Support NFS4 ACLs on Linux - Bugfixes
Diffstat (limited to 'archivers/libarchive')
-rw-r--r--archivers/libarchive/files/cat/test/CMakeLists.txt10
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_Z_upper.c5
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_b64encode.c2
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_grzip.c3
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_lrzip.c3
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_lz4.c7
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_lzma.c4
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_lzop.c3
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_uuencode.c2
-rw-r--r--archivers/libarchive/files/cpio/test/test_option_xz.c4
-rw-r--r--archivers/libarchive/files/doc/html/archive_read_add_passphrase.3.html2
-rw-r--r--archivers/libarchive/files/doc/html/archive_write_set_passphrase.3.html2
-rw-r--r--archivers/libarchive/files/doc/man/archive_read_format.36
-rw-r--r--archivers/libarchive/files/doc/pdf/archive_read_add_passphrase.3.pdfbin21985 -> 21985 bytes
-rw-r--r--archivers/libarchive/files/doc/pdf/archive_write_set_passphrase.3.pdfbin22237 -> 22237 bytes
-rw-r--r--archivers/libarchive/files/doc/text/archive_read_add_passphrase.3.txt34
-rw-r--r--archivers/libarchive/files/doc/text/archive_write_set_passphrase.3.txt34
-rw-r--r--archivers/libarchive/files/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki6
-rw-r--r--archivers/libarchive/files/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki6
-rw-r--r--archivers/libarchive/files/libarchive/archive_disk_acl_darwin.c559
-rw-r--r--archivers/libarchive/files/libarchive/archive_disk_acl_freebsd.c700
-rw-r--r--archivers/libarchive/files/libarchive/archive_disk_acl_linux.c743
-rw-r--r--archivers/libarchive/files/libarchive/archive_disk_acl_sunos.c821
-rw-r--r--archivers/libarchive/files/libarchive/archive_openssl_hmac_private.h2
-rw-r--r--archivers/libarchive/files/libarchive/archive_platform_acl.h49
-rw-r--r--archivers/libarchive/files/libarchive/archive_platform_xattr.h41
-rw-r--r--archivers/libarchive/files/libarchive/archive_random.c5
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_format.36
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_filter_lz4.c6
-rw-r--r--archivers/libarchive/files/libarchive/archive_version_details.c133
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_add_filter_lz4.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_filter_by_ext.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_warc.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_archive_read_close_twice_open_filename.c4
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c60
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu14
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_zip_compression_store.c15
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_zip_large.c14
-rw-r--r--archivers/libarchive/files/libarchive/test/test_xattr_platform.c104
-rw-r--r--archivers/libarchive/files/libarchive/xxhash.c12
-rw-r--r--archivers/libarchive/files/tar/test/test_option_acls.c510
-rw-r--r--archivers/libarchive/files/tar/test/test_option_fflags.c106
-rw-r--r--archivers/libarchive/files/tar/test/test_option_nodump.c2
-rw-r--r--archivers/libarchive/files/tar/test/test_option_xattrs.c88
-rw-r--r--archivers/libarchive/files/test_utils/test_main.c451
45 files changed, 4496 insertions, 88 deletions
diff --git a/archivers/libarchive/files/cat/test/CMakeLists.txt b/archivers/libarchive/files/cat/test/CMakeLists.txt
index 7f1ce5e77d1..0cd3aad84f4 100644
--- a/archivers/libarchive/files/cat/test/CMakeLists.txt
+++ b/archivers/libarchive/files/cat/test/CMakeLists.txt
@@ -29,6 +29,16 @@ IF(ENABLE_CAT AND ENABLE_TEST)
# Register target
#
ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
+ IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
+ IF(HAVE_LIBACL)
+ LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
+ ENDIF(HAVE_LIBACL)
+ IF(HAVE_LIBRICHACL)
+ LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+ TARGET_LINK_LIBRARIES(bsdcat_test ${TEST_ACL_LIBS})
+ ENDIF(ENABLE_ACL)
SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H)
#
diff --git a/archivers/libarchive/files/cpio/test/test_option_Z_upper.c b/archivers/libarchive/files/cpio/test/test_option_Z_upper.c
index d69a85ea58a..ff388427e37 100644
--- a/archivers/libarchive/files/cpio/test/test_option_Z_upper.c
+++ b/archivers/libarchive/files/cpio/test/test_option_Z_upper.c
@@ -43,17 +43,18 @@ DEFINE_TEST(test_option_Z_upper)
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without compress support");
+ free(p);
return;
}
failure("-Z option is broken");
assertEqualInt(r, 0);
- goto done;
+ free(p);
+ return;
}
free(p);
/* Check that the archive file has a compress signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x1f\x9d", 2);
-done:
free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_b64encode.c b/archivers/libarchive/files/cpio/test/test_option_b64encode.c
index 8f6b4157c01..7c15a823060 100644
--- a/archivers/libarchive/files/cpio/test/test_option_b64encode.c
+++ b/archivers/libarchive/files/cpio/test/test_option_b64encode.c
@@ -42,6 +42,7 @@ DEFINE_TEST(test_option_b64encode)
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "begin-base64 644", 16);
+ free(p);
/* Archive it with uuencode only. */
assertEqualInt(0,
@@ -51,4 +52,5 @@ DEFINE_TEST(test_option_b64encode)
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "begin-base64 644", 16);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_grzip.c b/archivers/libarchive/files/cpio/test/test_option_grzip.c
index dfce2e064e0..7e7dd2c8e6f 100644
--- a/archivers/libarchive/files/cpio/test/test_option_grzip.c
+++ b/archivers/libarchive/files/cpio/test/test_option_grzip.c
@@ -44,9 +44,10 @@ DEFINE_TEST(test_option_grzip)
systemf("echo f | %s -o --grzip >archive.out 2>archive.err",
testprog));
p = slurpfile(&s, "archive.err");
- p[s] = '\0';
+ free(p);
/* Check that the archive file has an grzip signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_lrzip.c b/archivers/libarchive/files/cpio/test/test_option_lrzip.c
index a84f75157a4..8d9c0d576cc 100644
--- a/archivers/libarchive/files/cpio/test/test_option_lrzip.c
+++ b/archivers/libarchive/files/cpio/test/test_option_lrzip.c
@@ -44,9 +44,10 @@ DEFINE_TEST(test_option_lrzip)
systemf("echo f | %s -o --lrzip >archive.out 2>archive.err",
testprog));
p = slurpfile(&s, "archive.err");
- p[s] = '\0';
+ free(p);
/* Check that the archive file has an lzma signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "LRZI\x00", 5);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_lz4.c b/archivers/libarchive/files/cpio/test/test_option_lz4.c
index afd683ddc77..ebd376736f4 100644
--- a/archivers/libarchive/files/cpio/test/test_option_lz4.c
+++ b/archivers/libarchive/files/cpio/test/test_option_lz4.c
@@ -43,6 +43,7 @@ DEFINE_TEST(test_option_lz4)
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without lz4 support");
+ free(p);
return;
}
/* POSIX permits different handling of the spawnp
@@ -52,6 +53,7 @@ DEFINE_TEST(test_option_lz4)
if (strstr(p, "Can't launch") != NULL && !canLz4()) {
skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
+ free(p);
return;
}
/* Some systems successfully spawn the new process,
@@ -61,6 +63,7 @@ DEFINE_TEST(test_option_lz4)
if (strstr(p, "Can't write") != NULL && !canLz4()) {
skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
+ free(p);
return;
}
/* On some systems the error won't be detected until closing
@@ -68,14 +71,18 @@ DEFINE_TEST(test_option_lz4)
if (strstr(p, "Error closing") != NULL && !canLz4()) {
skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
+ free(p);
return;
}
failure("--lz4 option is broken: %s", p);
+ free(p);
assertEqualInt(r, 0);
return;
}
+ free(p);
/* Check that the archive file has an lz4 signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x04\x22\x4d\x18", 4);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_lzma.c b/archivers/libarchive/files/cpio/test/test_option_lzma.c
index c6e33530150..b7cad3d1e99 100644
--- a/archivers/libarchive/files/cpio/test/test_option_lzma.c
+++ b/archivers/libarchive/files/cpio/test/test_option_lzma.c
@@ -43,14 +43,18 @@ DEFINE_TEST(test_option_lzma)
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without lzma support");
+ free(p);
return;
}
failure("--lzma option is broken");
assertEqualInt(r, 0);
+ free(p);
return;
}
+ free(p);
/* Check that the archive file has an lzma signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x5d\00\00", 3);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_lzop.c b/archivers/libarchive/files/cpio/test/test_option_lzop.c
index 9f1666e9c5b..aa40ef5b639 100644
--- a/archivers/libarchive/files/cpio/test/test_option_lzop.c
+++ b/archivers/libarchive/files/cpio/test/test_option_lzop.c
@@ -39,7 +39,7 @@ DEFINE_TEST(test_option_lzop)
r = systemf("echo f | %s -o --lzop >archive.out 2>archive.err",
testprog);
p = slurpfile(&s, "archive.err");
- p[s] = '\0';
+ free(p);
if (r != 0) {
if (!canLzop()) {
skipping("lzop is not supported on this platform");
@@ -53,4 +53,5 @@ DEFINE_TEST(test_option_lzop)
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_uuencode.c b/archivers/libarchive/files/cpio/test/test_option_uuencode.c
index ecf354f8f39..a42a0e03096 100644
--- a/archivers/libarchive/files/cpio/test/test_option_uuencode.c
+++ b/archivers/libarchive/files/cpio/test/test_option_uuencode.c
@@ -42,6 +42,7 @@ DEFINE_TEST(test_option_uuencode)
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "begin 644", 9);
+ free(p);
/* Archive it with uuencode only. */
assertEqualInt(0,
@@ -51,4 +52,5 @@ DEFINE_TEST(test_option_uuencode)
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "begin 644", 9);
+ free(p);
}
diff --git a/archivers/libarchive/files/cpio/test/test_option_xz.c b/archivers/libarchive/files/cpio/test/test_option_xz.c
index 02b5dfaad4a..f0d3b33d45b 100644
--- a/archivers/libarchive/files/cpio/test/test_option_xz.c
+++ b/archivers/libarchive/files/cpio/test/test_option_xz.c
@@ -44,14 +44,18 @@ DEFINE_TEST(test_option_xz)
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without xz support");
+ free(p);
return;
}
+ free(p);
failure("--xz option is broken");
assertEqualInt(r, 0);
return;
}
+ free(p);
/* Check that the archive file has an xz signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6);
+ free(p);
}
diff --git a/archivers/libarchive/files/doc/html/archive_read_add_passphrase.3.html b/archivers/libarchive/files/doc/html/archive_read_add_passphrase.3.html
index 34d7e000b25..3fd4f1cc6a6 100644
--- a/archivers/libarchive/files/doc/html/archive_read_add_passphrase.3.html
+++ b/archivers/libarchive/files/doc/html/archive_read_add_passphrase.3.html
@@ -1,5 +1,5 @@
<!-- Creator : groff version 1.22.3 -->
-<!-- CreationDate: Sat Feb 25 11:22:02 2017 -->
+<!-- CreationDate: Mon Jul 10 02:32:54 2017 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
diff --git a/archivers/libarchive/files/doc/html/archive_write_set_passphrase.3.html b/archivers/libarchive/files/doc/html/archive_write_set_passphrase.3.html
index 9d490d58a8d..04ff2a28c83 100644
--- a/archivers/libarchive/files/doc/html/archive_write_set_passphrase.3.html
+++ b/archivers/libarchive/files/doc/html/archive_write_set_passphrase.3.html
@@ -1,5 +1,5 @@
<!-- Creator : groff version 1.22.3 -->
-<!-- CreationDate: Sat Feb 25 11:22:06 2017 -->
+<!-- CreationDate: Mon Jul 10 02:32:57 2017 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
diff --git a/archivers/libarchive/files/doc/man/archive_read_format.3 b/archivers/libarchive/files/doc/man/archive_read_format.3
index 90d88c83860..548fc001f47 100644
--- a/archivers/libarchive/files/doc/man/archive_read_format.3
+++ b/archivers/libarchive/files/doc/man/archive_read_format.3
@@ -10,9 +10,9 @@
\fB\%archive_read_support_format_empty\fP,
\fB\%archive_read_support_format_iso9660\fP,
\fB\%archive_read_support_format_lha\fP,
-\fB\%archive_read_support_format_mtree,\fP
-\fB\%archive_read_support_format_rar,\fP
-\fB\%archive_read_support_format_raw,\fP
+\fB\%archive_read_support_format_mtree\fP,
+\fB\%archive_read_support_format_rar\fP,
+\fB\%archive_read_support_format_raw\fP,
\fB\%archive_read_support_format_tar\fP,
\fB\%archive_read_support_format_xar\fP,
\fB\%archive_read_support_format_zip\fP
diff --git a/archivers/libarchive/files/doc/pdf/archive_read_add_passphrase.3.pdf b/archivers/libarchive/files/doc/pdf/archive_read_add_passphrase.3.pdf
index 3aa0c7d556c..566e1352c42 100644
--- a/archivers/libarchive/files/doc/pdf/archive_read_add_passphrase.3.pdf
+++ b/archivers/libarchive/files/doc/pdf/archive_read_add_passphrase.3.pdf
Binary files differ
diff --git a/archivers/libarchive/files/doc/pdf/archive_write_set_passphrase.3.pdf b/archivers/libarchive/files/doc/pdf/archive_write_set_passphrase.3.pdf
index 9775e30756d..8aae5a7b5a6 100644
--- a/archivers/libarchive/files/doc/pdf/archive_write_set_passphrase.3.pdf
+++ b/archivers/libarchive/files/doc/pdf/archive_write_set_passphrase.3.pdf
Binary files differ
diff --git a/archivers/libarchive/files/doc/text/archive_read_add_passphrase.3.txt b/archivers/libarchive/files/doc/text/archive_read_add_passphrase.3.txt
index 7e90d7368ed..745ada7c9b4 100644
--- a/archivers/libarchive/files/doc/text/archive_read_add_passphrase.3.txt
+++ b/archivers/libarchive/files/doc/text/archive_read_add_passphrase.3.txt
@@ -1,35 +1,35 @@
ARCHIVE_READ_ADD_PASS... BSD Library Functions Manual ARCHIVE_READ_ADD_PASS...
-1mNAME0m
- 1marchive_read_add_passphrase22m, 1marchive_read_set_passphrase_callback 22m— func‐
+NAME
+ archive_read_add_passphrase, archive_read_set_passphrase_callback — func‐
tions for reading encrypted archives
-1mLIBRARY0m
+LIBRARY
Streaming Archive Library (libarchive, -larchive)
-1mSYNOPSIS0m
- 1m#include <archive.h>0m
+SYNOPSIS
+ #include <archive.h>
- 4mint0m
- 1marchive_read_add_passphrase22m(4mstruct24m 4marchive24m 4m*24m, 4mconst24m 4mchar24m 4m*passphrase24m);
+ int
+ archive_read_add_passphrase(struct archive *, const char *passphrase);
- 4mint0m
- 1marchive_read_set_passphrase_callback22m(4mstruct24m 4marchive24m 4m*24m, 4mvoid24m 4m*client_data24m,
- 4marchive_passphrase_callback24m 4m*24m);
+ int
+ archive_read_set_passphrase_callback(struct archive *, void *client_data,
+ archive_passphrase_callback *);
-1mDESCRIPTION0m
- 1marchive_read_add_passphrase22m()
+DESCRIPTION
+ archive_read_add_passphrase()
Register passphrases for reading an encryption archive. If
- 4mpassphrase24m is NULL or empty, this function will do nothing and
- 1mARCHIVE_FAILED 22mwill be returned. Otherwise, 1mARCHIVE_OK 22mwill be
+ passphrase is NULL or empty, this function will do nothing and
+ ARCHIVE_FAILED will be returned. Otherwise, ARCHIVE_OK will be
returned.
- 1marchive_read_set_passphrase_callback22m()
+ archive_read_set_passphrase_callback()
Register callback function that will be invoked to get a
passphrase for decrption after trying all passphrases registered
- by the 1marchive_read_add_passphrase22m() function failed.
+ by the archive_read_add_passphrase() function failed.
-1mSEE ALSO0m
+SEE ALSO
tar(1), libarchive(3), archive_read(3), archive_read_set_options(3)
BSD September 14, 2014 BSD
diff --git a/archivers/libarchive/files/doc/text/archive_write_set_passphrase.3.txt b/archivers/libarchive/files/doc/text/archive_write_set_passphrase.3.txt
index 1cccccd612b..75f5cb9dd0a 100644
--- a/archivers/libarchive/files/doc/text/archive_write_set_passphrase.3.txt
+++ b/archivers/libarchive/files/doc/text/archive_write_set_passphrase.3.txt
@@ -1,35 +1,35 @@
ARCHIVE_WRITE_SET_PAS... BSD Library Functions Manual ARCHIVE_WRITE_SET_PAS...
-1mNAME0m
- 1marchive_write_set_passphrase22m, 1marchive_write_set_passphrase_callback 22m—
+NAME
+ archive_write_set_passphrase, archive_write_set_passphrase_callback —
functions for writing encrypted archives
-1mLIBRARY0m
+LIBRARY
Streaming Archive Library (libarchive, -larchive)
-1mSYNOPSIS0m
- 1m#include <archive.h>0m
+SYNOPSIS
+ #include <archive.h>
- 4mint0m
- 1marchive_write_set_passphrase22m(4mstruct24m 4marchive24m 4m*24m, 4mconst24m 4mchar24m 4m*passphrase24m);
+ int
+ archive_write_set_passphrase(struct archive *, const char *passphrase);
- 4mint0m
- 1marchive_write_set_passphrase_callback22m(4mstruct24m 4marchive24m 4m*24m,
- 4mvoid24m 4m*client_data24m, 4marchive_passphrase_callback24m 4m*24m);
+ int
+ archive_write_set_passphrase_callback(struct archive *,
+ void *client_data, archive_passphrase_callback *);
-1mDESCRIPTION0m
- 1marchive_write_set_passphrase22m()
+DESCRIPTION
+ archive_write_set_passphrase()
Set a passphrase for writing an encryption archive. If
- 4mpassphrase24m is NULL or empty, this function will do nothing and
- 1mARCHIVE_FAILED 22mwill be returned. Otherwise, 1mARCHIVE_OK 22mwill be
+ passphrase is NULL or empty, this function will do nothing and
+ ARCHIVE_FAILED will be returned. Otherwise, ARCHIVE_OK will be
returned.
- 1marchive_write_set_passphrase_callback22m()
+ archive_write_set_passphrase_callback()
Register callback function that will be invoked to get a
passphrase for encrption if the passphrase was not set by the
- 1marchive_write_set_passphrase22m() function.
+ archive_write_set_passphrase() function.
-1mSEE ALSO0m
+SEE ALSO
tar(1), libarchive(3), archive_write(3), archive_write_set_options(3)
BSD September 21, 2014 BSD
diff --git a/archivers/libarchive/files/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki b/archivers/libarchive/files/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki
index 466505c5522..3f70ec9aa61 100644
--- a/archivers/libarchive/files/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki
+++ b/archivers/libarchive/files/doc/wiki/ManPageArchiveReadAddPassphrase3.wiki
@@ -37,6 +37,6 @@ function failed.
</dd></dl>
== SEE ALSO ==
[[ManPageBsdtar1]],
-[[ManPageLibarchive3]],
-[[ManPageArchiveRead3]],
-[[ManPageArchiveReadSetOptions3]]
+[[ManPageibarchive3]],
+[[ManPagerchiveead3]],
+[[ManPagerchiveeadetptions3]]
diff --git a/archivers/libarchive/files/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki b/archivers/libarchive/files/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki
index 4f6a97cc846..ec9791d8fbf 100644
--- a/archivers/libarchive/files/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki
+++ b/archivers/libarchive/files/doc/wiki/ManPageArchiveWriteSetPassphrase3.wiki
@@ -37,6 +37,6 @@ function.
</dd></dl>
== SEE ALSO ==
[[ManPageBsdtar1]],
-[[ManPageLibarchive3]],
-[[ManPageArchiveWrite3]],
-[[ManPageArchiveWriteSetOptions3]]
+[[ManPageibarchive3]],
+[[ManPagerchiverite3]],
+[[ManPagerchiveriteetptions3]]
diff --git a/archivers/libarchive/files/libarchive/archive_disk_acl_darwin.c b/archivers/libarchive/files/libarchive/archive_disk_acl_darwin.c
new file mode 100644
index 00000000000..48ad0165126
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_disk_acl_darwin.c
@@ -0,0 +1,559 @@
+/*-
+ * Copyright (c) 2017 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 "archive_platform.h"
+
+#if ARCHIVE_ACL_DARWIN
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_MEMBERSHIP_H
+#include <membership.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#define _ACL_PRIVATE /* For debugging */
+#include <sys/acl.h>
+#endif
+
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_read_disk_private.h"
+#include "archive_write_disk_private.h"
+
+typedef struct {
+ const int a_perm; /* Libarchive permission or flag */
+ const int p_perm; /* Platform permission or flag */
+} acl_perm_map_t;
+
+static const acl_perm_map_t acl_nfs4_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+#if HAVE_DECL_ACL_SYNCHRONIZE
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#endif
+};
+
+static const int acl_nfs4_perm_map_size =
+ (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
+
+static const acl_perm_map_t acl_nfs4_flag_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+};
+
+static const int acl_nfs4_flag_map_size =
+ (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
+
+static int translate_guid(struct archive *a, acl_entry_t acl_entry,
+ int *ae_id, int *ae_tag, const char **ae_name)
+{
+ void *q;
+ uid_t ugid;
+ int r, idtype;
+
+ q = acl_get_qualifier(acl_entry);
+ if (q == NULL)
+ return (1);
+ r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
+ if (r != 0) {
+ acl_free(q);
+ return (1);
+ }
+ if (idtype == ID_TYPE_UID) {
+ *ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ *ae_id = ugid;
+ *ae_name = archive_read_disk_uname(a, *ae_id);
+ } else if (idtype == ID_TYPE_GID) {
+ *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ *ae_id = ugid;
+ *ae_name = archive_read_disk_gname(a, *ae_id);
+ } else
+ r = 1;
+
+ acl_free(q);
+ return (r);
+}
+
+static void
+add_trivial_nfs4_acl(struct archive_entry *entry)
+{
+ mode_t mode;
+ int i;
+ const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
+ const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA;
+ const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
+ const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+ const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+
+ struct {
+ const int type;
+ const int tag;
+ int permset;
+ } tacl_entry[] = {
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
+ };
+
+ mode = archive_entry_mode(entry);
+
+ /* Permissions for everyone@ */
+ if (mode & 0004)
+ tacl_entry[5].permset |= rperm;
+ if (mode & 0002)
+ tacl_entry[5].permset |= wperm;
+ if (mode & 0001)
+ tacl_entry[5].permset |= eperm;
+
+ /* Permissions for group@ */
+ if (mode & 0040)
+ tacl_entry[4].permset |= rperm;
+ else if (mode & 0004)
+ tacl_entry[2].permset |= rperm;
+ if (mode & 0020)
+ tacl_entry[4].permset |= wperm;
+ else if (mode & 0002)
+ tacl_entry[2].permset |= wperm;
+ if (mode & 0010)
+ tacl_entry[4].permset |= eperm;
+ else if (mode & 0001)
+ tacl_entry[2].permset |= eperm;
+
+ /* Permissions for owner@ */
+ if (mode & 0400) {
+ tacl_entry[3].permset |= rperm;
+ if (!(mode & 0040) && (mode & 0004))
+ tacl_entry[0].permset |= rperm;
+ } else if ((mode & 0040) || (mode & 0004))
+ tacl_entry[1].permset |= rperm;
+ if (mode & 0200) {
+ tacl_entry[3].permset |= wperm;
+ if (!(mode & 0020) && (mode & 0002))
+ tacl_entry[0].permset |= wperm;
+ } else if ((mode & 0020) || (mode & 0002))
+ tacl_entry[1].permset |= wperm;
+ if (mode & 0100) {
+ tacl_entry[3].permset |= eperm;
+ if (!(mode & 0010) && (mode & 0001))
+ tacl_entry[0].permset |= eperm;
+ } else if ((mode & 0010) || (mode & 0001))
+ tacl_entry[1].permset |= eperm;
+
+ for (i = 0; i < 6; i++) {
+ if (tacl_entry[i].permset != 0) {
+ archive_entry_acl_add_entry(entry,
+ tacl_entry[i].type, tacl_entry[i].permset,
+ tacl_entry[i].tag, -1, NULL);
+ }
+ }
+
+ return;
+}
+
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t acl)
+{
+ acl_tag_t acl_tag;
+ acl_flagset_t acl_flagset;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ int i, entry_acl_type;
+ int r, s, ae_id, ae_tag, ae_perm;
+ const char *ae_name;
+
+ s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get first ACL entry");
+ return (ARCHIVE_WARN);
+ }
+
+ while (s == 0) {
+ ae_id = -1;
+ ae_name = NULL;
+ ae_perm = 0;
+
+ if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL tag type");
+ return (ARCHIVE_WARN);
+ }
+ switch (acl_tag) {
+ case ACL_EXTENDED_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ r = translate_guid(&a->archive, acl_entry,
+ &ae_id, &ae_tag, &ae_name);
+ break;
+ case ACL_EXTENDED_DENY:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ r = translate_guid(&a->archive, acl_entry,
+ &ae_id, &ae_tag, &ae_name);
+ break;
+ default:
+ /* Skip types that libarchive can't support. */
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+
+ /* Skip if translate_guid() above failed */
+ if (r != 0) {
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+
+ /*
+ * Libarchive stores "flag" (NFSv4 inheritance bits)
+ * in the ae_perm bitmap.
+ *
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get flagset from a NFSv4 ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ r = acl_get_flag_np(acl_flagset,
+ acl_nfs4_flag_map[i].p_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check flag in a NFSv4 "
+ "ACL flagset");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= acl_nfs4_flag_map[i].a_perm;
+ }
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL permission set");
+ return (ARCHIVE_WARN);
+ }
+
+ for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
+ /*
+ * acl_get_perm() is spelled differently on different
+ * platforms; see above.
+ */
+ r = acl_get_perm_np(acl_permset,
+ acl_nfs4_perm_map[i].p_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check permission in an ACL "
+ "permission set");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= acl_nfs4_perm_map[i].a_perm;
+ }
+
+#if !HAVE_DECL_ACL_SYNCHRONIZE
+ /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
+ ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+#endif
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag,
+ ae_id, ae_name);
+
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+set_acl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl,
+ int ae_requested_type, const char *tname)
+{
+ acl_t acl;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ acl_flagset_t acl_flagset;
+ int ret;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ uuid_t ae_uuid;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+
+ if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ errno = ENOENT;
+ archive_set_error(a, errno, "Unsupported ACL type");
+ return (ARCHIVE_FAILED);
+ }
+
+ acl = acl_init(entries);
+ if (acl == (acl_t)NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize ACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+ /*
+ * Mac OS doesn't support NFSv4 ACLs for
+ * owner@, group@ and everyone@.
+ * We skip any of these ACLs found.
+ */
+ if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
+ ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
+ ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
+ continue;
+
+ if (acl_create_entry(&acl, &acl_entry) != 0) {
+ archive_set_error(a, errno,
+ "Failed to create a new ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
+ break;
+ default:
+ /* We don't support any other types on MacOS */
+ continue;
+ }
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get ACL permission set");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_perms(acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear ACL permissions");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
+ if (ae_permset & acl_nfs4_perm_map[i].a_perm) {
+ if (acl_add_perm(acl_permset,
+ acl_nfs4_perm_map[i].p_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add ACL permission");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ }
+ }
+
+ /*
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get flagset from an NFSv4 ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_flags_np(acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear flags from an NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
+ if (acl_add_flag_np(acl_flagset,
+ acl_nfs4_flag_map[i].p_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add flag to "
+ "NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ }
+ }
+ }
+
+ if (fd >= 0) {
+ if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0)
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set acl on fd: %s", tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+ } else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set acl: %s",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
+ acl_free(acl);
+ return (ret);
+}
+
+int
+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ const char *accpath;
+ acl_t acl;
+ int r;
+
+ accpath = NULL;
+
+ if (*fd < 0) {
+ accpath = archive_read_disk_entry_setup_path(a, entry, fd);
+ if (accpath == NULL)
+ return (ARCHIVE_WARN);
+ }
+
+ archive_entry_acl_clear(entry);
+
+ acl = NULL;
+
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED);
+ else if (!a->follow_symlinks)
+ acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED);
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_EXTENDED);
+
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl);
+ acl_free(acl);
+ acl = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate NFSv4 ACLs");
+ }
+
+ /*
+ * Because Mac OS doesn't support owner@, group@ and everyone@
+ * ACLs we need to add NFSv4 ACLs mirroring the file mode to
+ * the archive entry. Otherwise extraction on non-Mac platforms
+ * would lead to an invalid file mode.
+ */
+ if ((archive_entry_acl_types(entry) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ add_trivial_nfs4_acl(entry);
+
+ return (r);
+ }
+ return (ARCHIVE_OK);
+}
+
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode)
+{
+ int ret = ARCHIVE_OK;
+
+ (void)mode; /* UNUSED */
+
+ if ((archive_acl_types(abstract_acl) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
+ }
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_DARWIN */
diff --git a/archivers/libarchive/files/libarchive/archive_disk_acl_freebsd.c b/archivers/libarchive/files/libarchive/archive_disk_acl_freebsd.c
new file mode 100644
index 00000000000..07d08ff962f
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_disk_acl_freebsd.c
@@ -0,0 +1,700 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2017 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 "archive_platform.h"
+
+#if ARCHIVE_ACL_FREEBSD
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#define _ACL_PRIVATE /* For debugging */
+#include <sys/acl.h>
+#endif
+
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_read_disk_private.h"
+#include "archive_write_disk_private.h"
+
+typedef struct {
+ const int a_perm; /* Libarchive permission or flag */
+ const int p_perm; /* Platform permission or flag */
+} acl_perm_map_t;
+
+static const acl_perm_map_t acl_posix_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+};
+
+static const int acl_posix_perm_map_size =
+ (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+static const acl_perm_map_t acl_nfs4_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+};
+
+static const int acl_nfs4_perm_map_size =
+ (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
+
+static const acl_perm_map_t acl_nfs4_flag_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+};
+
+static const int acl_nfs4_flag_map_size =
+ (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
+#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
+
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
+{
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ int brand;
+ acl_flagset_t acl_flagset;
+ acl_entry_type_t acl_type;
+#endif
+ acl_tag_t acl_tag;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ int i, entry_acl_type, perm_map_size;
+ const acl_perm_map_t *perm_map;
+ int r, s, ae_id, ae_tag, ae_perm;
+ void *q;
+ const char *ae_name;
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
+ // Make sure the "brand" on this ACL is consistent
+ // with the default_entry_acl_type bits provided.
+ if (acl_get_brand_np(acl, &brand) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read ACL brand");
+ return (ARCHIVE_WARN);
+ }
+ switch (brand) {
+ case ACL_BRAND_POSIX:
+ switch (default_entry_acl_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL entry type for POSIX.1e ACL");
+ return (ARCHIVE_WARN);
+ }
+ break;
+ case ACL_BRAND_NFS4:
+ if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL entry type for NFSv4 ACL");
+ return (ARCHIVE_WARN);
+ }
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL brand");
+ return (ARCHIVE_WARN);
+ }
+#endif
+
+ s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get first ACL entry");
+ return (ARCHIVE_WARN);
+ }
+
+ while (s == 1) {
+ ae_id = -1;
+ ae_name = NULL;
+ ae_perm = 0;
+
+ if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL tag type");
+ return (ARCHIVE_WARN);
+ }
+ switch (acl_tag) {
+ case ACL_USER:
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(uid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ }
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case ACL_GROUP:
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(gid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ }
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case ACL_MASK:
+ ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ case ACL_USER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case ACL_GROUP_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case ACL_OTHER:
+ ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ case ACL_EVERYONE:
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ break;
+#endif
+ default:
+ /* Skip types that libarchive can't support. */
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+
+ // XXX acl_type maps to allow/deny/audit/YYYY bits
+ entry_acl_type = default_entry_acl_type;
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /*
+ * acl_get_entry_type_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
+ archive_set_error(&a->archive, errno, "Failed "
+ "to get ACL type from a NFSv4 ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ switch (acl_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
+ default:
+ archive_set_error(&a->archive, errno,
+ "Invalid NFSv4 ACL entry type");
+ return (ARCHIVE_WARN);
+ }
+
+ /*
+ * Libarchive stores "flag" (NFSv4 inheritance bits)
+ * in the ae_perm bitmap.
+ *
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get flagset from a NFSv4 "
+ "ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ r = acl_get_flag_np(acl_flagset,
+ acl_nfs4_flag_map[i].p_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check flag in a NFSv4 "
+ "ACL flagset");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= acl_nfs4_flag_map[i].a_perm;
+ }
+ }
+#endif
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL permission set");
+ return (ARCHIVE_WARN);
+ }
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ perm_map_size = acl_nfs4_perm_map_size;
+ perm_map = acl_nfs4_perm_map;
+ } else {
+#endif
+ perm_map_size = acl_posix_perm_map_size;
+ perm_map = acl_posix_perm_map;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ }
+#endif
+
+ for (i = 0; i < perm_map_size; ++i) {
+ r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check permission in an ACL "
+ "permission set");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= perm_map[i].a_perm;
+ }
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag,
+ ae_id, ae_name);
+
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get next ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+set_acl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl,
+ int ae_requested_type, const char *tname)
+{
+ int acl_type = 0;
+ acl_t acl;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ acl_flagset_t acl_flagset;
+ int r;
+#endif
+ int ret;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ int perm_map_size;
+ const acl_perm_map_t *perm_map;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+
+
+ switch (ae_requested_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ acl_type = ACL_TYPE_ACCESS;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ acl_type = ACL_TYPE_DEFAULT;
+ break;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ acl_type = ACL_TYPE_NFS4;
+ break;
+#endif
+ default:
+ errno = ENOENT;
+ archive_set_error(a, errno, "Unsupported ACL type");
+ return (ARCHIVE_FAILED);
+ }
+
+ acl = acl_init(entries);
+ if (acl == (acl_t)NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize ACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+ if (acl_create_entry(&acl, &acl_entry) != 0) {
+ archive_set_error(a, errno,
+ "Failed to create a new ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ acl_set_tag_type(acl_entry, ACL_USER);
+ acl_set_qualifier(acl_entry, &ae_uid);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ acl_set_tag_type(acl_entry, ACL_GROUP);
+ acl_set_qualifier(acl_entry, &ae_gid);
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ acl_set_tag_type(acl_entry, ACL_USER_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ acl_set_tag_type(acl_entry, ACL_MASK);
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ acl_set_tag_type(acl_entry, ACL_OTHER);
+ break;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ acl_set_tag_type(acl_entry, ACL_EVERYONE);
+ break;
+#endif
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ r = 0;
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ r = acl_set_entry_type_np(acl_entry,
+ ACL_ENTRY_TYPE_ALLOW);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ r = acl_set_entry_type_np(acl_entry,
+ ACL_ENTRY_TYPE_DENY);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ r = acl_set_entry_type_np(acl_entry,
+ ACL_ENTRY_TYPE_AUDIT);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ r = acl_set_entry_type_np(acl_entry,
+ ACL_ENTRY_TYPE_ALARM);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ // These don't translate directly into the system ACL.
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ if (r != 0) {
+ archive_set_error(a, errno,
+ "Failed to set ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get ACL permission set");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_perms(acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear ACL permissions");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ perm_map_size = acl_nfs4_perm_map_size;
+ perm_map = acl_nfs4_perm_map;
+ } else {
+#endif
+ perm_map_size = acl_posix_perm_map_size;
+ perm_map = acl_posix_perm_map;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ }
+#endif
+
+ for (i = 0; i < perm_map_size; ++i) {
+ if (ae_permset & perm_map[i].a_perm) {
+ if (acl_add_perm(acl_permset,
+ perm_map[i].p_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add ACL permission");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ }
+ }
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /*
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get flagset from an NFSv4 "
+ "ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_flags_np(acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear flags from an NFSv4 "
+ "ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
+ if (acl_add_flag_np(acl_flagset,
+ acl_nfs4_flag_map[i].p_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add flag to "
+ "NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ /* Try restoring the ACL through 'fd' if we can. */
+ if (fd >= 0) {
+ if (acl_set_fd_np(fd, acl, acl_type) == 0)
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set acl on fd: %s", tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+ }
+#if HAVE_ACL_SET_LINK_NP
+ else if (acl_set_link_np(name, acl_type, acl) != 0)
+#else
+ /* FreeBSD older than 8.0 */
+ else if (acl_set_file(name, acl_type, acl) != 0)
+#endif
+ {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set acl: %s",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
+ acl_free(acl);
+ return (ret);
+}
+
+int
+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ const char *accpath;
+ acl_t acl;
+ int r;
+
+ accpath = NULL;
+
+ if (*fd < 0) {
+ accpath = archive_read_disk_entry_setup_path(a, entry, fd);
+ if (accpath == NULL)
+ return (ARCHIVE_WARN);
+ }
+
+ archive_entry_acl_clear(entry);
+
+ acl = NULL;
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ /* Try NFSv4 ACL first. */
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
+ else if (!a->follow_symlinks)
+ acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_NFS4);
+
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
+ acl_free(acl);
+ acl = NULL;
+ return (ARCHIVE_OK);
+ }
+
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ acl_free(acl);
+ acl = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate NFSv4 ACLs");
+ }
+
+ return (r);
+ }
+#endif
+
+ /* Retrieve access ACL from file. */
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
+#if HAVE_ACL_GET_LINK_NP
+ else if (!a->follow_symlinks)
+ acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
+#else
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ acl = NULL;
+#endif
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+
+#if HAVE_ACL_IS_TRIVIAL_NP
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
+ acl_free(acl);
+ acl = NULL;
+ }
+#endif
+
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ acl_free(acl);
+ acl = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate access ACLs");
+ return (r);
+ }
+ }
+
+ /* Only directories can have default ACLs. */
+ if (S_ISDIR(archive_entry_mode(entry))) {
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+ acl_free(acl);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate default ACLs");
+ return (r);
+ }
+ }
+ }
+ return (ARCHIVE_OK);
+}
+
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode)
+{
+ int ret = ARCHIVE_OK;
+
+ (void)mode; /* UNUSED */
+
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ }
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+
+ /* Simultaneous POSIX.1e and NFSv4 is not supported */
+ return (ret);
+ }
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ else if ((archive_acl_types(abstract_acl) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
+ }
+#endif
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_FREEBSD */
diff --git a/archivers/libarchive/files/libarchive/archive_disk_acl_linux.c b/archivers/libarchive/files/libarchive/archive_disk_acl_linux.c
new file mode 100644
index 00000000000..3928f3d6faf
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_disk_acl_linux.c
@@ -0,0 +1,743 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2017 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 "archive_platform.h"
+
+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_ACL_LIBACL_H
+#include <acl/libacl.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
+
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_read_disk_private.h"
+#include "archive_write_disk_private.h"
+
+typedef struct {
+ const int a_perm; /* Libarchive permission or flag */
+ const int p_perm; /* Platform permission or flag */
+} acl_perm_map_t;
+
+#if ARCHIVE_ACL_LIBACL
+static const acl_perm_map_t acl_posix_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+};
+
+static const int acl_posix_perm_map_size =
+ (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
+#endif /* ARCHIVE_ACL_LIBACL */
+
+#if ARCHIVE_ACL_LIBRICHACL
+static const acl_perm_map_t acl_nfs4_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
+};
+
+static const int acl_nfs4_perm_map_size =
+ (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
+
+static const acl_perm_map_t acl_nfs4_flag_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
+};
+
+static const int acl_nfs4_flag_map_size =
+ (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+
+#if ARCHIVE_ACL_LIBACL
+/*
+ * Translate POSIX.1e ACLs into libarchive internal structure
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
+{
+ acl_tag_t acl_tag;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ int i, entry_acl_type;
+ int r, s, ae_id, ae_tag, ae_perm;
+ void *q;
+ const char *ae_name;
+
+ s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get first ACL entry");
+ return (ARCHIVE_WARN);
+ }
+
+ while (s == 1) {
+ ae_id = -1;
+ ae_name = NULL;
+ ae_perm = 0;
+
+ if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL tag type");
+ return (ARCHIVE_WARN);
+ }
+ switch (acl_tag) {
+ case ACL_USER:
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(uid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ }
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case ACL_GROUP:
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(gid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ }
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case ACL_MASK:
+ ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ case ACL_USER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case ACL_GROUP_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case ACL_OTHER:
+ ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+ default:
+ /* Skip types that libarchive can't support. */
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+
+ // XXX acl_type maps to allow/deny/audit/YYYY bits
+ entry_acl_type = default_entry_acl_type;
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL permission set");
+ return (ARCHIVE_WARN);
+ }
+
+ for (i = 0; i < acl_posix_perm_map_size; ++i) {
+ r = acl_get_perm(acl_permset,
+ acl_posix_perm_map[i].p_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check permission in an ACL "
+ "permission set");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= acl_posix_perm_map[i].a_perm;
+ }
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag,
+ ae_id, ae_name);
+
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get next ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ }
+ return (ARCHIVE_OK);
+}
+#endif /* ARCHIVE_ACL_LIBACL */
+
+#if ARCHIVE_ACL_LIBRICHACL
+/*
+ * Translate RichACL into libarchive internal ACL
+ */
+static int
+translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,
+ struct richacl *richacl)
+{
+ int ae_id, ae_tag, ae_perm;
+ int entry_acl_type, i;
+ const char *ae_name;
+
+ struct richace *richace;
+
+ richacl_for_each_entry(richace, richacl) {
+ ae_name = NULL;
+ ae_tag = 0;
+ ae_perm = 0;
+ ae_id = -1;
+
+ switch (richace->e_type) {
+ case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case RICHACE_ACCESS_DENIED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ default: /* Unknown entry type, skip */
+ continue;
+ }
+
+ /* Unsupported */
+ if (richace->e_flags & RICHACE_UNMAPPED_WHO)
+ continue;
+
+ if (richace->e_flags & RICHACE_SPECIAL_WHO) {
+ switch (richace->e_id) {
+ case RICHACE_OWNER_SPECIAL_ID:
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case RICHACE_GROUP_SPECIAL_ID:
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case RICHACE_EVERYONE_SPECIAL_ID:
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ break;
+ default: /* Unknown special ID type */
+ continue;
+ }
+ } else {
+ ae_id = richace->e_id;
+ if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ ae_name = archive_read_disk_gname(&a->archive,
+ (gid_t)(richace->e_id));
+ } else {
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ ae_name = archive_read_disk_uname(&a->archive,
+ (uid_t)(richace->e_id));
+ }
+ }
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if ((richace->e_flags &
+ acl_nfs4_flag_map[i].p_perm) != 0)
+ ae_perm |= acl_nfs4_flag_map[i].a_perm;
+ }
+ for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
+ if ((richace->e_mask &
+ acl_nfs4_perm_map[i].p_perm) != 0)
+ ae_perm |=
+ acl_nfs4_perm_map[i].a_perm;
+ }
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag, ae_id, ae_name);
+ }
+ return (ARCHIVE_OK);
+}
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+
+#if ARCHIVE_ACL_LIBRICHACL
+static int
+_richacl_mode_to_mask(short mode)
+{
+ int mask = 0;
+
+ if (mode & S_IROTH)
+ mask |= RICHACE_POSIX_MODE_READ;
+ if (mode & S_IWOTH)
+ mask |= RICHACE_POSIX_MODE_WRITE;
+ if (mode & S_IXOTH)
+ mask |= RICHACE_POSIX_MODE_EXEC;
+
+ return (mask);
+}
+
+static void
+_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)
+{
+ richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);
+ richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);
+ richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);
+}
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+
+#if ARCHIVE_ACL_LIBRICHACL
+static int
+set_richacl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
+ int ae_requested_type, const char *tname)
+{
+ int ae_type, ae_permset, ae_tag, ae_id;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+ int ret;
+ int e = 0;
+ struct richacl *richacl = NULL;
+ struct richace *richace;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+
+ if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ errno = ENOENT;
+ archive_set_error(a, errno, "Unsupported ACL type");
+ return (ARCHIVE_FAILED);
+ }
+
+ richacl = richacl_alloc(entries);
+ if (richacl == NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize RichACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+
+ e = 0;
+
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+ richace = &(richacl->a_entries[e]);
+
+ richace->e_flags = 0;
+ richace->e_mask = 0;
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ richace->e_id = ae_uid;
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ richace->e_id = ae_gid;
+ richace->e_flags |= RICHACE_IDENTIFIER_GROUP;
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ richace->e_flags |= RICHACE_SPECIAL_WHO;
+ richace->e_id = RICHACE_OWNER_SPECIAL_ID;
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ richace->e_flags |= RICHACE_SPECIAL_WHO;
+ richace->e_id = RICHACE_GROUP_SPECIAL_ID;
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ richace->e_flags |= RICHACE_SPECIAL_WHO;
+ richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ richace->e_type =
+ RICHACE_ACCESS_ALLOWED_ACE_TYPE;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ richace->e_type =
+ RICHACE_ACCESS_DENIED_ACE_TYPE;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
+ if (ae_permset & acl_nfs4_perm_map[i].a_perm)
+ richace->e_mask |= acl_nfs4_perm_map[i].p_perm;
+ }
+
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if (ae_permset &
+ acl_nfs4_flag_map[i].a_perm)
+ richace->e_flags |= acl_nfs4_flag_map[i].p_perm;
+ }
+ e++;
+ }
+
+ /* Fill RichACL masks */
+ _richacl_mode_to_masks(richacl, mode);
+
+ if (fd >= 0) {
+ if (richacl_set_fd(fd, richacl) == 0)
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set richacl on fd: %s", tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+ } else if (richacl_set_file(name, richacl) != 0) {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set richacl: %s",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
+ richacl_free(richacl);
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_RICHACL */
+
+#if ARCHIVE_ACL_LIBACL
+static int
+set_acl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl,
+ int ae_requested_type, const char *tname)
+{
+ int acl_type = 0;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+ int ret;
+ acl_t acl = NULL;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+
+ switch (ae_requested_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ acl_type = ACL_TYPE_ACCESS;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ acl_type = ACL_TYPE_DEFAULT;
+ break;
+ default:
+ errno = ENOENT;
+ archive_set_error(a, errno, "Unsupported ACL type");
+ return (ARCHIVE_FAILED);
+ }
+
+ acl = acl_init(entries);
+ if (acl == (acl_t)NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize ACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+
+ if (acl_create_entry(&acl, &acl_entry) != 0) {
+ archive_set_error(a, errno,
+ "Failed to create a new ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ acl_set_tag_type(acl_entry, ACL_USER);
+ acl_set_qualifier(acl_entry, &ae_uid);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ acl_set_tag_type(acl_entry, ACL_GROUP);
+ acl_set_qualifier(acl_entry, &ae_gid);
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ acl_set_tag_type(acl_entry, ACL_USER_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ acl_set_tag_type(acl_entry, ACL_MASK);
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ acl_set_tag_type(acl_entry, ACL_OTHER);
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get ACL permission set");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_perms(acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear ACL permissions");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ for (i = 0; i < acl_posix_perm_map_size; ++i) {
+ if (ae_permset & acl_posix_perm_map[i].a_perm) {
+ if (acl_add_perm(acl_permset,
+ acl_posix_perm_map[i].p_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add ACL permission");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ }
+ }
+
+ }
+
+ if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
+ if (acl_set_fd(fd, acl) == 0)
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set acl on fd: %s", tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+ } else if (acl_set_file(name, acl_type, acl) != 0) {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set acl: %s",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
+ acl_free(acl);
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_LIBACL */
+
+int
+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ const char *accpath;
+ int r;
+#if ARCHIVE_ACL_LIBACL
+ acl_t acl;
+#endif
+#if ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl;
+ mode_t mode;
+#endif
+
+ accpath = NULL;
+ r = ARCHIVE_OK;
+
+ /* For default ACLs we need reachable accpath */
+ if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
+ accpath = archive_read_disk_entry_setup_path(a, entry, fd);
+ if (accpath == NULL)
+ return (ARCHIVE_WARN);
+ }
+
+ archive_entry_acl_clear(entry);
+
+#if ARCHIVE_ACL_LIBACL
+ acl = NULL;
+#endif
+#if ARCHIVE_ACL_LIBRICHACL
+ richacl = NULL;
+#endif
+
+#if ARCHIVE_ACL_LIBRICHACL
+ /* Try NFSv4 ACL first. */
+ if (*fd >= 0)
+ richacl = richacl_get_fd(*fd);
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one */
+ richacl = NULL;
+ else
+ richacl = richacl_get_file(accpath);
+
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ if (richacl != NULL) {
+ mode = archive_entry_mode(entry);
+ if (richacl_equiv_mode(richacl, &mode) == 0) {
+ richacl_free(richacl);
+ richacl = NULL;
+ return (ARCHIVE_OK);
+ }
+ }
+
+ if (richacl != NULL) {
+ r = translate_richacl(a, entry, richacl);
+ richacl_free(richacl);
+ richacl = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate NFSv4 ACLs");
+ }
+
+ return (r);
+ }
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+
+#if ARCHIVE_ACL_LIBACL
+ /* Retrieve access ACL from file. */
+ if (*fd >= 0)
+ acl = acl_get_fd(*fd);
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ acl = NULL;
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ acl_free(acl);
+ acl = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate access ACLs");
+ return (r);
+ }
+ }
+
+ /* Only directories can have default ACLs. */
+ if (S_ISDIR(archive_entry_mode(entry))) {
+ acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
+ if (acl != NULL) {
+ r = translate_acl(a, entry, acl,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+ acl_free(acl);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate default ACLs");
+ return (r);
+ }
+ }
+ }
+#endif /* ARCHIVE_ACL_LIBACL */
+ return (r);
+}
+
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode)
+{
+ int ret = ARCHIVE_OK;
+
+#if !ARCHIVE_ACL_LIBRICHACL
+ (void)mode; /* UNUSED */
+#endif
+
+#if ARCHIVE_ACL_LIBRICHACL
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_richacl(a, fd, name, abstract_acl, mode,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
+ }
+#if ARCHIVE_ACL_LIBACL
+ else
+#endif
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+#if ARCHIVE_ACL_LIBACL
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ }
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+ }
+#endif /* ARCHIVE_ACL_LIBACL */
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */
diff --git a/archivers/libarchive/files/libarchive/archive_disk_acl_sunos.c b/archivers/libarchive/files/libarchive/archive_disk_acl_sunos.c
new file mode 100644
index 00000000000..bc84fd6782f
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_disk_acl_sunos.c
@@ -0,0 +1,821 @@
+/*-
+ * Copyright (c) 2017 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 "archive_platform.h"
+
+#if ARCHIVE_ACL_SUNOS
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#define _ACL_PRIVATE /* For debugging */
+#include <sys/acl.h>
+#endif
+
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_read_disk_private.h"
+#include "archive_write_disk_private.h"
+
+typedef struct {
+ const int a_perm; /* Libarchive permission or flag */
+ const int p_perm; /* Platform permission or flag */
+} acl_perm_map_t;
+
+static const acl_perm_map_t acl_posix_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
+ {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
+ {ARCHIVE_ENTRY_ACL_READ, S_IROTH }
+};
+
+static const int acl_posix_perm_map_size =
+ (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+static const acl_perm_map_t acl_nfs4_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+};
+
+static const int acl_nfs4_perm_map_size =
+ (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
+
+static const acl_perm_map_t acl_nfs4_flag_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+#ifdef ACE_INHERITED_ACE
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#endif
+};
+
+const int acl_nfs4_flag_map_size =
+ (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
+
+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
+
+static void *
+sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
+{
+ int cnt, cntcmd;
+ size_t size;
+ void *aclp;
+
+ if (cmd == GETACL) {
+ cntcmd = GETACLCNT;
+ size = sizeof(aclent_t);
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else if (cmd == ACE_GETACL) {
+ cntcmd = ACE_GETACLCNT;
+ size = sizeof(ace_t);
+ }
+#endif
+ else {
+ errno = EINVAL;
+ *aclcnt = -1;
+ return (NULL);
+ }
+
+ aclp = NULL;
+ cnt = -2;
+
+ while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
+ if (path != NULL)
+ cnt = acl(path, cntcmd, 0, NULL);
+ else
+ cnt = facl(fd, cntcmd, 0, NULL);
+
+ if (cnt > 0) {
+ if (aclp == NULL)
+ aclp = malloc(cnt * size);
+ else
+ aclp = realloc(NULL, cnt * size);
+ if (aclp != NULL) {
+ if (path != NULL)
+ cnt = acl(path, cmd, cnt, aclp);
+ else
+ cnt = facl(fd, cmd, cnt, aclp);
+ }
+ } else {
+ if (aclp != NULL) {
+ free(aclp);
+ aclp = NULL;
+ }
+ break;
+ }
+ }
+
+ *aclcnt = cnt;
+ return (aclp);
+}
+
+/*
+ * Check if acl is trivial
+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
+ */
+static int
+sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
+ int is_dir, int *trivialp)
+{
+#if ARCHIVE_ACL_SUNOS_NFS4
+ int i, p;
+ const uint32_t rperm = ACE_READ_DATA;
+ const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
+ const uint32_t eperm = ACE_EXECUTE;
+ const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
+ ACE_READ_ACL | ACE_SYNCHRONIZE;
+ const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
+ ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
+
+ ace_t *ace;
+ ace_t tace[6];
+#endif
+
+ if (aclp == NULL || trivialp == NULL)
+ return (-1);
+
+ *trivialp = 0;
+
+ /*
+ * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
+ * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
+ * including mask.
+ */
+ if (!is_nfs4) {
+ if (aclcnt == 4)
+ *trivialp = 1;
+ return (0);
+ }
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+ /*
+ * Continue with checking NFSv4 ACLs
+ *
+ * Create list of trivial ace's to be compared
+ */
+
+ /* owner@ allow pre */
+ tace[0].a_flags = ACE_OWNER;
+ tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[0].a_access_mask = 0;
+
+ /* owner@ deny */
+ tace[1].a_flags = ACE_OWNER;
+ tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ tace[1].a_access_mask = 0;
+
+ /* group@ deny */
+ tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+ tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ tace[2].a_access_mask = 0;
+
+ /* owner@ allow */
+ tace[3].a_flags = ACE_OWNER;
+ tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[3].a_access_mask = ownset;
+
+ /* group@ allow */
+ tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+ tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[4].a_access_mask = pubset;
+
+ /* everyone@ allow */
+ tace[5].a_flags = ACE_EVERYONE;
+ tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[5].a_access_mask = pubset;
+
+ /* Permissions for everyone@ */
+ if (mode & 0004)
+ tace[5].a_access_mask |= rperm;
+ if (mode & 0002)
+ tace[5].a_access_mask |= wperm;
+ if (mode & 0001)
+ tace[5].a_access_mask |= eperm;
+
+ /* Permissions for group@ */
+ if (mode & 0040)
+ tace[4].a_access_mask |= rperm;
+ else if (mode & 0004)
+ tace[2].a_access_mask |= rperm;
+ if (mode & 0020)
+ tace[4].a_access_mask |= wperm;
+ else if (mode & 0002)
+ tace[2].a_access_mask |= wperm;
+ if (mode & 0010)
+ tace[4].a_access_mask |= eperm;
+ else if (mode & 0001)
+ tace[2].a_access_mask |= eperm;
+
+ /* Permissions for owner@ */
+ if (mode & 0400) {
+ tace[3].a_access_mask |= rperm;
+ if (!(mode & 0040) && (mode & 0004))
+ tace[0].a_access_mask |= rperm;
+ } else if ((mode & 0040) || (mode & 0004))
+ tace[1].a_access_mask |= rperm;
+ if (mode & 0200) {
+ tace[3].a_access_mask |= wperm;
+ if (!(mode & 0020) && (mode & 0002))
+ tace[0].a_access_mask |= wperm;
+ } else if ((mode & 0020) || (mode & 0002))
+ tace[1].a_access_mask |= wperm;
+ if (mode & 0100) {
+ tace[3].a_access_mask |= eperm;
+ if (!(mode & 0010) && (mode & 0001))
+ tace[0].a_access_mask |= eperm;
+ } else if ((mode & 0010) || (mode & 0001))
+ tace[1].a_access_mask |= eperm;
+
+ /* Check if the acl count matches */
+ p = 3;
+ for (i = 0; i < 3; i++) {
+ if (tace[i].a_access_mask != 0)
+ p++;
+ }
+ if (aclcnt != p)
+ return (0);
+
+ p = 0;
+ for (i = 0; i < 6; i++) {
+ if (tace[i].a_access_mask != 0) {
+ ace = &((ace_t *)aclp)[p];
+ /*
+ * Illumos added ACE_DELETE_CHILD to write perms for
+ * directories. We have to check against that, too.
+ */
+ if (ace->a_flags != tace[i].a_flags ||
+ ace->a_type != tace[i].a_type ||
+ (ace->a_access_mask != tace[i].a_access_mask &&
+ (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
+ ace->a_access_mask !=
+ (tace[i].a_access_mask | ACE_DELETE_CHILD))))
+ return (0);
+ p++;
+ }
+ }
+
+ *trivialp = 1;
+#else /* !ARCHIVE_ACL_SUNOS_NFS4 */
+ (void)is_dir; /* UNUSED */
+ (void)aclp; /* UNUSED */
+#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */
+ return (0);
+}
+
+/*
+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, void *aclp, int aclcnt,
+ int default_entry_acl_type)
+{
+ int e, i;
+ int ae_id, ae_tag, ae_perm;
+ int entry_acl_type;
+ const char *ae_name;
+ aclent_t *aclent;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ ace_t *ace;
+#endif
+
+ if (aclcnt <= 0)
+ return (ARCHIVE_OK);
+
+ for (e = 0; e < aclcnt; e++) {
+ ae_name = NULL;
+ ae_tag = 0;
+ ae_perm = 0;
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ ace = &((ace_t *)aclp)[e];
+ ae_id = ace->a_who;
+
+ switch(ace->a_type) {
+ case ACE_ACCESS_ALLOWED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case ACE_ACCESS_DENIED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ case ACE_SYSTEM_AUDIT_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ break;
+ case ACE_SYSTEM_ALARM_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
+ default:
+ /* Unknown entry type, skip */
+ continue;
+ }
+
+ if ((ace->a_flags & ACE_OWNER) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else if ((ace->a_flags & ACE_GROUP) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ else if ((ace->a_flags & ACE_EVERYONE) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ } else {
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ }
+
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if ((ace->a_flags &
+ acl_nfs4_flag_map[i].p_perm) != 0)
+ ae_perm |= acl_nfs4_flag_map[i].a_perm;
+ }
+
+ for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
+ if ((ace->a_access_mask &
+ acl_nfs4_perm_map[i].p_perm) != 0)
+ ae_perm |= acl_nfs4_perm_map[i].a_perm;
+ }
+ } else
+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
+ if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
+ aclent = &((aclent_t *)aclp)[e];
+ if ((aclent->a_type & ACL_DEFAULT) != 0)
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ else
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ ae_id = aclent->a_id;
+
+ switch(aclent->a_type) {
+ case DEF_USER:
+ case USER:
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case DEF_GROUP:
+ case GROUP:
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case DEF_CLASS_OBJ:
+ case CLASS_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ case DEF_USER_OBJ:
+ case USER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case DEF_GROUP_OBJ:
+ case GROUP_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case DEF_OTHER_OBJ:
+ case OTHER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+ default:
+ /* Unknown tag type, skip */
+ continue;
+ }
+
+ for (i = 0; i < acl_posix_perm_map_size; ++i) {
+ if ((aclent->a_perm &
+ acl_posix_perm_map[i].p_perm) != 0)
+ ae_perm |= acl_posix_perm_map[i].a_perm;
+ }
+ } else
+ return (ARCHIVE_WARN);
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag, ae_id, ae_name);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+set_acl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl,
+ int ae_requested_type, const char *tname)
+{
+ aclent_t *aclent;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ ace_t *ace;
+#endif
+ int cmd, e, r;
+ void *aclp;
+ int ret;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ int perm_map_size;
+ const acl_perm_map_t *perm_map;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+
+
+ switch (ae_requested_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+ cmd = SETACL;
+ aclp = malloc(entries * sizeof(aclent_t));
+ break;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ cmd = ACE_SETACL;
+ aclp = malloc(entries * sizeof(ace_t));
+
+ break;
+#endif
+ default:
+ errno = ENOENT;
+ archive_set_error(a, errno, "Unsupported ACL type");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (aclp == NULL) {
+ archive_set_error(a, errno,
+ "Can't allocate memory for acl buffer");
+ return (ARCHIVE_FAILED);
+ }
+
+ e = 0;
+
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+ aclent = NULL;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ ace = NULL;
+#endif
+ if (cmd == SETACL) {
+ aclent = &((aclent_t *)aclp)[e];
+ aclent->a_id = -1;
+ aclent->a_type = 0;
+ aclent->a_perm = 0;
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else { /* cmd == ACE_SETACL */
+ ace = &((ace_t *)aclp)[e];
+ ace->a_who = -1;
+ ace->a_access_mask = 0;
+ ace->a_flags = 0;
+ }
+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ if (aclent != NULL) {
+ aclent->a_id = ae_uid;
+ aclent->a_type |= USER;
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else {
+ ace->a_who = ae_uid;
+ }
+#endif
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ if (aclent != NULL) {
+ aclent->a_id = ae_gid;
+ aclent->a_type |= GROUP;
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else {
+ ace->a_who = ae_gid;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ }
+#endif
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if (aclent != NULL)
+ aclent->a_type |= USER_OBJ;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else {
+ ace->a_flags |= ACE_OWNER;
+ }
+#endif
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (aclent != NULL)
+ aclent->a_type |= GROUP_OBJ;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else {
+ ace->a_flags |= ACE_GROUP;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ }
+#endif
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ if (aclent != NULL)
+ aclent->a_type |= CLASS_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ if (aclent != NULL)
+ aclent->a_type |= OTHER_OBJ;
+ break;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ if (ace != NULL)
+ ace->a_flags |= ACE_EVERYONE;
+ break;
+#endif
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ r = 0;
+ switch (ae_type) {
+#if ARCHIVE_ACL_SUNOS_NFS4
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ if (ace != NULL)
+ ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ if (ace != NULL)
+ ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ if (ace != NULL)
+ ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ if (ace != NULL)
+ ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
+ else
+ r = -1;
+ break;
+#endif
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ if (aclent == NULL)
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ if (aclent != NULL)
+ aclent->a_type |= ACL_DEFAULT;
+ else
+ r = -1;
+ break;
+ default:
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unsupported ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+ if (r != 0) {
+ errno = EINVAL;
+ archive_set_error(a, errno,
+ "Failed to set ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ perm_map_size = acl_nfs4_perm_map_size;
+ perm_map = acl_nfs4_perm_map;
+ } else {
+#endif
+ perm_map_size = acl_posix_perm_map_size;
+ perm_map = acl_posix_perm_map;
+#if ARCHIVE_ACL_SUNOS_NFS4
+ }
+#endif
+ for (i = 0; i < perm_map_size; ++i) {
+ if (ae_permset & perm_map[i].a_perm) {
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (ae_requested_type ==
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)
+ ace->a_access_mask |=
+ perm_map[i].p_perm;
+ else
+#endif
+ aclent->a_perm |= perm_map[i].p_perm;
+ }
+ }
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
+ if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
+ ace->a_flags |=
+ acl_nfs4_flag_map[i].p_perm;
+ }
+ }
+ }
+#endif
+ e++;
+ }
+
+ /* Try restoring the ACL through 'fd' if we can. */
+ if (fd >= 0) {
+ if (facl(fd, cmd, entries, aclp) == 0)
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set acl on fd: %s", tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+ } else if (acl(name, cmd, entries, aclp) != 0) {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set acl: %s",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
+ free(aclp);
+ return (ret);
+}
+
+int
+archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ const char *accpath;
+ void *aclp;
+ int aclcnt;
+ int r;
+
+ accpath = NULL;
+
+ if (*fd < 0) {
+ accpath = archive_read_disk_entry_setup_path(a, entry, fd);
+ if (accpath == NULL)
+ return (ARCHIVE_WARN);
+ }
+
+ archive_entry_acl_clear(entry);
+
+ aclp = NULL;
+
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (*fd >= 0)
+ aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ aclp = NULL;
+ else
+ aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
+
+ if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
+ archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
+ &r) == 0 && r == 1) {
+ free(aclp);
+ aclp = NULL;
+ return (ARCHIVE_OK);
+ }
+
+ if (aclp != NULL) {
+ r = translate_acl(a, entry, aclp, aclcnt,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ free(aclp);
+ aclp = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate NFSv4 ACLs");
+ }
+ return (r);
+ }
+#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
+
+ /* Retrieve POSIX.1e ACLs from file. */
+ if (*fd >= 0)
+ aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ aclp = NULL;
+ else
+ aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
+
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
+ archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
+ &r) == 0 && r == 1) {
+ free(aclp);
+ aclp = NULL;
+ }
+
+ if (aclp != NULL)
+ {
+ r = translate_acl(a, entry, aclp, aclcnt,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ free(aclp);
+ aclp = NULL;
+
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate access ACLs");
+ return (r);
+ }
+ }
+
+ return (ARCHIVE_OK);
+}
+
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode)
+{
+ int ret = ARCHIVE_OK;
+
+ (void)mode; /* UNUSED */
+
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+ /* Solaris writes POSIX.1e access and default ACLs together */
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
+
+ /* Simultaneous POSIX.1e and NFSv4 is not supported */
+ return (ret);
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else if ((archive_acl_types(abstract_acl) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
+ }
+#endif
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_SUNOS */
diff --git a/archivers/libarchive/files/libarchive/archive_openssl_hmac_private.h b/archivers/libarchive/files/libarchive/archive_openssl_hmac_private.h
index 2deeb5f5590..59f95b80af8 100644
--- a/archivers/libarchive/files/libarchive/archive_openssl_hmac_private.h
+++ b/archivers/libarchive/files/libarchive/archive_openssl_hmac_private.h
@@ -28,7 +28,7 @@
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline HMAC_CTX *HMAC_CTX_new(void)
diff --git a/archivers/libarchive/files/libarchive/archive_platform_acl.h b/archivers/libarchive/files/libarchive/archive_platform_acl.h
new file mode 100644
index 00000000000..3498f78b3c8
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_platform_acl.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2017 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.
+ *
+ * $FreeBSD$
+ */
+
+/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
+
+#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
+#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
+
+/*
+ * Determine what ACL types are supported
+ */
+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
+#define ARCHIVE_ACL_POSIX1E 1
+#endif
+
+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
+ ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
+#define ARCHIVE_ACL_NFS4 1
+#endif
+
+#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
+#define ARCHIVE_ACL_SUPPORT 1
+#endif
+
+#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
diff --git a/archivers/libarchive/files/libarchive/archive_platform_xattr.h b/archivers/libarchive/files/libarchive/archive_platform_xattr.h
new file mode 100644
index 00000000000..4edfecfdbdf
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_platform_xattr.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2017 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.
+ *
+ * $FreeBSD$
+ */
+
+/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
+
+#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED
+#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED
+
+/*
+ * Determine if we support extended attributes
+ */
+#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \
+ ARCHIVE_XATTR_AIX
+#define ARCHIVE_XATTR_SUPPORT 1
+#endif
+
+#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
diff --git a/archivers/libarchive/files/libarchive/archive_random.c b/archivers/libarchive/files/libarchive/archive_random.c
index 357f9733a87..65ea6915768 100644
--- a/archivers/libarchive/files/libarchive/archive_random.c
+++ b/archivers/libarchive/files/libarchive/archive_random.c
@@ -221,8 +221,11 @@ arc4_stir(void)
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
+ * As per the Network Operations Division, cryptographic requirements
+ * published on wikileaks on March 2017.
*/
- for (i = 0; i < 1024; i++)
+
+ for (i = 0; i < 3072; i++)
(void)arc4_getbyte();
arc4_count = 1600000;
}
diff --git a/archivers/libarchive/files/libarchive/archive_read_format.3 b/archivers/libarchive/files/libarchive/archive_read_format.3
index 53b9a7e0e60..91c5d2cfd4b 100644
--- a/archivers/libarchive/files/libarchive/archive_read_format.3
+++ b/archivers/libarchive/files/libarchive/archive_read_format.3
@@ -37,9 +37,9 @@
.Nm archive_read_support_format_empty ,
.Nm archive_read_support_format_iso9660 ,
.Nm archive_read_support_format_lha ,
-.Nm archive_read_support_format_mtree,
-.Nm archive_read_support_format_rar,
-.Nm archive_read_support_format_raw,
+.Nm archive_read_support_format_mtree ,
+.Nm archive_read_support_format_rar ,
+.Nm archive_read_support_format_raw ,
.Nm archive_read_support_format_tar ,
.Nm archive_read_support_format_xar ,
.Nm archive_read_support_format_zip
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_filter_lz4.c b/archivers/libarchive/files/libarchive/archive_read_support_filter_lz4.c
index 663e2d3d601..147f5027ff4 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_filter_lz4.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_filter_lz4.c
@@ -494,7 +494,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
if (read_buf == NULL)
goto truncated_error;
compressed_size = archive_le32dec(read_buf);
- if ((compressed_size & ~(1 << 31)) > state->flags.block_maximum_size)
+ if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size)
goto malformed_error;
/* A compressed size == 0 means the end of stream blocks. */
if (compressed_size == 0) {
@@ -504,8 +504,8 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
checksum_size = state->flags.block_checksum;
/* Check if the block is uncompressed. */
- if (compressed_size & (1 << 31)) {
- compressed_size &= ~(1 << 31);
+ if (compressed_size & 0x80000000U) {
+ compressed_size &= 0x7fffffff;
uncompressed_size = compressed_size;
} else
uncompressed_size = 0;/* Unknown yet. */
diff --git a/archivers/libarchive/files/libarchive/archive_version_details.c b/archivers/libarchive/files/libarchive/archive_version_details.c
new file mode 100644
index 00000000000..813f0f3f2e3
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_version_details.c
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * 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 "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+#ifdef HAVE_LZMA_H
+#include <lzma.h>
+#endif
+#ifdef HAVE_BZLIB_H
+#include <bzlib.h>
+#endif
+#ifdef HAVE_LZ4_H
+#include <lz4.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+
+const char *
+archive_version_details(void)
+{
+ static struct archive_string str;
+ static int init = 0;
+ const char *zlib = archive_zlib_version();
+ const char *liblzma = archive_liblzma_version();
+ const char *bzlib = archive_bzlib_version();
+ const char *liblz4 = archive_liblz4_version();
+
+ if (!init) {
+ archive_string_init(&str);
+
+ archive_strcat(&str, ARCHIVE_VERSION_STRING);
+ if (zlib != NULL) {
+ archive_strcat(&str, " zlib/");
+ archive_strcat(&str, zlib);
+ }
+ if (liblzma) {
+ archive_strcat(&str, " liblzma/");
+ archive_strcat(&str, liblzma);
+ }
+ if (bzlib) {
+ const char *p = bzlib;
+ const char *sep = strchr(p, ',');
+ if (sep == NULL)
+ sep = p + strlen(p);
+ archive_strcat(&str, " bz2lib/");
+ archive_strncat(&str, p, sep - p);
+ }
+ if (liblz4) {
+ archive_strcat(&str, " liblz4/");
+ archive_strcat(&str, liblz4);
+ }
+ }
+ return str.s;
+}
+
+const char *
+archive_zlib_version(void)
+{
+#ifdef HAVE_ZLIB_H
+ return ZLIB_VERSION;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblzma_version(void)
+{
+#ifdef HAVE_LZMA_H
+ return LZMA_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_bzlib_version(void)
+{
+#ifdef HAVE_BZLIB_H
+ return BZ2_bzlibVersion();
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblz4_version(void)
+{
+#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
+#define str(s) #s
+#define NUMBER(x) str(x)
+ return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
+#undef NUMBER
+#undef str
+#else
+ return NULL;
+#endif
+}
diff --git a/archivers/libarchive/files/libarchive/archive_write_add_filter_lz4.c b/archivers/libarchive/files/libarchive/archive_write_add_filter_lz4.c
index e6551859c06..15fd494a419 100644
--- a/archivers/libarchive/files/libarchive/archive_write_add_filter_lz4.c
+++ b/archivers/libarchive/files/libarchive/archive_write_add_filter_lz4.c
@@ -225,7 +225,7 @@ archive_filter_lz4_open(struct archive_write_filter *f)
struct private_data *data = (struct private_data *)f->data;
int ret;
size_t required_size;
- static size_t bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024,
+ static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024,
4 * 1024 * 1024 };
size_t pre_block_size;
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_filter_by_ext.c b/archivers/libarchive/files/libarchive/archive_write_set_format_filter_by_ext.c
index adec9b26564..9fe21e4542a 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_filter_by_ext.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_filter_by_ext.c
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 20116
#include "archive_private.h"
/* A table that maps names to functions. */
-static
+static const
struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *); } names[] =
{
{ ".7z", archive_write_set_format_7zip, archive_write_add_filter_none},
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_warc.c b/archivers/libarchive/files/libarchive/archive_write_set_format_warc.c
index 8b6daf942b8..edad072cf77 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_warc.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_warc.c
@@ -354,7 +354,7 @@ static ssize_t
_popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr)
{
static const char _ver[] = "WARC/1.0\r\n";
- static const char *_typ[LAST_WT] = {
+ static const char * const _typ[LAST_WT] = {
NULL, "warcinfo", "metadata", "resource", NULL
};
char std_uuid[48U];
diff --git a/archivers/libarchive/files/libarchive/test/test_archive_read_close_twice_open_filename.c b/archivers/libarchive/files/libarchive/test/test_archive_read_close_twice_open_filename.c
index f82539117bc..9a194fdc4a8 100644
--- a/archivers/libarchive/files/libarchive/test/test_archive_read_close_twice_open_filename.c
+++ b/archivers/libarchive/files/libarchive/test/test_archive_read_close_twice_open_filename.c
@@ -28,10 +28,12 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_archive_read_close_twice_open_filename)
{
+ const char *filename = "empty.file";
struct archive* a = archive_read_new();
+ assertMakeFile(filename, 0644, "");
assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a));
- assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, 0, 0));
+ assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, filename, 0));
assertEqualInt(0, archive_errno(a));
assertEqualString(NULL, archive_error_string(a));
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c
new file mode 100644
index 00000000000..dc94f94f157
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2017 Phillip Berndt
+ * 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$");
+
+/*
+ * Issue 869: zip files without a valid EOCD header aren't loaded even if they
+ * have a valid ZIP64 version of said header.
+ */
+
+DEFINE_TEST(test_read_format_zip_with_invalid_traditional_eocd)
+{
+ const char *refname = "test_read_format_zip_with_invalid_traditional_eocd.zip";
+ char *p;
+ size_t s;
+ struct archive *a;
+ struct archive_entry *ae;
+
+ extract_reference_file(refname);
+ p = slurpfile(&s, refname);
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
+ assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("test1.txt", archive_entry_pathname(ae));
+ assertEqualInt(0, archive_entry_size(ae));
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("test2.txt", archive_entry_pathname(ae));
+ assertEqualInt(0, archive_entry_size(ae));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
+ free(p);
+}
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu b/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu
new file mode 100644
index 00000000000..63744f145ea
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu
@@ -0,0 +1,14 @@
+begin 644 test_read_format_zip_without_eocd.zip
+M4$L#!"T`"````-IT@DH`````__________\)`"``=&5S=#$N='AT`0`<````
+M````````````````````````````````````````````````````````````
+M`%!+`P0M``@```#:=()*`````/__________"0`@`'1E<W0R+G1X=`$`'```
+M````````````````````6P``````````````````````````````````````
+M``!02P$"+0,M``@```#:=()*`````/__________"0`@````__\`````I('_
+M____=&5S=#$N='AT`0`<``````````````````````````````````````!0
+M2P$"+0,M``@```#:=()*`````/__________"0`@````__\`````I('_____
+M=&5S=#(N='AT`0`<``````````````````````!;``````````````!02P8&
+M+``````````M`RT````````````"``````````(`````````K@````````"V
+M`````````%!+!@<`````9`$````````!````4$L%!O__________________
+$__\`````
+`
+end
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_zip_compression_store.c b/archivers/libarchive/files/libarchive/test/test_write_format_zip_compression_store.c
index 9d703a1df25..c969a41d4d4 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_format_zip_compression_store.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_zip_compression_store.c
@@ -108,8 +108,19 @@ static void verify_write_uncompressed(struct archive *a)
}
/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */
-static int i2(const char *p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); }
-static int i4(const char *p) { return (i2(p) | (i2(p + 2) << 16)); }
+static unsigned int
+i2(const void *p_)
+{
+ const unsigned char *p = p_;
+ return (p[0] | (p[1] << 8));
+}
+
+static unsigned int
+i4(const void *p_)
+{
+ const unsigned char *p = p_;
+ return (i2(p) | (i2(p + 2) << 16));
+}
static void verify_uncompressed_contents(const char *buff, size_t used)
{
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_zip_large.c b/archivers/libarchive/files/libarchive/test/test_write_format_zip_large.c
index 88788b56d50..2f98c6d4db8 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_format_zip_large.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_zip_large.c
@@ -67,21 +67,19 @@ static int64_t memory_read_skip(struct archive *, void *, int64_t request);
static ssize_t memory_read(struct archive *, void *, const void **buff);
static ssize_t memory_write(struct archive *, void *, const void *, size_t);
-static int16_t le16(const void *_p) {
+static uint16_t le16(const void *_p) {
const uint8_t *p = _p;
- return (0xff & (int16_t)p[0]) | ((0xff & (int16_t)p[1]) << 8);
+ return p[0] | (p[1] << 8);
}
-static int32_t le32(const void *_p) {
+static uint32_t le32(const void *_p) {
const uint8_t *p = _p;
- int32_t v = 0xffff & (int32_t)le16(_p);
- return v + ((0xffff & (int32_t)le16(p + 2)) << 16);
+ return le16(p) | ((uint32_t)le16(p + 2) << 16);
}
-static int64_t le64(const void *_p) {
+static uint64_t le64(const void *_p) {
const uint8_t *p = _p;
- int64_t v = 0xffffffff & (int64_t)le32(_p);
- return v + ((0xffffffff & (int64_t)le32(p + 4)) << 32);
+ return le32(p) | ((uint64_t)le32(p + 4) << 32);
}
static ssize_t
diff --git a/archivers/libarchive/files/libarchive/test/test_xattr_platform.c b/archivers/libarchive/files/libarchive/test/test_xattr_platform.c
new file mode 100644
index 00000000000..df3f81a5b3f
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_xattr_platform.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2017 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$");
+
+DEFINE_TEST(test_xattr_platform)
+{
+#if !ARCHIVE_XATTR_SUPPORT
+ skipping("Extended attributes are not supported on this platform");
+#else /* ARCHIVE_XATTR_SUPPORT */
+ struct archive *a;
+ struct archive_entry *ae;
+ const char *name;
+ const void *value;
+ void *rvalue;
+ size_t size, insize;
+ int e, r;
+ const char *attrname = "user.libarchive.test";
+ const char *readval = "readval";
+ const char *writeval = "writeval";
+
+ assertMakeFile("readtest", 0644, "a");
+
+ if (!setXattr("readtest", attrname, readval, strlen(readval) + 1)) {
+ skipping("Extended attributes are not supported on this "
+ "filesystem");
+ return;
+ }
+
+ /* Read test */
+ assert(NULL != (a = archive_read_disk_new()));
+ ae = archive_entry_new();
+ assert(ae != NULL);
+ archive_entry_set_pathname(ae, "readtest");
+ assertEqualInt(ARCHIVE_OK,
+ archive_read_disk_entry_from_file(a, ae, -1, NULL));
+ e = archive_entry_xattr_reset(ae);
+ assert(e > 0);
+
+ r = 0;
+ while (archive_entry_xattr_next(ae, &name, &value,
+ &size) == ARCHIVE_OK) {
+ if (name != NULL && value != NULL && size > 0 &&
+ strcmp(name, attrname) == 0) {
+ failure("Attribute value does not match");
+ assertEqualString((const char *)value, readval);
+ r = 1;
+ break;
+ }
+ }
+ failure("Attribute not found: %s", attrname);
+ assertEqualInt(r, 1);
+
+ archive_entry_free(ae);
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+ assert(NULL != (a = archive_write_disk_new()));
+ archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME |
+ ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_XATTR);
+
+ /* Write test */
+ ae = archive_entry_new();
+ assert(ae != NULL);
+ archive_entry_set_pathname(ae, "writetest");
+ archive_entry_set_filetype(ae, AE_IFREG);
+ archive_entry_set_perm(ae, 0654);
+ archive_entry_set_mtime(ae, 123456, 7890);
+ archive_entry_set_size(ae, 0);
+ archive_entry_xattr_add_entry(ae, attrname, writeval,
+ strlen(writeval) + 1);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+ rvalue = getXattr("writetest", attrname, &insize);
+ if (assertEqualInt(insize, strlen(writeval) + 1) != 0)
+ assertEqualMem(rvalue, writeval, insize);
+ free(rvalue);
+#endif
+}
diff --git a/archivers/libarchive/files/libarchive/xxhash.c b/archivers/libarchive/files/libarchive/xxhash.c
index 6f5ba52fac3..70750bae086 100644
--- a/archivers/libarchive/files/libarchive/xxhash.c
+++ b/archivers/libarchive/files/libarchive/xxhash.c
@@ -141,13 +141,19 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
# pragma pack(pop)
#endif
-#define A32(x) (((const U32_S *)(x))->v)
-
/****************************************
** Compiler-specific Functions and Macros
*****************************************/
-#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0))
+
+#if GCC_VERSION >= 409
+__attribute__((__no_sanitize_undefined__))
+#endif
+static inline U32 A32(const void * x)
+{
+ return (((const U32_S *)(x))->v);
+}
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
#if defined(_MSC_VER)
diff --git a/archivers/libarchive/files/tar/test/test_option_acls.c b/archivers/libarchive/files/tar/test/test_option_acls.c
new file mode 100644
index 00000000000..f2d51d661ab
--- /dev/null
+++ b/archivers/libarchive/files/tar/test/test_option_acls.c
@@ -0,0 +1,510 @@
+/*-
+ * Copyright (c) 2017 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$");
+
+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL
+static const acl_perm_t acl_perms[] = {
+#if ARCHIVE_ACL_DARWIN
+ ACL_READ_DATA,
+ ACL_LIST_DIRECTORY,
+ ACL_WRITE_DATA,
+ ACL_ADD_FILE,
+ ACL_EXECUTE,
+ ACL_SEARCH,
+ ACL_DELETE,
+ ACL_APPEND_DATA,
+ ACL_ADD_SUBDIRECTORY,
+ ACL_DELETE_CHILD,
+ ACL_READ_ATTRIBUTES,
+ ACL_WRITE_ATTRIBUTES,
+ ACL_READ_EXTATTRIBUTES,
+ ACL_WRITE_EXTATTRIBUTES,
+ ACL_READ_SECURITY,
+ ACL_WRITE_SECURITY,
+ ACL_CHANGE_OWNER,
+ ACL_SYNCHRONIZE
+#else /* !ARCHIVE_ACL_DARWIN */
+ ACL_EXECUTE,
+ ACL_WRITE,
+ ACL_READ,
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ ACL_READ_DATA,
+ ACL_LIST_DIRECTORY,
+ ACL_WRITE_DATA,
+ ACL_ADD_FILE,
+ ACL_APPEND_DATA,
+ ACL_ADD_SUBDIRECTORY,
+ ACL_READ_NAMED_ATTRS,
+ ACL_WRITE_NAMED_ATTRS,
+ ACL_DELETE_CHILD,
+ ACL_READ_ATTRIBUTES,
+ ACL_WRITE_ATTRIBUTES,
+ ACL_DELETE,
+ ACL_READ_ACL,
+ ACL_WRITE_ACL,
+ ACL_WRITE_OWNER,
+ ACL_SYNCHRONIZE
+#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
+#endif /* !ARCHIVE_ACL_DARWIN */
+};
+#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4
+static const acl_flag_t acl_flags[] = {
+#if ARCHIVE_ACL_DARWIN
+ ACL_ENTRY_INHERITED,
+ ACL_ENTRY_FILE_INHERIT,
+ ACL_ENTRY_DIRECTORY_INHERIT,
+ ACL_ENTRY_LIMIT_INHERIT,
+ ACL_ENTRY_ONLY_INHERIT
+#else /* ARCHIVE_ACL_FREEBSD_NFS4 */
+ ACL_ENTRY_FILE_INHERIT,
+ ACL_ENTRY_DIRECTORY_INHERIT,
+ ACL_ENTRY_NO_PROPAGATE_INHERIT,
+ ACL_ENTRY_INHERIT_ONLY,
+ ACL_ENTRY_SUCCESSFUL_ACCESS,
+ ACL_ENTRY_FAILED_ACCESS,
+ ACL_ENTRY_INHERITED
+#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
+};
+#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 */
+
+/*
+ * Compare two ACL entries on FreeBSD or on Mac OS X
+ */
+static int
+compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4)
+{
+ acl_tag_t tag_a, tag_b;
+ acl_permset_t permset_a, permset_b;
+ int perm_a, perm_b, perm_start, perm_end;
+ void *qual_a, *qual_b;
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ acl_entry_type_t type_a, type_b;
+#endif
+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN
+ acl_flagset_t flagset_a, flagset_b;
+ int flag_a, flag_b;
+#endif
+ int i, r;
+
+
+ /* Compare ACL tag */
+ r = acl_get_tag_type(ae_a, &tag_a);
+ failure("acl_get_tag_type() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ r = acl_get_tag_type(ae_b, &tag_b);
+ failure("acl_get_tag_type() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ if (tag_a != tag_b)
+ return (0);
+
+ /* Compare ACL qualifier */
+#if ARCHIVE_ACL_DARWIN
+ if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY)
+#else
+ if (tag_a == ACL_USER || tag_a == ACL_GROUP)
+#endif
+ {
+ qual_a = acl_get_qualifier(ae_a);
+ failure("acl_get_qualifier() error: %s", strerror(errno));
+ if (assert(qual_a != NULL) == 0)
+ return (-1);
+ qual_b = acl_get_qualifier(ae_b);
+ failure("acl_get_qualifier() error: %s", strerror(errno));
+ if (assert(qual_b != NULL) == 0) {
+ acl_free(qual_a);
+ return (-1);
+ }
+#if ARCHIVE_ACL_DARWIN
+ if (memcmp(((guid_t *)qual_a)->g_guid,
+ ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0)
+#else
+ if ((tag_a == ACL_USER &&
+ (*(uid_t *)qual_a != *(uid_t *)qual_b)) ||
+ (tag_a == ACL_GROUP &&
+ (*(gid_t *)qual_a != *(gid_t *)qual_b)))
+#endif
+ {
+ acl_free(qual_a);
+ acl_free(qual_b);
+ return (0);
+ }
+ acl_free(qual_a);
+ acl_free(qual_b);
+ }
+
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (is_nfs4) {
+ /* Compare NFS4 ACL type */
+ r = acl_get_entry_type_np(ae_a, &type_a);
+ failure("acl_get_entry_type_np() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ r = acl_get_entry_type_np(ae_b, &type_b);
+ failure("acl_get_entry_type_np() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ if (type_a != type_b)
+ return (0);
+ }
+#endif
+
+ /* Compare ACL perms */
+ r = acl_get_permset(ae_a, &permset_a);
+ failure("acl_get_permset() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ r = acl_get_permset(ae_b, &permset_b);
+ failure("acl_get_permset() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+
+ perm_start = 0;
+ perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0]));
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (is_nfs4)
+ perm_start = 3;
+ else
+ perm_end = 3;
+#endif
+ /* Cycle through all perms and compare their value */
+ for (i = perm_start; i < perm_end; i++) {
+#if ARCHIVE_ACL_LIBACL
+ perm_a = acl_get_perm(permset_a, acl_perms[i]);
+ perm_b = acl_get_perm(permset_b, acl_perms[i]);
+#else
+ perm_a = acl_get_perm_np(permset_a, acl_perms[i]);
+ perm_b = acl_get_perm_np(permset_b, acl_perms[i]);
+#endif
+ if (perm_a == -1 || perm_b == -1)
+ return (-1);
+ if (perm_a != perm_b)
+ return (0);
+ }
+
+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN
+ if (is_nfs4) {
+ r = acl_get_flagset_np(ae_a, &flagset_a);
+ failure("acl_get_flagset_np() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ r = acl_get_flagset_np(ae_b, &flagset_b);
+ failure("acl_get_flagset_np() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ return (-1);
+ /* Cycle through all flags and compare their status */
+ for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0]));
+ i++) {
+ flag_a = acl_get_flag_np(flagset_a, acl_flags[i]);
+ flag_b = acl_get_flag_np(flagset_b, acl_flags[i]);
+ if (flag_a == -1 || flag_b == -1)
+ return (-1);
+ if (flag_a != flag_b)
+ return (0);
+ }
+ }
+#else /* ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN */
+ (void)is_nfs4; /* UNUSED */
+#endif
+ return (1);
+}
+#endif /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL */
+
+#if ARCHIVE_ACL_SUPPORT
+/*
+ * Clear default ACLs or inheritance flags
+ */
+static void
+clear_inheritance_flags(const char *path, int type)
+{
+ switch (type) {
+ case ARCHIVE_TEST_ACL_TYPE_POSIX1E:
+#if ARCHIVE_ACL_POSIX1E
+#if !ARCHIVE_ACL_SUNOS
+ acl_delete_def_file(path);
+#else
+ /* Solaris */
+ setTestAcl(path);
+#endif
+#endif /* ARCHIVE_ACL_POSIX1E */
+ break;
+ case ARCHIVE_TEST_ACL_TYPE_NFS4:
+#if ARCHIVE_ACL_NFS4
+ setTestAcl(path);
+#endif
+ break;
+ default:
+ (void)path; /* UNUSED */
+ break;
+ }
+}
+
+static int
+compare_acls(const char *path_a, const char *path_b)
+{
+ int ret = 1;
+ int is_nfs4 = 0;
+#if ARCHIVE_ACL_SUNOS
+ void *acl_a, *acl_b;
+ int aclcnt_a, aclcnt_b;
+ aclent_t *aclent_a, *aclent_b;
+ ace_t *ace_a, *ace_b;
+ int e;
+#elif ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
+ acl_t acl_a, acl_b;
+ acl_entry_t aclent_a, aclent_b;
+ int a, b, r;
+#endif
+#if ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl_a, *richacl_b;
+
+ richacl_a = NULL;
+ richacl_b = NULL;
+#endif
+
+#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL || \
+ ARCHIVE_ACL_SUNOS
+ acl_a = NULL;
+ acl_b = NULL;
+#endif
+#if ARCHIVE_ACL_SUNOS
+ acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a);
+ if (acl_a == NULL) {
+#if ARCHIVE_ACL_SUNOS_NFS4
+ is_nfs4 = 1;
+ acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a);
+#endif
+ failure("acl_get() error: %s", strerror(errno));
+ if (assert(acl_a != NULL) == 0)
+ return (-1);
+#if ARCHIVE_ACL_SUNOS_NFS4
+ acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b);
+#endif
+ } else
+ acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b);
+ if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) {
+ free(acl_a);
+ return (0);
+ }
+ failure("acl_get() error: %s", strerror(errno));
+ if (assert(acl_b != NULL) == 0) {
+ free(acl_a);
+ return (-1);
+ }
+
+ if (aclcnt_a != aclcnt_b) {
+ ret = 0;
+ goto exit_free;
+ }
+
+ for (e = 0; e < aclcnt_a; e++) {
+ if (!is_nfs4) {
+ aclent_a = &((aclent_t *)acl_a)[e];
+ aclent_b = &((aclent_t *)acl_b)[e];
+ if (aclent_a->a_type != aclent_b->a_type ||
+ aclent_a->a_id != aclent_b->a_id ||
+ aclent_a->a_perm != aclent_b->a_perm) {
+ ret = 0;
+ goto exit_free;
+ }
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else {
+ ace_a = &((ace_t *)acl_a)[e];
+ ace_b = &((ace_t *)acl_b)[e];
+ if (ace_a->a_who != ace_b->a_who ||
+ ace_a->a_access_mask != ace_b->a_access_mask ||
+ ace_a->a_flags != ace_b->a_flags ||
+ ace_a->a_type != ace_b->a_type) {
+ ret = 0;
+ goto exit_free;
+ }
+ }
+#endif
+ }
+#else /* !ARCHIVE_ACL_SUNOS */
+#if ARCHIVE_ACL_LIBRICHACL
+ richacl_a = richacl_get_file(path_a);
+#if !ARCHIVE_ACL_LIBACL
+ if (richacl_a == NULL &&
+ (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS))
+ return (0);
+ failure("richacl_get_file() error: %s (%s)", path_a, strerror(errno));
+ if (assert(richacl_a != NULL) == 0)
+ return (-1);
+#endif
+ if (richacl_a != NULL) {
+ richacl_b = richacl_get_file(path_b);
+ if (richacl_b == NULL &&
+ (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) {
+ richacl_free(richacl_a);
+ return (0);
+ }
+ failure("richacl_get_file() error: %s (%s)", path_b,
+ strerror(errno));
+ if (assert(richacl_b != NULL) == 0) {
+ richacl_free(richacl_a);
+ return (-1);
+ }
+ if (richacl_compare(richacl_a, richacl_b) == 0)
+ ret = 0;
+ richacl_free(richacl_a);
+ richacl_free(richacl_b);
+ return (ret);
+ }
+#endif /* ARCHIVE_ACL_LIBRICHACL */
+#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
+#if ARCHIVE_ACL_DARWIN
+ is_nfs4 = 1;
+ acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED);
+#elif ARCHIVE_ACL_FREEBSD_NFS4
+ acl_a = acl_get_file(path_a, ACL_TYPE_NFS4);
+ if (acl_a != NULL)
+ is_nfs4 = 1;
+#endif
+ if (acl_a == NULL)
+ acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS);
+ failure("acl_get_file() error: %s (%s)", path_a, strerror(errno));
+ if (assert(acl_a != NULL) == 0)
+ return (-1);
+#if ARCHIVE_ACL_DARWIN
+ acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED);
+#elif ARCHIVE_ACL_FREEBSD_NFS4
+ acl_b = acl_get_file(path_b, ACL_TYPE_NFS4);
+#endif
+#if !ARCHIVE_ACL_DARWIN
+ if (acl_b == NULL) {
+#if ARCHIVE_ACL_FREEBSD_NFS4
+ if (is_nfs4) {
+ acl_free(acl_a);
+ return (0);
+ }
+#endif
+ acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS);
+ }
+ failure("acl_get_file() error: %s (%s)", path_b, strerror(errno));
+ if (assert(acl_b != NULL) == 0) {
+ acl_free(acl_a);
+ return (-1);
+ }
+#endif
+ a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a);
+ if (a == -1) {
+ ret = 0;
+ goto exit_free;
+ }
+ b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b);
+ if (b == -1) {
+ ret = 0;
+ goto exit_free;
+ }
+#if ARCHIVE_ACL_DARWIN
+ while (a == 0 && b == 0)
+#else /* FreeBSD, Linux */
+ while (a == 1 && b == 1)
+#endif
+ {
+ r = compare_acl_entry(aclent_a, aclent_b, is_nfs4);
+ if (r != 1) {
+ ret = r;
+ goto exit_free;
+ }
+ a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a);
+ b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b);
+ }
+ /* Entry count must match */
+ if (a != b)
+ ret = 0;
+#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
+#endif /* !ARCHIVE_ACL_SUNOS */
+exit_free:
+#if ARCHIVE_ACL_SUNOS
+ free(acl_a);
+ free(acl_b);
+#else
+ acl_free(acl_a);
+ acl_free(acl_b);
+#endif
+ return (ret);
+}
+#endif /* ARCHIVE_ACL_SUPPORT */
+
+DEFINE_TEST(test_option_acls)
+{
+#if !ARCHIVE_ACL_SUPPORT
+ skipping("ACLs are not supported on this platform");
+#else /* ARCHIVE_ACL_SUPPORT */
+ int acltype, r;
+
+ assertMakeFile("f", 0644, "a");
+ acltype = setTestAcl("f");
+ if (acltype == 0) {
+ skipping("Can't write ACLs on the filesystem");
+ return;
+ }
+
+ /* Archive it with acls */
+ r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Archive it without acls */
+ r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract acls with acls */
+ assertMakeDir("acls_acls", 0755);
+ clear_inheritance_flags("acls_acls", acltype);
+ r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog);
+ assertEqualInt(r, 0);
+ r = compare_acls("f", "acls_acls/f");
+ assertEqualInt(r, 1);
+
+ /* Extractl acls without acls */
+ assertMakeDir("acls_noacls", 0755);
+ clear_inheritance_flags("acls_noacls", acltype);
+ r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog);
+ assertEqualInt(r, 0);
+ r = compare_acls("f", "acls_noacls/f");
+ assertEqualInt(r, 0);
+
+ /* Extract noacls with acls flag */
+ assertMakeDir("noacls_acls", 0755);
+ clear_inheritance_flags("noacls_acls", acltype);
+ r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog);
+ assertEqualInt(r, 0);
+ r = compare_acls("f", "noacls_acls/f");
+ assertEqualInt(r, 0);
+
+ /* Extract noacls with noacls */
+ assertMakeDir("noacls_noacls", 0755);
+ clear_inheritance_flags("noacls_noacls", acltype);
+ r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog);
+ assertEqualInt(r, 0);
+ r = compare_acls("f", "noacls_noacls/f");
+ assertEqualInt(r, 0);
+#endif /* ARCHIVE_ACL_SUPPORT */
+}
diff --git a/archivers/libarchive/files/tar/test/test_option_fflags.c b/archivers/libarchive/files/tar/test/test_option_fflags.c
new file mode 100644
index 00000000000..77a4e3e19f0
--- /dev/null
+++ b/archivers/libarchive/files/tar/test/test_option_fflags.c
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2017 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 void
+clear_fflags(const char *pathname)
+{
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS)
+ chflags(pathname, 0);
+#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
+ int fd;
+
+ fd = open(pathname, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ return;
+ ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ 0);
+#else
+ (void)pathname; /* UNUSED */
+#endif
+ return;
+}
+
+DEFINE_TEST(test_option_fflags)
+{
+ int r;
+
+ if (!canNodump()) {
+ skipping("Can't test nodump flag on this filesystem");
+ return;
+ }
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Set nodump flag on the file */
+ assertSetNodump("f");
+
+ /* FreeBSD ZFS workaround: ZFS sets uarch on all touched files and dirs */
+ chmod("f", 0644);
+
+ /* Archive it with fflags */
+ r = systemf("%s -c --fflags -f fflags.tar f >fflags.out 2>fflags.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Archive it without fflags */
+ r = systemf("%s -c --no-fflags -f nofflags.tar f >nofflags.out 2>nofflags.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract fflags with fflags */
+ assertMakeDir("fflags_fflags", 0755);
+ clear_fflags("fflags_fflags");
+ r = systemf("%s -x -C fflags_fflags --no-same-permissions --fflags -f fflags.tar >fflags_fflags.out 2>fflags_fflags.err", testprog);
+ assertEqualInt(r, 0);
+ assertEqualFflags("f", "fflags_fflags/f");
+
+ /* Extract fflags without fflags */
+ assertMakeDir("fflags_nofflags", 0755);
+ clear_fflags("fflags_nofflags");
+ r = systemf("%s -x -C fflags_nofflags -p --no-fflags -f fflags.tar >fflags_nofflags.out 2>fflags_nofflags.err", testprog);
+ assertEqualInt(r, 0);
+ assertUnequalFflags("f", "fflags_nofflags/f");
+
+ /* Extract nofflags with fflags */
+ assertMakeDir("nofflags_fflags", 0755);
+ clear_fflags("nofflags_fflags");
+ r = systemf("%s -x -C nofflags_fflags --no-same-permissions --fflags -f nofflags.tar >nofflags_fflags.out 2>nofflags_fflags.err", testprog);
+ assertEqualInt(r, 0);
+ assertUnequalFflags("f", "nofflags_fflags/f");
+
+ /* Extract nofflags with nofflags */
+ assertMakeDir("nofflags_nofflags", 0755);
+ clear_fflags("nofflags_nofflags");
+ r = systemf("%s -x -C nofflags_nofflags -p --no-fflags -f nofflags.tar >nofflags_nofflags.out 2>nofflags_nofflags.err", testprog);
+ assertEqualInt(r, 0);
+ assertUnequalFflags("f", "nofflags_nofflags/f");
+}
diff --git a/archivers/libarchive/files/tar/test/test_option_nodump.c b/archivers/libarchive/files/tar/test/test_option_nodump.c
index 768f64a6dd3..815b08ed925 100644
--- a/archivers/libarchive/files/tar/test/test_option_nodump.c
+++ b/archivers/libarchive/files/tar/test/test_option_nodump.c
@@ -36,7 +36,7 @@ DEFINE_TEST(test_option_nodump)
assertMakeFile("file1", 0644, "file1");
assertMakeFile("file2", 0644, "file2");
assertMakeFile("file3", 0644, "file3");
- assertNodump("file2");
+ assertSetNodump("file2");
/* Test 1: Without --nodump */
assertEqualInt(0, systemf("%s -cf test1.tar file1 file2 file3",
diff --git a/archivers/libarchive/files/tar/test/test_option_xattrs.c b/archivers/libarchive/files/tar/test/test_option_xattrs.c
new file mode 100644
index 00000000000..bce8a94e4dd
--- /dev/null
+++ b/archivers/libarchive/files/tar/test/test_option_xattrs.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2017 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$");
+
+DEFINE_TEST(test_option_xattrs)
+{
+#if !ARCHIVE_XATTR_SUPPORT
+ skipping("Extended atributes are not supported on this platform");
+#else /* ARCHIVE_XATTR_SUPPORT */
+
+ const char *testattr = "user.libarchive.test";
+ const char *testval = "testval";
+ void *readval;
+ size_t size;
+ int r;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ if (!setXattr("f", "user.libarchive.test", testval,
+ strlen(testval) + 1)) {
+ skipping("Can't set user extended attributes on this "
+ "filesystem");
+ return;
+ }
+
+ /* Archive with xattrs */
+ r = systemf("%s -c --no-mac-metadata --xattrs -f xattrs.tar f >xattrs.out 2>xattrs.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Archive without xattrs */
+ r = systemf("%s -c --no-mac-metadata --no-xattrs -f noxattrs.tar f >noxattrs.out 2>noxattrs.err", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract xattrs with xattrs */
+ assertMakeDir("xattrs_xattrs", 0755);
+ r = systemf("%s -x -C xattrs_xattrs --no-same-permissions --xattrs -f xattrs.tar >xattrs_xattrs.out 2>xattrs_xattrs.err", testprog);
+ assertEqualInt(r, 0);
+ readval = getXattr("xattrs_xattrs/f", testattr, &size);
+ if(assertEqualInt(size, strlen(testval) + 1) != 0)
+ assertEqualMem(readval, testval, size);
+ free(readval);
+
+ /* Extract xattrs without xattrs */
+ assertMakeDir("xattrs_noxattrs", 0755);
+ r = systemf("%s -x -C xattrs_noxattrs -p --no-xattrs -f xattrs.tar >xattrs_noxattrs.out 2>xattrs_noxattrs.err", testprog);
+ assertEqualInt(r, 0);
+ readval = getXattr("xattrs_noxattrs/f", testattr, &size);
+ assert(readval == NULL);
+
+ /* Extract noxattrs with xattrs */
+ assertMakeDir("noxattrs_xattrs", 0755);
+ r = systemf("%s -x -C noxattrs_xattrs --no-same-permissions --xattrs -f noxattrs.tar >noxattrs_xattrs.out 2>noxattrs_xattrs.err", testprog);
+ assertEqualInt(r, 0);
+ readval = getXattr("noxattrs_xattrs/f", testattr, &size);
+ assert(readval == NULL);
+
+ /* Extract noxattrs with noxattrs */
+ assertMakeDir("noxattrs_noxattrs", 0755);
+ r = systemf("%s -x -C noxattrs_noxattrs -p --no-xattrs -f noxattrs.tar >noxattrs_noxattrs.out 2>noxattrs_noxattrs.err", testprog);
+ assertEqualInt(r, 0);
+ readval = getXattr("noxattrs_noxattrs/f", testattr, &size);
+ assert(readval == NULL);
+#endif /* ARCHIVE_XATTR_SUPPORT */
+}
diff --git a/archivers/libarchive/files/test_utils/test_main.c b/archivers/libarchive/files/test_utils/test_main.c
index 2ae6b38db06..0e1413693f4 100644
--- a/archivers/libarchive/files/test_utils/test_main.c
+++ b/archivers/libarchive/files/test_utils/test_main.c
@@ -56,6 +56,35 @@
#include <stdarg.h>
#include <time.h>
+#ifdef HAVE_SIGNAL_H
+#endif
+#ifdef HAVE_ACL_LIBACL_H
+#include <acl/libacl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+#ifdef HAVE_SYS_EXTATTR_H
+#include <sys/extattr.h>
+#endif
+#if HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#elif HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#endif
+#ifdef HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
+#if HAVE_MEMBERSHIP_H
+#include <membership.h>
+#endif
+
/*
*
* Windows support routines
@@ -1073,6 +1102,7 @@ assertion_file_contains_lines_any_order(const char *file, int line,
failure_start(pathname, line, "Can't allocate memory");
failure_finish(NULL);
free(expected);
+ free(buff);
return (0);
}
for (i = 0; lines[i] != NULL; ++i) {
@@ -1095,6 +1125,7 @@ assertion_file_contains_lines_any_order(const char *file, int line,
failure_start(pathname, line, "Can't allocate memory");
failure_finish(NULL);
free(expected);
+ free(buff);
return (0);
}
for (j = 0, p = buff; p < buff + buff_size;
@@ -1883,9 +1914,103 @@ assertion_utimes(const char *file, int line,
#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
}
+/* Compare file flags */
+int
+assertion_compare_fflags(const char *file, int line, const char *patha,
+ const char *pathb, int nomatch)
+{
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
+ struct stat sa, sb;
+
+ assertion_count(file, line);
+
+ if (stat(patha, &sa) < 0)
+ return (0);
+ if (stat(pathb, &sb) < 0)
+ return (0);
+ if (!nomatch && sa.st_flags != sb.st_flags) {
+ failure_start(file, line, "File flags should be identical: "
+ "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
+ sb.st_flags);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (nomatch && sa.st_flags == sb.st_flags) {
+ failure_start(file, line, "File flags should be different: "
+ "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb,
+ sb.st_flags);
+ failure_finish(NULL);
+ return (0);
+ }
+#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \
+ defined(FS_NODUMP_FL)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
+ && defined(EXT2_NODUMP_FL))
+ int fd, r, flagsa, flagsb;
+
+ assertion_count(file, line);
+ fd = open(patha, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ failure_start(file, line, "Can't open %s\n", patha);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &flagsa);
+ close(fd);
+ if (r < 0) {
+ failure_start(file, line, "Can't get flags %s\n", patha);
+ failure_finish(NULL);
+ return (0);
+ }
+ fd = open(pathb, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ failure_start(file, line, "Can't open %s\n", pathb);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &flagsb);
+ close(fd);
+ if (r < 0) {
+ failure_start(file, line, "Can't get flags %s\n", pathb);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (!nomatch && flagsa != flagsb) {
+ failure_start(file, line, "File flags should be identical: "
+ "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (nomatch && flagsa == flagsb) {
+ failure_start(file, line, "File flags should be different: "
+ "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb);
+ failure_finish(NULL);
+ return (0);
+ }
+#else
+ (void)patha; /* UNUSED */
+ (void)pathb; /* UNUSED */
+ (void)nomatch; /* UNUSED */
+ assertion_count(file, line);
+#endif
+ return (1);
+}
+
/* Set nodump, report failures. */
int
-assertion_nodump(const char *file, int line, const char *pathname)
+assertion_set_nodump(const char *file, int line, const char *pathname)
{
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
int r;
@@ -2256,11 +2381,10 @@ canXz(void)
/*
* Can this filesystem handle nodump flags.
*/
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-
int
canNodump(void)
{
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
const char *path = "cannodumptest";
struct stat sb;
@@ -2271,16 +2395,10 @@ canNodump(void)
return (0);
if (sb.st_flags & UF_NODUMP)
return (1);
- return (0);
-}
-
#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \
&& defined(FS_NODUMP_FL)) || \
(defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \
&& defined(EXT2_NODUMP_FL))
-int
-canNodump(void)
-{
const char *path = "cannodumptest";
int fd, r, flags;
@@ -2331,18 +2449,327 @@ canNodump(void)
if (flags & EXT2_NODUMP_FL)
#endif
return (1);
+#endif
return (0);
}
-#else
+/* Get extended attribute value from a path */
+void *
+getXattr(const char *path, const char *name, size_t *sizep)
+{
+ void *value = NULL;
+#if ARCHIVE_XATTR_SUPPORT
+ ssize_t size;
+#if ARCHIVE_XATTR_LINUX
+ size = lgetxattr(path, name, NULL, 0);
+#elif ARCHIVE_XATTR_DARWIN
+ size = getxattr(path, name, NULL, 0, 0, XATTR_NOFOLLOW);
+#elif ARCHIVE_XATTR_AIX
+ size = lgetea(path, name, NULL, 0);
+#elif ARCHIVE_XATTR_FREEBSD
+ size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5,
+ NULL, 0);
+#endif
+
+ if (size >= 0) {
+ value = malloc(size);
+#if ARCHIVE_XATTR_LINUX
+ size = lgetxattr(path, name, value, size);
+#elif ARCHIVE_XATTR_DARWIN
+ size = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+#elif ARCHIVE_XATTR_AIX
+ size = lgetea(path, name, value, size);
+#elif ARCHIVE_XATTR_FREEBSD
+ size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5,
+ value, size);
+#endif
+ if (size < 0) {
+ free(value);
+ value = NULL;
+ }
+ }
+ if (size < 0)
+ *sizep = 0;
+ else
+ *sizep = (size_t)size;
+#else /* !ARCHIVE_XATTR_SUPPORT */
+ (void)path; /* UNUSED */
+ (void)name; /* UNUSED */
+ *sizep = 0;
+#endif /* !ARCHIVE_XATTR_SUPPORT */
+ return (value);
+}
+/*
+ * Set extended attribute on a path
+ * Returns 0 on error, 1 on success
+ */
int
-canNodump()
-{
+setXattr(const char *path, const char *name, const void *value, size_t size)
+{
+#if ARCHIVE_XATTR_SUPPORT
+#if ARCHIVE_XATTR_LINUX
+ if (lsetxattr(path, name, value, size, 0) == 0)
+#elif ARCHIVE_XATTR_DARWIN
+ if (setxattr(path, name, value, size, 0, XATTR_NOFOLLOW) == 0)
+#elif ARCHIVE_XATTR_AIX
+ if (lsetea(path, name, value, size, 0) == 0)
+#elif ARCHIVE_XATTR_FREEBSD
+ if (extattr_set_link(path, EXTATTR_NAMESPACE_USER, name + 5, value,
+ size) > -1)
+#else
+ if (0)
+#endif
+ return (1);
+#else /* !ARCHIVE_XATTR_SUPPORT */
+ (void)path; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)value; /* UNUSED */
+ (void)size; /* UNUSED */
+#endif /* !ARCHIVE_XATTR_SUPPORT */
return (0);
}
+#if ARCHIVE_ACL_SUNOS
+/* Fetch ACLs on Solaris using acl() or facl() */
+void *
+sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
+{
+ int cnt, cntcmd;
+ size_t size;
+ void *aclp;
+
+ if (cmd == GETACL) {
+ cntcmd = GETACLCNT;
+ size = sizeof(aclent_t);
+ }
+#if ARCHIVE_ACL_SUNOS_NFS4
+ else if (cmd == ACE_GETACL) {
+ cntcmd = ACE_GETACLCNT;
+ size = sizeof(ace_t);
+ }
+#endif
+ else {
+ errno = EINVAL;
+ *aclcnt = -1;
+ return (NULL);
+ }
+
+ aclp = NULL;
+ cnt = -2;
+ while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
+ if (path != NULL)
+ cnt = acl(path, cntcmd, 0, NULL);
+ else
+ cnt = facl(fd, cntcmd, 0, NULL);
+
+ if (cnt > 0) {
+ if (aclp == NULL)
+ aclp = malloc(cnt * size);
+ else
+ aclp = realloc(NULL, cnt * size);
+ if (aclp != NULL) {
+ if (path != NULL)
+ cnt = acl(path, cmd, cnt, aclp);
+ else
+ cnt = facl(fd, cmd, cnt, aclp);
+ }
+ } else {
+ if (aclp != NULL) {
+ free(aclp);
+ aclp = NULL;
+ }
+ break;
+ }
+ }
+
+ *aclcnt = cnt;
+ return (aclp);
+}
+#endif /* ARCHIVE_ACL_SUNOS */
+
+/*
+ * Set test ACLs on a path
+ * Return values:
+ * 0: error setting ACLs
+ * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set
+ * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set
+ */
+int
+setTestAcl(const char *path)
+{
+#if ARCHIVE_ACL_SUPPORT
+ int r = 1;
+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN
+ acl_t acl;
+#endif
+#if ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl;
+#endif
+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD
+ const char *acltext_posix1e = "user:1:rw-,"
+ "group:15:r-x,"
+ "user::rwx,"
+ "group::rwx,"
+ "other::r-x,"
+ "mask::rwx";
+#elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */
+ aclent_t aclp_posix1e[] = {
+ { USER_OBJ, -1, 4 | 2 | 1 },
+ { USER, 1, 4 | 2 },
+ { GROUP_OBJ, -1, 4 | 2 | 1 },
+ { GROUP, 15, 4 | 1 },
+ { CLASS_OBJ, -1, 4 | 2 | 1 },
+ { OTHER_OBJ, -1, 4 | 2 | 1 }
+ };
+#endif
+#if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */
+ const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1,"
+ "group:15:rxaRcs::allow:15,"
+ "owner@:rwpxaARWcCos::allow,"
+ "group@:rwpxaRcs::allow,"
+ "everyone@:rxaRcs::allow";
+#elif ARCHIVE_ACL_LIBRICHACL
+ const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask,"
+ "group:rwpxaRcS::mask,"
+ "other:rxaRcS::mask,"
+ "user:1:rwpaRcS::allow,"
+ "group:15:rxaRcS::allow,"
+ "owner@:rwpxaARWcCoS::allow,"
+ "group@:rwpxaRcS::allow,"
+ "everyone@:rxaRcS::allow";
+#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */
+ ace_t aclp_nfs4[] = {
+ { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
+ ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL |
+ ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
+ { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
+ ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
+ ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE },
+ { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
+ ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES |
+ ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS |
+ ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE,
+ ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE },
+ { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
+ ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
+ ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP,
+ ACE_ACCESS_ALLOWED_ACE_TYPE },
+ { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES |
+ ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
+ ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE }
+ };
+#elif ARCHIVE_ACL_DARWIN /* Mac OS X */
+ acl_entry_t aclent;
+ acl_permset_t permset;
+ const uid_t uid = 1;
+ uuid_t uuid;
+ int i;
+ const acl_perm_t acl_perms[] = {
+ ACL_READ_DATA,
+ ACL_WRITE_DATA,
+ ACL_APPEND_DATA,
+ ACL_EXECUTE,
+ ACL_READ_ATTRIBUTES,
+ ACL_READ_EXTATTRIBUTES,
+ ACL_READ_SECURITY,
+#if HAVE_DECL_ACL_SYNCHRONIZE
+ ACL_SYNCHRONIZE
+#endif
+ };
+#endif /* ARCHIVE_ACL_DARWIN */
+
+#if ARCHIVE_ACL_FREEBSD
+ acl = acl_from_text(acltext_nfs4);
+ failure("acl_from_text() error: %s", strerror(errno));
+ if (assert(acl != NULL) == 0)
+ return (0);
+#elif ARCHIVE_ACL_LIBRICHACL
+ richacl = richacl_from_text(acltext_nfs4, NULL, NULL);
+ failure("richacl_from_text() error: %s", strerror(errno));
+ if (assert(richacl != NULL) == 0)
+ return (0);
+#elif ARCHIVE_ACL_DARWIN
+ acl = acl_init(1);
+ failure("acl_init() error: %s", strerror(errno));
+ if (assert(acl != NULL) == 0)
+ return (0);
+ r = acl_create_entry(&acl, &aclent);
+ failure("acl_create_entry() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW);
+ failure("acl_set_tag_type() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ r = acl_get_permset(aclent, &permset);
+ failure("acl_get_permset() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) {
+ r = acl_add_perm(permset, acl_perms[i]);
+ failure("acl_add_perm() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ }
+ r = acl_set_permset(aclent, permset);
+ failure("acl_set_permset() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ r = mbr_uid_to_uuid(uid, uuid);
+ failure("mbr_uid_to_uuid() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ r = acl_set_qualifier(aclent, uuid);
+ failure("acl_set_qualifier() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+#endif /* ARCHIVE_ACL_DARWIN */
+
+#if ARCHIVE_ACL_NFS4
+#if ARCHIVE_ACL_FREEBSD
+ r = acl_set_file(path, ACL_TYPE_NFS4, acl);
+ acl_free(acl);
+#elif ARCHIVE_ACL_LIBRICHACL
+ r = richacl_set_file(path, richacl);
+ richacl_free(richacl);
+#elif ARCHIVE_ACL_SUNOS_NFS4
+ r = acl(path, ACE_SETACL,
+ (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);
+#elif ARCHIVE_ACL_DARWIN
+ r = acl_set_file(path, ACL_TYPE_EXTENDED, acl);
+ acl_free(acl);
+#endif
+ if (r == 0)
+ return (ARCHIVE_TEST_ACL_TYPE_NFS4);
+#endif /* ARCHIVE_ACL_NFS4 */
+
+#if ARCHIVE_ACL_POSIX1E
+#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
+ acl = acl_from_text(acltext_posix1e);
+ failure("acl_from_text() error: %s", strerror(errno));
+ if (assert(acl != NULL) == 0)
+ return (0);
+
+ r = acl_set_file(path, ACL_TYPE_ACCESS, acl);
+ acl_free(acl);
+#elif ARCHIVE_ACL_SUNOS
+ r = acl(path, SETACL,
+ (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e);
+#endif
+ if (r == 0)
+ return (ARCHIVE_TEST_ACL_TYPE_POSIX1E);
+ else
+ return (0);
+#endif /* ARCHIVE_ACL_POSIX1E */
+#if ARCHIVE_ACL_DARWIN
+testacl_free:
+ acl_free(acl);
#endif
+#endif /* ARCHIVE_ACL_SUPPORT */
+ (void)path; /* UNUSED */
+ return (0);
+}
/*
* Sleep as needed; useful for verifying disk timestamp changes by