summaryrefslogtreecommitdiff
path: root/archivers/libarchive/files/libarchive
diff options
context:
space:
mode:
Diffstat (limited to 'archivers/libarchive/files/libarchive')
-rw-r--r--archivers/libarchive/files/libarchive/CMakeLists.txt20
-rw-r--r--archivers/libarchive/files/libarchive/archive.h20
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry.c234
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry.h94
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_acl.3335
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_strmode.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_match.c14
-rw-r--r--archivers/libarchive/files/libarchive/archive_options.c11
-rw-r--r--archivers/libarchive/files/libarchive/archive_pack_dev.c4
-rw-r--r--archivers/libarchive/files/libarchive/archive_pack_dev.h2
-rw-r--r--archivers/libarchive/files/libarchive/archive_platform.h28
-rw-r--r--archivers/libarchive/files/libarchive/archive_read.c16
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_append_filter.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk.36
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c1090
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk_posix.c137
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk_private.h12
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk_set_standard_lookup.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_disk_windows.c59
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_open_filename.c20
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_open_memory.c3
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_private.h3
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_filter_lzop.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_filter_uu.c44
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_filter_xz.c194
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_7zip.c39
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_ar.c22
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_cab.c15
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_cpio.c17
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c40
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_lha.c12
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c71
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_rar.c5
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_tar.c281
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_warc.c237
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_xar.c87
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_zip.c158
-rw-r--r--archivers/libarchive/files/libarchive/archive_string.c117
-rw-r--r--archivers/libarchive/files/libarchive/archive_string.h8
-rw-r--r--archivers/libarchive/files/libarchive/archive_util.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_windows.c4
-rw-r--r--archivers/libarchive/files/libarchive/archive_windows.h4
-rw-r--r--archivers/libarchive/files/libarchive/archive_write.c8
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_add_filter_program.c1
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_add_filter_xz.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk_acl.c545
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk_posix.c584
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk_set_standard_lookup.c6
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk_windows.c7
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_open.311
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_open_memory.c3
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_7zip.c4
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_ar.c3
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_cpio.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_cpio_newc.c5
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_gnutar.c14
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_iso9660.c60
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_mtree.c4
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_pax.c183
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_shar.c3
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c11
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_xar.c21
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_zip.c12
-rw-r--r--archivers/libarchive/files/libarchive/config_freebsd.h2
-rw-r--r--archivers/libarchive/files/libarchive/libarchive-formats.54
-rw-r--r--archivers/libarchive/files/libarchive/tar.511
-rw-r--r--archivers/libarchive/files/libarchive/test/CMakeLists.txt20
-rw-r--r--archivers/libarchive/files/libarchive/test/list.h23
-rw-r--r--archivers/libarchive/files/libarchive/test/main.c2991
-rw-r--r--archivers/libarchive/files/libarchive/test/read_open_memory.c33
-rw-r--r--archivers/libarchive/files/libarchive/test/test.h337
-rw-r--r--archivers/libarchive/files/libarchive/test/test_acl_freebsd_nfs4.c547
-rw-r--r--archivers/libarchive/files/libarchive/test/test_acl_freebsd_posix1e.c265
-rw-r--r--archivers/libarchive/files/libarchive/test/test_acl_pax.c367
-rw-r--r--archivers/libarchive/files/libarchive/test/test_acl_pax.tar.uu117
-rw-r--r--archivers/libarchive/files/libarchive/test/test_archive_api_feature.c8
-rw-r--r--archivers/libarchive/files/libarchive/test/test_archive_string.c24
-rw-r--r--archivers/libarchive/files/libarchive/test/test_compat_gtar.c40
-rw-r--r--archivers/libarchive/files/libarchive/test/test_compat_solaris_tar_acl.c299
-rw-r--r--archivers/libarchive/files/libarchive/test/test_fuzz.c30
-rw-r--r--archivers/libarchive/files/libarchive/test/test_pax_filename_encoding.c8
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_disk.c6
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_disk_directory_traversals.c33
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_7zip.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_cpio_afio.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_isorr_bz2.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_rar.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_raw.c27
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip.c5
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_comment_stored.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_filename.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_mac_metadata.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_zip_sfx.c2
-rw-r--r--archivers/libarchive/files/libarchive/test/test_sparse_basic.c73
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_disk_appledouble.c4
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_filter_lzop.c6
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_iso9660.c205
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_zip_empty.c2
98 files changed, 4466 insertions, 5999 deletions
diff --git a/archivers/libarchive/files/libarchive/CMakeLists.txt b/archivers/libarchive/files/libarchive/CMakeLists.txt
index 4cc9a2ca2c1..1f85c014586 100644
--- a/archivers/libarchive/files/libarchive/CMakeLists.txt
+++ b/archivers/libarchive/files/libarchive/CMakeLists.txt
@@ -38,6 +38,8 @@ SET(libarchive_SOURCES
archive_hmac.c
archive_hmac_private.h
archive_match.c
+ archive_openssl_evp_private.h
+ archive_openssl_hmac_private.h
archive_options.c
archive_options_private.h
archive_pack_dev.h
@@ -166,15 +168,33 @@ SET(libarchive_MANS
archive_entry_time.3
archive_read.3
archive_read_add_passphrase.3
+ archive_read_data.3
archive_read_disk.3
+ archive_read_extract.3
+ archive_read_filter.3
+ archive_read_format.3
+ archive_read_free.3
+ archive_read_header.3
+ archive_read_new.3
+ archive_read_open.3
archive_read_set_options.3
archive_util.3
archive_write.3
+ archive_write_blocksize.3
+ archive_write_data.3
archive_write_disk.3
+ archive_write_filter.3
+ archive_write_finish_entry.3
+ archive_write_format.3
+ archive_write_free.3
+ archive_write_header.3
+ archive_write_new.3
+ archive_write_open.3
archive_write_set_options.3
archive_write_set_passphrase.3
cpio.5
libarchive.3
+ libarchive_changes.3
libarchive_internals.3
libarchive-formats.5
mtree.5
diff --git a/archivers/libarchive/files/libarchive/archive.h b/archivers/libarchive/files/libarchive/archive.h
index 1794dd34fc5..d400735a272 100644
--- a/archivers/libarchive/files/libarchive/archive.h
+++ b/archivers/libarchive/files/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3003001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.2.1"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -373,7 +373,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
* 4) Repeatedly call archive_read_next_header to get information about
* successive archive entries. Call archive_read_data to extract
* data for entries of interest.
- * 5) Call archive_read_finish to end processing.
+ * 5) Call archive_read_free to end processing.
*/
__LA_DECL struct archive *archive_read_new(void);
@@ -562,7 +562,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *);
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
@@ -984,12 +984,12 @@ __LA_DECL int archive_read_disk_can_descend(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
-/* Request that the access time of the entry visited by travesal be restored. */
+/* Request that the access time of the entry visited by traversal be restored. */
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
/*
* Set behavior. The "flags" argument selects optional behavior.
*/
-/* Request that the access time of the entry visited by travesal be restored.
+/* Request that the access time of the entry visited by traversal be restored.
* This is the same as archive_read_disk_set_atime_restored. */
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
/* Default: Do not skip an entry which has nodump flags. */
@@ -1001,6 +1001,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
/* Default: Xattrs are read from disk. */
#define ARCHIVE_READDISK_NO_XATTR (0x0010)
+/* Default: ACLs are read from disk. */
+#define ARCHIVE_READDISK_NO_ACL (0x0020)
+/* Default: File flags are read from disk. */
+#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
@@ -1124,7 +1128,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *,
/*
* Flags to tell a matching type of time stamps. These are used for
- * following functinos.
+ * following functions.
*/
/* Time flag: mtime to be tested. */
#define ARCHIVE_MATCH_MTIME (0x0100)
@@ -1144,7 +1148,7 @@ __LA_DECL int archive_match_include_date(struct archive *, int _flag,
const char *_datestr);
__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
const wchar_t *_datestr);
-/* Set inclusion time by a particluar file. */
+/* Set inclusion time by a particular file. */
__LA_DECL int archive_match_include_file_time(struct archive *,
int _flag, const char *_pathname);
__LA_DECL int archive_match_include_file_time_w(struct archive *,
diff --git a/archivers/libarchive/files/libarchive/archive_entry.c b/archivers/libarchive/files/libarchive/archive_entry.c
index 4ac19660893..10eff11b287 100644
--- a/archivers/libarchive/files/libarchive/archive_entry.c
+++ b/archivers/libarchive/files/libarchive/archive_entry.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a)
{
struct archive_entry *entry;
- entry = (struct archive_entry *)malloc(sizeof(*entry));
+ entry = (struct archive_entry *)calloc(1, sizeof(*entry));
if (entry == NULL)
return (NULL);
- memset(entry, 0, sizeof(*entry));
entry->archive = a;
return (entry);
}
@@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
}
/*
+ * Return a bitmask of ACL types in an archive entry ACL list
+ */
+int
+archive_entry_acl_types(struct archive_entry *entry)
+{
+ return (archive_acl_types(&entry->acl));
+}
+
+/*
* Return a count of entries matching "want_type".
*/
int
@@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
}
/*
- * Generate a text version of the ACL. The flags parameter controls
+ * Generate a text version of the ACL. The flags parameter controls
* the style of the generated ACL.
*/
+wchar_t *
+archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+ int flags)
+{
+ return (archive_acl_to_text_w(&entry->acl, len, flags,
+ entry->archive));
+}
+
+char *
+archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+ int flags)
+{
+ return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
+}
+
+char *
+_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
+ int flags, struct archive_string_conv *sc)
+{
+ return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
+}
+
+/*
+ * ACL text parser.
+ */
+int
+archive_entry_acl_from_text_w(struct archive_entry *entry,
+ const wchar_t *wtext, int type)
+{
+ return (archive_acl_from_text_w(&entry->acl, wtext, type));
+}
+
+int
+archive_entry_acl_from_text(struct archive_entry *entry,
+ const char *text, int type)
+{
+ return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
+}
+
+int
+_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
+ int type, struct archive_string_conv *sc)
+{
+ return (archive_acl_from_text_l(&entry->acl, text, type, sc));
+}
+
+/* Deprecated */
+static int
+archive_entry_acl_text_compat(int *flags)
+{
+ if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
+ return (1);
+
+ /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
+ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
+
+ /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
+ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
+
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
+
+ return (0);
+}
+
+/* Deprecated */
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
- const wchar_t *r;
- r = archive_acl_text_w(entry->archive, &entry->acl, flags);
- if (r == NULL && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (r);
+ if (entry->acl.acl_text_w != NULL) {
+ free(entry->acl.acl_text_w);
+ entry->acl.acl_text_w = NULL;
+ }
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
+ NULL, flags, entry->archive);
+ return (entry->acl.acl_text_w);
}
+/* Deprecated */
const char *
archive_entry_acl_text(struct archive_entry *entry, int flags)
{
- const char *p;
- if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
- && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (p);
+ if (entry->acl.acl_text != NULL) {
+ free(entry->acl.acl_text);
+ entry->acl.acl_text = NULL;
+ }
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
+ flags, NULL);
+
+ return (entry->acl.acl_text);
}
+/* Deprecated */
int
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
const char **acl_text, size_t *len, struct archive_string_conv *sc)
{
- return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
+ if (entry->acl.acl_text != NULL) {
+ free(entry->acl.acl_text);
+ entry->acl.acl_text = NULL;
+ }
+
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
+ (ssize_t *)len, flags, sc);
+
+ *acl_text = entry->acl.acl_text;
+
+ return (0);
}
/*
@@ -1553,7 +1649,10 @@ static struct flag {
{ "nosappnd", L"nosappnd", SF_APPEND, 0 },
{ "nosappend", L"nosappend", SF_APPEND, 0 },
#endif
-#ifdef EXT2_APPEND_FL /* 'a' */
+#if defined(FS_APPEND_FL) /* 'a' */
+ { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 },
+ { "nosappend", L"nosappend", FS_APPEND_FL, 0 },
+#elif defined(EXT2_APPEND_FL) /* 'a' */
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
#endif
@@ -1566,7 +1665,11 @@ static struct flag {
{ "noschange", L"noschange", SF_IMMUTABLE, 0 },
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
#endif
-#ifdef EXT2_IMMUTABLE_FL /* 'i' */
+#if defined(FS_IMMUTABLE_FL) /* 'i' */
+ { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 },
+ { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 },
+ { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 },
+#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
@@ -1590,7 +1693,9 @@ static struct flag {
#ifdef UF_NODUMP
{ "nodump", L"nodump", 0, UF_NODUMP},
#endif
-#ifdef EXT2_NODUMP_FL /* 'd' */
+#if defined(FS_NODUMP_FL) /* 'd' */
+ { "nodump", L"nodump", 0, FS_NODUMP_FL},
+#elif defined(EXT2_NODUMP_FL) /* 'd' */
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
#endif
#ifdef UF_OPAQUE
@@ -1603,65 +1708,124 @@ static struct flag {
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
-#ifdef EXT2_UNRM_FL
+#if defined(FS_UNRM_FL)
+ { "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
+#elif defined(EXT2_UNRM_FL)
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
-#ifdef EXT2_BTREE_FL
+#if defined(FS_BTREE_FL)
+ { "nobtree", L"nobtree", FS_BTREE_FL, 0 },
+#elif defined(EXT2_BTREE_FL)
{ "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
#endif
-#ifdef EXT2_ECOMPR_FL
+#if defined(FS_ECOMPR_FL)
+ { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 },
+#elif defined(EXT2_ECOMPR_FL)
{ "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
#endif
-#ifdef EXT2_COMPR_FL /* 'c' */
+#if defined(FS_COMPR_FL) /* 'c' */
+ { "nocompress", L"nocompress", FS_COMPR_FL, 0 },
+#elif defined(EXT2_COMPR_FL) /* 'c' */
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
#endif
-#ifdef EXT2_NOATIME_FL /* 'A' */
+#if defined(FS_NOATIME_FL) /* 'A' */
+ { "noatime", L"noatime", 0, FS_NOATIME_FL},
+#elif defined(EXT2_NOATIME_FL) /* 'A' */
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
#endif
-#ifdef EXT2_DIRTY_FL
+#if defined(FS_DIRTY_FL)
+ { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0},
+#elif defined(EXT2_DIRTY_FL)
{ "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
#endif
-#ifdef EXT2_COMPRBLK_FL
-#ifdef EXT2_NOCOMPR_FL
+#if defined(FS_COMPRBLK_FL)
+#if defined(FS_NOCOMPR_FL)
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL},
+#else
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0},
+#endif
+#elif defined(EXT2_COMPRBLK_FL)
+#if defined(EXT2_NOCOMPR_FL)
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
#else
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
#endif
#endif
-#ifdef EXT2_DIRSYNC_FL
+#if defined(FS_DIRSYNC_FL)
+ { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
+#elif defined(EXT2_DIRSYNC_FL)
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
#endif
-#ifdef EXT2_INDEX_FL
+#if defined(FS_INDEX_FL)
+ { "nohashidx", L"nohashidx", FS_INDEX_FL, 0},
+#elif defined(EXT2_INDEX_FL)
{ "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
#endif
-#ifdef EXT2_IMAGIC_FL
+#if defined(FS_IMAGIC_FL)
+ { "noimagic", L"noimagic", FS_IMAGIC_FL, 0},
+#elif defined(EXT2_IMAGIC_FL)
{ "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
#endif
-#ifdef EXT3_JOURNAL_DATA_FL
+#if defined(FS_JOURNAL_DATA_FL)
+ { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
+#elif defined(EXT3_JOURNAL_DATA_FL)
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
#endif
-#ifdef EXT2_SECRM_FL
+#if defined(FS_SECRM_FL)
+ { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
+#elif defined(EXT2_SECRM_FL)
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
#endif
-#ifdef EXT2_SYNC_FL
+#if defined(FS_SYNC_FL)
+ { "nosync", L"nosync", FS_SYNC_FL, 0},
+#elif defined(EXT2_SYNC_FL)
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
#endif
-#ifdef EXT2_NOTAIL_FL
+#if defined(FS_NOTAIL_FL)
+ { "notail", L"notail", 0, FS_NOTAIL_FL},
+#elif defined(EXT2_NOTAIL_FL)
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
#endif
-#ifdef EXT2_TOPDIR_FL
+#if defined(FS_TOPDIR_FL)
+ { "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
+#elif defined(EXT2_TOPDIR_FL)
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
#endif
-#ifdef EXT2_RESERVED_FL
+#ifdef FS_ENCRYPT_FL
+ { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0},
+#endif
+#ifdef FS_HUGE_FILE_FL
+ { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0},
+#endif
+#ifdef FS_EXTENT_FL
+ { "noextent", L"noextent", FS_EXTENT_FL, 0},
+#endif
+#ifdef FS_EA_INODE_FL
+ { "noeainode", L"noeainode", FS_EA_INODE_FL, 0},
+#endif
+#ifdef FS_EOFBLOCKS_FL
+ { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0},
+#endif
+#ifdef FS_NOCOW_FL
+ { "nocow", L"nocow", FS_NOCOW_FL, 0},
+#endif
+#ifdef FS_INLINE_DATA_FL
+ { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0},
+#endif
+#ifdef FS_PROJINHERIT_FL
+ { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
+#endif
+#if defined(FS_RESERVED_FL)
+ { "noreserved", L"noreserved", FS_RESERVED_FL, 0},
+#elif defined(EXT2_RESERVED_FL)
{ "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
#endif
-
{ NULL, NULL, 0, 0 }
};
diff --git a/archivers/libarchive/files/libarchive/archive_entry.h b/archivers/libarchive/files/libarchive/archive_entry.h
index dab2c9d8287..7645f0cf601 100644
--- a/archivers/libarchive/files/libarchive/archive_entry.h
+++ b/archivers/libarchive/files/libarchive/archive_entry.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3003001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -65,6 +66,27 @@ typedef int64_t la_int64_t;
# endif
#endif
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
@@ -104,6 +126,12 @@ typedef int64_t la_int64_t;
# define __LA_DECL
#endif
+#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
+# define __LA_DEPRECATED __attribute__((deprecated))
+#else
+# define __LA_DEPRECATED
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -420,6 +448,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
/*
* Inheritance values (NFS4 ACLs only); included in permset.
*/
+#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
@@ -433,15 +462,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
- | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
+ | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
+ | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
/* We need to be able to specify combinations of these. */
-#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
-#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
-#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
@@ -492,21 +522,51 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
* Construct a text-format ACL. The flags argument is a bitmask that
* can include any of the following:
*
+ * Flags only for archive entries with POSIX.1e ACL:
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
- * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
- * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
- * each ACL entry. ('star' introduced this for POSIX.1e, this flag
- * also applies to NFS4.)
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
- * default ACL entry, as used in old Solaris ACLs.
+ * default ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
+ * "mask" entries.
+ *
+ * Flags only for archive entries with NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
+ * unset permissions and flags in NFSv4 ACL permission and flag fields
+ *
+ * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
+ * each ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
+ * instead of newline.
*/
-#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
-#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
+#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
+#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
+#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
+#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
+#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
+
+__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
+ const wchar_t * /* wtext */, int /* type */);
+__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
+ const char * /* text */, int /* type */);
+
+/* Deprecated constants */
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
+
+/* Deprecated functions */
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
- int /* flags */);
+ int /* flags */) __LA_DEPRECATED;
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
- int /* flags */);
+ int /* flags */) __LA_DEPRECATED;
+
+/* Return bitmask of ACL types in an archive entry */
+__LA_DECL int archive_entry_acl_types(struct archive_entry *);
/* Return a count of entries matching 'want_type' */
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
diff --git a/archivers/libarchive/files/libarchive/archive_entry_acl.3 b/archivers/libarchive/files/libarchive/archive_entry_acl.3
index 5aff9968235..c5115f7274d 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_acl.3
+++ b/archivers/libarchive/files/libarchive/archive_entry_acl.3
@@ -1,4 +1,5 @@
.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 2, 2012
+.Dd February 15, 2017
.Dt ARCHIVE_ENTRY_ACL 3
.Os
.Sh NAME
@@ -30,10 +31,14 @@
.Nm archive_entry_acl_add_entry_w ,
.Nm archive_entry_acl_clear ,
.Nm archive_entry_acl_count ,
+.Nm archive_entry_acl_from_text ,
+.Nm archive_entry_acl_from_text_w,
.Nm archive_entry_acl_next ,
.Nm archive_entry_acl_next_w ,
.Nm archive_entry_acl_reset ,
-.Nm archive_entry_acl_text_w
+.Nm archive_entry_acl_to_text ,
+.Nm archive_entry_acl_to_text_w ,
+.Nm archive_entry_acl_types
.Nd functions for manipulating Access Control Lists in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
.Ft int
+.Fo archive_entry_acl_from_text
+.Fa "struct archive_entry *a"
+.Fa "const char *text"
+.Fa "int type"
+.Fc
+.Ft int
+.Fo archive_entry_acl_from_text_w
+.Fa "struct archive_entry *a"
+.Fa "const wchar_t *text"
+.Fa "int type"
+.Fc
+.Ft int
.Fo archive_entry_acl_next
.Fa "struct archive_entry *a"
.Fa "int type"
@@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive)
.Fc
.Ft int
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
-.Ft const wchar_t *
-.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
+.Ft char *
+.Fo archive_entry_acl_to_text
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft wchar_t *
+.Fo archive_entry_acl_to_text_w
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fn archive_entry_acl_types "struct archive_entry *a"
.\" enum?
.Sh DESCRIPTION
-An
-.Dq Access Control List
-is a generalisation of the classic Unix permission system.
+The
+.Dq Access Control Lists (ACLs)
+extend the standard Unix perssion model.
The ACL interface of
.Nm libarchive
-is derived from the POSIX.1e draft, but restricted to simplify dealing
-with practical implementations in various Operating Systems and archive formats.
-.Pp
-An ACL consists of a number of independent entries.
+supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by
+various levels of ACL support in operating systems, file systems and archive
+formats.
+.Ss POSIX.1e Access Control Lists
+A POSIX.1e ACL consists of a number of independent entries.
Each entry specifies the permission set as bitmask of basic permissions.
-Valid permissions are:
+Valid permissions in the
+.Fa permset
+are:
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
-.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
-.It Dv ARCHIVE_ENTRY_ACL_WRITE
-.It Dv ARCHIVE_ENTRY_ACL_READ
+.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r )
+.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w )
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
.El
The permissions correspond to the normal Unix permissions.
.Pp
-The tag specifies the principal to which the permission applies.
+The
+.Fa tag
+specifies the principal to which the permission applies.
Valid values are:
-.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
.It Dv ARCHIVE_ENTRY_ACL_USER
The user specified by the name field.
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
@@ -119,8 +153,9 @@ The group who owns the file.
.It Dv ARCHIVE_ENTRY_ACL_MASK
The maximum permissions to be obtained via group permissions.
.It Dv ARCHIVE_ENTRY_ACL_OTHER
-Any principal who doesn't have a user or group entry.
+Any principal who is not file owner or a member of the owning group.
.El
+.Pp
The principals
.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
@@ -129,19 +164,123 @@ and
are equivalent to user, group and other in the classic Unix permission
model and specify non-extended ACL entries.
.Pp
-All files have an access ACL
+All files with have an access ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
This specifies the permissions required for access to the file itself.
Directories have an additional ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
which controls the initial access ACL for newly created directory entries.
+.Ss NFSv4 Access Control Lists
+A NFSv4 ACL consists of multiple individual entries called Access Control
+Entries (ACEs).
+.Pp
+There are four possible types of a NFSv4 ACE:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+Allow principal to perform actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+Prevent principal from performing actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+Log access attempts by principal which require given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+Trigger a system alarm on access attempts by principal which require given
+permissions.
+.El
+.Pp
+The
+.Fa tag
+specifies the principal to which the permission applies.
+Valid values are:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.It Dv ARCHIVE_ENTRY_ACL_USER
+The user specified by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
+The owner of the file.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP
+The group specied by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
+The group who owns the file.
+.It Dv ARCHIVE_ENTRY_ACL_EVERYONE
+Any principal who is not file owner or a member of the owning group.
+.El
+.Pp
+Entries with the
+.Dv ARCHIVE_ENTRY_ACL_USER
+or
+.Dv ARCHIVE_ENTRY_ACL_GROUP
+tag store the user and group name in the
+.Fa name
+string and optionally the user or group ID in the
+.Fa qualifier
+integer.
+.Pp
+NFSv4 ACE permissions and flags are stored in the same
+.Fa permset
+bitfield. Some permissions share the same constant and permission character but
+have different effect on directories than on files. The following ACE
+permissions are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r )
+Read data (file).
+.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r )
+List entries (directory).
+.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w )
+Write data (file).
+.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w )
+Create files (directory).
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
+Execute file or change into a directory.
+.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p )
+Append data (file).
+.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p )
+Create subdirectories (directory).
+.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D )
+Remove files and subdirectories inside a directory.
+.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d )
+Remove file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a )
+Read file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A )
+Write file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R )
+Read named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W )
+Write named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c )
+Read file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C )
+Write file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o )
+Change owner of a file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s )
+Use synchronous I/O.
+.El
.Pp
+The following NFSv4 ACL inheritance flags are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f )
+Inherit parent directory ACE to files.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d )
+Inherit parent directory ACE to subdirectories.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i )
+Only inherit, do not apply the permission on the directory itself.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
+Do not propagate inherit flags. Only first-level entries inherit ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
+Trigger alarm or audit on succesful access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
+Trigger alarm or audit on failed access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
+Mark that ACE was inherited.
+.El
+.Ss Functions
.Fn archive_entry_acl_add_entry
and
.Fn archive_entry_acl_add_entry_w
add a single ACL entry.
For the access ACL and non-extended principals, the classic Unix permissions
-are updated.
+are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
+entries.
.Pp
.Fn archive_entry_acl_clear
removes all ACL entries and resets the enumeration pointer.
@@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer.
counts the ACL entries that have the given type mask.
.Fa type
can be the bitwise-or of
-.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
-and
-.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
-If
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.El
+for POSIX.1e ACLs and
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+.El
+for NFSv4 ACLs. For POSIX.1e ACLs if
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
is included and at least one extended ACL entry is found,
the three non-extened ACLs are added.
.Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+add new
+.Pq or merge with existing
+ACL entries from
+.Pq wide
+text. The argument
+.Fa type
+may take one of the following values:
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4
+.El
+Supports all formats that can be created with
+.Fn archive_entry_acl_to_text
+or respective
+.Fn archive_entry_acl_to_text_w .
+Existing ACL entries are preserved. To get a clean new ACL from text
+.Fn archive_entry_acl_clear
+must be called first. Entries prefixed with
+.Dq default:
+are treated as
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+unless
+.Fa type
+is
+.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 .
+Invalid entries, non-parseable ACL entries and entries beginning with
+the
+.Sq #
+character
+.Pq comments
+are skipped.
+.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@@ -179,29 +362,81 @@ or set using
Otherwise, the function returns the same value as
.Fn archive_entry_acl_count .
.Pp
-.Fn archive_entry_acl_text_w
-converts the ACL entries for the given type mask into a wide string.
-In addition to the normal type flags,
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+.Fn archive_entry_acl_to_text
and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-can be specified to further customize the result.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
+.Fn archive_entry_acl_to_text_w
+convert the ACL entries for the given type into a
+.Pq wide
+string of ACL entries separated by newline. If the the pointer
+.Fa len_p
+is not NULL, then the function shall return the length of the string
+.Pq not including the NULL terminator
+in the location pointed to by
+.Fa len_p .
+The
+.Fa flag
+argument is a bitwise-or.
+.Pp
+The following flags are effective only on POSIX.1e ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+Output access ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+Output POSIX.1e default ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
+Prefix each default ACL entry with the word
+.Dq default: .
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
+The mask and other ACLs don not contain a double colon.
+.El
+.Pp
+The following flags are effecive only on NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT
+Do not output minus characters for unset permissions and flags in NFSv4 ACL
+permission and flag fields.
+.El
+.Pp
+The following flags are effective on both POSIX.1e and NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+Add an additional colon-separated field containing the user or group id.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
+Separate ACL entries with comma instead of newline.
+.El
+.Pp
+If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
+It the entry contains POSIX.1e ACLs and none of the flags
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
or
-.Fn archive_entry_acl_text_w .
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+are specified, both access and default entries are returned and default entries
+are prefixed with
+.Dq default: .
+.Pp
+.Fn archive_entry_acl_types
+get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
+ACL entries cannot be mixed, this function is a very efficient way to detect if
+an ACL already contains POSIX.1e or NFSv4 ACL entries.
.Sh RETURN VALUES
.Fn archive_entry_acl_count
and
.Fn archive_entry_acl_reset
returns the number of ACL entries that match the given type mask.
-If the type mask includes
+For POSIX.1e ACLS if the type mask includes
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
and at least one extended ACL entry exists, the three classic Unix
permissions are counted.
.Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+return
+.Dv ARCHIVE_OK
+if all entries were successfully parsed and
+.Dv ARCHIVE_WARN
+if one or more entries were invalid or non-parseable.
+.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@@ -216,20 +451,16 @@ if
.Fn archive_entry_acl_reset
has not been called first.
.Pp
-.Fn archive_entry_text_w
-returns a wide string representation of the ACL entrise matching the
-given type mask.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
-or
-.Fn archive_entry_acl_text_w .
+.Fn archive_entry_acl_to_text
+returns a string representing the ACL entries matching the given type and
+flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_to_text_w
+returns a wide string representing the ACL entries matching the given type
+and flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_types
+returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
.Sh SEE ALSO
-.Xr archive_entry 3
-.Xr libarchive 3 ,
-.Sh BUGS
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
-and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-are not documented.
+.Xr archive_entry 3 ,
+.Xr libarchive 3
diff --git a/archivers/libarchive/files/libarchive/archive_entry_strmode.c b/archivers/libarchive/files/libarchive/archive_entry_strmode.c
index 16cb3f7bb33..af2517a3219 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_strmode.c
+++ b/archivers/libarchive/files/libarchive/archive_entry_strmode.c
@@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry)
if (mode & 0001) bp[9] = 't';
else bp[9] = 'T';
}
- if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
+ if (archive_entry_acl_types(entry) != 0)
bp[10] = '+';
return (bp);
diff --git a/archivers/libarchive/files/libarchive/archive_match.c b/archivers/libarchive/files/libarchive/archive_match.c
index 4c41badf1f8..be72066eac6 100644
--- a/archivers/libarchive/files/libarchive/archive_match.c
+++ b/archivers/libarchive/files/libarchive/archive_match.c
@@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a,
}
/*
- * Utilty functions to get statistic information for inclusion patterns.
+ * Utility functions to get statistic information for inclusion patterns.
*/
int
archive_match_path_unmatched_inclusions(struct archive *_a)
@@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
}
}
- /* If something error happend, report it immediately. */
+ /* If an error occurred, report it immediately. */
if (r < ARCHIVE_OK) {
archive_copy_error(&(a->archive), ar);
archive_read_free(ar);
@@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
#endif /* _WIN32 && !__CYGWIN__ */
/*
- * Call back funtions for archive_rb.
+ * Call back functions for archive_rb.
*/
static int
cmp_node_mbs(const struct archive_rb_node *n1,
@@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag,
&(a->exclusion_tree), pathname);
/*
- * We always overwrite comparison condision.
+ * We always overwrite comparison condition.
* If you do not want to overwrite it, you should not
* call archive_match_exclude_entry(). We cannot know
* what behavior you really expect since overwriting
@@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
if (nsec == a->older_ctime_nsec &&
(a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
== 0)
- return (1); /* Eeual, skip it. */
+ return (1); /* Equal, skip it. */
}
}
if (a->newer_mtime_filter) {
@@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
}
}
- /* If there is no excluson list, include the file. */
+ /* If there is no exclusion list, include the file. */
if (a->exclusion_entry_list.count == 0)
return (0);
@@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
break;
}
- /* Add oowner id. */
+ /* Add owner id. */
if (i == ids->count)
ids->ids[ids->count++] = id;
else if (ids->ids[i] != id) {
diff --git a/archivers/libarchive/files/libarchive/archive_options.c b/archivers/libarchive/files/libarchive/archive_options.c
index dbf3e80e902..6496025a5f6 100644
--- a/archivers/libarchive/files/libarchive/archive_options.c
+++ b/archivers/libarchive/files/libarchive/archive_options.c
@@ -26,6 +26,10 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
#include "archive_options_private.h"
static const char *
@@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options,
if (options == NULL || options[0] == '\0')
return ARCHIVE_OK;
- data = (char *)malloc(strlen(options) + 1);
- strcpy(data, options);
+ if ((data = strdup(options)) == NULL) {
+ archive_set_error(a,
+ ENOMEM, "Out of memory adding file to list");
+ return (ARCHIVE_FATAL);
+ }
s = (const char *)data;
do {
diff --git a/archivers/libarchive/files/libarchive/archive_pack_dev.c b/archivers/libarchive/files/libarchive/archive_pack_dev.c
index bb4082c88a9..ccd88129a15 100644
--- a/archivers/libarchive/files/libarchive/archive_pack_dev.c
+++ b/archivers/libarchive/files/libarchive/archive_pack_dev.c
@@ -1,4 +1,4 @@
-/* $NetBSD: archive_pack_dev.c,v 1.2 2016/06/20 17:24:57 joerg Exp $ */
+/* $NetBSD: archive_pack_dev.c,v 1.3 2017/02/25 21:11:20 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#endif
#if !defined(lint)
-__RCSID("$NetBSD: archive_pack_dev.c,v 1.2 2016/06/20 17:24:57 joerg Exp $");
+__RCSID("$NetBSD: archive_pack_dev.c,v 1.3 2017/02/25 21:11:20 joerg Exp $");
#endif /* not lint */
#ifdef HAVE_LIMITS_H
diff --git a/archivers/libarchive/files/libarchive/archive_pack_dev.h b/archivers/libarchive/files/libarchive/archive_pack_dev.h
index 91956d49569..15e59f4a151 100644
--- a/archivers/libarchive/files/libarchive/archive_pack_dev.h
+++ b/archivers/libarchive/files/libarchive/archive_pack_dev.h
@@ -1,4 +1,4 @@
-/* $NetBSD: archive_pack_dev.h,v 1.2 2016/06/20 17:24:57 joerg Exp $ */
+/* $NetBSD: archive_pack_dev.h,v 1.3 2017/02/25 21:11:20 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
diff --git a/archivers/libarchive/files/libarchive/archive_platform.h b/archivers/libarchive/files/libarchive/archive_platform.h
index b06c3cd28fa..c9a96020162 100644
--- a/archivers/libarchive/files/libarchive/archive_platform.h
+++ b/archivers/libarchive/files/libarchive/archive_platform.h
@@ -147,8 +147,25 @@
* acl_set_file(), and ACL_USER, we assume it has the rest of the
* POSIX.1e draft functions used in archive_read_extract.c.
*/
-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
+#if HAVE_ACL_USER
#define HAVE_POSIX_ACL 1
+#elif HAVE_ACL_TYPE_EXTENDED
+#define HAVE_DARWIN_ACL 1
+#endif
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
+#define HAVE_SUN_ACL 1
+#endif
+
+/* Define if platform supports NFSv4 ACLs */
+#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
+#define HAVE_NFS4_ACL 1
#endif
/*
@@ -159,6 +176,15 @@
#define CAN_RESTORE_METADATA_FD
#endif
+/*
+ * glibc 2.24 deprecates readdir_r
+ */
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#define USE_READDIR_R 1
+#else
+#undef USE_READDIR_R
+#endif
+
/* Set up defaults for internal error codes. */
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
#if HAVE_EFTYPE
diff --git a/archivers/libarchive/files/libarchive/archive_read.c b/archivers/libarchive/files/libarchive/archive_read.c
index 0bbacc8f185..d1fecebfd09 100644
--- a/archivers/libarchive/files/libarchive/archive_read.c
+++ b/archivers/libarchive/files/libarchive/archive_read.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
+static int close_filters(struct archive_read *);
static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
@@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a)
{
slot = choose_format(a);
if (slot < 0) {
- __archive_read_close_filters(a);
+ close_filters(a);
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
@@ -582,7 +583,6 @@ choose_filters(struct archive_read *a)
/* Verify the filter by asking it for some data. */
__archive_read_filter_ahead(a->filter, 1, &avail);
if (avail < 0) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -601,7 +601,6 @@ choose_filters(struct archive_read *a)
a->filter = filter;
r = (best_bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
@@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a,
return (a->format->read_data)(a, buff, size, offset);
}
-int
-__archive_read_close_filters(struct archive_read *a)
+static int
+close_filters(struct archive_read *a)
{
struct archive_read_filter *f = a->filter;
int r = ARCHIVE_OK;
@@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a)
void
__archive_read_free_filters(struct archive_read *a)
{
+ /* Make sure filters are closed and their buffers are freed */
+ close_filters(a);
+
while (a->filter != NULL) {
struct archive_read_filter *t = a->filter->upstream;
free(a->filter);
@@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a)
/* TODO: Clean up the formatters. */
/* Release the filter objects. */
- r1 = __archive_read_close_filters(a);
+ r1 = close_filters(a);
if (r1 < r)
r = r1;
diff --git a/archivers/libarchive/files/libarchive/archive_read_append_filter.c b/archivers/libarchive/files/libarchive/archive_read_append_filter.c
index 3a0d4d68d89..5e4d1630798 100644
--- a/archivers/libarchive/files/libarchive/archive_read_append_filter.c
+++ b/archivers/libarchive/files/libarchive/archive_read_append_filter.c
@@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code)
a->filter = filter;
r2 = (bidder->init)(a->filter);
if (r2 != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a,
a->filter = filter;
r = (bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk.3 b/archivers/libarchive/files/libarchive/archive_read_disk.3
index 525dc59cb49..2a5c1305ebd 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk.3
+++ b/archivers/libarchive/files/libarchive/archive_read_disk.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 2, 2012
+.Dd December 30, 2016
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
@@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_read_disk_set_symlink_physical "struct archive *"
.Ft int
.Fn archive_read_disk_set_symlink_hybrid "struct archive *"
-.Ft int
+.Ft const char *
.Fn archive_read_disk_gname "struct archive *" "gid_t"
-.Ft int
+.Ft const char *
.Fn archive_read_disk_uname "struct archive *" "uid_t"
.Ft int
.Fo archive_read_disk_set_gname_lookup
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c b/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c
index 74fe353d9d3..b2f1d17d971 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c
+++ b/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +38,11 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#ifdef HAVE_DARWIN_ACL
+#include <membership.h>
+#include <grp.h>
+#include <pwd.h>
+#endif
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
@@ -117,6 +123,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#define ACL_GET_PERM acl_get_perm_np
#endif
+/* NFSv4 platform ACL type */
+#if HAVE_SUN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
+#elif HAVE_DARWIN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
+#endif
+
static int setup_acls(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_mac_metadata(struct archive_read_disk *,
@@ -125,6 +140,10 @@ static int setup_xattrs(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_sparse(struct archive_read_disk *,
struct archive_entry *, int *fd);
+#if defined(HAVE_LINUX_FIEMAP_H)
+static int setup_sparse_fiemap(struct archive_read_disk *,
+ struct archive_entry *, int *fd);
+#endif
int
archive_read_disk_entry_from_file(struct archive *_a,
@@ -184,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a,
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
/* On FreeBSD, we get flags for free with the stat. */
/* TODO: Does this belong in copy_stat()? */
- if (st->st_flags != 0)
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
archive_entry_set_fflags(entry, st->st_flags, 0);
#endif
-#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/* Linux requires an extra ioctl to pull the flags. Although
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
- if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
+ (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
@@ -204,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
if (fd >= 0) {
int stflags;
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+ r = ioctl(fd,
+#if defined(FS_IOC_GETFLAGS)
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@@ -250,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls(a, entry, &fd);
- if (!a->suppress_xattr) {
+ r = 0;
+ if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
+ r = setup_acls(a, entry, &fd);
+ if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
}
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
r = r1;
@@ -302,20 +331,17 @@ setup_mac_metadata(struct archive_read_disk *a,
name = archive_entry_sourcepath(entry);
if (name == NULL)
name = archive_entry_pathname(entry);
+ else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't change dir to read extended attributes");
+ return (ARCHIVE_FAILED);
+ }
if (name == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't open file to read extended attributes: No name");
return (ARCHIVE_WARN);
}
- if (a->tree != NULL) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't change dir");
- return (ARCHIVE_FAILED);
- }
- }
-
/* Short-circuit if there's nothing to do. */
have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
if (have_attrs == -1) {
@@ -400,34 +426,87 @@ setup_mac_metadata(struct archive_read_disk *a,
}
#endif
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *, acl_entry_t,
+ int *, int *, const char **);
-#ifdef HAVE_POSIX_ACL
+static void add_trivial_nfs4_acl(struct archive_entry *);
+#endif
+
+#if HAVE_SUN_ACL
+static int
+sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
+#endif
+
+#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
static int translate_acl(struct archive_read_disk *a,
- struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
+ struct archive_entry *entry,
+#if HAVE_SUN_ACL
+ acl_t *acl,
+#else
+ acl_t acl,
+#endif
+ int archive_entry_acl_type);
static int
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
- acl_t acl;
-#if HAVE_ACL_IS_TRIVIAL_NP
- int r;
+#if HAVE_SUN_ACL
+ acl_t *acl;
+#else
+ acl_t acl;
#endif
+ int r;
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
+ accpath = NULL;
+
+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
+ if (*fd < 0)
+#else
+ /* For default ACLs on Linux we need reachable accpath */
+ if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
+#endif
+ {
+ accpath = archive_entry_sourcepath(entry);
+ if (accpath == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ accpath = archive_entry_pathname(entry);
+ if (accpath == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read ACLs");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL &&
+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
+ *fd < 0 &&
+#endif
+ (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ accpath, O_RDONLY | O_NONBLOCK);
+ }
+ }
archive_entry_acl_clear(entry);
-#ifdef ACL_TYPE_NFS4
- /* Try NFS4 ACL first. */
+ acl = NULL;
+
+#if HAVE_NFS4_ACL
+ /* Try NFSv4 ACL first. */
if (*fd >= 0)
+#if HAVE_SUN_ACL
+ /* Solaris reads both POSIX.1e and NFSv4 ACL here */
+ facl_get(*fd, 0, &acl);
+#elif HAVE_ACL_GET_FD_NP
+ acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#else
acl = acl_get_fd(*fd);
+#endif
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
- acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+ acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
#else
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
@@ -436,21 +515,62 @@ setup_acls(struct archive_read_disk *a,
acl = NULL;
#endif
else
- acl = acl_get_file(accpath, ACL_TYPE_NFS4);
-#if HAVE_ACL_IS_TRIVIAL_NP
+#if HAVE_SUN_ACL
+ /* Solaris reads both POSIX.1e and NFSv4 ACLs here */
+ acl_get(accpath, 0, &acl);
+#else
+ acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#endif
+
+
+#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
/* Ignore "trivial" ACLs that just mirror the file mode. */
- acl_is_trivial_np(acl, &r);
- if (r) {
- acl_free(acl);
- acl = NULL;
- }
+ if (acl != NULL) {
+#if HAVE_SUN_ACL
+ if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
+ &r) == 0 && r == 1)
+#elif HAVE_ACL_IS_TRIVIAL_NP
+ if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
#endif
+ {
+ acl_free(acl);
+ acl = NULL;
+ /*
+ * Simultaneous NFSv4 and POSIX.1e ACLs for the same
+ * entry are not allowed, so we should return here
+ */
+ return (ARCHIVE_OK);
+ }
+ }
+#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
if (acl != NULL) {
- translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
acl_free(acl);
- return (ARCHIVE_OK);
- }
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate "
+#if !HAVE_SUN_ACL
+ "NFSv4 "
+#endif
+ "ACLs");
+ }
+#if HAVE_DARWIN_ACL
+ /*
+ * 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);
#endif
+ return (r);
+ }
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_POSIX_ACL
+ /* This code path is skipped on MacOS and Solaris */
/* Retrieve access ACL from file. */
if (*fd >= 0)
@@ -467,88 +587,609 @@ setup_acls(struct archive_read_disk *a,
#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) {
+ if (r) {
+ acl_free(acl);
+ acl = NULL;
+ }
+ }
+#endif
+
if (acl != NULL) {
- translate_acl(a, entry, acl,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ 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 HAVE_ACL_GET_FD_NP
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
+ else
+#endif
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
- translate_acl(a, entry, acl,
+ 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 /* HAVE_POSIX_ACL */
return (ARCHIVE_OK);
}
/*
- * Translate system ACL into libarchive internal structure.
+ * Translate system ACL permissions into libarchive internal structure
*/
-
-static struct {
- int archive_perm;
- int platform_perm;
+static const struct {
+ const int archive_perm;
+ const int platform_perm;
} acl_perm_map[] = {
- {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
- {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
- {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
- {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}
+#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
+ {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}
+#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
+ {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},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else /* POSIX.1e ACL permissions */
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
+ {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}
#endif
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#ifdef ACL_TYPE_NFS4
-static struct {
- int archive_inherit;
- int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+ const int archive_inherit;
+ const int platform_inherit;
} acl_inherit_map[] = {
- {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+#if HAVE_SUN_ACL /* Solaris ACL inheritance flags */
+ {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},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
+ {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}
+#else /* FreeBSD NFSv4 ACL inheritance flags */
+ {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_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}
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#endif
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_DARWIN_ACL
+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;
+ struct passwd *pwd;
+ struct group *grp;
+
+ 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;
+ pwd = getpwuuid(q);
+ if (pwd == NULL) {
+ *ae_id = ugid;
+ *ae_name = NULL;
+ } else {
+ *ae_id = pwd->pw_uid;
+ *ae_name = archive_read_disk_uname(a, *ae_id);
+ }
+ } else if (idtype == ID_TYPE_GID) {
+ *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ grp = getgruuid(q);
+ if (grp == NULL) {
+ *ae_id = ugid;
+ *ae_name = NULL;
+ } else {
+ *ae_id = grp->gr_gid;
+ *ae_name = archive_read_disk_gname(a, *ae_id);
+ }
+ } else
+ r = 1;
+
+ acl_free(q);
+ return (r);
+}
+
+/*
+ * Add trivial NFSv4 ACL entries from mode
+ */
+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;
+}
+#elif HAVE_SUN_ACL
+/*
+ * Check if acl is trivial
+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
+ */
+static int
+sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
+{
+ 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];
+
+ if (acl == NULL || trivialp == NULL)
+ return (-1);
+
+ *trivialp = 0;
+
+ /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
+ if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
+ return (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 (acl->acl_type == ACLENT_T) {
+ if (acl->acl_cnt == 4)
+ *trivialp = 1;
+ return (0);
+ }
+
+ if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
+ return (-1);
+
+ /*
+ * 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 (acl->acl_cnt != p)
+ return (0);
+
+ p = 0;
+ for (i = 0; i < 6; i++) {
+ if (tace[i].a_access_mask != 0) {
+ ace = &((ace_t *)acl->acl_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 &&
+ ((acl->acl_flags & ACL_IS_DIR) == 0 ||
+ (tace[i].a_access_mask & wperm) == 0 ||
+ ace->a_access_mask !=
+ (tace[i].a_access_mask | ACE_DELETE_CHILD))))
+ return (0);
+ p++;
+ }
+ }
+
+ *trivialp = 1;
+ return (0);
+}
+#endif /* HAVE_SUN_ACL */
+
+#if HAVE_SUN_ACL
+/*
+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t *acl, 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;
+ ace_t *ace;
+
+ (void)default_entry_acl_type;
+
+ if (acl->acl_cnt <= 0)
+ return (ARCHIVE_OK);
+
+ for (e = 0; e < acl->acl_cnt; e++) {
+ ae_name = NULL;
+ ae_tag = 0;
+ ae_perm = 0;
+
+ if (acl->acl_type == ACE_T) {
+ ace = &((ace_t *)acl->acl_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 < (int)(sizeof(acl_inherit_map) /
+ sizeof(acl_inherit_map[0])); ++i) {
+ if ((ace->a_flags &
+ acl_inherit_map[i].platform_inherit) != 0)
+ ae_perm |=
+ acl_inherit_map[i].archive_inherit;
+ }
+
+ for (i = 0; i < (int)(sizeof(acl_perm_map) /
+ sizeof(acl_perm_map[0])); ++i) {
+ if ((ace->a_access_mask &
+ acl_perm_map[i].platform_perm) != 0)
+ ae_perm |=
+ acl_perm_map[i].archive_perm;
+ }
+ } else {
+ aclent = &((aclent_t *)acl->acl_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;
+ }
+
+ if ((aclent->a_perm & 1) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ if ((aclent->a_perm & 2) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+ if ((aclent->a_perm & 4) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_READ;
+ } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag, ae_id, ae_name);
+ }
+ return (ARCHIVE_OK);
+}
+#else /* !HAVE_SUN_ACL */
+/*
+ * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
+ * MacOS (NFSv4 only) 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;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
acl_entry_type_t acl_type;
+ int brand;
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
acl_flagset_t acl_flagset;
- int brand, r;
#endif
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int i, entry_acl_type;
- int s, ae_id, ae_tag, ae_perm;
+ int r, s, ae_id, ae_tag, ae_perm;
+#if !HAVE_DARWIN_ACL
+ void *q;
+#endif
const char *ae_name;
-
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_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.
- acl_get_brand_np(acl, &brand);
+ 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) {
@@ -556,40 +1197,67 @@ translate_acl(struct archive_read_disk *a,
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
break;
default:
- // XXX set warning message?
- return ARCHIVE_FAILED;
+ 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) {
- // XXX set warning message?
- return ARCHIVE_FAILED;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL entry type for NFSv4 ACL");
+ return (ARCHIVE_WARN);
}
break;
default:
- // XXX set warning message?
- return ARCHIVE_FAILED;
- break;
+ 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);
- while (s == 1) {
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get first ACL entry");
+ return (ARCHIVE_WARN);
+ }
+
+#if HAVE_DARWIN_ACL
+ while (s == 0)
+#else /* FreeBSD, Linux */
+ while (s == 1)
+#endif
+ {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
- acl_get_tag_type(acl_entry, &acl_tag);
+ 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) {
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
case ACL_USER:
- ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
- ae_name = archive_read_disk_uname(&a->archive, ae_id);
+ 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:
- ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
- ae_name = archive_read_disk_gname(&a->archive, ae_id);
+ 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:
@@ -604,24 +1272,52 @@ translate_acl(struct archive_read_disk *a,
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
+#else /* HAVE_DARWIN_ACL */
+ 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;
+#endif /* HAVE_DARWIN_ACL */
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
- // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
- // non-NFSv4 ACLs
+#if HAVE_DARWIN_ACL
+ /* Skip if translate_guid() above failed */
+ if (r != 0) {
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+#endif
+
+#if !HAVE_DARWIN_ACL
+ // XXX acl_type maps to allow/deny/audit/YYYY bits
entry_acl_type = default_entry_acl_type;
-#ifdef ACL_TYPE_NFS4
- r = acl_get_entry_type_np(acl_entry, &acl_type);
- if (r == 0) {
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
+ if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+#if HAVE_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;
@@ -635,29 +1331,54 @@ translate_acl(struct archive_read_disk *a,
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(acl_entry, &acl_flagset);
- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
- if (acl_get_flag_np(acl_flagset,
- acl_inherit_map[i].platform_inherit))
- ae_perm |= acl_inherit_map[i].archive_inherit;
+#endif /* HAVE_ACL_TYPE_NFS4 */
- }
-#endif
+ /*
+ * 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 < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+ r = acl_get_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit);
+ 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_inherit_map[i].archive_inherit;
+ }
+ }
+#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */
- acl_get_permset(acl_entry, &acl_permset);
+ 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 < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.
*/
- if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+ r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_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_perm_map[i].archive_perm;
}
@@ -666,10 +1387,18 @@ translate_acl(struct archive_read_disk *a,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+#if !HAVE_DARWIN_ACL
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get next ACL entry");
+ return (ARCHIVE_WARN);
+ }
+#endif
}
return (ARCHIVE_OK);
}
-#else
+#endif /* !HAVE_SUN_ACL */
+#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
static int
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
@@ -679,7 +1408,7 @@ setup_acls(struct archive_read_disk *a,
(void)fd; /* UNUSED */
return (ARCHIVE_OK);
}
-#endif
+#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
@@ -699,15 +1428,10 @@ setup_acls(struct archive_read_disk *a,
static int
setup_xattr(struct archive_read_disk *a,
- struct archive_entry *entry, const char *name, int fd)
+ struct archive_entry *entry, const char *name, int fd, const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
#if HAVE_FGETXATTR
if (fd >= 0)
@@ -772,21 +1496,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
ssize_t list_size;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -849,7 +1575,7 @@ setup_xattrs(struct archive_read_disk *a,
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
- setup_xattr(a, entry, p, *fd);
+ setup_xattr(a, entry, p, *fd, path);
}
free(list);
@@ -870,19 +1596,16 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd);
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *path);
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd)
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
if (fd >= 0)
size = extattr_get_fd(fd, namespace, name, NULL, 0);
@@ -932,21 +1655,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
int namespace = EXTATTR_NAMESPACE_USER;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -996,7 +1721,7 @@ setup_xattrs(struct archive_read_disk *a,
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
- setup_xattr(a, entry, namespace, name, buff, *fd);
+ setup_xattr(a, entry, namespace, name, buff, *fd, path);
p += 1 + len;
}
@@ -1024,7 +1749,7 @@ setup_xattrs(struct archive_read_disk *a,
#if defined(HAVE_LINUX_FIEMAP_H)
/*
- * Linux sparse interface.
+ * Linux FIEMAP sparse interface.
*
* The FIEMAP ioctl returns an "extent" for each physical allocation
* on disk. We need to process those to generate a more compact list
@@ -1039,7 +1764,7 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
-setup_sparse(struct archive_read_disk *a,
+setup_sparse_fiemap(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
char buff[4096];
@@ -1090,8 +1815,8 @@ setup_sparse(struct archive_read_disk *a,
if (r < 0) {
/* When something error happens, it is better we
* should return ARCHIVE_OK because an earlier
- * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
- goto exit_setup_sparse;
+ * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
+ goto exit_setup_sparse_fiemap;
}
if (fm->fm_mapped_extents == 0) {
if (iters == 0) {
@@ -1126,14 +1851,24 @@ setup_sparse(struct archive_read_disk *a,
} else
break;
}
-exit_setup_sparse:
+exit_setup_sparse_fiemap:
return (exit_sts);
}
-#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
+#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
+static int
+setup_sparse(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ return setup_sparse_fiemap(a, entry, fd);
+}
+#endif
+#endif /* defined(HAVE_LINUX_FIEMAP_H) */
+
+#if defined(SEEK_HOLE) && defined(SEEK_DATA)
/*
- * FreeBSD and Solaris sparse interface.
+ * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
*/
static int
@@ -1141,8 +1876,8 @@ setup_sparse(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
int64_t size;
- off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
- off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
+ off_t initial_off;
+ off_t off_s, off_e;
int exit_sts = ARCHIVE_OK;
int check_fully_sparse = 0;
@@ -1168,8 +1903,10 @@ setup_sparse(struct archive_read_disk *a,
}
if (*fd >= 0) {
+#ifdef _PC_MIN_HOLE_SIZE
if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
+#endif
initial_off = lseek(*fd, 0, SEEK_CUR);
if (initial_off != 0)
lseek(*fd, 0, SEEK_SET);
@@ -1180,8 +1917,10 @@ setup_sparse(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
+#ifdef _PC_MIN_HOLE_SIZE
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
+#endif
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
@@ -1192,6 +1931,19 @@ setup_sparse(struct archive_read_disk *a,
initial_off = 0;
}
+#ifndef _PC_MIN_HOLE_SIZE
+ /* Check if the underlying filesystem supports seek hole */
+ off_s = lseek(*fd, 0, SEEK_HOLE);
+ if (off_s < 0)
+#if defined(HAVE_LINUX_FIEMAP_H)
+ return setup_sparse_fiemap(a, entry, fd);
+#else
+ goto exit_setup_sparse;
+#endif
+ else if (off_s > 0)
+ lseek(*fd, 0, SEEK_SET);
+#endif
+
off_s = 0;
size = archive_entry_size(entry);
while (off_s < size) {
@@ -1223,7 +1975,7 @@ setup_sparse(struct archive_read_disk *a,
goto exit_setup_sparse;
}
if (off_s == 0 && off_e == size)
- break;/* This is not spase. */
+ break;/* This is not sparse. */
archive_entry_sparse_add_entry(entry, off_s,
off_e - off_s);
off_s = off_e;
@@ -1241,7 +1993,7 @@ exit_setup_sparse:
return (exit_sts);
}
-#else
+#elif !defined(HAVE_LINUX_FIEMAP_H)
/*
* Generic (stub) sparse support.
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk_posix.c b/archivers/libarchive/files/libarchive/archive_read_disk_posix.c
index f54cda69c12..6961ae6a42f 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk_posix.c
+++ b/archivers/libarchive/files/libarchive/archive_read_disk_posix.c
@@ -165,7 +165,7 @@ struct filesystem {
int synthetic;
int remote;
int noatime;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
size_t name_max;
#endif
long incr_xfer_size;
@@ -200,7 +200,7 @@ struct tree {
DIR *d;
#define INVALID_DIR_HANDLE NULL
struct dirent *de;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
struct dirent *dirent;
size_t dirent_allocated;
#endif
@@ -244,7 +244,7 @@ struct tree {
int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
- int allocated_filesytem;
+ int allocated_filesystem;
int entry_fd;
int entry_eof;
@@ -465,8 +465,7 @@ archive_read_disk_new(void)
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
a->open_on_current_dir = open_on_current_dir;
a->tree_current_dir_fd = tree_current_dir_fd;
a->tree_enter_working_dir = tree_enter_working_dir;
@@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a)
int
archive_read_disk_set_atime_restored(struct archive *_a)
{
-#ifndef HAVE_UTIMES
- static int warning_done = 0;
-#endif
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
#ifdef HAVE_UTIMES
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
#else
- if (warning_done)
- /* Warning was already emitted; suppress further warnings. */
- return (ARCHIVE_OK);
-
+ /* Display warning and unset flag */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore access time on this system");
- warning_done = 1;
+ a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
return (ARCHIVE_WARN);
#endif
}
@@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
- if (flags & ARCHIVE_READDISK_NO_XATTR)
- a->suppress_xattr = 1;
- else
- a->suppress_xattr = 0;
return (r);
}
@@ -675,7 +653,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a)
asize = cf->min_xfer_size;
/* Increase a buffer size up to 64K bytes in
- * a proper incremant size. */
+ * a proper increment size. */
while (asize < 1024*64)
asize += incr;
/* Take a margin to adjust to the filesystem
@@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
} while (lst == NULL);
#ifdef __APPLE__
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
/* If we're using copyfile(), ignore "._XXX" files. */
const char *bname = strrchr(tree_current_path(t), '/');
if (bname == NULL)
@@ -938,7 +916,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_path_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
descend = 0;
}
@@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t,
* Honor nodump flag.
* If the file is marked with nodump flag, do not return this entry.
*/
- if (a->honor_nodump) {
+ if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
if (st->st_flags & UF_NODUMP)
return (ARCHIVE_RETRY);
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
- defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
int stflags;
@@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t,
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
- r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+ r = ioctl(t->entry_fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
&stflags);
+#ifdef FS_NODUMP_FL
+ if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
+#else
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+#endif
return (ARCHIVE_RETRY);
}
}
@@ -1026,7 +1015,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
/* Save the times to be restored. This must be in before
* calling archive_read_disk_descend() or any chance of it,
- * especially, invokng a callback. */
+ * especially, invoking a callback. */
t->restore_time.mtime = archive_entry_mtime(entry);
t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
t->restore_time.atime = archive_entry_atime(entry);
@@ -1041,7 +1030,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_time_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1067,7 +1056,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
a->tree = tree_open(pathname, a->symlink_mode,
- a->restore_time);
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
@@ -1382,7 +1372,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
for (i = 0; i < t->max_filesystem_id; i++) {
if (t->filesystem_table[i].dev == dev) {
- /* There is the filesytem ID we've already generated. */
+ /* There is the filesystem ID we've already generated. */
t->current_filesystem_id = i;
t->current_filesystem = &(t->filesystem_table[i]);
return (ARCHIVE_OK);
@@ -1390,10 +1380,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
}
/*
- * This is the new filesytem which we have to generate a new ID for.
+ * This is the new filesystem which we have to generate a new ID for.
*/
fid = t->max_filesystem_id++;
- if (t->max_filesystem_id > t->allocated_filesytem) {
+ if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
void *p;
@@ -1406,7 +1396,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
- t->allocated_filesytem = s;
+ t->allocated_filesystem = s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1504,10 +1494,19 @@ setup_current_filesystem(struct archive_read_disk *a)
struct tree *t = a->tree;
struct statfs sfs;
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
-# if defined(HAVE_STRUCT_VFSCONF)
- struct vfsconf vfc;
-# else
+/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
+ * this accurate; some platforms have both and we need the one that's
+ * used by getvfsbyname()
+ *
+ * Then the following would become:
+ * #if defined(GETVFSBYNAME_ARG_TYPE)
+ * GETVFSBYNAME_ARG_TYPE vfc;
+ * #endif
+ */
+# if defined(HAVE_STRUCT_XVFSCONF)
struct xvfsconf vfc;
+# else
+ struct vfsconf vfc;
# endif
#endif
int r, xr = 0;
@@ -1583,7 +1582,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
t->current_filesystem->name_max = sfs.f_namemax;
@@ -1606,7 +1605,7 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
#endif
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -1647,7 +1646,7 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "statvfs failed");
return (ARCHIVE_FAILED);
} else if (xr == 1) {
- /* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN
+ /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
* for pathconf() function. */
t->current_filesystem->xfer_align = sfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
@@ -1808,7 +1807,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = sfs.f_namelen;
#endif
@@ -1892,7 +1891,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = sfs.f_namemax;
#endif
@@ -1909,7 +1908,7 @@ static int
setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
-#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
+#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
long nm;
#endif
t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1921,7 +1920,7 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->min_xfer_size = -1;
t->current_filesystem->incr_xfer_size = -1;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
# if defined(_PC_NAME_MAX)
if (tree_current_is_symblic_link_target(t)) {
@@ -1935,7 +1934,7 @@ setup_current_filesystem(struct archive_read_disk *a)
if (nm == -1)
# endif /* _PC_NAME_MAX */
/*
- * Some sysmtes (HP-UX or others?) incorrectly defined
+ * Some systems (HP-UX or others?) incorrectly defined
* NAME_MAX macro to be a smaller value.
*/
# if defined(NAME_MAX) && NAME_MAX >= 255
@@ -1949,7 +1948,7 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
# endif /* _PC_NAME_MAX */
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -2054,8 +2053,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
{
struct tree_entry *te;
- te = malloc(sizeof(*te));
- memset(te, 0, sizeof(*te));
+ te = calloc(1, sizeof(*te));
te->next = t->stack;
te->parent = t->current;
if (te->parent)
@@ -2113,9 +2111,8 @@ tree_open(const char *path, int symlink_mode, int restore_time)
{
struct tree *t;
- if ((t = malloc(sizeof(*t))) == NULL)
+ if ((t = calloc(1, sizeof(*t))) == NULL)
return (NULL);
- memset(t, 0, sizeof(*t));
archive_string_init(&t->path);
archive_string_ensure(&t->path, 31);
t->initial_symlink_mode = symlink_mode;
@@ -2125,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time)
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
@@ -2357,7 +2354,7 @@ tree_dir_next_posix(struct tree *t)
size_t namelen;
if (t->d == NULL) {
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
size_t dirent_size;
#endif
@@ -2378,7 +2375,7 @@ tree_dir_next_posix(struct tree *t)
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
dirent_size = offsetof(struct dirent, d_name) +
t->filesystem_table[t->current->filesystem_id].name_max + 1;
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
@@ -2395,11 +2392,11 @@ tree_dir_next_posix(struct tree *t)
}
t->dirent_allocated = dirent_size;
}
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
}
for (;;) {
errno = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
#ifdef _AIX
/* Note: According to the man page, return value 9 indicates
@@ -2651,7 +2648,7 @@ tree_free(struct tree *t)
if (t == NULL)
return;
archive_string_free(&t->path);
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
free(t->dirent);
#endif
free(t->sparse_list);
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk_private.h b/archivers/libarchive/files/libarchive/archive_read_disk_private.h
index 2569321da54..b5a8328b7bf 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk_private.h
+++ b/archivers/libarchive/files/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@ struct archive_read_disk {
int (*tree_current_dir_fd)(struct tree*);
int (*tree_enter_working_dir)(struct tree*);
- /* Set 1 if users request to restore atime . */
- int restore_time;
- /* Set 1 if users request to honor nodump flag . */
- int honor_nodump;
- /* Set 1 if users request to enable mac copyfile. */
- int enable_copyfile;
- /* Set 1 if users request to traverse mount points. */
- int traverse_mount_points;
- /* Set 1 if users want to suppress xattr information. */
- int suppress_xattr;
+ /* Bitfield with ARCHIVE_READDISK_* tunables */
+ int flags;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk_set_standard_lookup.c b/archivers/libarchive/files/libarchive/archive_read_disk_set_standard_lookup.c
index d6b2d55b8d7..c7fd2471ecb 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk_set_standard_lookup.c
+++ b/archivers/libarchive/files/libarchive/archive_read_disk_set_standard_lookup.c
@@ -232,6 +232,7 @@ static const char *
lookup_uname_helper(struct name_cache *cache, id_t id)
{
struct passwd *result;
+ (void)cache; /* UNUSED */
result = getpwuid((uid_t)id);
@@ -298,6 +299,7 @@ static const char *
lookup_gname_helper(struct name_cache *cache, id_t id)
{
struct group *result;
+ (void)cache; /* UNUSED */
result = getgrgid((gid_t)id);
diff --git a/archivers/libarchive/files/libarchive/archive_read_disk_windows.c b/archivers/libarchive/files/libarchive/archive_read_disk_windows.c
index 566d264e9a4..3b903304f08 100644
--- a/archivers/libarchive/files/libarchive/archive_read_disk_windows.c
+++ b/archivers/libarchive/files/libarchive/archive_read_disk_windows.c
@@ -168,7 +168,7 @@ struct tree {
int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
- int allocated_filesytem;
+ int allocated_filesystem;
HANDLE entry_fh;
int entry_eof;
@@ -389,18 +389,16 @@ archive_read_disk_new(void)
{
struct archive_read_disk *a;
- a = (struct archive_read_disk *)malloc(sizeof(*a));
+ a = (struct archive_read_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_read_disk_vtable();
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
return (&a->archive);
}
@@ -496,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
@@ -511,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
return (r);
}
@@ -803,7 +790,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_path_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -853,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
return (ARCHIVE_RETRY);
}
@@ -863,7 +850,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
/* Save the times to be restored. This must be in before
* calling archive_read_disk_descend() or any chance of it,
- * especially, invokng a callback. */
+ * especially, invoking a callback. */
t->restore_time.lastWriteTime = st->ftLastWriteTime;
t->restore_time.lastAccessTime = st->ftLastAccessTime;
t->restore_time.filetype = archive_entry_filetype(entry);
@@ -875,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_time_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -901,7 +888,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1220,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
- a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
+ a->tree = tree_open(pathname, a->symlink_mode,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate directory traversal data");
@@ -1261,7 +1250,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
for (i = 0; i < t->max_filesystem_id; i++) {
if (t->filesystem_table[i].dev == dev) {
- /* There is the filesytem ID we've already generated. */
+ /* There is the filesystem ID we've already generated. */
t->current_filesystem_id = i;
t->current_filesystem = &(t->filesystem_table[i]);
return (ARCHIVE_OK);
@@ -1269,10 +1258,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
}
/*
- * There is a new filesytem, we generate a new ID for.
+ * There is a new filesystem, we generate a new ID for.
*/
fid = t->max_filesystem_id++;
- if (t->max_filesystem_id > t->allocated_filesytem) {
+ if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
void *p;
@@ -1285,7 +1274,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
- t->allocated_filesytem = (int)s;
+ t->allocated_filesystem = (int)s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1402,7 +1391,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
return (0);
- /* Close a file descritor.
+ /* Close a file descriptor.
* It will not be used for SetFileTime() because it has been opened
* by a read only mode.
*/
@@ -1437,8 +1426,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
{
struct tree_entry *te;
- te = malloc(sizeof(*te));
- memset(te, 0, sizeof(*te));
+ te = calloc(1, sizeof(*te));
te->next = t->stack;
te->parent = t->current;
if (te->parent)
@@ -1507,8 +1495,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
{
struct tree *t;
- t = malloc(sizeof(*t));
- memset(t, 0, sizeof(*t));
+ t = calloc(1, sizeof(*t));
archive_string_init(&(t->full_path));
archive_string_init(&t->path);
archive_wstring_ensure(&t->path, 15);
@@ -1522,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
struct archive_wstring ws;
wchar_t *pathname, *p, *base;
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->visit_type = 0;
t->tree_errno = 0;
t->full_path_dir_length = 0;
diff --git a/archivers/libarchive/files/libarchive/archive_read_open_filename.c b/archivers/libarchive/files/libarchive/archive_read_open_filename.c
index 5611aa85aa4..86635e21928 100644
--- a/archivers/libarchive/files/libarchive/archive_read_open_filename.c
+++ b/archivers/libarchive/files/libarchive/archive_read_open_filename.c
@@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data)
void *buffer;
const char *filename = NULL;
const wchar_t *wfilename = NULL;
- int fd;
+ int fd = -1;
int is_disk_like = 0;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
@@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data)
#else
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unexpedted operation in archive_read_open_filename");
- return (ARCHIVE_FATAL);
+ goto fail;
#endif
}
if (fstat(fd, &st) != 0) {
@@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data)
else
archive_set_error(a, errno, "Can't stat '%s'",
filename);
- return (ARCHIVE_FATAL);
+ goto fail;
}
/*
@@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data)
mine->block_size = new_block_size;
}
buffer = malloc(mine->block_size);
- if (mine == NULL || buffer == NULL) {
+ if (buffer == NULL) {
archive_set_error(a, ENOMEM, "No memory");
- free(mine);
- free(buffer);
- return (ARCHIVE_FATAL);
+ goto fail;
}
mine->buffer = buffer;
mine->fd = fd;
@@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data)
mine->use_lseek = 1;
return (ARCHIVE_OK);
+fail:
+ /*
+ * Don't close file descriptors not opened or ones pointing referring
+ * to `FNT_STDIN`.
+ */
+ if (fd != -1 && fd != 0)
+ close(fd);
+ return (ARCHIVE_FATAL);
}
static ssize_t
diff --git a/archivers/libarchive/files/libarchive/archive_read_open_memory.c b/archivers/libarchive/files/libarchive/archive_read_open_memory.c
index ff935a708f5..311be47046a 100644
--- a/archivers/libarchive/files/libarchive/archive_read_open_memory.c
+++ b/archivers/libarchive/files/libarchive/archive_read_open_memory.c
@@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff,
{
struct read_memory_data *mine;
- mine = (struct read_memory_data *)malloc(sizeof(*mine));
+ mine = (struct read_memory_data *)calloc(1, sizeof(*mine));
if (mine == NULL) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
- memset(mine, 0, sizeof(*mine));
mine->start = mine->p = (const unsigned char *)buff;
mine->end = mine->start + size;
mine->read_size = read_size;
diff --git a/archivers/libarchive/files/libarchive/archive_read_private.h b/archivers/libarchive/files/libarchive/archive_read_private.h
index 9b61a5380a2..78546dca34a 100644
--- a/archivers/libarchive/files/libarchive/archive_read_private.h
+++ b/archivers/libarchive/files/libarchive/archive_read_private.h
@@ -221,7 +221,7 @@ struct archive_read {
struct {
struct archive_read_passphrase *first;
struct archive_read_passphrase **last;
- int candiate;
+ int candidate;
archive_passphrase_callback *callback;
void *client_data;
} passphrases;
@@ -252,7 +252,6 @@ int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_program(struct archive_read_filter *, const char *);
void __archive_read_free_filters(struct archive_read *);
-int __archive_read_close_filters(struct archive_read *);
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_filter_lzop.c b/archivers/libarchive/files/libarchive/archive_read_support_filter_lzop.c
index 44ac9964ae1..a1c392f4f36 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_filter_lzop.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_filter_lzop.c
@@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p)
}
/*
- * Drive lzo uncompresison.
+ * Drive lzo uncompression.
*/
out_size = (lzo_uint)state->uncompressed_size;
r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_filter_uu.c b/archivers/libarchive/files/libarchive/archive_read_support_filter_uu.c
index 787a619f2f3..641297990d2 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_filter_uu.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_filter_uu.c
@@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
avail -= len;
if (l == 6) {
+ /* "begin " */
if (!uuchar[*b])
return (0);
/* Get a length of decoded bytes. */
@@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
if (l > 45)
/* Normally, maximum length is 45(character 'M'). */
return (0);
- while (l && len-nl > 0) {
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- if (!uuchar[*b++])
- return (0);
- len -= 2;
- --l;
- }
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- --len;
- --l;
- }
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- --len;
- --l;
- }
+ if (l > len - nl)
+ return (0); /* Line too short. */
+ while (l) {
+ if (!uuchar[*b++])
+ return (0);
+ --len;
+ --l;
}
- if (len-nl < 0)
- return (0);
if (len-nl == 1 &&
(uuchar[*b] || /* Check sum. */
(*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
@@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
b += nl;
if (avail && uuchar[*b])
return (firstline+30);
- }
- if (l == 13) {
+ } else if (l == 13) {
+ /* "begin-base64 " */
while (len-nl > 0) {
if (!base64[*b++])
return (0);
@@ -510,6 +495,13 @@ read_more:
}
llen = len;
if ((nl == 0) && (uudecode->state != ST_UUEND)) {
+ if (total == 0 && ravail <= 0) {
+ /* There is nothing more to read, fail */
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Missing format data");
+ return (ARCHIVE_FATAL);
+ }
/*
* Save remaining data which does not contain
* NL('\n','\r').
@@ -566,7 +558,7 @@ read_more:
"Insufficient compressed data");
return (ARCHIVE_FATAL);
}
- /* Get length of undecoded bytes of curent line. */
+ /* Get length of undecoded bytes of current line. */
l = UUDECODE(*b++);
body--;
if (l > body) {
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_filter_xz.c b/archivers/libarchive/files/libarchive/archive_read_support_filter_xz.c
index 4e0a95feeb0..11807cf6768 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_filter_xz.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_filter_xz.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#endif
#if HAVE_LZMA_H
#include <lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
#endif
#include "archive.h"
@@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **);
static int xz_filter_close(struct archive_read_filter *);
static int xz_lzma_bidder_init(struct archive_read_filter *);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-struct private_data {
- lzmadec_stream stream;
- unsigned char *out_block;
- size_t out_block_size;
- int64_t total_out;
- char eof; /* True = found end of compressed data. */
-};
-
-/* Lzma-only filter */
-static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
-static int lzma_filter_close(struct archive_read_filter *);
#endif
/*
@@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a)
bidder->free = NULL;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return (ARCHIVE_OK);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
- return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external lzma program for lzma decompression");
@@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
/* Second through fifth bytes are dictionary size, stored in
* little-endian order. The minimum dictionary size is
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
- * -d12 and the maxinam dictionary size is 1 << 27(128MiB)
+ * -d12 and the maximum dictionary size is 1 << 27(128MiB)
* which the one uses with option -d27.
* NOTE: A comment of LZMA SDK source code says this dictionary
* range is from 1 << 12 to 1 << 30. */
@@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self)
return (ARCHIVE_FATAL);
}
ret = lzma_raw_decoder(&(state->stream), filters);
-#if LZMA_VERSION < 50010000
free(filters[0].options);
-#endif
if (ret != LZMA_OK) {
set_error(self, ret);
return (ARCHIVE_FATAL);
@@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self)
#else
-#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-/*
- * If we have the older liblzmadec library, then we can handle
- * LZMA streams but not XZ streams.
- */
-
-/*
- * Setup the callbacks.
- */
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
- static const size_t out_block_size = 64 * 1024;
- void *out_block;
- struct private_data *state;
- ssize_t ret, avail_in;
-
- self->code = ARCHIVE_FILTER_LZMA;
- self->name = "lzma";
-
- state = (struct private_data *)calloc(sizeof(*state), 1);
- out_block = (unsigned char *)malloc(out_block_size);
- if (state == NULL || out_block == NULL) {
- archive_set_error(&self->archive->archive, ENOMEM,
- "Can't allocate data for lzma decompression");
- free(out_block);
- free(state);
- return (ARCHIVE_FATAL);
- }
-
- self->data = state;
- state->out_block_size = out_block_size;
- state->out_block = out_block;
- self->read = lzma_filter_read;
- self->skip = NULL; /* not supported */
- self->close = lzma_filter_close;
-
- /* Prime the lzma library with 18 bytes of input. */
- state->stream.next_in = (unsigned char *)(uintptr_t)
- __archive_read_filter_ahead(self->upstream, 18, &avail_in);
- if (state->stream.next_in == NULL)
- return (ARCHIVE_FATAL);
- state->stream.avail_in = avail_in;
- state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
-
- /* Initialize compression library. */
- ret = lzmadec_init(&(state->stream));
- __archive_read_filter_consume(self->upstream,
- avail_in - state->stream.avail_in);
- if (ret == LZMADEC_OK)
- return (ARCHIVE_OK);
-
- /* Library setup failed: Clean up. */
- archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
- "Internal error initializing lzma library");
-
- /* Override the error message if we know what really went wrong. */
- switch (ret) {
- case LZMADEC_HEADER_ERROR:
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Internal error initializing compression library: "
- "invalid header");
- break;
- case LZMADEC_MEM_ERROR:
- archive_set_error(&self->archive->archive, ENOMEM,
- "Internal error initializing compression library: "
- "out of memory");
- break;
- }
-
- free(state->out_block);
- free(state);
- self->data = NULL;
- return (ARCHIVE_FATAL);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-lzma_filter_read(struct archive_read_filter *self, const void **p)
-{
- struct private_data *state;
- size_t decompressed;
- ssize_t avail_in, ret;
-
- state = (struct private_data *)self->data;
-
- /* Empty our output buffer. */
- state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
-
- /* Try to fill the output buffer. */
- while (state->stream.avail_out > 0 && !state->eof) {
- state->stream.next_in = (unsigned char *)(uintptr_t)
- __archive_read_filter_ahead(self->upstream, 1, &avail_in);
- if (state->stream.next_in == NULL && avail_in < 0) {
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "truncated lzma input");
- return (ARCHIVE_FATAL);
- }
- state->stream.avail_in = avail_in;
-
- /* Decompress as much as we can in one pass. */
- ret = lzmadec_decode(&(state->stream), avail_in == 0);
- switch (ret) {
- case LZMADEC_STREAM_END: /* Found end of stream. */
- state->eof = 1;
- /* FALL THROUGH */
- case LZMADEC_OK: /* Decompressor made some progress. */
- __archive_read_filter_consume(self->upstream,
- avail_in - state->stream.avail_in);
- break;
- case LZMADEC_BUF_ERROR: /* Insufficient input data? */
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Insufficient compressed data");
- return (ARCHIVE_FATAL);
- default:
- /* Return an error. */
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Lzma decompression failed");
- return (ARCHIVE_FATAL);
- }
- }
-
- decompressed = state->stream.next_out - state->out_block;
- state->total_out += decompressed;
- if (decompressed == 0)
- *p = NULL;
- else
- *p = state->out_block;
- return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lzma_filter_close(struct archive_read_filter *self)
-{
- struct private_data *state;
- int ret;
-
- state = (struct private_data *)self->data;
- ret = ARCHIVE_OK;
- switch (lzmadec_end(&(state->stream))) {
- case LZMADEC_OK:
- break;
- default:
- archive_set_error(&(self->archive->archive),
- ARCHIVE_ERRNO_MISC,
- "Failed to clean up %s compressor",
- self->archive->archive.compression_name);
- ret = ARCHIVE_FATAL;
- }
-
- free(state->out_block);
- free(state);
- return (ret);
-}
-
-#else
-
/*
*
* If we have no suitable library on this system, we can't actually do
@@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self)
return (r);
}
-#endif /* HAVE_LZMADEC_H */
-
-
static int
xz_bidder_init(struct archive_read_filter *self)
{
@@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self)
return (r);
}
-
#endif /* HAVE_LZMA_H */
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_7zip.c b/archivers/libarchive/files/libarchive/archive_read_support_format_7zip.c
index 1dfe52b8539..3387eaf7e7f 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_7zip.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_7zip.c
@@ -213,7 +213,7 @@ struct _7zip {
int header_is_encoded;
uint64_t header_bytes_remaining;
unsigned long header_crc32;
- /* Header offset to check that reading pointes of the file contens
+ /* Header offset to check that reading points of the file contents
* will not exceed the header. */
uint64_t header_offset;
/* Base offset of the archive file for a seek in case reading SFX. */
@@ -263,22 +263,22 @@ struct _7zip {
/*
* Decompressor controllers.
*/
- /* Decording LZMA1 and LZMA2 data. */
+ /* Decoding LZMA1 and LZMA2 data. */
#ifdef HAVE_LZMA_H
lzma_stream lzstream;
int lzstream_valid;
#endif
- /* Decording bzip2 data. */
+ /* Decoding bzip2 data. */
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
bz_stream bzstream;
int bzstream_valid;
#endif
- /* Decording deflate data. */
+ /* Decoding deflate data. */
#ifdef HAVE_ZLIB_H
z_stream stream;
int stream_valid;
#endif
- /* Decording PPMd data. */
+ /* Decoding PPMd data. */
int ppmd7_stat;
CPpmd7 ppmd7_context;
CPpmd7z_RangeDec range_dec;
@@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
/*
* If bytes_avail > SFX_MIN_ADDR we do not have to call
* __archive_read_seek() at this time since we have
- * alredy had enough data.
+ * already had enough data.
*/
if (bytes_avail > SFX_MIN_ADDR)
__archive_read_consume(a, SFX_MIN_ADDR);
@@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
symsize += size;
}
if (symsize == 0) {
- /* If there is no synname, handle it as a regular
+ /* If there is no symname, handle it as a regular
* file. */
zip_entry->mode &= ~AE_IFMT;
zip_entry->mode |= AE_IFREG;
@@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
#endif
{
lzma_options_delta delta_opt;
- lzma_filter filters[LZMA_FILTERS_MAX];
-#if LZMA_VERSION < 50010000
- lzma_filter *ff;
-#endif
+ lzma_filter filters[LZMA_FILTERS_MAX], *ff;
int fi = 0;
if (zip->lzstream_valid) {
@@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
else
filters[fi].id = LZMA_FILTER_LZMA1;
filters[fi].options = NULL;
-#if LZMA_VERSION < 50010000
ff = &filters[fi];
-#endif
r = lzma_properties_decode(&filters[fi], NULL,
coder1->properties, (size_t)coder1->propertiesSize);
if (r != LZMA_OK) {
@@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_VLI_UNKNOWN;
filters[fi].options = NULL;
r = lzma_raw_decoder(&(zip->lzstream), filters);
-#if LZMA_VERSION < 50010000
free(ff->options);
-#endif
if (r != LZMA_OK) {
set_error(a, r);
return (ARCHIVE_FAILED);
@@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
switch (type) {
case kEmptyStream:
+ if (h->emptyStreamBools != NULL)
+ return (-1);
h->emptyStreamBools = calloc((size_t)zip->numFiles,
sizeof(*h->emptyStreamBools));
if (h->emptyStreamBools == NULL)
@@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
}
+ if (h->emptyFileBools != NULL)
+ return (-1);
h->emptyFileBools = calloc(empty_streams,
sizeof(*h->emptyFileBools));
if (h->emptyFileBools == NULL)
@@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
}
+ if (h->antiBools != NULL)
+ return (-1);
h->antiBools = calloc(empty_streams,
sizeof(*h->antiBools));
if (h->antiBools == NULL)
@@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((ll & 1) || ll < zip->numFiles * 4)
return (-1);
+ if (zip->entry_names != NULL)
+ return (-1);
zip->entry_names = malloc(ll);
if (zip->entry_names == NULL)
return (-1);
@@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((p = header_bytes(a, 2)) == NULL)
return (-1);
allAreDefined = *p;
+ if (h->attrBools != NULL)
+ return (-1);
h->attrBools = calloc((size_t)zip->numFiles,
sizeof(*h->attrBools));
if (h->attrBools == NULL)
@@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (r);
/*
- * Skip the bytes we alrady has skipped in skip_stream().
+ * Skip the bytes we already has skipped in skip_stream().
*/
while (skip_bytes) {
ssize_t skipped;
@@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
return (ARCHIVE_FATAL);
}
- /* Allocate memory for the decorded data of a sub
+ /* Allocate memory for the decoded data of a sub
* stream. */
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
if (b[i] == NULL) {
@@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
if (zip->folder_index == 0) {
/*
* Optimization for a list mode.
- * Avoid unncecessary decoding operations.
+ * Avoid unnecessary decoding operations.
*/
zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
+= skip_bytes;
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
index 4b5b66bd50a..b6b9fc3c6dc 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
@@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
- ar = (struct ar *)malloc(sizeof(*ar));
+ ar = (struct ar *)calloc(1, sizeof(*ar));
if (ar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ar data");
return (ARCHIVE_FATAL);
}
- memset(ar, 0, sizeof(*ar));
ar->strtab = NULL;
r = __archive_read_register_format(a,
@@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_filetype(entry, AE_IFREG);
/* Get the size of the filename table. */
number = ar_atol10(h + AR_size_offset, AR_size_size);
- if (number > SIZE_MAX) {
+ if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Filename table too large");
return (ARCHIVE_FATAL);
@@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
* If we can't look up the real name, warn and return
* the entry with the wrong name.
*/
- if (ar->strtab == NULL || number > ar->strtab_size) {
+ if (ar->strtab == NULL || number >= ar->strtab_size) {
archive_set_error(&a->archive, EINVAL,
"Can't find long filename for GNU/SVR4 archive entry");
archive_entry_copy_pathname(entry, filename);
@@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
/* Parse the size of the name, adjust the file size. */
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
- bsd_name_length = (size_t)number;
- /* Guard against the filename + trailing NUL
- * overflowing a size_t and against the filename size
- * being larger than the entire entry. */
- if (number > (uint64_t)(bsd_name_length + 1)
- || (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
+ /* Sanity check the filename length:
+ * = Must be <= SIZE_MAX - 1
+ * = Must be <= 1MB
+ * = Cannot be bigger than the entire entry
+ */
+ if (number > SIZE_MAX - 1
+ || number > 1024 * 1024
+ || (int64_t)number > ar->entry_bytes_remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Bad input file size");
return (ARCHIVE_FATAL);
}
+ bsd_name_length = (size_t)number;
ar->entry_bytes_remaining -= bsd_name_length;
/* Adjust file size reported to client. */
archive_entry_set_size(entry, ar->entry_bytes_remaining);
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_cab.c b/archivers/libarchive/files/libarchive/archive_read_support_format_cab.c
index fc70684afa0..e2f8c6b70ae 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_cab.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_cab.c
@@ -67,7 +67,7 @@ struct lzx_dec {
/* The length how many bytes we can copy decoded code from
* the window. */
int copy_len;
- /* Translation reversal for x86 proccessor CALL byte sequence(E8).
+ /* Translation reversal for x86 processor CALL byte sequence(E8).
* This is used for LZX only. */
uint32_t translation_size;
char translation;
@@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
cab = (struct cab *)(a->format->data);
if (cab->found_header == 0 &&
p[0] == 'M' && p[1] == 'Z') {
- /* This is an executable? Must be self-extracting... */
+ /* This is an executable? Must be self-extracting... */
err = cab_skip_sfx(a);
if (err < ARCHIVE_WARN)
return (err);
- if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
+ /* Re-read header after processing the SFX. */
+ if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
return (truncated_error(a));
}
@@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
if (mszip > 0) {
+ if (bytes_avail <= 0)
+ goto nomszip;
if (bytes_avail <= mszip) {
if (mszip == 2) {
if (cab->stream.next_in[0] != 0x43)
@@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
/*
* Note: I suspect there is a bug in makecab.exe because, in rare
* case, compressed bytes are still remaining regardless we have
- * gotten all uncompressed bytes, which size is recoded in CFDATA,
+ * gotten all uncompressed bytes, which size is recorded in CFDATA,
* as much as we need, and we have to use the garbage so as to
* correctly compute the sum of CFDATA accordingly.
*/
@@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
}
/*
- * Translation reversal of x86 proccessor CALL byte sequence(E8).
+ * Translation reversal of x86 processor CALL byte sequence(E8).
*/
lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
cfdata->uncompressed_size,
@@ -2270,7 +2273,7 @@ static int
lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
{
/*
- * x86 proccessor family can read misaligned data without an access error.
+ * x86 processor family can read misaligned data without an access error.
*/
int n = CACHE_BITS - br->cache_avail;
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_cpio.c b/archivers/libarchive/files/libarchive/archive_read_support_format_cpio.c
index b09db0e9a59..ffd4a8580ab 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_cpio.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_cpio.c
@@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
cpio = (struct cpio *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) {
- /* Handle filnames as libarchive 2.x */
+ /* Handle filenames as libarchive 2.x */
cpio->init_default_conversion = (val != NULL)?1:0;
return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
@@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
struct archive_entry *entry)
{
struct cpio *cpio;
- const void *h;
+ const void *h, *hl;
struct archive_string_conv *sconv;
size_t namelength;
size_t name_pad;
@@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a,
"Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
return (ARCHIVE_FATAL);
}
- h = __archive_read_ahead(a,
+ hl = __archive_read_ahead(a,
(size_t)cpio->entry_bytes_remaining, NULL);
- if (h == NULL)
+ if (hl == NULL)
return (ARCHIVE_FATAL);
- if (archive_entry_copy_symlink_l(entry, (const char *)h,
+ if (archive_entry_copy_symlink_l(entry, (const char *)hl,
(size_t)cpio->entry_bytes_remaining, sconv) != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
@@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a,
* header. XXX */
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
- if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
+ if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
+ 11) == 0) {
/* TODO: Store file location of start of block. */
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
@@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio,
* NOTE: if a filename suffix is ".z", it is the file gziped by afio.
* it would be nice that we can show uncompressed file size and we can
* uncompressed file contents automatically, unfortunately we have nothing
- * to get a uncompressed file size while reading each header. it means
- * we also cannot uncompressed file contens under the our framework.
+ * to get a uncompressed file size while reading each header. It means
+ * we also cannot uncompress file contents under our framework.
*/
static int
header_afiol(struct archive_read *a, struct cpio *cpio,
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
index f41ba386562..76da4069ef1 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
@@ -322,7 +322,7 @@ struct iso9660 {
struct archive_string pathname;
char seenRockridge; /* Set true if RR extensions are used. */
- char seenSUSP; /* Set true if SUSP is beging used. */
+ char seenSUSP; /* Set true if SUSP is being used. */
char seenJoliet;
unsigned char suspOffset;
@@ -374,7 +374,7 @@ struct iso9660 {
size_t utf16be_path_len;
unsigned char *utf16be_previous_path;
size_t utf16be_previous_path_len;
- /* Null buufer used in bidder to improve its performance. */
+ /* Null buffer used in bidder to improve its performance. */
unsigned char null[2048];
};
@@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_string_conversion_from_charset(
&(a->archive), "UTF-16BE", 1);
if (iso9660->sconv_utf16be == NULL)
- /* Coundn't allocate memory */
+ /* Couldn't allocate memory */
return (ARCHIVE_FATAL);
}
if (iso9660->utf16be_path == NULL) {
@@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if ((file->utf16be_name = malloc(name_len)) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory for file name");
- return (NULL);
+ goto fail;
}
memcpy(file->utf16be_name, p, name_len);
file->utf16be_bytes = name_len;
@@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
file->symlink_continues = 0;
rr_start += iso9660->suspOffset;
r = parse_rockridge(a, file, rr_start, rr_end);
- if (r != ARCHIVE_OK) {
- free(file);
- return (NULL);
- }
+ if (r != ARCHIVE_OK)
+ goto fail;
/*
* A file size of symbolic link files in ISO images
* made by makefs is not zero and its location is
@@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: file does not have "CL" extension.
@@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE and CL");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: The file type must be a directory.
@@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE");
- return (NULL);
+ goto fail;
}
} else if (parent != NULL && parent->rr_moved)
file->rr_moved_has_re_only = 0;
@@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: The file type must be a regular file.
@@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
parent->subdirs++;
/* Overwrite an offset and a number of this "CL" entry
@@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
}
if (file->cl_offset == file->offset ||
@@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
}
}
@@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
#endif
register_file(iso9660, file);
return (file);
+fail:
+ archive_string_free(&file->name);
+ free(file);
+ return (NULL);
}
static int
@@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660)
return (ARCHIVE_FATAL);
} while (heap->cnt &&
heap->reqs[0].offset == iso9660->current_position);
- /* NOTE: Do not move this consume's code to fron of
+ /* NOTE: Do not move this consume's code to front of
* do-while loop. Registration of nested CE extension
* might cause error because of current position. */
__archive_read_consume(a, step);
@@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
if (file == NULL) {
/*
* If directory entries all which are descendant of
- * rr_moved are stil remaning, expose their.
+ * rr_moved are still remaining, expose their.
*/
if (iso9660->re_files.first != NULL &&
iso9660->rr_moved != NULL &&
@@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
empty_files.last = &empty_files.first;
/* Collect files which has the same file serial number.
* Peek pending_files so that file which number is different
- * is not put bak. */
+ * is not put back. */
while (iso9660->pending_files.used > 0 &&
(iso9660->pending_files.files[0]->number == -1 ||
iso9660->pending_files.files[0]->number == number)) {
@@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
/* This file has the same offset
* but it's wrong offset which empty files
* and symlink files have.
- * NOTE: This wrong offse was recorded by
+ * NOTE: This wrong offset was recorded by
* old mkisofs utility. If ISO images is
* created by latest mkisofs, this does not
* happen.
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_lha.c b/archivers/libarchive/files/libarchive/archive_read_support_format_lha.c
index dbfc1cd87c8..d77a7c2e476 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_lha.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_lha.c
@@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
/* Get a real compressed file size. */
lha->compsize -= extdsize - 2;
+ if (lha->compsize < 0)
+ goto invalid; /* Invalid compressed file size */
+
if (sum_calculated != headersum) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"LHa header sum error");
@@ -1711,12 +1714,15 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
*/
for (;len >= 8; len -= 8) {
/* This if statement expects compiler optimization will
- * remove the stament which will not be executed. */
+ * remove the statement which will not be executed. */
#undef bswap16
#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */
# define bswap16(x) _byteswap_ushort(x)
-#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
- || defined(__clang__)
+#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
+/* GCC 4.8 and later has __builtin_bswap16() */
+# define bswap16(x) __builtin_bswap16(x)
+#elif defined(__clang__)
+/* All clang versions have __builtin_bswap16() */
# define bswap16(x) __builtin_bswap16(x)
#else
# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c b/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
index 8c3be9a294f..4231ff5002b 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
@@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
+#define MTREE_HASHTABLE_SIZE 1024
+
struct mtree_option {
struct mtree_option *next;
char *value;
@@ -86,6 +88,8 @@ struct mtree_entry {
char *name;
char full;
char used;
+ unsigned int name_hash;
+ struct mtree_entry *hashtable_next;
};
struct mtree {
@@ -98,6 +102,7 @@ struct mtree {
const char *archive_format_name;
struct mtree_entry *entries;
struct mtree_entry *this_entry;
+ struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
struct archive_string current_dir;
struct archive_string contents_name;
@@ -110,6 +115,7 @@ struct mtree {
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
static int detect_form(struct archive_read *, int *);
+static unsigned int hash(const char *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
- mtree = (struct mtree *)malloc(sizeof(*mtree));
+ mtree = (struct mtree *)calloc(1, sizeof(*mtree));
if (mtree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate mtree data");
return (ARCHIVE_FATAL);
}
- memset(mtree, 0, sizeof(*mtree));
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
@@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
return (avail);
}
+/*
+ * <---------------- ravail --------------------->
+ * <-- diff ------> <--- avail ----------------->
+ * <---- len ----------->
+ * | Previous lines | line being parsed nl extra |
+ * ^
+ * b
+ *
+ */
static ssize_t
next_line(struct archive_read *a,
const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
@@ -339,7 +353,7 @@ next_line(struct archive_read *a,
*b += diff;
*avail -= diff;
tested = len;/* Skip some bytes we already determinated. */
- len = get_line_size(*b, *avail, nl);
+ len = get_line_size(*b + len, *avail - len, nl);
if (len >= 0)
len += tested;
}
@@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d)
}
} else
break;
- } else if (strncmp(p, "/set", 4) == 0) {
+ } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
multiline = 2;
- } else if (strncmp(p, "/unset", 6) == 0) {
+ } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
break;
/* This line continues. */
@@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
- struct mtree_entry *entry;
+ struct mtree_entry *entry, *ht_iter;
struct mtree_option *iter;
const char *next, *eq, *name, *end;
size_t name_len, len;
int r, i;
+ unsigned int ht_idx;
if ((entry = malloc(sizeof(*entry))) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
entry->name = NULL;
entry->used = 0;
entry->full = 0;
+ entry->name_hash = 0;
+ entry->hashtable_next = NULL;
/* Add this entry to list. */
if (*last_entry == NULL)
@@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
memcpy(entry->name, name, name_len);
entry->name[name_len] = '\0';
parse_escapes(entry->name, entry);
+ entry->name_hash = hash(entry->name);
+
+ ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
+ if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
+ while (ht_iter->hashtable_next)
+ ht_iter = ht_iter->hashtable_next;
+ ht_iter->hashtable_next = entry;
+ } else {
+ mtree->entry_hashtable[ht_idx] = entry;
+ }
for (iter = *global; iter != NULL; iter = iter->next) {
r = add_option(a, &entry->options, iter->value,
@@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
if (*p != '/') {
r = process_add_entry(a, mtree, &global, p, len,
&last_entry, is_form_d);
- } else if (strncmp(p, "/set", 4) == 0) {
+ } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
if (p[4] != ' ' && p[4] != '\t')
break;
r = process_global_set(a, &global, p);
- } else if (strncmp(p, "/unset", 6) == 0) {
+ } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
if (p[6] != ' ' && p[6] != '\t')
break;
r = process_global_unset(a, &global, p);
@@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* with pathname canonicalization, which is a very
* tricky subject.)
*/
- for (mp = mentry->next; mp != NULL; mp = mp->next) {
+ for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
if (mp->full && !mp->used
- && strcmp(mentry->name, mp->name) == 0) {
+ && mentry->name_hash == mp->name_hash
+ && strcmp(mentry->name, mp->name) == 0) {
/* Later lines override earlier ones. */
mp->used = 1;
r1 = parse_line(a, entry, mtree, mp,
@@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (*val == '.') {
++val;
ns = (long)mtree_atol10(&val);
- } else
- ns = 0;
+ if (ns < 0)
+ ns = 0;
+ else if (ns > 999999999)
+ ns = 999999999;
+ }
if (m > my_time_t_max)
m = my_time_t_max;
else if (m < my_time_t_min)
@@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
find_off = u - mtree->line.s;
}
}
+
+static unsigned int
+hash(const char *p)
+{
+ /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
+ as used by ELF for hashing function names. */
+ unsigned g, h = 0;
+ while (*p != '\0') {
+ h = (h << 4) + *p++;
+ if ((g = h & 0xF0000000) != 0) {
+ h ^= g >> 24;
+ h &= 0x0FFFFFFF;
+ }
+ }
+ return h;
+}
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_rar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_rar.c
index f729f173645..1e9849fdd62 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_rar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_rar.c
@@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_support_format_rar");
- rar = (struct rar *)malloc(sizeof(*rar));
+ rar = (struct rar *)calloc(sizeof(*rar), 1);
if (rar == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
return (ARCHIVE_FATAL);
}
- memset(rar, 0, sizeof(*rar));
/*
* Until enough data has been read, we cannot tell about
@@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
- /* Main header is password encrytped, so we cannot read any
+ /* Main header is password encrypted, so we cannot read any
file names or any other info about files from the header. */
if (rar->main_flags & MHD_PASSWORD)
{
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
index b0521a627ce..bd7f13d52ee 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -136,6 +137,7 @@ struct tar {
int64_t entry_padding;
int64_t entry_bytes_unconsumed;
int64_t realsize;
+ int sparse_allowed;
struct sparse_block *sparse_list;
struct sparse_block *sparse_last;
int64_t sparse_offset;
@@ -202,9 +204,14 @@ static int archive_read_format_tar_read_header(struct archive_read *,
struct archive_entry *);
static int checksum(struct archive_read *, const void *);
static int pax_attribute(struct archive_read *, struct tar *,
- struct archive_entry *, const char *key, const char *value);
+ struct archive_entry *, const char *key, const char *value,
+ size_t value_length);
+static int pax_attribute_acl(struct archive_read *, struct tar *,
+ struct archive_entry *, const char *, int);
+static int pax_attribute_xattr(struct archive_entry *, const char *,
+ const char *);
static int pax_header(struct archive_read *, struct tar *,
- struct archive_entry *, char *attr);
+ struct archive_entry *, struct archive_string *);
static void pax_time(const char *, int64_t *sec, long *nanos);
static ssize_t readline(struct archive_read *, struct tar *, const char **,
ssize_t limit, size_t *);
@@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a)
return (ARCHIVE_OK);
}
+/*
+ * Validate number field
+ *
+ * This has to be pretty lenient in order to accommodate the enormous
+ * variety of tar writers in the world:
+ * = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
+ * zeros and allows fields to be terminated with space or null characters
+ * = Many writers use different termination (in particular, libarchive
+ * omits terminator bytes to squeeze one or two more digits)
+ * = Many writers pad with space and omit leading zeros
+ * = GNU tar and star write base-256 values if numbers are too
+ * big to be represented in octal
+ *
+ * Examples of specific tar headers that we should support:
+ * = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
+ * null bytes, pads size with spaces and other numeric fields with zeroes
+ * = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
+ * may have uid and gid fields filled with spaces without any octal digits
+ * at all and pads all numeric fields with spaces
+ *
+ * This should tolerate all variants in use. It will reject a field
+ * where the writer just left garbage after a trailing NUL.
+ */
+static int
+validate_number_field(const char* p_field, size_t i_size)
+{
+ unsigned char marker = (unsigned char)p_field[0];
+ if (marker == 128 || marker == 255 || marker == 0) {
+ /* Base-256 marker, there's nothing we can check. */
+ return 1;
+ } else {
+ /* Must be octal */
+ size_t i = 0;
+ /* Skip any leading spaces */
+ while (i < i_size && p_field[i] == ' ') {
+ ++i;
+ }
+ /* Skip octal digits. */
+ while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
+ ++i;
+ }
+ /* Any remaining characters must be space or NUL padding. */
+ while (i < i_size) {
+ if (p_field[i] != ' ' && p_field[i] != 0) {
+ return 0;
+ }
+ ++i;
+ }
+ return 1;
+ }
+}
static int
archive_read_format_tar_bid(struct archive_read *a, int best_bid)
@@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
return (0);
bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */
- /* Sanity check: Look at first byte of mode field. */
- switch (255 & (unsigned)header->mode[0]) {
- case 0: case 255:
- /* Base-256 value: No further verification possible! */
- break;
- case ' ': /* Not recommended, but not illegal, either. */
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- /* Octal Value. */
- /* TODO: Check format of remainder of this field. */
- break;
- default:
- /* Not a valid mode; bail out here. */
- return (0);
+ /*
+ * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
+ */
+ if (bid > 0 && (
+ validate_number_field(header->mode, sizeof(header->mode)) == 0
+ || validate_number_field(header->uid, sizeof(header->uid)) == 0
+ || validate_number_field(header->gid, sizeof(header->gid)) == 0
+ || validate_number_field(header->mtime, sizeof(header->mtime)) == 0
+ || validate_number_field(header->size, sizeof(header->size)) == 0
+ || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
+ || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
+ bid = 0;
}
- /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
return (bid);
}
@@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a,
tar = (struct tar *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) {
- /* Handle UTF-8 filnames as libarchive 2.x */
+ /* Handle UTF-8 filenames as libarchive 2.x */
tar->compat_2x = (val != NULL && val[0] != 0);
tar->init_default_conversion = tar->compat_2x;
return (ARCHIVE_OK);
@@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
tar->sparse_gnu_pending = 0;
/* Read initial sparse map. */
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
- tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
return ((int)bytes_read);
+ tar->entry_bytes_remaining -= bytes_read;
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
{
const struct archive_entry_header_ustar *header;
size_t size;
- int err;
+ int err, acl_type;
int64_t type;
char *acl, *p;
@@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
switch ((int)type & ~0777777) {
case 01000000:
/* POSIX.1e ACL */
+ acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
break;
case 03000000:
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Solaris NFSv4 ACLs not supported");
- return (ARCHIVE_WARN);
+ /* NFSv4 ACL */
+ acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4;
+ break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Malformed Solaris ACL attribute (unsupported type %o)",
@@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
return (ARCHIVE_FATAL);
}
archive_strncpy(&(tar->localname), acl, p - acl);
- err = archive_acl_parse_l(archive_entry_acl(entry),
- tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl);
+ err = archive_acl_from_text_l(archive_entry_acl(entry),
+ tar->localname.s, acl_type, tar->sconv_acl);
if (err != ARCHIVE_OK) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
@@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar,
if (tar->entry_bytes_remaining < 0) {
tar->entry_bytes_remaining = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Tar entry has negative size?");
- err = ARCHIVE_WARN;
+ "Tar entry has negative size");
+ return (ARCHIVE_FATAL);
+ }
+ if (tar->entry_bytes_remaining == INT64_MAX) {
+ /* Note: tar_atol returns INT64_MAX on overflow */
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Tar entry size overflow");
+ return (ARCHIVE_FATAL);
}
tar->realsize = tar->entry_bytes_remaining;
archive_entry_set_size(entry, tar->entry_bytes_remaining);
@@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar,
* sparse information in the extended area.
*/
/* FALLTHROUGH */
+ case '0':
+ /*
+ * Enable sparse file "read" support only for regular
+ * files and explicit GNU sparse files. However, we
+ * don't allow non-standard file types to be sparse.
+ */
+ tar->sparse_allowed = 1;
+ /* FALLTHROUGH */
default: /* Regular file and non-standard types */
/*
* Per POSIX: non-recognized types should always be
@@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar,
* and then skip any fields in the standard header that were
* defined in the pax header.
*/
- err2 = pax_header(a, tar, entry, tar->pax_header.s);
+ err2 = pax_header(a, tar, entry, &tar->pax_header);
err = err_combine(err, err2);
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
return (err);
@@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar,
*/
static int
pax_header(struct archive_read *a, struct tar *tar,
- struct archive_entry *entry, char *attr)
+ struct archive_entry *entry, struct archive_string *in_as)
{
- size_t attr_length, l, line_length;
+ size_t attr_length, l, line_length, value_length;
char *p;
char *key, *value;
struct archive_string *as;
struct archive_string_conv *sconv;
int err, err2;
+ char *attr = in_as->s;
- attr_length = strlen(attr);
+ attr_length = in_as->length;
tar->pax_hdrcharset_binary = 0;
archive_string_empty(&(tar->entry_gname));
archive_string_empty(&(tar->entry_linkpath));
@@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar,
}
*p = '\0';
- /* Identify null-terminated 'value' portion. */
value = p + 1;
+ /* Some values may be binary data */
+ value_length = attr + line_length - 1 - value;
+
/* Identify this attribute and set it in the entry. */
- err2 = pax_attribute(a, tar, entry, key, value);
+ err2 = pax_attribute(a, tar, entry, key, value, value_length);
if (err2 == ARCHIVE_FATAL)
return (err2);
err = err_combine(err, err2);
@@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry,
return 0;
}
+static int
+pax_attribute_schily_xattr(struct archive_entry *entry,
+ const char *name, const char *value, size_t value_length)
+{
+ if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0)
+ return 1;
+
+ name += 13;
+
+ archive_entry_xattr_add_entry(entry, name, value, value_length);
+
+ return 0;
+}
+
+static int
+pax_attribute_acl(struct archive_read *a, struct tar *tar,
+ struct archive_entry *entry, const char *value, int type)
+{
+ int r;
+ const char* errstr;
+
+ switch (type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ errstr = "SCHILY.acl.access";
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ errstr = "SCHILY.acl.default";
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ errstr = "SCHILY.acl.ace";
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL type: %d", type);
+ return(ARCHIVE_FATAL);
+ }
+
+ if (tar->sconv_acl == NULL) {
+ tar->sconv_acl =
+ archive_string_conversion_from_charset(
+ &(a->archive), "UTF-8", 1);
+ if (tar->sconv_acl == NULL)
+ return (ARCHIVE_FATAL);
+ }
+
+ r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
+ tar->sconv_acl);
+ if (r != ARCHIVE_OK) {
+ if (r == ARCHIVE_FATAL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "%s %s", "Can't allocate memory for ",
+ errstr);
+ return (r);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
+ }
+ return (r);
+}
+
/*
* Parse a single key=value attribute. key/value pointers are
* assumed to point into reasonably long-lived storage.
@@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry,
*/
static int
pax_attribute(struct archive_read *a, struct tar *tar,
- struct archive_entry *entry, const char *key, const char *value)
+ struct archive_entry *entry, const char *key, const char *value, size_t value_length)
{
int64_t s;
long n;
@@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
* NULL pointer to strlen(). */
switch (key[0]) {
case 'G':
+ /* Reject GNU.sparse.* headers on non-regular files. */
+ if (strncmp(key, "GNU.sparse", 10) == 0 &&
+ !tar->sparse_allowed) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Non-regular file cannot be sparse");
+ return (ARCHIVE_FATAL);
+ }
+
/* GNU "0.0" sparse pax format. */
if (strcmp(key, "GNU.sparse.numblocks") == 0) {
tar->sparse_offset = -1;
@@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
case 'S':
/* We support some keys used by the "star" archiver */
if (strcmp(key, "SCHILY.acl.access") == 0) {
- if (tar->sconv_acl == NULL) {
- tar->sconv_acl =
- archive_string_conversion_from_charset(
- &(a->archive), "UTF-8", 1);
- if (tar->sconv_acl == NULL)
- return (ARCHIVE_FATAL);
- }
-
- r = archive_acl_parse_l(archive_entry_acl(entry),
- value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- tar->sconv_acl);
- if (r != ARCHIVE_OK) {
- err = r;
- if (err == ARCHIVE_FATAL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "SCHILY.acl.access");
- return (err);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Parse error: SCHILY.acl.access");
- }
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ if (r == ARCHIVE_FATAL)
+ return (r);
} else if (strcmp(key, "SCHILY.acl.default") == 0) {
- if (tar->sconv_acl == NULL) {
- tar->sconv_acl =
- archive_string_conversion_from_charset(
- &(a->archive), "UTF-8", 1);
- if (tar->sconv_acl == NULL)
- return (ARCHIVE_FATAL);
- }
-
- r = archive_acl_parse_l(archive_entry_acl(entry),
- value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
- tar->sconv_acl);
- if (r != ARCHIVE_OK) {
- err = r;
- if (err == ARCHIVE_FATAL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "SCHILY.acl.default");
- return (err);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Parse error: SCHILY.acl.default");
- }
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+ if (r == ARCHIVE_FATAL)
+ return (r);
+ } else if (strcmp(key, "SCHILY.acl.ace") == 0) {
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ if (r == ARCHIVE_FATAL)
+ return (r);
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
archive_entry_set_rdevmajor(entry,
(dev_t)tar_atol10(value, strlen(value)));
@@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
+ } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
+ pax_attribute_schily_xattr(entry, key, value,
+ value_length);
} else if (strcmp(key, "SUN.holesdata") == 0) {
/* A Solaris extension for sparse. */
r = solaris_sparse_parse(a, tar, entry, value);
@@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
{
struct sparse_block *p;
- p = (struct sparse_block *)malloc(sizeof(*p));
+ p = (struct sparse_block *)calloc(1, sizeof(*p));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
- memset(p, 0, sizeof(*p));
if (tar->sparse_last != NULL)
tar->sparse_last->next = p;
else
@@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
tar_flush_unconsumed(a, unconsumed);
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
to_skip = 0x1ff & -bytes_read;
+ /* Fail if tar->entry_bytes_remaing would get negative */
+ if (to_skip > remaining)
+ return (ARCHIVE_FATAL);
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
return ((ssize_t)(bytes_read + to_skip));
@@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
last_digit_limit = INT64_MAX % base;
/* the pointer will not be dereferenced if char_cnt is zero
- * due to the way the && operator is evaulated.
+ * due to the way the && operator is evaluated.
*/
while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
p++;
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_warc.c b/archivers/libarchive/files/libarchive/archive_read_support_format_warc.c
index 9d801328756..b1624651426 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_warc.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_warc.c
@@ -88,7 +88,7 @@ typedef enum {
WT_RVIS,
/* conversion, unsupported */
WT_CONV,
- /* continutation, unsupported at the moment */
+ /* continuation, unsupported at the moment */
WT_CONT,
/* invalid type */
LAST_WT
@@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz);
static time_t _warc_rdrtm(const char *buf, size_t bsz);
static time_t _warc_rdmtm(const char *buf, size_t bsz);
static const char *_warc_find_eoh(const char *buf, size_t bsz);
+static const char *_warc_find_eol(const char *buf, size_t bsz);
-
int
archive_read_support_format_warc(struct archive *_a)
{
@@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
- if ((w = malloc(sizeof(*w))) == NULL) {
+ if ((w = calloc(1, sizeof(*w))) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate warc data");
return (ARCHIVE_FATAL);
}
- memset(w, 0, sizeof(*w));
r = __archive_read_register_format(
a, w, "warc",
@@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid)
/* otherwise snarf the record's version number */
ver = _warc_rdver(hdr, nrd);
- if (ver == 0U || ver > 10000U) {
- /* oh oh oh, best not to wager ... */
+ if (ver < 1200U || ver > 10000U) {
+ /* we only support WARC 0.12 to 1.0 */
return -1;
}
@@ -255,23 +254,32 @@ start_over:
&a->archive, ARCHIVE_ERRNO_MISC,
"Bad record header");
return (ARCHIVE_FATAL);
- } else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) {
- /* nawww, I wish they promised backward compatibility
- * anyhoo, in their infinite wisdom the 28500 guys might
- * come up with something we can't possibly handle so
- * best end things here */
+ }
+ ver = _warc_rdver(buf, eoh - buf);
+ /* we currently support WARC 0.12 to 1.0 */
+ if (ver == 0U) {
archive_set_error(
&a->archive, ARCHIVE_ERRNO_MISC,
- "Unsupported record version");
+ "Invalid record version");
return (ARCHIVE_FATAL);
- } else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) {
+ } else if (ver < 1200U || ver > 10000U) {
+ archive_set_error(
+ &a->archive, ARCHIVE_ERRNO_MISC,
+ "Unsupported record version: %u.%u",
+ ver / 10000, (ver % 10000) / 100);
+ return (ARCHIVE_FATAL);
+ }
+ cntlen = _warc_rdlen(buf, eoh - buf);
+ if (cntlen < 0) {
/* nightmare! the specs say content-length is mandatory
* so I don't feel overly bad stopping the reader here */
archive_set_error(
&a->archive, EINVAL,
"Bad content length");
return (ARCHIVE_FATAL);
- } else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) {
+ }
+ rtime = _warc_rdrtm(buf, eoh - buf);
+ if (rtime == (time_t)-1) {
/* record time is mandatory as per WARC/1.0,
* so just barf here, fast and loud */
archive_set_error(
@@ -285,7 +293,7 @@ start_over:
if (ver != w->pver) {
/* stringify this entry's version */
archive_string_sprintf(&w->sver,
- "WARC/%u.%u", ver / 10000, ver % 10000);
+ "WARC/%u.%u", ver / 10000, (ver % 10000) / 100);
/* remember the version */
w->pver = ver;
}
@@ -318,7 +326,7 @@ start_over:
}
memcpy(w->pool.str, fnam.str, fnam.len);
w->pool.str[fnam.len] = '\0';
- /* let noone else know about the pool, it's a secret, shhh */
+ /* let no one else know about the pool, it's a secret, shhh */
fnam.str = w->pool.str;
/* snarf mtime or deduce from rtime
@@ -535,7 +543,7 @@ xstrpisotime(const char *s, char **endptr)
/* as a courtesy to our callers, and since this is a non-standard
* routine, we skip leading whitespace */
- while (isspace((unsigned char)*s))
+ while (*s == ' ' || *s == '\t')
++s;
/* read year */
@@ -563,7 +571,7 @@ xstrpisotime(const char *s, char **endptr)
goto out;
}
- /* massage TM to fulfill some of POSIX' contraints */
+ /* massage TM to fulfill some of POSIX' constraints */
tm.tm_year -= 1900;
tm.tm_mon--;
@@ -578,51 +586,43 @@ out:
}
static unsigned int
-_warc_rdver(const char buf[10], size_t bsz)
+_warc_rdver(const char *buf, size_t bsz)
{
static const char magic[] = "WARC/";
- unsigned int ver;
-
- (void)bsz; /* UNUSED */
+ const char *c;
+ unsigned int ver = 0U;
+ unsigned int end = 0U;
- if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
- /* nope */
- return 99999U;
+ if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
+ /* buffer too small or invalid magic */
+ return ver;
}
/* looks good so far, read the version number for a laugh */
buf += sizeof(magic) - 1U;
- /* most common case gets a quick-check here */
- if (memcmp(buf, "1.0\r\n", 5U) == 0) {
- ver = 10000U;
- } else {
- switch (*buf) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- if (buf[1U] == '.') {
- char *on;
-
- /* set up major version */
- ver = (buf[0U] - '0') * 10000U;
- /* minor version, anyone? */
- ver += (strtol(buf + 2U, &on, 10)) * 100U;
- /* don't parse anything else */
- if (on > buf + 2U) {
- break;
- }
- }
- /* FALLTHROUGH */
- case '9':
- default:
- /* just make the version ridiculously high */
- ver = 999999U;
- break;
+
+ if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
+ /* we support a maximum of 2 digits in the minor version */
+ if (isdigit(buf[3U]))
+ end = 1U;
+ /* set up major version */
+ ver = (buf[0U] - '0') * 10000U;
+ /* set up minor version */
+ if (end == 1U) {
+ ver += (buf[2U] - '0') * 1000U;
+ ver += (buf[3U] - '0') * 100U;
+ } else
+ ver += (buf[2U] - '0') * 100U;
+ /*
+ * WARC below version 0.12 has a space-separated header
+ * WARC 0.12 and above terminates the version with a CRLF
+ */
+ c = buf + 3U + end;
+ if (ver >= 1200U) {
+ if (memcmp(c, "\r\n", 2U) != 0)
+ ver = 0U;
+ } else if (ver < 1200U) {
+ if (*c != ' ' && *c != '\t')
+ ver = 0U;
}
}
return ver;
@@ -632,34 +632,27 @@ static unsigned int
_warc_rdtyp(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Type:";
- const char *const eob = buf + bsz;
- const char *val;
+ const char *val, *eol;
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
/* no bother */
return WT_NONE;
}
- /* overread whitespace */
val += sizeof(_key) - 1U;
- while (val < eob && isspace((unsigned char)*val))
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return WT_NONE;
+ }
+
+ /* overread whitespace */
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
- if (val + 8U > eob) {
- ;
- } else if (memcmp(val, "resource", 8U) == 0) {
- return WT_RSRC;
- } else if (memcmp(val, "warcinfo", 8U) == 0) {
- return WT_INFO;
- } else if (memcmp(val, "metadata", 8U) == 0) {
- return WT_META;
- } else if (memcmp(val, "request", 7U) == 0) {
- return WT_REQ;
- } else if (memcmp(val, "response", 8U) == 0) {
- return WT_RSP;
- } else if (memcmp(val, "conversi", 8U) == 0) {
- return WT_CONV;
- } else if (memcmp(val, "continua", 8U) == 0) {
- return WT_CONT;
+ if (val + 8U == eol) {
+ if (memcmp(val, "resource", 8U) == 0)
+ return WT_RSRC;
+ else if (memcmp(val, "response", 8U) == 0)
+ return WT_RSP;
}
return WT_NONE;
}
@@ -668,10 +661,7 @@ static warc_string_t
_warc_rduri(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Target-URI:";
- const char *const eob = buf + bsz;
- const char *val;
- const char *uri;
- const char *eol;
+ const char *val, *uri, *eol, *p;
warc_string_t res = {0U, NULL};
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
@@ -680,25 +670,32 @@ _warc_rduri(const char *buf, size_t bsz)
}
/* overread whitespace */
val += sizeof(_key) - 1U;
- while (val < eob && isspace((unsigned char)*val))
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return res;
+ }
+
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
/* overread URL designators */
- if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) {
+ if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
/* not touching that! */
return res;
- } else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) {
- /* no end of line? :O */
- return res;
}
- /* massage uri to point to after :// */
+ /* spaces inside uri are not allowed, CRLF should follow */
+ for (p = val; p < eol; p++) {
+ if (isspace(*p))
+ return res;
+ }
+
+ /* there must be at least space for ftp */
+ if (uri < (val + 3U))
+ return res;
+
+ /* move uri to point to after :// */
uri += 3U;
- /* also massage eol to point to the first whitespace
- * after the last non-whitespace character before
- * the end of the line */
- while (eol > uri && isspace((unsigned char)eol[-1]))
- --eol;
/* now then, inspect the URI */
if (memcmp(val, "file", 4U) == 0) {
@@ -721,7 +718,7 @@ static ssize_t
_warc_rdlen(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nContent-Length:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
long int len;
@@ -729,14 +726,24 @@ _warc_rdlen(const char *buf, size_t bsz)
/* no bother */
return -1;
}
-
- /* strtol kindly overreads whitespace for us, so use that */
val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return -1;
+ }
+
+ /* skip leading whitespace */
+ while (val < eol && (*val == ' ' || *val == '\t'))
+ val++;
+ /* there must be at least one digit */
+ if (!isdigit(*val))
+ return -1;
len = strtol(val, &on, 10);
- if (on == NULL || !isspace((unsigned char)*on)) {
- /* hm, can we trust that number? Best not. */
+ if (on != eol) {
+ /* line must end here */
return -1;
}
+
return (size_t)len;
}
@@ -744,7 +751,7 @@ static time_t
_warc_rdrtm(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Date:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
time_t res;
@@ -752,13 +759,17 @@ _warc_rdrtm(const char *buf, size_t bsz)
/* no bother */
return (time_t)-1;
}
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+ /* no end of line */
+ return -1;
+ }
/* xstrpisotime() kindly overreads whitespace for us, so use that */
- val += sizeof(_key) - 1U;
res = xstrpisotime(val, &on);
- if (on == NULL || !isspace((unsigned char)*on)) {
- /* hm, can we trust that number? Best not. */
- return (time_t)-1;
+ if (on != eol) {
+ /* line must end here */
+ return -1;
}
return res;
}
@@ -767,7 +778,7 @@ static time_t
_warc_rdmtm(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nLast-Modified:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
time_t res;
@@ -775,13 +786,17 @@ _warc_rdmtm(const char *buf, size_t bsz)
/* no bother */
return (time_t)-1;
}
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+ /* no end of line */
+ return -1;
+ }
/* xstrpisotime() kindly overreads whitespace for us, so use that */
- val += sizeof(_key) - 1U;
res = xstrpisotime(val, &on);
- if (on == NULL || !isspace((unsigned char)*on)) {
- /* hm, can we trust that number? Best not. */
- return (time_t)-1;
+ if (on != eol) {
+ /* line must end here */
+ return -1;
}
return res;
}
@@ -798,4 +813,12 @@ _warc_find_eoh(const char *buf, size_t bsz)
return hit;
}
+static const char*
+_warc_find_eol(const char *buf, size_t bsz)
+{
+ static const char _marker[] = "\r\n";
+ const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
+
+ return hit;
+}
/* archive_read_support_format_warc.c ends here */
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_xar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_xar.c
index ab887505ce1..7a22beb9d8e 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_xar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_xar.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#endif
#if HAVE_LZMA_H
#include <lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
@@ -334,9 +332,6 @@ struct xar {
#if HAVE_LZMA_H && HAVE_LIBLZMA
lzma_stream lzstream;
int lzstream_valid;
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
- lzmadec_stream lzstream;
- int lzstream_valid;
#endif
/*
* For Checksum data.
@@ -399,6 +394,7 @@ static void checksum_update(struct archive_read *, const void *,
size_t, const void *, size_t);
static int checksum_final(struct archive_read *, const void *,
size_t, const void *, size_t);
+static void checksum_cleanup(struct archive_read *);
static int decompression_init(struct archive_read *, enum enctype);
static int decompress(struct archive_read *, const void **,
size_t *, const void *, size_t *);
@@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a)
int r;
xar = (struct xar *)(a->format->data);
+ checksum_cleanup(a);
r = decompression_cleanup(a);
hdlink = xar->hdlink_list;
while (hdlink != NULL) {
@@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a)
}
for (i = 0; i < xar->file_queue.used; i++)
file_free(xar->file_queue.files[i]);
+ free(xar->file_queue.files);
while (xar->unknowntags != NULL) {
struct unknown_tag *tag;
@@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding)
xar->lzstream.total_in = 0;
xar->lzstream.total_out = 0;
break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
- case LZMA:
- if (xar->lzstream_valid)
- lzmadec_end(&(xar->lzstream));
- r = lzmadec_init(&(xar->lzstream));
- if (r != LZMADEC_OK) {
- switch (r) {
- case LZMADEC_HEADER_ERROR:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Internal error initializing "
- "compression library: "
- "invalid header");
- break;
- case LZMADEC_MEM_ERROR:
- archive_set_error(&a->archive,
- ENOMEM,
- "Internal error initializing "
- "compression library: "
- "out of memory");
- break;
- }
- return (ARCHIVE_FATAL);
- }
- xar->lzstream_valid = 1;
- xar->lzstream.total_in = 0;
- xar->lzstream.total_out = 0;
- break;
#endif
/*
* Unsupported compression.
@@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
case BZIP2:
#endif
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
case LZMA:
-#endif
case XZ:
#endif
switch (xar->entry_encoding) {
@@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
*used = avail_in - xar->lzstream.avail_in;
*outbytes = avail_out - xar->lzstream.avail_out;
break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
- case LZMA:
- xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
- xar->lzstream.avail_in = avail_in;
- xar->lzstream.next_out = (unsigned char *)outbuff;
- xar->lzstream.avail_out = avail_out;
- r = lzmadec_decode(&(xar->lzstream), 0);
- switch (r) {
- case LZMADEC_STREAM_END: /* Found end of stream. */
- switch (lzmadec_end(&(xar->lzstream))) {
- case LZMADEC_OK:
- break;
- default:
- archive_set_error(&(a->archive),
- ARCHIVE_ERRNO_MISC,
- "Failed to clean up lzmadec decompressor");
- return (ARCHIVE_FATAL);
- }
- xar->lzstream_valid = 0;
- /* FALLTHROUGH */
- case LZMADEC_OK: /* Decompressor made some progress. */
- break;
- default:
- archive_set_error(&(a->archive),
- ARCHIVE_ERRNO_MISC,
- "lzmadec decompression failed(%d)",
- r);
- return (ARCHIVE_FATAL);
- }
- *used = avail_in - xar->lzstream.avail_in;
- *outbytes = avail_out - xar->lzstream.avail_out;
- break;
#endif
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
case BZIP2:
#endif
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
case LZMA:
-#endif
case XZ:
#endif
case NONE:
@@ -1788,6 +1722,16 @@ decompression_cleanup(struct archive_read *a)
}
static void
+checksum_cleanup(struct archive_read *a) {
+ struct xar *xar;
+
+ xar = (struct xar *)(a->format->data);
+
+ _checksum_final(&(xar->a_sumwrk), NULL, 0);
+ _checksum_final(&(xar->e_sumwrk), NULL, 0);
+}
+
+static void
xmlattr_cleanup(struct xmlattr_list *list)
{
struct xmlattr *attr, *next;
@@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len)
struct xar *xar;
const void *d;
size_t outbytes;
- size_t used;
+ size_t used = 0;
int r;
a = (struct archive_read *)context;
@@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a,
value = strdup(atts[1]);
if (attr == NULL || name == NULL || value == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ free(attr);
+ free(name);
+ free(value);
return (ARCHIVE_FATAL);
}
attr->name = name;
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_zip.c b/archivers/libarchive/files/libarchive/archive_read_support_format_zip.c
index 34ab04ecc9b..08bcf1f537c 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_zip.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_zip.c
@@ -199,7 +199,7 @@ struct zip {
struct trad_enc_ctx tctx;
char tctx_valid;
- /* WinZip AES decyption. */
+ /* WinZip AES decryption. */
/* Contexts used for AES decryption. */
archive_crypto_ctx cctx;
char cctx_valid;
@@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
}
static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
{
unsigned temp = ctx->keys[2] | 2;
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
max = (unsigned)((in_len < out_len)? in_len: out_len);
for (i = 0; i < max; i++) {
- uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx);
+ uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
out[i] = t;
trad_enc_update_keys(ctx, t);
}
@@ -418,18 +418,30 @@ zip_time(const char *p)
* id1+size1+data1 + id2+size2+data2 ...
* triplets. id and size are 2 bytes each.
*/
-static void
-process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
+static int
+process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
{
unsigned offset = 0;
- while (offset < extra_length - 4) {
+ if (extra_length == 0) {
+ return ARCHIVE_OK;
+ }
+
+ if (extra_length < 4) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
+ return ARCHIVE_FAILED;
+ }
+ while (offset <= extra_length - 4) {
unsigned short headerid = archive_le16dec(p + offset);
unsigned short datasize = archive_le16dec(p + offset + 2);
offset += 4;
if (offset + datasize > extra_length) {
- break;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Extra data overflow: Need %d bytes but only found %d bytes",
+ (int)datasize, (int)(extra_length - offset));
+ return ARCHIVE_FAILED;
}
#ifdef DEBUG
fprintf(stderr, "Header id 0x%04x, length %d\n",
@@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* Zip64 extended information extra field. */
zip_entry->flags |= LA_USED_ZIP64;
if (zip_entry->uncompressed_size == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->uncompressed_size =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit uncompressed size");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->uncompressed_size = t;
offset += 8;
datasize -= 8;
}
if (zip_entry->compressed_size == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->compressed_size =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit compressed size");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->compressed_size = t;
offset += 8;
datasize -= 8;
}
if (zip_entry->local_header_offset == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->local_header_offset =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit local header offset");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->local_header_offset = t;
offset += 8;
datasize -= 8;
}
@@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
break;
}
case 0x9901:
- /* WinZIp AES extra data field. */
+ /* WinZip AES extra data field. */
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =
@@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
}
offset += datasize;
}
-#ifdef DEBUG
- if (offset != extra_length)
- {
- fprintf(stderr,
- "Extra data field contents do not match reported size!\n");
+ if (offset != extra_length) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed extra data: Consumed %d bytes of %d bytes",
+ (int)offset, (int)extra_length);
+ return ARCHIVE_FAILED;
}
-#endif
+ return ARCHIVE_OK;
}
/*
@@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
- process_extra(h, extra_length, zip_entry);
+ if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
+ return ARCHIVE_FATAL;
+ }
__archive_read_consume(a, extra_length);
/* Work around a bug in Info-Zip: When reading from a pipe, it
@@ -850,29 +876,33 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= AE_IFREG;
}
- if ((zip_entry->mode & AE_IFMT) == 0) {
- /* Especially in streaming mode, we can end up
- here without having seen proper mode information.
- Guess from the filename. */
+ /* If the mode is totally empty, set some sane default. */
+ if (zip_entry->mode == 0) {
+ zip_entry->mode |= 0664;
+ }
+
+ /* Make sure that entries with a trailing '/' are marked as directories
+ * even if the External File Attributes contains bogus values. If this
+ * is not a directory and there is no type, assume regularfile. */
+ if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
+ int has_slash;
+
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
- if (len > 0 && wp[len - 1] == L'/')
- zip_entry->mode |= AE_IFDIR;
- else
- zip_entry->mode |= AE_IFREG;
+ has_slash = len > 0 && wp[len - 1] == L'/';
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
- if (len > 0 && cp[len - 1] == '/')
- zip_entry->mode |= AE_IFDIR;
- else
- zip_entry->mode |= AE_IFREG;
+ has_slash = len > 0 && cp[len - 1] == '/';
}
- if (zip_entry->mode == AE_IFDIR) {
- zip_entry->mode |= 0775;
- } else if (zip_entry->mode == AE_IFREG) {
- zip_entry->mode |= 0664;
+ /* Correct file type as needed. */
+ if (has_slash) {
+ zip_entry->mode &= ~AE_IFMT;
+ zip_entry->mode |= AE_IFDIR;
+ zip_entry->mode |= 0111;
+ } else if ((zip_entry->mode & AE_IFMT) == 0) {
+ zip_entry->mode |= AE_IFREG;
}
}
@@ -887,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_wstrcat(&s, wp);
archive_wstrappend_wchar(&s, L'/');
archive_entry_copy_pathname_w(entry, s.s);
+ archive_wstring_free(&s);
}
} else {
cp = archive_entry_pathname(entry);
@@ -897,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_strcat(&s, cp);
archive_strappend_char(&s, '/');
archive_entry_set_pathname(entry, s.s);
+ archive_string_free(&s);
}
}
}
@@ -1136,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|| (zip->hctx_valid
&& zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
if (zip->entry->flags & LA_USED_ZIP64) {
+ uint64_t compressed, uncompressed;
zip->entry->crc32 = archive_le32dec(p + 4);
- zip->entry->compressed_size =
- archive_le64dec(p + 8);
- zip->entry->uncompressed_size =
- archive_le64dec(p + 16);
+ compressed = archive_le64dec(p + 8);
+ uncompressed = archive_le64dec(p + 16);
+ if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Overflow of 64-bit file sizes");
+ return ARCHIVE_FAILED;
+ }
+ zip->entry->compressed_size = compressed;
+ zip->entry->uncompressed_size = uncompressed;
zip->unconsumed = 24;
} else {
zip->entry->crc32 = archive_le32dec(p + 4);
@@ -1293,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
&& bytes_avail > zip->entry_bytes_remaining) {
bytes_avail = (ssize_t)zip->entry_bytes_remaining;
}
- if (bytes_avail <= 0) {
+ if (bytes_avail < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file body");
return (ARCHIVE_FATAL);
@@ -1417,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
zip->unconsumed = 4;
}
if (zip->entry->flags & LA_USED_ZIP64) {
+ uint64_t compressed, uncompressed;
zip->entry->crc32 = archive_le32dec(p);
- zip->entry->compressed_size = archive_le64dec(p + 4);
- zip->entry->uncompressed_size = archive_le64dec(p + 12);
+ compressed = archive_le64dec(p + 4);
+ uncompressed = archive_le64dec(p + 12);
+ if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Overflow of 64-bit file sizes");
+ return ARCHIVE_FAILED;
+ }
+ zip->entry->compressed_size = compressed;
+ zip->entry->uncompressed_size = uncompressed;
zip->unconsumed += 20;
} else {
zip->entry->crc32 = archive_le32dec(p);
@@ -1500,7 +1548,7 @@ read_decryption_header(struct archive_read *a)
case 0x6720:/* Blowfish */
case 0x6721:/* Twofish */
case 0x6801:/* RC4 */
- /* Suuported encryption algorithm. */
+ /* Supported encryption algorithm. */
break;
default:
archive_set_error(&a->archive,
@@ -1609,7 +1657,7 @@ read_decryption_header(struct archive_read *a)
__archive_read_consume(a, 4);
/*return (ARCHIVE_OK);
- * This is not fully implemnted yet.*/
+ * This is not fully implemented yet.*/
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Encrypted file is unsupported");
return (ARCHIVE_FAILED);
@@ -1691,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a)
}
/*
- * Initialize ctx for Traditional PKWARE Decyption.
+ * Initialize ctx for Traditional PKWARE Decryption.
*/
r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
p, ENC_HEADER_SIZE, &crcchk);
@@ -2691,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
"Truncated ZIP file header");
return ARCHIVE_FATAL;
}
- process_extra(p + filename_length, extra_length, zip_entry);
+ if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
+ return ARCHIVE_FATAL;
+ }
/*
* Mac resource fork files are stored under the
diff --git a/archivers/libarchive/files/libarchive/archive_string.c b/archivers/libarchive/files/libarchive/archive_string.c
index 282c58e1eb9..592ead2bdd5 100644
--- a/archivers/libarchive/files/libarchive/archive_string.c
+++ b/archivers/libarchive/files/libarchive/archive_string.c
@@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
return (as);
}
+struct archive_string *
+archive_array_append(struct archive_string *as, const char *p, size_t s)
+{
+ return archive_string_append(as, p, s);
+}
+
void
archive_string_concat(struct archive_string *dest, struct archive_string *src)
{
@@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
}
if (count == 0 && length != 0)
ret = -1;
- } while (0);
+ break;
+ } while (1);
}
dest->length += count;
dest->s[dest->length] = L'\0';
@@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
wcs = dest->s + dest->length;
/*
* We cannot use mbsrtowcs/mbstowcs here because those may convert
- * extra MBS when strlen(p) > len and one wide character consis of
+ * extra MBS when strlen(p) > len and one wide character consists of
* multi bytes.
*/
while (*mbs && mbs_length > 0) {
@@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc,
sc->cd = iconv_open(tc, fc);
if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
/*
- * Unfortunaly, all of iconv implements do support
+ * Unfortunately, all of iconv implements do support
* "CP932" character-set, so we should use "SJIS"
* instead if iconv_open failed.
*/
@@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc,
/*
* archive_mstring on Windows directly convert multi-bytes
* into archive_wstring in order not to depend on locale
- * so that you can do a I18N programing. This will be
+ * so that you can do a I18N programming. This will be
* used only in archive_mstring_copy_mbs_len_l so far.
*/
if (flag & SCONV_FROM_CHARSET) {
@@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset,
* in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
* unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
* So we should make a string conversion between CP_ACP and CP_OEMCP
- * for compatibillty.
+ * for compatibility.
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
struct archive_string_conv *
@@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
* A filename in UTF-8 was made with libarchive 2.x in a wrong
* assumption that wchar_t was Unicode.
* This option enables simulating the assumption in order to read
- * that filname correctly.
+ * that filename correctly.
*/
case SCONV_SET_OPT_UTF8_LIBARCHIVE2X:
#if (defined(_WIN32) && !defined(__CYGWIN__)) \
@@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
struct archive_string_conv *sc)
{
const void *s;
- size_t length;
+ size_t length = 0;
int i, r = 0, r2;
+ if (_p != NULL && n > 0) {
+ if (sc != NULL && (sc->flag & SCONV_FROM_UTF16))
+ length = utf16nbytes(_p, n);
+ else
+ length = mbsnbytes(_p, n);
+ }
+
/* We must allocate memory even if there is no data for conversion
* or copy. This simulates archive_string_append behavior. */
- if (_p == NULL || n == 0) {
+ if (length == 0) {
int tn = 1;
if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
tn = 2;
@@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
* If sc is NULL, we just make a copy.
*/
if (sc == NULL) {
- length = mbsnbytes(_p, n);
if (archive_string_append(as, _p, length) == NULL)
return (-1);/* No memory */
return (0);
}
- if (sc->flag & SCONV_FROM_UTF16)
- length = utf16nbytes(_p, n);
- else
- length = mbsnbytes(_p, n);
s = _p;
i = 0;
if (sc->nconverter > 1) {
@@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
#if HAVE_ICONV
/*
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
@@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
/*
* Translate a string from a some CodePage to an another CodePage by
- * Windows APIs, and copy the result. Return -1 if conversion failes.
+ * Windows APIs, and copy the result. Return -1 if conversion fails.
*/
static int
strncat_in_codepage(struct archive_string *as,
@@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
/*
* If a character is ASCII, this just copies it. If not, this
- * assigns '?' charater instead but in UTF-8 locale this assigns
+ * assigns '?' character instead but in UTF-8 locale this assigns
* byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD,
* a Replacement Character in Unicode.
*/
@@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
- /* Invalide sequence or there are not plenty bytes. */
+ /* Invalid sequence or there are not plenty bytes. */
if ((int)n < cnt) {
cnt = (int)n;
for (i = 1; i < cnt; i++) {
@@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
goto invalid_sequence;
}
- /* The code point larger than 0x10FFFF is not leagal
+ /* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > UNICODE_MAX)
goto invalid_sequence;
@@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
int cnt;
cnt = _utf8_to_unicode(pwc, s, n);
- /* Any of Surrogate pair is not leagal Unicode values. */
+ /* Any of Surrogate pair is not legal Unicode values. */
if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
return (-3);
return (cnt);
@@ -2457,7 +2466,7 @@ invalid_sequence:
/*
* Convert a Unicode code point to a single UTF-8 sequence.
*
- * NOTE:This function does not check if the Unicode is leagal or not.
+ * NOTE:This function does not check if the Unicode is legal or not.
* Please you definitely check it before calling this.
*/
static size_t
@@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
/*
* Surrogate pair values(0xd800 through 0xdfff) are only
- * used by UTF-16, so, after above culculation, the code
+ * used by UTF-16, so, after above calculation, the code
* must not be surrogate values, and Unicode has no codes
- * larger than 0x10ffff. Thus, those are not leagal Unicode
+ * larger than 0x10ffff. Thus, those are not legal Unicode
* values.
*/
if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {
@@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2)
/*
* Normalize UTF-8/UTF-16BE characters to Form C and copy the result.
*
- * TODO: Convert composition exclusions,which are never converted
+ * TODO: Convert composition exclusions, which are never converted
* from NFC,NFD,NFKC and NFKD, to Form C.
*/
static int
@@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
}
/*
- * As libarchie 2.x, translates the UTF-8 characters into
+ * As libarchive 2.x, translates the UTF-8 characters into
* wide-characters in the assumption that WCS is Unicode.
*/
if (n < 0) {
@@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
/*
* Convert a UTF-16BE/LE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
@@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
ll = WideCharToMultiByte(sc->to_cp, 0,
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
NULL, &defchar);
- if (ll == 0 &&
- GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- /* Need more buffer for MBS. */
- ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
- if (archive_string_ensure(as, ll +1) == NULL)
- return (-1);
- mbs = as->s + as->length;
- mbs_size = as->buffer_length - as->length -1;
- continue;
+ /* Exit loop if we succeeded */
+ if (ll != 0 ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ break;
}
- } while (0);
+ /* Else expand buffer and loop to try again. */
+ ll = WideCharToMultiByte(sc->to_cp, 0,
+ (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
+ if (archive_string_ensure(as, ll +1) == NULL)
+ return (-1);
+ mbs = as->s + as->length;
+ mbs_size = as->buffer_length - as->length -1;
+ } while (1);
archive_string_free(&tmp);
as->length += ll;
as->s[as->length] = '\0';
@@ -3596,7 +3606,7 @@ is_big_endian(void)
/*
* Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
win_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
do {
count = MultiByteToWideChar(sc->from_cp,
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
- if (count == 0 &&
- GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- /* Need more buffer for UTF-16 string */
- count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, (int)length, NULL, 0);
- if (archive_string_ensure(as16, (count +1) * 2)
- == NULL)
- return (-1);
- u16 = as16->s + as16->length;
- avail = as16->buffer_length - 2;
- continue;
+ /* Exit loop if we succeeded */
+ if (count != 0 ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ break;
}
- } while (0);
+ /* Expand buffer and try again */
+ count = MultiByteToWideChar(sc->from_cp,
+ MB_PRECOMPOSED, s, (int)length, NULL, 0);
+ if (archive_string_ensure(as16, (count +1) * 2)
+ == NULL)
+ return (-1);
+ u16 = as16->s + as16->length;
+ avail = as16->buffer_length - 2;
+ } while (1);
as16->length += count * 2;
as16->s[as16->length] = 0;
as16->s[as16->length+1] = 0;
@@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
/*
* Convert a UTF-16BE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
best_effort_strncat_from_utf16(struct archive_string *as, const void *_p,
@@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p,
/*
* Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
- * Internationalization programing on Windows must use Wide
+ * Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
*/
if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) {
@@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
archive_string_empty(&(aes->aes_utf8));
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
- * Internationalization programing on Windows must use Wide
+ * Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
*/
if (sc == NULL) {
diff --git a/archivers/libarchive/files/libarchive/archive_string.h b/archivers/libarchive/files/libarchive/archive_string.h
index 23f49165749..56dfbb28f28 100644
--- a/archivers/libarchive/files/libarchive/archive_string.h
+++ b/archivers/libarchive/files/libarchive/archive_string.h
@@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char);
struct archive_wstring *
archive_wstrappend_wchar(struct archive_wstring *, wchar_t);
+/* Append a raw array to an archive_string, resizing as necessary */
+struct archive_string *
+archive_array_append(struct archive_string *, const char *, size_t);
+
/* Convert a Unicode string to current locale and append the result. */
/* Returns -1 if conversion fails. */
int
@@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int);
/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
int
archive_strncpy_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
int
archive_strncat_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
diff --git a/archivers/libarchive/files/libarchive/archive_util.c b/archivers/libarchive/files/libarchive/archive_util.c
index cc3d1c46072..6b3bd61163d 100644
--- a/archivers/libarchive/files/libarchive/archive_util.c
+++ b/archivers/libarchive/files/libarchive/archive_util.c
@@ -580,7 +580,7 @@ void
__archive_ensure_cloexec_flag(int fd)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)fd; /* UNSED */
+ (void)fd; /* UNUSED */
#else
int flags;
diff --git a/archivers/libarchive/files/libarchive/archive_windows.c b/archivers/libarchive/files/libarchive/archive_windows.c
index d4e93fe78aa..6ff8749ae74 100644
--- a/archivers/libarchive/files/libarchive/archive_windows.c
+++ b/archivers/libarchive/files/libarchive/archive_windows.c
@@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
has_backslash = 1;
}
/*
- * If there is no backslach chars, return the original.
+ * If there is no backslash chars, return the original.
*/
if (!has_backslash)
return (entry);
@@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e)
return;
}
- for (i = 0; i < (int)sizeof(doserrors); i++)
+ for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
{
if (doserrors[i].winerr == e)
{
diff --git a/archivers/libarchive/files/libarchive/archive_windows.h b/archivers/libarchive/files/libarchive/archive_windows.h
index 8cf1c56d89d..e77cd08fc3b 100644
--- a/archivers/libarchive/files/libarchive/archive_windows.h
+++ b/archivers/libarchive/files/libarchive/archive_windows.h
@@ -218,16 +218,20 @@
#define S_IWUSR _S_IWUSR
#define S_IRUSR _S_IRUSR
#endif
+#ifndef S_IRWXG
#define S_IRWXG _S_IRWXG
#define S_IXGRP _S_IXGRP
#define S_IWGRP _S_IWGRP
+#endif
#ifndef S_IRGRP
#define S_IRGRP _S_IRGRP
#endif
+#ifndef S_IRWXO
#define S_IRWXO _S_IRWXO
#define S_IXOTH _S_IXOTH
#define S_IWOTH _S_IWOTH
#define S_IROTH _S_IROTH
+#endif
#endif
diff --git a/archivers/libarchive/files/libarchive/archive_write.c b/archivers/libarchive/files/libarchive/archive_write.c
index e3fa3357ba7..0634a22967f 100644
--- a/archivers/libarchive/files/libarchive/archive_write.c
+++ b/archivers/libarchive/files/libarchive/archive_write.c
@@ -109,10 +109,9 @@ archive_write_new(void)
struct archive_write *a;
unsigned char *nulls;
- a = (struct archive_write *)malloc(sizeof(*a));
+ a = (struct archive_write *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_write_vtable();
@@ -126,12 +125,11 @@ archive_write_new(void)
/* Initialize a block of nulls for padding purposes. */
a->null_length = 1024;
- nulls = (unsigned char *)malloc(a->null_length);
+ nulls = (unsigned char *)calloc(1, a->null_length);
if (nulls == NULL) {
free(a);
return (NULL);
}
- memset(nulls, 0, a->null_length);
a->nulls = nulls;
return (&a->archive);
}
@@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f,
if (length == 0)
return(ARCHIVE_OK);
if (f->write == NULL)
- /* If unset, a fatal error has already ocuured, so this filter
+ /* If unset, a fatal error has already occurred, so this filter
* didn't open. We cannot write anything. */
return(ARCHIVE_FATAL);
r = (f->write)(f, buff, length);
diff --git a/archivers/libarchive/files/libarchive/archive_write_add_filter_program.c b/archivers/libarchive/files/libarchive/archive_write_add_filter_program.c
index 31a1b6f9678..55b5e8ecdf8 100644
--- a/archivers/libarchive/files/libarchive/archive_write_add_filter_program.c
+++ b/archivers/libarchive/files/libarchive/archive_write_add_filter_program.c
@@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data)
if (data->child)
CloseHandle(data->child);
#endif
+ free(data->program_name);
free(data->child_buf);
free(data);
}
diff --git a/archivers/libarchive/files/libarchive/archive_write_add_filter_xz.c b/archivers/libarchive/files/libarchive/archive_write_add_filter_xz.c
index 46a6c38aa6e..b0f25a6ef0e 100644
--- a/archivers/libarchive/files/libarchive/archive_write_add_filter_xz.c
+++ b/archivers/libarchive/files/libarchive/archive_write_add_filter_xz.c
@@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
if (f->code == ARCHIVE_FILTER_XZ) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
if (data->threads != 1) {
- bzero(&mt_options, sizeof(mt_options));
+ memset(&mt_options, 0, sizeof(mt_options));
mt_options.threads = data->threads;
mt_options.timeout = 300;
mt_options.filters = data->lzmafilters;
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk_acl.c b/archivers/libarchive/files/libarchive/archive_write_disk_acl.c
index 5cbba54f08f..144ab7e72e1 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk_acl.c
+++ b/archivers/libarchive/files/libarchive/archive_write_disk_acl.c
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
+#if HAVE_DARWIN_ACL
+#include <membership.h>
+#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
@@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#include "archive_acl_private.h"
#include "archive_write_disk_private.h"
-#ifndef HAVE_POSIX_ACL
+#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
/* Default empty function body to satisfy mainline code. */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
@@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
return (ARCHIVE_OK);
}
-#else
+#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
+
+#if HAVE_SUN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
+#elif HAVE_DARWIN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
+#endif
static int set_acl(struct archive *, int fd, const char *,
struct archive_acl *,
acl_type_t, int archive_entry_acl_type, const char *tn);
-/*
- * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
- */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl)
{
- int ret;
+ int ret = ARCHIVE_OK;
- if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) {
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
- if (ret != ARCHIVE_OK)
- return (ret);
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+#if !HAVE_DARWIN_ACL
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+#if HAVE_SUN_ACL
+ /* Solaris writes POSIX.1e access and default ACLs together */
+ ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
+ ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
+#else /* HAVE_POSIX_ACL */
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ACL_TYPE_ACCESS, 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,
+ ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
+ "default");
+#endif /* !HAVE_SUN_ACL */
+ /* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
-#ifdef ACL_TYPE_NFS4
- } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
+ }
+#endif /* !HAVE_DARWIN_ACL */
+#if HAVE_NFS4_ACL
+ if ((archive_acl_types(abstract_acl) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
- return (ret);
-#endif
- } else
- return ARCHIVE_OK;
+ }
+#endif /* HAVE_NFS4_ACL */
+ return (ret);
}
-static struct {
- int archive_perm;
- int platform_perm;
+/*
+ * Translate system ACL permissions into libarchive internal structure
+ */
+static const struct {
+ const int archive_perm;
+ const int platform_perm;
} acl_perm_map[] = {
+#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
+ {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}
+#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
+ {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},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else /* POSIX.1e ACL permissions */
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@@ -114,33 +181,69 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#ifdef ACL_TYPE_NFS4
-static struct {
- int archive_inherit;
- int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+ const int archive_inherit;
+ const int platform_inherit;
} acl_inherit_map[] = {
+#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */
+ {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},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
+ {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}
+#else /* FreeBSD NFSv4 ACL inheritance flags */
{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_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}
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#endif
+#endif /* HAVE_NFS4_ACL */
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
acl_type_t acl_type, int ae_requested_type, const char *tname)
{
+#if HAVE_SUN_ACL
+ aclent_t *aclent;
+ ace_t *ace;
+ int e, r;
+ acl_t *acl;
+#else
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
acl_flagset_t acl_flagset;
#endif
+#endif /* HAVE_SUN_ACL */
+#if HAVE_ACL_TYPE_NFS4
+ int r;
+#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
+#if HAVE_DARWIN_ACL
+ uuid_t ae_uuid;
+#endif
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
@@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name,
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
+
+#if HAVE_SUN_ACL
+ acl = NULL;
+ acl = malloc(sizeof(acl_t));
+ if (acl == NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL type");
+ return (ARCHIVE_FAILED);
+ }
+ if (acl_type == ACE_T)
+ acl->acl_entry_size = sizeof(ace_t);
+ else if (acl_type == ACLENT_T)
+ acl->acl_entry_size = sizeof(aclent_t);
+ else {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL type");
+ acl_free(acl);
+ return (ARCHIVE_FAILED);
+ }
+ acl->acl_type = acl_type;
+ acl->acl_cnt = entries;
+
+ acl->acl_aclp = malloc(entries * acl->acl_entry_size);
+ if (acl->acl_aclp == NULL) {
+ archive_set_error(a, errno,
+ "Can't allocate memory for acl buffer");
+ acl_free(acl);
+ return (ARCHIVE_FAILED);
+ }
+#else /* !HAVE_SUN_ACL */
acl = acl_init(entries);
+ if (acl == (acl_t)NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize ACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+#endif /* !HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ e = 0;
+#endif
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
- acl_create_entry(&acl, &acl_entry);
-
+#if HAVE_SUN_ACL
+ ace = NULL;
+ aclent = NULL;
+ if (acl->acl_type == ACE_T) {
+ ace = &((ace_t *)acl->acl_aclp)[e];
+ ace->a_who = -1;
+ ace->a_access_mask = 0;
+ ace->a_flags = 0;
+ } else {
+ aclent = &((aclent_t *)acl->acl_aclp)[e];
+ aclent->a_id = -1;
+ aclent->a_type = 0;
+ aclent->a_perm = 0;
+ }
+#else /* !HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+ /*
+ * 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;
+#endif
+ 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;
+ }
+#endif /* !HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+ 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;
+ }
+#endif
switch (ae_tag) {
+#if HAVE_SUN_ACL
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ if (acl->acl_type == ACE_T)
+ ace->a_who = ae_uid;
+ else {
+ aclent->a_id = ae_uid;
+ aclent->a_type |= USER;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ if (acl->acl_type == ACE_T) {
+ ace->a_who = ae_gid;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ } else {
+ aclent->a_id = ae_gid;
+ aclent->a_type |= GROUP;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if (acl->acl_type == ACE_T)
+ ace->a_flags |= ACE_OWNER;
+ else
+ aclent->a_type |= USER_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (acl->acl_type == ACE_T) {
+ ace->a_flags |= ACE_GROUP;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ } else
+ aclent->a_type |= GROUP_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ aclent->a_type |= CLASS_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ aclent->a_type |= OTHER_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ ace->a_flags |= ACE_EVERYONE;
+ break;
+#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_USER:
- acl_set_tag_type(acl_entry, ACL_USER);
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
+ acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
+#else /* MacOS */
+ if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
+ sizeof(uid_t), ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+#endif /* HAVE_DARWIN_ACL */
break;
case ARCHIVE_ENTRY_ACL_GROUP:
- acl_set_tag_type(acl_entry, ACL_GROUP);
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
+ acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
+#else /* MacOS */
+ if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
+ sizeof(gid_t), ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+#endif /* HAVE_DARWIN_ACL */
break;
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
@@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name,
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
+#endif /* !HAVE_DARWIN_ACL */
+#endif /* !HAVE_SUN_ACL */
default:
- /* XXX */
- break;
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
}
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
+ r = 0;
switch (ae_type) {
+#if HAVE_SUN_ACL
+ 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;
+ 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;
+#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_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;
+#endif /* !HAVE_SUN_ACL */
default:
- // XXX error handling here.
- break;
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
}
-#endif
- acl_get_permset(acl_entry, &acl_permset);
- acl_clear_perms(acl_permset);
+ if (r != 0) {
+#if HAVE_SUN_ACL
+ errno = EINVAL;
+#endif
+ archive_set_error(a, errno,
+ "Failed to set ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ if (acl->acl_type == ACLENT_T) {
+ if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
+ aclent->a_perm |= 1;
+ if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
+ aclent->a_perm |= 2;
+ if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
+ aclent->a_perm |= 4;
+ } else
+#else
+ 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;
+ }
+#endif /* !HAVE_SUN_ACL */
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
- if (ae_permset & acl_perm_map[i].archive_perm)
- acl_add_perm(acl_permset,
- acl_perm_map[i].platform_perm);
+ if (ae_permset & acl_perm_map[i].archive_perm) {
+#if HAVE_SUN_ACL
+ ace->a_access_mask |=
+ acl_perm_map[i].platform_perm;
+#else
+ if (acl_add_perm(acl_permset,
+ acl_perm_map[i].platform_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add ACL permission");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif
+ }
}
-#ifdef ACL_TYPE_NFS4
- acl_get_flagset_np(acl_entry, &acl_flagset);
- acl_clear_flags_np(acl_flagset);
- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
- if (ae_permset & acl_inherit_map[i].archive_inherit)
- acl_add_flag_np(acl_flagset,
- acl_inherit_map[i].platform_inherit);
+#if HAVE_NFS4_ACL
+#if HAVE_SUN_ACL
+ if (acl_type == ACE_T)
+#elif HAVE_DARWIN_ACL
+ if (acl_type == ACL_TYPE_EXTENDED)
+#else /* FreeBSD */
+ if (acl_type == ACL_TYPE_NFS4)
+#endif
+ {
+#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
+ /*
+ * 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;
+ }
+#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
+ if (ae_permset & acl_inherit_map[i].archive_inherit) {
+#if HAVE_SUN_ACL
+ ace->a_flags |=
+ acl_inherit_map[i].platform_inherit;
+#else /* !HAVE_SUN_ACL */
+ if (acl_add_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add flag to NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* HAVE_SUN_ACL */
+ }
+ }
}
+#endif /* HAVE_NFS4_ACL */
+#if HAVE_SUN_ACL
+ e++;
#endif
}
+#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
/* Try restoring the ACL through 'fd' if we can. */
-#if HAVE_ACL_SET_FD
- if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
- ret = ARCHIVE_OK;
- else
-#else
-#if HAVE_ACL_SET_FD_NP
- if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
- ret = ARCHIVE_OK;
- else
+#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
+ if (fd >= 0)
+#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+ if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
#endif
+ {
+#if HAVE_SUN_ACL
+ if (facl_set(fd, acl) == 0)
+#elif HAVE_ACL_SET_FD_NP
+ if (acl_set_fd_np(fd, acl, acl_type) == 0)
+#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+ if (acl_set_fd(fd, acl) == 0)
#endif
-#if HAVE_ACL_SET_LINK_NP
- if (acl_set_link_np(name, acl_type, acl) != 0) {
- archive_set_error(a, errno, "Failed to set %s acl", tname);
- ret = ARCHIVE_WARN;
- }
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set %s acl on fd", tname);
+ }
+ }
+ } else
+#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ if (acl_set(name, acl) != 0)
+#elif HAVE_ACL_SET_LINK_NP
+ if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* TODO: Skip this if 'name' is a symlink. */
- if (acl_set_file(name, acl_type, acl) != 0) {
- archive_set_error(a, errno, "Failed to set %s acl", tname);
- ret = ARCHIVE_WARN;
- }
+ 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 %s acl",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
acl_free(acl);
return (ret);
}
-#endif
+#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk_posix.c b/archivers/libarchive/files/libarchive/archive_write_disk_posix.c
index 67aacf15a00..5a01e8450ce 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk_posix.c
+++ b/archivers/libarchive/files/libarchive/archive_write_disk_posix.c
@@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl1.h>
#endif
+/*
+ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
+ *
+ * It assumes that the input is an integer type of no more than 64 bits.
+ * If the number is less than zero, t must be a signed type, so it fits in
+ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
+ * without loss. But it could be a large unsigned value, so we have to clip it
+ * to INT64_MAX.*
+ */
+#define to_int64_time(t) \
+ ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
+
#if __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
@@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$");
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
+#define O_CLOEXEC 0
+#endif
+
+/* Ignore non-int O_NOFOLLOW constant. */
+/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
+#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#undef O_NOFOLLOW
+#endif
+
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
#endif
struct fixup_entry {
@@ -298,7 +320,7 @@ struct archive_write_disk {
#define MAXIMUM_DIR_MODE 0775
/*
- * Maxinum uncompressed size of a decmpfs block.
+ * Maximum uncompressed size of a decmpfs block.
*/
#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
/*
@@ -313,7 +335,7 @@ struct archive_write_disk {
#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
/* Size to write compressed data to resource fork. */
#define COMPRESSED_W_SIZE (64 * 1024)
-/* decmpfs difinitions. */
+/* decmpfs definitions. */
#define MAX_DECMPFS_XATTR_SIZE 3802
#ifndef DECMPFS_XATTR_NAME
#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
@@ -326,12 +348,19 @@ struct archive_write_disk {
#define HFS_BLOCKS(s) ((s) >> 12)
+static void fsobj_error(int *, struct archive_string *, int, const char *,
+ const char *);
+static int check_symlinks_fsobj(char *, int *, struct archive_string *,
+ int);
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+ const char *pathname);
#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
static void edit_deep_directories(struct archive_write_disk *ad);
#endif
+static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
+ int);
static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, char *);
static int create_parent_dir(struct archive_write_disk *, char *);
@@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
-static int _archive_write_disk_header(struct archive *, struct archive_entry *);
+static int _archive_write_disk_header(struct archive *,
+ struct archive_entry *);
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
static int _archive_write_disk_finish_entry(struct archive *);
-static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
-static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+ size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+ size_t, int64_t);
static int
lazy_stat(struct archive_write_disk *a)
@@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
/*
* NOTE: UF_COMPRESSED is ignored even if the filesystem
* supports HFS+ Compression because the file should
- * have at least an extended attriute "com.apple.decmpfs"
+ * have at least an extended attribute "com.apple.decmpfs"
* before the flag is set to indicate that the file have
- * been compressed. If hte filesystem does not support
+ * been compressed. If the filesystem does not support
* HFS+ Compression the system call will fail.
*/
if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
@@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->restore_pwd >= 0) {
r = fchdir(a->restore_pwd);
if (r != 0) {
- archive_set_error(&a->archive, errno, "chdir() failure");
+ archive_set_error(&a->archive, errno,
+ "chdir() failure");
ret = ARCHIVE_FATAL;
}
close(a->restore_pwd);
@@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
if (archive_entry_birthtime_is_set(entry)) {
fe->birthtime = archive_entry_birthtime(entry);
- fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
+ fe->birthtime_nanos = archive_entry_birthtime_nsec(
+ entry);
} else {
/* If birthtime is unset, use mtime. */
fe->birthtime = fe->mtime;
@@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
fe->mac_metadata = malloc(metadata_size);
if (fe->mac_metadata != NULL) {
- memcpy(fe->mac_metadata, metadata, metadata_size);
+ memcpy(fe->mac_metadata, metadata,
+ metadata_size);
fe->mac_metadata_size = metadata_size;
fe->fixup |= TODO_MAC_METADATA;
}
@@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
a->compressed_buffer_remaining = a->compressed_buffer_size;
- /* If the compressed size is not enouph smaller than
+ /* If the compressed size is not enough smaller than
* the uncompressed size. cancel HFS+ compression.
* TODO: study a behavior of ditto utility and improve
* the condition to fall back into no HFS+ compression. */
@@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
(uint32_t *)(a->resource_fork + RSRC_H_SIZE);
/* Set the block count to the resource fork. */
archive_le32enc(a->decmpfs_block_info++, block_count);
- /* Get the position where we are goint to set compressed
+ /* Get the position where we are going to set compressed
* data. */
a->compressed_rsrc_position =
RSRC_H_SIZE + 4 + (block_count * 8);
@@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
bytes_to_write = size;
/* Seek if necessary to the specified offset. */
if (a->offset < a->fd_offset) {
- /* Can't support backword move. */
+ /* Can't support backward move. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Seek failed");
return (ARCHIVE_FATAL);
@@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a,
return (r);
if ((size_t)r < size) {
archive_set_error(&a->archive, 0,
- "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize);
+ "Too much data: Truncating file at %ju bytes",
+ (uintmax_t)a->filesize);
return (ARCHIVE_WARN);
}
#if ARCHIVE_VERSION_NUMBER < 3999000
@@ -1666,10 +1702,26 @@ _archive_write_disk_finish_entry(struct archive *_a)
* ACLs that prevent attribute changes (including time).
*/
if (a->todo & TODO_ACLS) {
- int r2 = archive_write_disk_set_acls(&a->archive, a->fd,
- archive_entry_pathname(a->entry),
- archive_entry_acl(a->entry));
+ int r2;
+#ifdef HAVE_DARWIN_ACL
+ /*
+ * On Mac OS, platform ACLs are stored also in mac_metadata by
+ * the operating system. If mac_metadata is present it takes
+ * precedence and we skip extracting libarchive NFSv4 ACLs
+ */
+ const void *metadata;
+ size_t metadata_size;
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
+ if ((a->todo & TODO_MAC_METADATA) == 0 ||
+ metadata == NULL || metadata_size == 0) {
+#endif
+ r2 = archive_write_disk_set_acls(&a->archive, a->fd,
+ archive_entry_pathname(a->entry),
+ archive_entry_acl(a->entry));
if (r2 < ret) ret = r2;
+#ifdef HAVE_DARWIN_ACL
+ }
+#endif
}
finish_metadata:
@@ -1755,10 +1807,9 @@ archive_write_disk_new(void)
{
struct archive_write_disk *a;
- a = (struct archive_write_disk *)malloc(sizeof(*a));
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
@@ -1796,7 +1847,7 @@ edit_deep_directories(struct archive_write_disk *a)
char *tail = a->name;
/* If path is short, avoid the open() below. */
- if (strlen(tail) <= PATH_MAX)
+ if (strlen(tail) < PATH_MAX)
return;
/* Try to record our starting dir. */
@@ -1806,7 +1857,7 @@ edit_deep_directories(struct archive_write_disk *a)
return;
/* As long as the path is too long... */
- while (strlen(tail) > PATH_MAX) {
+ while (strlen(tail) >= PATH_MAX) {
/* Locate a dir prefix shorter than PATH_MAX. */
tail += PATH_MAX - 8;
while (tail > a->name && *tail != '/')
@@ -1993,8 +2044,9 @@ restore_entry(struct archive_write_disk *a)
if (en) {
/* Everything failed; give up here. */
- archive_set_error(&a->archive, en, "Can't create '%s'",
- a->name);
+ if ((&a->archive)->error == NULL)
+ archive_set_error(&a->archive, en, "Can't create '%s'",
+ a->name);
return (ARCHIVE_FAILED);
}
@@ -2014,6 +2066,11 @@ create_filesystem_object(struct archive_write_disk *a)
const char *linkname;
mode_t final_mode, mode;
int r;
+ /* these for check_symlinks_fsobj */
+ char *linkname_copy; /* non-const copy of linkname */
+ struct stat st;
+ struct archive_string error_string;
+ int error_number;
/* We identify hard/symlinks according to the link names. */
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
@@ -2022,6 +2079,43 @@ create_filesystem_object(struct archive_write_disk *a)
#if !HAVE_LINK
return (EPERM);
#else
+ archive_string_init(&error_string);
+ linkname_copy = strdup(linkname);
+ if (linkname_copy == NULL) {
+ return (EPERM);
+ }
+ /*
+ * TODO: consider using the cleaned-up path as the link
+ * target?
+ */
+ r = cleanup_pathname_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ r = check_symlinks_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ free(linkname_copy);
+ archive_string_free(&error_string);
r = link(linkname, a->name) ? errno : 0;
/*
* New cpio and pax formats allow hardlink entries
@@ -2039,11 +2133,20 @@ create_filesystem_object(struct archive_write_disk *a)
a->todo = 0;
a->deferred = 0;
} else if (r == 0 && a->filesize > 0) {
- a->fd = open(a->name,
- O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
- __archive_ensure_cloexec_flag(a->fd);
- if (a->fd < 0)
+#ifdef HAVE_LSTAT
+ r = lstat(a->name, &st);
+#else
+ r = stat(a->name, &st);
+#endif
+ if (r != 0)
r = errno;
+ else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
+ a->fd = open(a->name, O_WRONLY | O_TRUNC |
+ O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ __archive_ensure_cloexec_flag(a->fd);
+ if (a->fd < 0)
+ r = errno;
+ }
}
return (r);
#endif
@@ -2190,8 +2293,13 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
- archive_write_disk_set_acls(&a->archive,
- -1, p->name, &p->acl);
+#ifdef HAVE_DARWIN_ACL
+ if ((p->fixup & TODO_MAC_METADATA) == 0 ||
+ p->mac_metadata == NULL ||
+ p->mac_metadata_size == 0)
+#endif
+ archive_write_disk_set_acls(&a->archive,
+ -1, p->name, &p->acl);
if (p->fixup & TODO_FFLAGS)
set_fflags_platform(a, -1, p->name,
p->mode, p->fflags_set, 0);
@@ -2351,116 +2459,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
return (a->current_fixup);
}
-/* TODO: Make this work. */
-/*
- * TODO: The deep-directory support bypasses this; disable deep directory
- * support if we're doing symlink checks.
- */
+/* Error helper for new *_fsobj functions */
+static void
+fsobj_error(int *a_eno, struct archive_string *a_estr,
+ int err, const char *errstr, const char *path)
+{
+ if (a_eno)
+ *a_eno = err;
+ if (a_estr)
+ archive_string_sprintf(a_estr, errstr, path);
+}
+
/*
* TODO: Someday, integrate this with the deep dir support; they both
* scan the path and both can be optimized by comparing against other
* recent paths.
*/
/* TODO: Extend this to support symlinks on Windows Vista and later. */
+
+/*
+ * Checks the given path to see if any elements along it are symlinks. Returns
+ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
+ */
static int
-check_symlinks(struct archive_write_disk *a)
+check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
{
#if !defined(HAVE_LSTAT)
/* Platform doesn't have lstat, so we can't look for symlinks. */
- (void)a; /* UNUSED */
+ (void)path; /* UNUSED */
+ (void)error_number; /* UNUSED */
+ (void)error_string; /* UNUSED */
+ (void)flags; /* UNUSED */
return (ARCHIVE_OK);
#else
- char *pn;
+ int res = ARCHIVE_OK;
+ char *tail;
+ char *head;
+ int last;
char c;
int r;
struct stat st;
+ int restore_pwd;
+
+ /* Nothing to do here if name is empty */
+ if(path[0] == '\0')
+ return (ARCHIVE_OK);
/*
* Guard against symlink tricks. Reject any archive entry whose
* destination would be altered by a symlink.
+ *
+ * Walk the filename in chunks separated by '/'. For each segment:
+ * - if it doesn't exist, continue
+ * - if it's symlink, abort or remove it
+ * - if it's a directory and it's not the last chunk, cd into it
+ * As we go:
+ * head points to the current (relative) path
+ * tail points to the temporary \0 terminating the segment we're
+ * currently examining
+ * c holds what used to be in *tail
+ * last is 1 if this is the last tail
*/
- /* Whatever we checked last time doesn't need to be re-checked. */
- pn = a->name;
- if (archive_strlen(&(a->path_safe)) > 0) {
- char *p = a->path_safe.s;
- while ((*pn != '\0') && (*p == *pn))
- ++p, ++pn;
- }
+ restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(restore_pwd);
+ if (restore_pwd < 0)
+ return (ARCHIVE_FATAL);
+ head = path;
+ tail = path;
+ last = 0;
+ /* TODO: reintroduce a safe cache here? */
/* Skip the root directory if the path is absolute. */
- if(pn == a->name && pn[0] == '/')
- ++pn;
- c = pn[0];
- /* Keep going until we've checked the entire name. */
- while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
+ if(tail == path && tail[0] == '/')
+ ++tail;
+ /* Keep going until we've checked the entire name.
+ * head, tail, path all alias the same string, which is
+ * temporarily zeroed at tail, so be careful restoring the
+ * stashed (c=tail[0]) for error messages.
+ * Exiting the loop with break is okay; continue is not.
+ */
+ while (!last) {
+ /*
+ * Skip the separator we just consumed, plus any adjacent ones
+ */
+ while (*tail == '/')
+ ++tail;
/* Skip the next path element. */
- while (*pn != '\0' && *pn != '/')
- ++pn;
- c = pn[0];
- pn[0] = '\0';
+ while (*tail != '\0' && *tail != '/')
+ ++tail;
+ /* is this the last path component? */
+ last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
+ /* temporarily truncate the string here */
+ c = tail[0];
+ tail[0] = '\0';
/* Check that we haven't hit a symlink. */
- r = lstat(a->name, &st);
+ r = lstat(head, &st);
if (r != 0) {
+ tail[0] = c;
/* We've hit a dir that doesn't exist; stop now. */
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ break;
+ } else {
+ /*
+ * Treat any other error as fatal - best to be
+ * paranoid here.
+ * Note: This effectively disables deep
+ * directory support when security checks are
+ * enabled. Otherwise, very long pathnames that
+ * trigger an error here could evade the
+ * sandbox.
+ * TODO: We could do better, but it would
+ * probably require merging the symlink checks
+ * with the deep-directory editing.
+ */
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not stat %s", path);
+ res = ARCHIVE_FAILED;
break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (!last) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /* Our view is now from inside this dir: */
+ head = tail + 1;
+ }
} else if (S_ISLNK(st.st_mode)) {
- if (c == '\0') {
+ if (last) {
/*
* Last element is symlink; remove it
* so we can overwrite it with the
* item being extracted.
*/
- if (unlink(a->name)) {
- archive_set_error(&a->archive, errno,
+ if (unlink(head)) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
"Could not remove symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ path);
+ res = ARCHIVE_FAILED;
+ break;
}
- a->pst = NULL;
/*
* Even if we did remove it, a warning
* is in order. The warning is silly,
* though, if we're just replacing one
* symlink with another symlink.
*/
- if (!S_ISLNK(a->mode)) {
- archive_set_error(&a->archive, 0,
- "Removing symlink %s",
- a->name);
+ tail[0] = c;
+ /*
+ * FIXME: not sure how important this is to
+ * restore
+ */
+ /*
+ if (!S_ISLNK(path)) {
+ fsobj_error(a_eno, a_estr, 0,
+ "Removing symlink %s", path);
}
+ */
/* Symlink gone. No more problem! */
- pn[0] = c;
- return (0);
- } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
+ res = ARCHIVE_OK;
+ break;
+ } else if (flags & ARCHIVE_EXTRACT_UNLINK) {
/* User asked us to remove problems. */
- if (unlink(a->name) != 0) {
- archive_set_error(&a->archive, 0,
- "Cannot remove intervening symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ if (unlink(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot remove intervening "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ tail[0] = c;
+ } else if ((flags &
+ ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+ /*
+ * We are not the last element and we want to
+ * follow symlinks if they are a directory.
+ *
+ * This is needed to extract hardlinks over
+ * symlinks.
+ */
+ r = stat(head, &st);
+ if (r != 0) {
+ tail[0] = c;
+ if (errno == ENOENT) {
+ break;
+ } else {
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not stat %s", path);
+ res = (ARCHIVE_FAILED);
+ break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /*
+ * Our view is now from inside
+ * this dir:
+ */
+ head = tail + 1;
+ } else {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
}
- a->pst = NULL;
} else {
- archive_set_error(&a->archive, 0,
- "Cannot extract through symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
}
}
- pn[0] = c;
- if (pn[0] != '\0')
- pn++; /* Advance to the next segment. */
+ /* be sure to always maintain this */
+ tail[0] = c;
+ if (tail[0] != '\0')
+ tail++; /* Advance to the next segment. */
}
- pn[0] = c;
- /* We've checked and/or cleaned the whole path, so remember it. */
- archive_strcpy(&a->path_safe, a->name);
- return (ARCHIVE_OK);
+ /* Catches loop exits via break */
+ tail[0] = c;
+#ifdef HAVE_FCHDIR
+ /* If we changed directory above, restore it here. */
+ if (restore_pwd >= 0) {
+ r = fchdir(restore_pwd);
+ if (r != 0) {
+ fsobj_error(a_eno, a_estr, errno,
+ "chdir() failure", "");
+ }
+ close(restore_pwd);
+ restore_pwd = -1;
+ if (r != 0) {
+ res = (ARCHIVE_FATAL);
+ }
+ }
+#endif
+ /* TODO: reintroduce a safe cache here? */
+ return res;
#endif
}
+/*
+ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
+ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
+ */
+static int
+check_symlinks(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ a->pst = NULL; /* to be safe */
+ return rc;
+}
+
+
#if defined(__CYGWIN__)
/*
* 1. Convert a path separator from '\' to '/' .
@@ -2471,7 +2746,7 @@ check_symlinks(struct archive_write_disk *a)
* See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
*/
static void
-cleanup_pathname_win(struct archive_write_disk *a)
+cleanup_pathname_win(char *path)
{
wchar_t wc;
char *p;
@@ -2482,7 +2757,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
mb = 0;
complete = 1;
utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
- for (p = a->name; *p != '\0'; p++) {
+ for (p = path; *p != '\0'; p++) {
++alen;
if (*p == '\\') {
/* If previous byte is smaller than 128,
@@ -2507,7 +2782,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
/*
* Convert path separator in wide-character.
*/
- p = a->name;
+ p = path;
while (*p != '\0' && alen) {
l = mbtowc(&wc, p, alen);
if (l == (size_t)-1) {
@@ -2534,26 +2809,27 @@ cleanup_pathname_win(struct archive_write_disk *a)
* is set) if the path is absolute.
*/
static int
-cleanup_pathname(struct archive_write_disk *a)
+cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
{
char *dest, *src;
char separator = '\0';
- dest = src = a->name;
+ dest = src = path;
if (*src == '\0') {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Invalid empty pathname");
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Invalid empty ", "pathname");
return (ARCHIVE_FAILED);
}
#if defined(__CYGWIN__)
- cleanup_pathname_win(a);
+ cleanup_pathname_win(path);
#endif
/* Skip leading '/'. */
if (*src == '/') {
- if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Path is absolute");
+ if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Path is ", "absolute");
return (ARCHIVE_FAILED);
}
@@ -2580,10 +2856,11 @@ cleanup_pathname(struct archive_write_disk *a)
} else if (src[1] == '.') {
if (src[2] == '/' || src[2] == '\0') {
/* Conditionally warn about '..' */
- if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
- archive_set_error(&a->archive,
+ if (flags
+ & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
+ fsobj_error(a_eno, a_estr,
ARCHIVE_ERRNO_MISC,
- "Path contains '..'");
+ "Path contains ", "'..'");
return (ARCHIVE_FAILED);
}
}
@@ -2614,7 +2891,7 @@ cleanup_pathname(struct archive_write_disk *a)
* We've just copied zero or more path elements, not including the
* final '/'.
*/
- if (dest == a->name) {
+ if (dest == path) {
/*
* Nothing got copied. The path must have been something
* like '.' or '/' or './' or '/././././/./'.
@@ -2629,6 +2906,23 @@ cleanup_pathname(struct archive_write_disk *a)
return (ARCHIVE_OK);
}
+static int
+cleanup_pathname(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ return rc;
+}
+
/*
* Create the parent directory of the specified path, assuming path
* is already in mutable storage.
@@ -2707,7 +3001,8 @@ create_dir(struct archive_write_disk *a, char *path)
}
} else if (errno != ENOENT && errno != ENOTDIR) {
/* Stat failed? */
- archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
+ archive_set_error(&a->archive, errno,
+ "Can't test directory '%s'", path);
return (ARCHIVE_FAILED);
} else if (slash != NULL) {
*slash = '\0';
@@ -3172,12 +3467,19 @@ set_fflags(struct archive_write_disk *a)
#ifdef UF_APPEND
critical_flags |= UF_APPEND;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ critical_flags |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
critical_flags |= EXT2_APPEND_FL;
#endif
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ critical_flags |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
critical_flags |= EXT2_IMMUTABLE_FL;
#endif
+#ifdef FS_JOURNAL_DATA_FL
+ critical_flags |= FS_JOURNAL_DATA_FL;
+#endif
if (a->todo & TODO_FFLAGS) {
archive_entry_fflags(a->entry, &set, &clear);
@@ -3232,7 +3534,8 @@ clear_nochange_fflags(struct archive_write_disk *a)
nochange_flags |= EXT2_IMMUTABLE_FL;
#endif
- return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags));
+ return (set_fflags_platform(a, a->fd, a->name, mode, 0,
+ nochange_flags));
}
@@ -3288,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
return (ARCHIVE_WARN);
}
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/*
* Linux uses ioctl() to read and write file flags.
*/
@@ -3301,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
int newflags, oldflags;
int sf_mask = 0;
- if (set == 0 && clear == 0)
+ if (set == 0 && clear == 0)
return (ARCHIVE_OK);
/* Only regular files and dirs can have flags. */
if (!S_ISREG(mode) && !S_ISDIR(mode))
@@ -3322,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
* defines. (?) The code below degrades reasonably gracefully
* if sf_mask is incomplete.
*/
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ sf_mask |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
sf_mask |= EXT2_IMMUTABLE_FL;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ sf_mask |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
sf_mask |= EXT2_APPEND_FL;
#endif
+#if defined(FS_JOURNAL_DATA_FL)
+ sf_mask |= FS_JOURNAL_DATA_FL;
+#endif
/*
* XXX As above, this would be way simpler if we didn't have
* to read the current flags from disk. XXX
@@ -3335,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
ret = ARCHIVE_OK;
/* Read the current file flags. */
- if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &oldflags) < 0)
goto fail;
/* Try setting the flags as given. */
newflags = (oldflags & ~clear) | set;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
if (errno != EPERM)
goto fail;
@@ -3349,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
newflags &= ~sf_mask;
oldflags &= sf_mask;
newflags |= oldflags;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
/* We couldn't set the flags, so report the failure. */
@@ -3757,7 +4088,8 @@ set_xattrs(struct archive_write_disk *a)
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
- archive_set_error(&a->archive, errno,
+ archive_set_error(&a->archive,
+ errno,
"Cannot restore extended "
"attributes on this file "
"system");
@@ -3768,7 +4100,8 @@ set_xattrs(struct archive_write_disk *a)
ret = ARCHIVE_WARN;
}
} else {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid extended attribute encountered");
ret = ARCHIVE_WARN;
}
@@ -3812,19 +4145,22 @@ set_xattrs(struct archive_write_disk *a)
errno = 0;
#if HAVE_EXTATTR_SET_FD
if (a->fd >= 0)
- e = extattr_set_fd(a->fd, namespace, name, value, size);
+ e = extattr_set_fd(a->fd, namespace, name,
+ value, size);
else
#endif
/* TODO: should we use extattr_set_link() instead? */
{
- e = extattr_set_file(archive_entry_pathname(entry),
- namespace, name, value, size);
+ e = extattr_set_file(
+ archive_entry_pathname(entry), namespace,
+ name, value, size);
}
if (e != (int)size) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
- archive_set_error(&a->archive, errno,
+ archive_set_error(&a->archive,
+ errno,
"Cannot restore extended "
"attributes on this file "
"system");
@@ -3870,10 +4206,10 @@ older(struct stat *st, struct archive_entry *entry)
{
/* First, test the seconds and return if we have a definite answer. */
/* Definitely older. */
- if (st->st_mtime < archive_entry_mtime(entry))
+ if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
return (1);
/* Definitely younger. */
- if (st->st_mtime > archive_entry_mtime(entry))
+ if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
return (0);
/* If this platform supports fractional seconds, try those. */
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk_set_standard_lookup.c b/archivers/libarchive/files/libarchive/archive_write_disk_set_standard_lookup.c
index 3b868fbad19..5c766d75dd0 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk_set_standard_lookup.c
+++ b/archivers/libarchive/files/libarchive/archive_write_disk_set_standard_lookup.c
@@ -84,15 +84,13 @@ static void cleanup(void *);
int
archive_write_disk_set_standard_lookup(struct archive *a)
{
- struct bucket *ucache = malloc(cache_size * sizeof(struct bucket));
- struct bucket *gcache = malloc(cache_size * sizeof(struct bucket));
+ struct bucket *ucache = calloc(cache_size, sizeof(struct bucket));
+ struct bucket *gcache = calloc(cache_size, sizeof(struct bucket));
if (ucache == NULL || gcache == NULL) {
free(ucache);
free(gcache);
return (ARCHIVE_FATAL);
}
- memset(ucache, 0, cache_size * sizeof(struct bucket));
- memset(gcache, 0, cache_size * sizeof(struct bucket));
archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
return (ARCHIVE_OK);
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk_windows.c b/archivers/libarchive/files/libarchive/archive_write_disk_windows.c
index da76c54db5b..94b016edf01 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk_windows.c
+++ b/archivers/libarchive/files/libarchive/archive_write_disk_windows.c
@@ -192,7 +192,7 @@ struct archive_write_disk {
/*
* Default mode for dirs created automatically (will be modified by umask).
- * Note that POSIX specifies 0777 for implicity-created dirs, "modified
+ * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
* by the process' file creation mask."
*/
#define DEFAULT_DIR_MODE 0777
@@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a)
}
/*
- * A full-pathname pointig a network drive
+ * A full-pathname pointing to a network drive
* like "\\<server-name>\<share-name>\file".
*/
if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
@@ -1221,10 +1221,9 @@ archive_write_disk_new(void)
{
struct archive_write_disk *a;
- a = (struct archive_write_disk *)malloc(sizeof(*a));
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
diff --git a/archivers/libarchive/files/libarchive/archive_write_open.3 b/archivers/libarchive/files/libarchive/archive_write_open.3
index a52959b98fc..457873e6148 100644
--- a/archivers/libarchive/files/libarchive/archive_write_open.3
+++ b/archivers/libarchive/files/libarchive/archive_write_open.3
@@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries.
This is the most generic form of this function, which accepts
pointers to three callback functions which will be invoked by
the compression layer to write the constructed archive.
+This does not alter the default archive padding.
.It Fn archive_write_open_fd
A convenience form of
.Fn archive_write_open
@@ -123,12 +124,21 @@ is currently in use.
You should be careful to ensure that this variable
remains allocated until after the archive is
closed.
+This function will disable padding unless you
+have specifically set the block size.
.El
More information about the
.Va struct archive
object and the overall design of the library can be found in the
.Xr libarchive 3
overview.
+.Pp
+Note that the convenience forms above vary in how
+they block the output.
+See
+.Xr archive_write_blocksize 3
+if you need to control the block size used for writes
+or the end-of-file padding behavior.
.\"
.Sh CLIENT CALLBACKS
To use this library, you will need to define and register
@@ -226,6 +236,7 @@ functions.
.Xr tar 1 ,
.Xr libarchive 3 ,
.Xr archive_write 3 ,
+.Xr archive_write_blocksize 3 ,
.Xr archive_write_filter 3 ,
.Xr archive_write_format 3 ,
.Xr archive_write_new 3 ,
diff --git a/archivers/libarchive/files/libarchive/archive_write_open_memory.c b/archivers/libarchive/files/libarchive/archive_write_open_memory.c
index 4f8d679e582..ea6ae0ac524 100644
--- a/archivers/libarchive/files/libarchive/archive_write_open_memory.c
+++ b/archivers/libarchive/files/libarchive/archive_write_open_memory.c
@@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t
{
struct write_memory_data *mine;
- mine = (struct write_memory_data *)malloc(sizeof(*mine));
+ mine = (struct write_memory_data *)calloc(1, sizeof(*mine));
if (mine == NULL) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
- memset(mine, 0, sizeof(*mine));
mine->buff = buff;
mine->size = buffSize;
mine->client_size = used;
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_7zip.c b/archivers/libarchive/files/libarchive/archive_write_set_format_7zip.c
index fc6ccfe0ba8..41ed74daf1b 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_7zip.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_7zip.c
@@ -205,7 +205,7 @@ struct _7zip {
/*
* The list of the file entries which has its contents is used to
* manage struct file objects.
- * We use 'next' a menber of struct file to chain.
+ * We use 'next' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
if (r < 0)
return (r);
- /* Write Nume size. */
+ /* Write Name size. */
r = enc_uint64(a, zip->total_bytes_entry_name+1);
if (r < 0)
return (r);
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
index 9f17564c34c..c9771d81a12 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
@@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a)
if (a->format_free != NULL)
(a->format_free)(a);
- ar = (struct ar_w *)malloc(sizeof(*ar));
+ ar = (struct ar_w *)calloc(1, sizeof(*ar));
if (ar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
return (ARCHIVE_FATAL);
}
- memset(ar, 0, sizeof(*ar));
a->format_data = ar;
a->format_name = "ar";
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_cpio.c b/archivers/libarchive/files/libarchive/archive_write_set_format_cpio.c
index 352649365d6..a4c9d1ed276 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_cpio.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_cpio.c
@@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_cpio_newc.c b/archivers/libarchive/files/libarchive/archive_write_set_format_cpio_newc.c
index a9bfa808cc1..957f1a333a6 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_cpio_newc.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_cpio_newc.c
@@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- cpio = (struct cpio *)malloc(sizeof(*cpio));
+ cpio = (struct cpio *)calloc(1, sizeof(*cpio));
if (cpio == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
return (ARCHIVE_FATAL);
}
- memset(cpio, 0, sizeof(*cpio));
a->format_data = cpio;
a->format_name = "cpio";
a->format_options = archive_write_newc_options;
@@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_gnutar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_gnutar.c
index 1d635d2dc3d..2d858c9f752 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_gnutar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_gnutar.c
@@ -119,9 +119,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', '0','\0',
/* gid, null termination: 8 bytes */
'0','0','0','0','0','0', '0','\0',
- /* size, space termation: 12 bytes */
+ /* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
- /* mtime, space termation: 12 bytes */
+ /* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a,
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
@@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_pathname(temp, "././@LongLink");
archive_entry_set_size(temp, length);
ret = archive_format_gnutar_header(a, buff, temp, 'K');
+ archive_entry_free(temp);
if (ret < ARCHIVE_WARN)
goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
- if(ret < ARCHIVE_WARN)
+ if (ret < ARCHIVE_WARN)
goto exit_write_header;
- archive_entry_free(temp);
/* Write name and trailing null byte. */
ret = __archive_write_output(a, gnutar->linkname, length);
- if(ret < ARCHIVE_WARN)
+ if (ret < ARCHIVE_WARN)
goto exit_write_header;
/* Pad to 512 bytes */
ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
@@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_pathname(temp, "././@LongLink");
archive_entry_set_size(temp, length);
ret = archive_format_gnutar_header(a, buff, temp, 'L');
+ archive_entry_free(temp);
if (ret < ARCHIVE_WARN)
goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
if(ret < ARCHIVE_WARN)
goto exit_write_header;
- archive_entry_free(temp);
/* Write pathname + trailing null byte. */
ret = __archive_write_output(a, pathname, length);
if(ret < ARCHIVE_WARN)
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_iso9660.c b/archivers/libarchive/files/libarchive/archive_write_set_format_iso9660.c
index cb3e54e8d21..c0ca435d15c 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_iso9660.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_iso9660.c
@@ -161,7 +161,7 @@ struct isofile {
/* Used for managing struct isofile list. */
struct isofile *allnext;
struct isofile *datanext;
- /* Used for managing a hardlined struct isofile list. */
+ /* Used for managing a hardlinked struct isofile list. */
struct isofile *hlnext;
struct isofile *hardlink_target;
@@ -436,7 +436,7 @@ struct iso_option {
* Type : string
* Default: Auto detect
* : We check a size of boot image;
- * : If ths size is just 1.22M/1.44M/2.88M,
+ * : If the size is just 1.22M/1.44M/2.88M,
* : we assume boot_type is 'fd';
* : otherwise boot_type is 'no-emulation'.
* COMPAT :
@@ -528,7 +528,7 @@ struct iso_option {
* - allow more then 8 depths of directory trees;
* - disable a version number to a File Name;
* - disable a forced period to the tail of a File Name;
- * - the maxinum length of files and directories is raised to 193.
+ * - the maximum length of files and directories is raised to 193.
* if rockridge option is disabled, raised to 207.
*/
unsigned int iso_level:3;
@@ -626,7 +626,7 @@ struct iso_option {
* : NOTE Our rockridge=useful option does not set a zero
* : to uid and gid, you should use application
* : option such as --gid,--gname,--uid and --uname
- * : badtar options instead.
+ * : bsdtar options instead.
* Type : boolean/string
* Default: Enabled as rockridge=useful
* COMPAT : mkisofs -r / -R
@@ -660,7 +660,7 @@ struct iso_option {
* : for making zisofs.
* : When the file size is less than one Logical Block
* : size, that file will not zisofs'ed since it does
- * : reduece an ISO-image size.
+ * : reduce an ISO-image size.
* :
* : When you specify option 'boot=<boot-image>', that
* : 'boot-image' file won't be converted to zisofs file.
@@ -680,7 +680,7 @@ struct iso9660 {
/* The creation time of ISO image. */
time_t birth_time;
/* A file stream of a temporary file, which file contents
- * save to until ISO iamge can be created. */
+ * save to until ISO image can be created. */
int temp_fd;
struct isofile *cur_file;
@@ -703,7 +703,7 @@ struct iso9660 {
} all_file_list;
/* A list of struct isofile entries which have its
- * contents and are not a directory, a hardlined file
+ * contents and are not a directory, a hardlinked file
* and a symlink file. */
struct {
struct isofile *first;
@@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a)
iso9660->primary.rootent);
if (ret < 0)
return (ret);
- /* Make sure we have UTF-16BE convertors.
- * if there is no file entry, convertors are still
- * uninitilized. */
+ /* Make sure we have UTF-16BE converters.
+ * if there is no file entry, converters are still
+ * uninitialized. */
if (iso9660->sconv_to_utf16be == NULL) {
iso9660->sconv_to_utf16be =
archive_string_conversion_to_charset(
@@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a)
* Write an ISO 9660 image.
*/
- /* Switc to start using wbuff as file buffer. */
+ /* Switch to start using wbuff as file buffer. */
iso9660->wbuff_remaining = wb_buffmax();
iso9660->wbuff_type = WB_TO_STREAM;
iso9660->wbuff_offset = 0;
@@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t)
tzset();
localtime_r(t, tm);
#elif HAVE__LOCALTIME64_S
- _localtime64_s(tm, t);
+ __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
+ _localtime64_s(tm, &tmp_t);
#else
memcpy(tm, localtime(t), sizeof(*tm));
#endif
@@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t)
static void
set_date_time_null(unsigned char *p)
{
- memset(p, '0', 16);
+ memset(p, (int)'0', 16);
p[16] = 0;
}
@@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
gid = archive_entry_gid(file->entry);
if (iso9660->opt.rr == OPT_RR_USEFUL) {
/*
- * This action is simular mkisofs -r option
+ * This action is similar to mkisofs -r option
* but our rockridge=useful option does not
* set a zero to uid and gid.
*/
@@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
* +----+----+----+----+----+
* 10 11 12 13 14 15
*
- * - cflg : flag of componet
- * - clen : length of componet
+ * - cflg : flag of component
+ * - clen : length of component
*/
const char *sl;
char sl_last;
@@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
/*
* flg len
* +----+----+
- * | 02 | 00 | CURREENT component.
+ * | 02 | 00 | CURRENT component.
* +----+----+ (".")
*/
if (nc != NULL) {
@@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
"Abstract File", 0, D_CHAR);
if (r != ARCHIVE_OK)
return (r);
- /* Bibliongraphic File Identifier */
+ /* Bibliographic File Identifier */
r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
&(iso9660->bibliographic_file_identifier),
"Bibliongraphic File", 0, D_CHAR);
@@ -4073,7 +4074,10 @@ write_information_block(struct archive_write *a)
memset(info.s, 0, info_size);
opt = 0;
#if defined(HAVE__CTIME64_S)
- _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
+ {
+ __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
+ _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ }
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
@@ -4558,7 +4562,7 @@ write_file_descriptors(struct archive_write *a)
file->cur_content = &(file->content);
do {
blocks += file->cur_content->blocks;
- /* Next fragument */
+ /* Next fragment */
file->cur_content = file->cur_content->next;
} while (file->cur_content != NULL);
}
@@ -4748,7 +4752,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
}
/*
- * Converte a filename to UTF-16BE.
+ * Convert a filename to UTF-16BE.
*/
if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
iso9660->sconv_to_utf16be)) {
@@ -5512,7 +5516,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
file->cur_content->location = location;
location += file->cur_content->blocks;
total_block += file->cur_content->blocks;
- /* Next fragument */
+ /* Next fragment */
file->cur_content = file->cur_content->next;
} while (file->cur_content != NULL);
}
@@ -6135,7 +6139,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
off = ffmax - extlen;
if (off == 0) {
/* A dot('.') character
- * does't place to the first
+ * doesn't place to the first
* byte of identifier. */
off ++;
extlen --;
@@ -6164,7 +6168,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
np->id_len = l = ext_off + np->ext_len;
/* Make an offset of the number which is used to be set
- * hexadecimal number to avoid duplicate identififier. */
+ * hexadecimal number to avoid duplicate identifier. */
if (iso9660->opt.iso_level == 1) {
if (ext_off >= 5)
noff = 5;
@@ -6742,7 +6746,7 @@ isoent_rr_move(struct archive_write *a)
int r;
pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
- /* Theare aren't level 8 directories reaching a deepr level. */
+ /* There aren't level 8 directories reaching a deeper level. */
if (pt->cnt == 0)
return (ARCHIVE_OK);
@@ -6813,7 +6817,7 @@ _compare_path_table(const void *v1, const void *v2)
if (cmp != 0)
return (cmp);
- /* Compare indetifier */
+ /* Compare identifier */
s1 = p1->identifier;
s2 = p2->identifier;
l = p1->ext_off;
@@ -6855,7 +6859,7 @@ _compare_path_table_joliet(const void *v1, const void *v2)
if (cmp != 0)
return (cmp);
- /* Compare indetifier */
+ /* Compare identifier */
s1 = (const unsigned char *)p1->identifier;
s2 = (const unsigned char *)p2->identifier;
l = p1->ext_off;
@@ -7149,7 +7153,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
iso9660->el_torito.catalog = isoent;
/*
- * Get a boot medai type.
+ * Get a boot media type.
*/
switch (iso9660->opt.boot_type) {
default:
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_mtree.c b/archivers/libarchive/files/libarchive/archive_write_set_format_mtree.c
index b686303d9a4..493d4735661 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_mtree.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_mtree.c
@@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
len = strlen(p);
/*
- * Add "./" prefiex.
+ * Add "./" prefix.
* NOTE: If the pathname does not have a path separator, we have
- * to add "./" to the head of the pathename because mtree reader
+ * to add "./" to the head of the pathname because mtree reader
* will suppose that it is v1(a.k.a classic) mtree format and
* change the directory unexpectedly and so it will make a wrong
* path.
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c b/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
index 6f7fe783900..6a301ac2d19 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,15 +62,24 @@ struct pax {
struct sparse_block *sparse_tail;
struct archive_string_conv *sconv_utf8;
int opt_binary;
+
+ unsigned flags;
+#define WRITE_SCHILY_XATTR (1 << 0)
+#define WRITE_LIBARCHIVE_XATTR (1 << 1)
};
static void add_pax_attr(struct archive_string *, const char *key,
const char *value);
+static void add_pax_attr_binary(struct archive_string *,
+ const char *key,
+ const char *value, size_t value_len);
static void add_pax_attr_int(struct archive_string *,
const char *key, int64_t value);
static void add_pax_attr_time(struct archive_string *,
const char *key, int64_t sec,
unsigned long nanos);
+static int add_pax_acl(struct archive_write *,
+ struct archive_entry *, struct pax *, int);
static ssize_t archive_write_pax_data(struct archive_write *,
const void *, size_t);
static int archive_write_pax_close(struct archive_write *);
@@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- pax = (struct pax *)malloc(sizeof(*pax));
+ pax = (struct pax *)calloc(1, sizeof(*pax));
if (pax == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate pax data");
return (ARCHIVE_FATAL);
}
- memset(pax, 0, sizeof(*pax));
+ pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
+
a->format_data = pax;
a->format_name = "pax";
a->format_options = archive_write_pax_options;
@@ -273,6 +284,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
static void
add_pax_attr(struct archive_string *as, const char *key, const char *value)
{
+ add_pax_attr_binary(as, key, value, strlen(value));
+}
+
+/*
+ * Add a key/value attribute to the pax header. This function handles
+ * binary values.
+ */
+static void
+add_pax_attr_binary(struct archive_string *as, const char *key,
+ const char *value, size_t value_len)
+{
int digits, i, len, next_ten;
char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */
@@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
* PAX attributes have the following layout:
* <len> <space> <key> <=> <value> <nl>
*/
- len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1;
+ len = 1 + (int)strlen(key) + 1 + (int)value_len + 1;
/*
* The <len> field includes the length of the <len> field, so
@@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
archive_strappend_char(as, ' ');
archive_strcat(as, key);
archive_strappend_char(as, '=');
- archive_strcat(as, value);
+ archive_array_append(as, value, value_len);
archive_strappend_char(as, '\n');
}
+static void
+archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name,
+ const void *value, size_t value_len)
+{
+ struct archive_string s;
+ char *encoded_value;
+
+ if (pax->flags & WRITE_LIBARCHIVE_XATTR) {
+ encoded_value = base64_encode((const char *)value, value_len);
+
+ if (encoded_name != NULL && encoded_value != NULL) {
+ archive_string_init(&s);
+ archive_strcpy(&s, "LIBARCHIVE.xattr.");
+ archive_strcat(&s, encoded_name);
+ add_pax_attr(&(pax->pax_header), s.s, encoded_value);
+ archive_string_free(&s);
+ }
+ free(encoded_value);
+ }
+ if (pax->flags & WRITE_SCHILY_XATTR) {
+ archive_string_init(&s);
+ archive_strcpy(&s, "SCHILY.xattr.");
+ archive_strcat(&s, encoded_name);
+ add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len);
+ archive_string_free(&s);
+ }
+}
+
static int
archive_write_pax_header_xattrs(struct archive_write *a,
struct pax *pax, struct archive_entry *entry)
{
- struct archive_string s;
int i = archive_entry_xattr_reset(entry);
while (i--) {
const char *name;
const void *value;
- char *encoded_value;
char *url_encoded_name = NULL, *encoded_name = NULL;
size_t size;
int r;
@@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a,
}
}
- encoded_value = base64_encode((const char *)value, size);
+ archive_write_pax_header_xattr(pax, encoded_name,
+ value, size);
- if (encoded_name != NULL && encoded_value != NULL) {
- archive_string_init(&s);
- archive_strcpy(&s, "LIBARCHIVE.xattr.");
- archive_strcat(&s, encoded_name);
- add_pax_attr(&(pax->pax_header), s.s, encoded_value);
- archive_string_free(&s);
- }
- free(encoded_value);
}
return (ARCHIVE_OK);
}
@@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
return (ARCHIVE_OK);
}
+/* Add ACL to pax header */
+static int
+add_pax_acl(struct archive_write *a,
+ struct archive_entry *entry, struct pax *pax, int flags)
+{
+ char *p;
+ const char *attr;
+ int acl_types;
+
+ acl_types = archive_entry_acl_types(entry);
+
+ if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ attr = "SCHILY.acl.ace";
+ else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+ attr = "SCHILY.acl.access";
+ else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ attr = "SCHILY.acl.default";
+ else
+ return (ARCHIVE_FATAL);
+
+ p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
+ if (p == NULL) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM, "%s %s",
+ "Can't allocate memory for ", attr);
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
+ "Can't translate ", attr, " to UTF-8");
+ return(ARCHIVE_WARN);
+ } else if (*p != '\0') {
+ add_pax_attr(&(pax->pax_header),
+ attr, p);
+ free(p);
+ }
+ return(ARCHIVE_OK);
+}
+
/*
* TODO: Consider adding 'comment' and 'charset' fields to
* archive_entry so that clients can specify them. Also, consider
@@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a,
const char *p;
const char *suffix;
int need_extension, r, ret;
+ int acl_types;
int sparse_count;
uint64_t sparse_total, real_size;
struct pax *pax;
@@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a,
/* Copy entry so we can modify it as needed. */
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
if (entry_main == entry_original)
@@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && p != NULL && *p != '\0')
need_extension = 1;
- /* If there are non-trivial ACL entries, we need an extension. */
- if (!need_extension && archive_entry_acl_count(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
- need_extension = 1;
-
- /* If there are non-trivial ACL entries, we need an extension. */
- if (!need_extension && archive_entry_acl_count(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
- need_extension = 1;
-
/* If there are extended attributes, we need an extension */
if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
need_extension = 1;
@@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && sparse_count > 0)
need_extension = 1;
+ acl_types = archive_entry_acl_types(entry_original);
+
+ /* If there are any ACL entries, we need an extension */
+ if (!need_extension && acl_types != 0)
+ need_extension = 1;
+
/*
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
@@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a,
add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
/* I use star-compatible ACL attributes. */
- r = archive_entry_acl_text_l(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
- ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
- &p, NULL, pax->sconv_utf8);
- if (r != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "ACL.access");
+ if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
+ ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
+ if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate ACL.access to UTF-8");
- ret = ARCHIVE_WARN;
- } else if (p != NULL && *p != '\0') {
- add_pax_attr(&(pax->pax_header),
- "SCHILY.acl.access", p);
}
- r = archive_entry_acl_text_l(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
- ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
- &p, NULL, pax->sconv_utf8);
- if (r != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "ACL.default");
+ if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+ if (ret == ARCHIVE_FATAL)
+ return (ARCHIVE_FATAL);
+ }
+ if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+ if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate ACL.default to UTF-8");
- ret = ARCHIVE_WARN;
- } else if (p != NULL && *p != '\0') {
- add_pax_attr(&(pax->pax_header),
- "SCHILY.acl.default", p);
}
/* We use GNU-tar-compatible sparse attributes. */
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_shar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_shar.c
index c033fb32f7e..5be310a0781 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_shar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_shar.c
@@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- shar = (struct shar *)malloc(sizeof(*shar));
+ shar = (struct shar *)calloc(1, sizeof(*shar));
if (shar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
return (ARCHIVE_FATAL);
}
- memset(shar, 0, sizeof(*shar));
archive_string_init(&shar->work);
archive_string_init(&shar->quoted_name);
a->format_data = shar;
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
index 484ab34b230..c54aeabdb19 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
@@ -114,9 +114,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
- /* size, space termation: 12 bytes */
+ /* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
- /* mtime, space termation: 12 bytes */
+ /* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a)
return (ARCHIVE_FATAL);
}
- ustar = (struct ustar *)malloc(sizeof(*ustar));
+ ustar = (struct ustar *)calloc(1, sizeof(*ustar));
if (ustar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
return (ARCHIVE_FATAL);
}
- memset(ustar, 0, sizeof(*ustar));
a->format_data = ustar;
a->format_name = "ustar";
a->format_options = archive_write_ustar_options;
@@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
* case getting WCS failed. On POSIX, this is a
* normal operation.
*/
- if (p != NULL && p[strlen(p) - 1] != '/') {
+ if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
struct archive_string as;
archive_string_init(&as);
@@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_xar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_xar.c
index a2dbc03991d..495f0d441e5 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_xar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_xar.c
@@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$");
* - When writing an XML element <link type="<file-type>">, <file-type>
* which is a file type a symbolic link is referencing is always marked
* as "broken". Xar utility uses stat(2) to get the file type, but, in
- * libarcive format writer, we should not use it; if it is needed, we
+ * libarchive format writer, we should not use it; if it is needed, we
* should get about it at archive_read_disk.c.
* - It is possible to appear both <flags> and <ext2> elements.
* Xar utility generates <flags> on BSD platform and <ext2> on Linux
@@ -192,7 +192,7 @@ struct file {
struct file *parent; /* parent directory entry */
/*
* To manage sub directory files.
- * We use 'chnext' a menber of struct file to chain.
+ * We use 'chnext' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -258,7 +258,7 @@ struct xar {
/*
* The list of all file entries is used to manage struct file
* objects.
- * We use 'next' a menber of struct file to chain.
+ * We use 'next' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -266,7 +266,7 @@ struct xar {
} file_list;
/*
* The list of hard-linked file entries.
- * We use 'hlnext' a menber of struct file to chain.
+ * We use 'hlnext' (a member of struct file) to chain.
*/
struct archive_rb_tree hardlink_rbtree;
};
@@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
case AE_IFLNK:
/*
* xar utility has checked a file type, which
- * a symblic-link file has referenced.
+ * a symbolic-link file has referenced.
* For example:
* <link type="directory">../ref/</link>
* The symlink target file is "../ref/" and its
@@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
* The symlink target file is "../f" and its
* file type is a regular file.
*
- * But our implemention cannot do it, and then we
- * always record that a attribute "type" is "borken",
+ * But our implementation cannot do it, and then we
+ * always record that a attribute "type" is "broken",
* for example:
* <link type="broken">foo/bar</link>
* It means "foo/bar" is not reachable.
@@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a)
}
/*
- * Start recoding TOC
+ * Start recording TOC
*/
r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
if (r < 0) {
@@ -1961,6 +1961,7 @@ file_free(struct file *file)
archive_string_free(&(file->basename));
archive_string_free(&(file->symlink));
archive_string_free(&(file->script));
+ archive_entry_free(file->entry);
free(file);
}
@@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar)
archive_entry_set_nlink(target->entry, hl->nlink);
if (hl->nlink > 1)
/* It means this file is a hardlink
- * targe itself. */
+ * target itself. */
target->hardlink_target = target;
for (nf = target->hlnext;
nf != NULL; nf = nf->hlnext) {
@@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a,
*strm = lzma_init_data;
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
if (threads > 1) {
- bzero(&mt_options, sizeof(mt_options));
+ memset(&mt_options, 0, sizeof(mt_options));
mt_options.threads = threads;
mt_options.timeout = 300;
mt_options.filters = lzmafilters;
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_zip.c b/archivers/libarchive/files/libarchive/archive_write_set_format_zip.c
index e4edb818819..f69b8467f44 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_zip.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_zip.c
@@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
zip->entry = __la_win_entry_in_posix_pathseparator(entry);
if (zip->entry == entry)
@@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|| zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) {
memcpy(e, "\001\231\007\000\001\000AE", 8);
- /* AES vendoer version AE-2 does not store a CRC.
+ /* AES vendor version AE-2 does not store a CRC.
* WinZip 11 uses AE-1, which does store the CRC,
* but it does not store the CRC when the file size
* is less than 20 bytes. So we simulate what
@@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
switch (zip->entry_encryption) {
case ENCRYPTION_TRADITIONAL:
- /* Initialize traditoinal PKWARE encryption context. */
+ /* Initialize traditional PKWARE encryption context. */
if (!zip->tctx_valid) {
ret = init_traditional_pkware_encryption(a);
if (ret != ARCHIVE_OK)
@@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
}
static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
{
unsigned temp = ctx->keys[2] | 2;
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
for (i = 0; i < max; i++) {
uint8_t t = in[i];
- out[i] = t ^ trad_enc_decypt_byte(ctx);
+ out[i] = t ^ trad_enc_decrypt_byte(ctx);
trad_enc_update_keys(ctx, t);
}
return i;
@@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a)
return (ARCHIVE_FAILED);
}
- /* Set a passowrd verification value after the 'salt'. */
+ /* Set a password verification value after the 'salt'. */
salt[salt_len] = derived_key[key_len * 2];
salt[salt_len + 1] = derived_key[key_len * 2 + 1];
diff --git a/archivers/libarchive/files/libarchive/config_freebsd.h b/archivers/libarchive/files/libarchive/config_freebsd.h
index 2073431635e..215e886befa 100644
--- a/archivers/libarchive/files/libarchive/config_freebsd.h
+++ b/archivers/libarchive/files/libarchive/config_freebsd.h
@@ -28,6 +28,7 @@
/* FreeBSD 5.0 and later have ACL and extattr support. */
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
+#define HAVE_ACL_GET_FD_NP 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
@@ -39,6 +40,7 @@
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
#define HAVE_EXTATTR_SET_FILE 1
+#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#endif
diff --git a/archivers/libarchive/files/libarchive/libarchive-formats.5 b/archivers/libarchive/files/libarchive/libarchive-formats.5
index 9cec760052e..62359ddc20b 100644
--- a/archivers/libarchive/files/libarchive/libarchive-formats.5
+++ b/archivers/libarchive/files/libarchive/libarchive-formats.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2012
+.Dd December 27, 2016
.Dt LIBARCHIVE-FORMATS 5
.Os
.Sh NAME
@@ -191,8 +191,6 @@ and device numbers.
.It Solaris extensions
Libarchive recognizes ACL and extended attribute records written
by Solaris tar.
-Currently, libarchive only has support for old-style ACLs; the
-newer NFSv4 ACLs are recognized but discarded.
.El
.Pp
The first tar program appeared in Seventh Edition Unix in 1979.
diff --git a/archivers/libarchive/files/libarchive/tar.5 b/archivers/libarchive/files/libarchive/tar.5
index 6e6f0c096c9..30b837dc413 100644
--- a/archivers/libarchive/files/libarchive/tar.5
+++ b/archivers/libarchive/files/libarchive/tar.5
@@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2009 Tim Kientzle
+.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 23, 2011
+.Dd December 27, 2016
.Dt TAR 5
.Os
.Sh NAME
@@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit.
Vendor-specific attributes used by Joerg Schilling's
.Nm star
implementation.
-.It Cm SCHILY.acl.access , Cm SCHILY.acl.default
-Stores the access and default ACLs as textual strings in a format
+.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace
+Stores the access, default and NFSv4 ACLs as textual strings in a format
that is an extension of the format specified by POSIX.1e draft 17.
-In particular, each user or group access specification can include a fourth
-colon-separated field with the numeric UID or GID.
+In particular, each user or group access specification can include
+an additional colon-separated field with the numeric UID or GID.
This allows ACLs to be restored on systems that may not have complete
user or group information available (such as when NIS/YP or LDAP services
are temporarily unavailable).
diff --git a/archivers/libarchive/files/libarchive/test/CMakeLists.txt b/archivers/libarchive/files/libarchive/test/CMakeLists.txt
index 124aa3a8b1b..5016eed369e 100644
--- a/archivers/libarchive/files/libarchive/test/CMakeLists.txt
+++ b/archivers/libarchive/files/libarchive/test/CMakeLists.txt
@@ -6,14 +6,15 @@
IF(ENABLE_TEST)
SET(libarchive_test_SOURCES
../../test_utils/test_utils.c
- main.c
+ ../../test_utils/test_main.c
read_open_memory.c
test.h
- test_acl_freebsd_nfs4.c
- test_acl_freebsd_posix1e.c
test_acl_nfs4.c
test_acl_pax.c
+ test_acl_platform_nfs4.c
+ test_acl_platform_posix1e.c
test_acl_posix1e.c
+ test_acl_text.c
test_archive_api_feature.c
test_archive_clear_error.c
test_archive_cmdline.c
@@ -58,8 +59,11 @@ IF(ENABLE_TEST)
test_compat_lzop.c
test_compat_mac.c
test_compat_pax_libarchive_2x.c
+ test_compat_perl_archive_tar.c
+ test_compat_plexus_archiver_tar.c
test_compat_solaris_pax_sparse.c
test_compat_solaris_tar_acl.c
+ test_compat_star_acl.c
test_compat_tar_hardlink.c
test_compat_uudecode.c
test_compat_uudecode_large.c
@@ -138,6 +142,7 @@ IF(ENABLE_TEST)
test_read_format_lha_bugfix_0.c
test_read_format_lha_filename.c
test_read_format_mtree.c
+ test_read_format_mtree_crash747.c
test_read_format_pax_bz2.c
test_read_format_rar.c
test_read_format_rar_encryption_data.c
@@ -164,6 +169,8 @@ IF(ENABLE_TEST)
test_read_format_zip_encryption_header.c
test_read_format_zip_encryption_partially.c
test_read_format_zip_filename.c
+ test_read_format_zip_high_compression.c
+ test_read_format_zip_jar.c
test_read_format_zip_mac_metadata.c
test_read_format_zip_malformed.c
test_read_format_zip_msdos.c
@@ -176,6 +183,7 @@ IF(ENABLE_TEST)
test_read_format_zip_winzip_aes_large.c
test_read_format_zip_zip64.c
test_read_large.c
+ test_read_pax_schily_xattr.c
test_read_pax_truncated.c
test_read_position.c
test_read_set_format.c
@@ -198,6 +206,9 @@ IF(ENABLE_TEST)
test_write_disk_no_hfs_compression.c
test_write_disk_perms.c
test_write_disk_secure.c
+ test_write_disk_secure744.c
+ test_write_disk_secure745.c
+ test_write_disk_secure746.c
test_write_disk_sparse.c
test_write_disk_symlink.c
test_write_disk_times.c
@@ -292,10 +303,11 @@ IF(ENABLE_TEST)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/libarchive/test)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_libarchive_test
- COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR})
+ COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR} -vv)
ADD_DEPENDENCIES(run_all_tests run_libarchive_test)
ENDIF(ENABLE_TEST)
diff --git a/archivers/libarchive/files/libarchive/test/list.h b/archivers/libarchive/files/libarchive/test/list.h
index 89b22c63d40..5a9f91058c4 100644
--- a/archivers/libarchive/files/libarchive/test/list.h
+++ b/archivers/libarchive/files/libarchive/test/list.h
@@ -1,8 +1,12 @@
-DEFINE_TEST(test_acl_freebsd_nfs4)
-DEFINE_TEST(test_acl_freebsd_posix1e)
DEFINE_TEST(test_acl_nfs4)
-DEFINE_TEST(test_acl_pax)
+DEFINE_TEST(test_acl_pax_posix1e)
+DEFINE_TEST(test_acl_pax_nfs4)
+DEFINE_TEST(test_acl_platform_nfs4)
+DEFINE_TEST(test_acl_platform_posix1e_restore)
+DEFINE_TEST(test_acl_platform_posix1e_read)
DEFINE_TEST(test_acl_posix1e)
+DEFINE_TEST(test_acl_from_text)
+DEFINE_TEST(test_acl_to_text)
DEFINE_TEST(test_archive_api_feature)
DEFINE_TEST(test_archive_clear_error)
DEFINE_TEST(test_archive_cmdline)
@@ -112,8 +116,12 @@ DEFINE_TEST(test_compat_lzma)
DEFINE_TEST(test_compat_lzop)
DEFINE_TEST(test_compat_mac)
DEFINE_TEST(test_compat_pax_libarchive_2x)
+DEFINE_TEST(test_compat_perl_archive_tar)
+DEFINE_TEST(test_compat_plexus_archiver_tar)
DEFINE_TEST(test_compat_solaris_pax_sparse)
DEFINE_TEST(test_compat_solaris_tar_acl)
+DEFINE_TEST(test_compat_star_acl_posix1e)
+DEFINE_TEST(test_compat_star_acl_nfs4)
DEFINE_TEST(test_compat_tar_hardlink)
DEFINE_TEST(test_compat_uudecode)
DEFINE_TEST(test_compat_uudecode_large)
@@ -260,6 +268,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v1_form)
DEFINE_TEST(test_read_format_mtree_nomagic_v2_form)
DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form)
DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
+DEFINE_TEST(test_read_format_mtree_crash747)
DEFINE_TEST(test_read_format_pax_bz2)
DEFINE_TEST(test_read_format_rar_basic)
DEFINE_TEST(test_read_format_rar_subblock)
@@ -321,6 +330,9 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251_win)
DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP1251)
DEFINE_TEST(test_read_format_zip_filename_UTF8_CP1251)
DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2)
+DEFINE_TEST(test_read_format_zip_high_compression)
+DEFINE_TEST(test_read_format_zip_high_compression2)
+DEFINE_TEST(test_read_format_zip_jar)
DEFINE_TEST(test_read_format_zip_mac_metadata)
DEFINE_TEST(test_read_format_zip_malformed)
DEFINE_TEST(test_read_format_zip_msdos)
@@ -338,6 +350,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
DEFINE_TEST(test_read_format_zip_zip64a)
DEFINE_TEST(test_read_format_zip_zip64b)
DEFINE_TEST(test_read_large)
+DEFINE_TEST(test_schily_xattr_pax)
DEFINE_TEST(test_read_pax_truncated)
DEFINE_TEST(test_read_position)
DEFINE_TEST(test_read_set_format)
@@ -379,6 +392,10 @@ DEFINE_TEST(test_write_disk_lookup)
DEFINE_TEST(test_write_disk_mac_metadata)
DEFINE_TEST(test_write_disk_no_hfs_compression)
DEFINE_TEST(test_write_disk_perms)
+DEFINE_TEST(test_write_disk_secure744)
+DEFINE_TEST(test_write_disk_secure745)
+DEFINE_TEST(test_write_disk_secure746a)
+DEFINE_TEST(test_write_disk_secure746b)
DEFINE_TEST(test_write_disk_secure)
DEFINE_TEST(test_write_disk_sparse)
DEFINE_TEST(test_write_disk_symlink)
diff --git a/archivers/libarchive/files/libarchive/test/main.c b/archivers/libarchive/files/libarchive/test/main.c
deleted file mode 100644
index 0f50e940c9c..00000000000
--- a/archivers/libarchive/files/libarchive/test/main.c
+++ /dev/null
@@ -1,2991 +0,0 @@
-/*
- * Copyright (c) 2003-2009 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 "test.h"
-#include "test_utils.h"
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h> /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
-#endif
-#include <limits.h>
-#include <locale.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <stdarg.h>
-#include <time.h>
-
-/*
- * This same file is used pretty much verbatim for all test harnesses.
- *
- * The next few lines are the only differences.
- * TODO: Move this into a separate configuration header, have all test
- * suites share one copy of this file.
- */
-__FBSDID("$FreeBSD: head/lib/libarchive/test/main.c 201247 2009-12-30 05:59:21Z kientzle $");
-#define KNOWNREF "test_compat_gtar_1.tar.uu"
-#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
-#undef PROGRAM /* Testing a library, not a program. */
-#define LIBRARY "libarchive"
-#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x))
-#define EXTRA_ERRNO(x) archive_errno((struct archive *)(x))
-#define EXTRA_VERSION archive_version_details()
-
-/*
- *
- * Windows support routines
- *
- * Note: Configuration is a tricky issue. Using HAVE_* feature macros
- * in the test harness is dangerous because they cover up
- * configuration errors. The classic example of this is omitting a
- * configure check. If libarchive and libarchive_test both look for
- * the same feature macro, such errors are hard to detect. Platform
- * macros (e.g., _WIN32 or __GNUC__) are a little better, but can
- * easily lead to very messy code. It's best to limit yourself
- * to only the most generic programming techniques in the test harness
- * and thus avoid conditionals altogether. Where that's not possible,
- * try to minimize conditionals by grouping platform-specific tests in
- * one place (e.g., test_acl_freebsd) or by adding new assert()
- * functions (e.g., assertMakeHardlink()) to cover up platform
- * differences. Platform-specific coding in libarchive_test is often
- * a symptom that some capability is missing from libarchive itself.
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#include <direct.h>
-#include <windows.h>
-#ifndef F_OK
-#define F_OK (0)
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(m) ((m) & _S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(m) ((m) & _S_IFREG)
-#endif
-#if !defined(__BORLANDC__)
-#define access _access
-#undef chdir
-#define chdir _chdir
-#endif
-#ifndef fileno
-#define fileno _fileno
-#endif
-/*#define fstat _fstat64*/
-#if !defined(__BORLANDC__)
-#define getcwd _getcwd
-#endif
-#define lstat stat
-/*#define lstat _stat64*/
-/*#define stat _stat64*/
-#define rmdir _rmdir
-#if !defined(__BORLANDC__)
-#define strdup _strdup
-#define umask _umask
-#endif
-#define int64_t __int64
-#endif
-
-#if defined(HAVE__CrtSetReportMode)
-# include <crtdbg.h>
-#endif
-
-/* Path to working directory for current test */
-const char *testworkdir;
-#ifdef PROGRAM
-/* Pathname of exe to be tested. */
-const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-const char *testprog;
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static void *GetFunctionKernel32(const char *);
-static int my_CreateSymbolicLinkA(const char *, const char *, int);
-static int my_CreateHardLinkA(const char *, const char *);
-static int my_GetFileInformationByName(const char *,
- BY_HANDLE_FILE_INFORMATION *);
-
-static void *
-GetFunctionKernel32(const char *name)
-{
- static HINSTANCE lib;
- static int set;
- if (!set) {
- set = 1;
- lib = LoadLibrary("kernel32.dll");
- }
- if (lib == NULL) {
- fprintf(stderr, "Can't load kernel32.dll?!\n");
- exit(1);
- }
- return (void *)GetProcAddress(lib, name);
-}
-
-static int
-my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateSymbolicLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, flags);
-}
-
-static int
-my_CreateHardLinkA(const char *linkname, const char *target)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateHardLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, NULL);
-}
-
-static int
-my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
-{
- HANDLE h;
- int r;
-
- memset(bhfi, 0, sizeof(*bhfi));
- h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return (0);
- r = GetFileInformationByHandle(h, bhfi);
- CloseHandle(h);
- return (r);
-}
-#endif
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
-static void
-invalid_parameter_handler(const wchar_t * expression,
- const wchar_t * function, const wchar_t * file,
- unsigned int line, uintptr_t pReserved)
-{
- /* nop */
-}
-#endif
-
-/*
- *
- * OPTIONS FLAGS
- *
- */
-
-/* Enable core dump on failure. */
-static int dump_on_failure = 0;
-/* Default is to remove temp dirs and log data for successful tests. */
-static int keep_temp_files = 0;
-/* Default is to run the specified tests once and report errors. */
-static int until_failure = 0;
-/* Default is to just report pass/fail for each test. */
-static int verbosity = 0;
-#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
-#define VERBOSITY_PASSFAIL 0 /* Default */
-#define VERBOSITY_LIGHT_REPORT 1 /* -v */
-#define VERBOSITY_FULL 2 /* -vv */
-/* A few places generate even more output for verbosity > VERBOSITY_FULL,
- * mostly for debugging the test harness itself. */
-/* Cumulative count of assertion failures. */
-static int failures = 0;
-/* Cumulative count of reported skips. */
-static int skips = 0;
-/* Cumulative count of assertions checked. */
-static int assertions = 0;
-
-/* Directory where uuencoded reference files can be found. */
-static const char *refdir;
-
-/*
- * Report log information selectively to console and/or disk log.
- */
-static int log_console = 0;
-static FILE *logfile;
-static void
-vlogprintf(const char *fmt, va_list ap)
-{
-#ifdef va_copy
- va_list lfap;
- va_copy(lfap, ap);
-#endif
- if (log_console)
- vfprintf(stdout, fmt, ap);
- if (logfile != NULL)
-#ifdef va_copy
- vfprintf(logfile, fmt, lfap);
- va_end(lfap);
-#else
- vfprintf(logfile, fmt, ap);
-#endif
-}
-
-static void
-logprintf(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogprintf(fmt, ap);
- va_end(ap);
-}
-
-/* Set up a message to display only if next assertion fails. */
-static char msgbuff[4096];
-static const char *msg, *nextmsg;
-void
-failure(const char *fmt, ...)
-{
- va_list ap;
- if (fmt == NULL) {
- nextmsg = NULL;
- } else {
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
- }
-}
-
-/*
- * Copy arguments into file-local variables.
- * This was added to permit vararg assert() functions without needing
- * variadic wrapper macros. Turns out that the vararg capability is almost
- * never used, so almost all of the vararg assertions can be simplified
- * by removing the vararg capability and reworking the wrapper macro to
- * pass __FILE__, __LINE__ directly into the function instead of using
- * this hook. I suspect this machinery is used so rarely that we
- * would be better off just removing it entirely. That would simplify
- * the code here noticeably.
- */
-static const char *skipping_filename;
-static int skipping_line;
-void skipping_setup(const char *filename, int line)
-{
- skipping_filename = filename;
- skipping_line = line;
-}
-
-/* Called at the beginning of each assert() function. */
-static void
-assertion_count(const char *file, int line)
-{
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- ++assertions;
- /* Proper handling of "failure()" message. */
- msg = nextmsg;
- nextmsg = NULL;
- /* Uncomment to print file:line after every assertion.
- * Verbose, but occasionally useful in tracking down crashes. */
- /* printf("Checked %s:%d\n", file, line); */
-}
-
-/*
- * For each test source file, we remember how many times each
- * assertion was reported. Cleared before each new test,
- * used by test_summarize().
- */
-static struct line {
- int count;
- int skip;
-} failed_lines[10000];
-const char *failed_filename;
-
-/* Count this failure, setup up log destination and handle initial report. */
-static void
-failure_start(const char *filename, int line, const char *fmt, ...)
-{
- va_list ap;
-
- /* Record another failure for this line. */
- ++failures;
- failed_filename = filename;
- failed_lines[line].count++;
-
- /* Determine whether to log header to console. */
- switch (verbosity) {
- case VERBOSITY_LIGHT_REPORT:
- log_console = (failed_lines[line].count < 2);
- break;
- default:
- log_console = (verbosity >= VERBOSITY_FULL);
- }
-
- /* Log file:line header for this failure */
- va_start(ap, fmt);
-#if _MSC_VER
- logprintf("%s(%d): ", filename, line);
-#else
- logprintf("%s:%d: ", filename, line);
-#endif
- vlogprintf(fmt, ap);
- va_end(ap);
- logprintf("\n");
-
- if (msg != NULL && msg[0] != '\0') {
- logprintf(" Description: %s\n", msg);
- msg = NULL;
- }
-
- /* Determine whether to log details to console. */
- if (verbosity == VERBOSITY_LIGHT_REPORT)
- log_console = 0;
-}
-
-/* Complete reporting of failed tests. */
-/*
- * The 'extra' hook here is used by libarchive to include libarchive
- * error messages with assertion failures. It could also be used
- * to add strerror() output, for example. Just define the EXTRA_DUMP()
- * macro appropriately.
- */
-static void
-failure_finish(void *extra)
-{
- (void)extra; /* UNUSED (maybe) */
-#ifdef EXTRA_DUMP
- if (extra != NULL) {
- logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
- logprintf(" detail: %s\n", EXTRA_DUMP(extra));
- }
-#endif
-
- if (dump_on_failure) {
- fprintf(stderr,
- " *** forcing core dump so failure can be debugged ***\n");
- abort();
- }
-}
-
-/* Inform user that we're skipping some checks. */
-void
-test_skipping(const char *fmt, ...)
-{
- char buff[1024];
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- va_end(ap);
- /* Use failure() message if set. */
- msg = nextmsg;
- nextmsg = NULL;
- /* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
- --failures; /* Undo failures++ in failure_start() */
- /* Don't failure_finish() here. */
- /* Mark as skip, so doesn't count as failed test. */
- failed_lines[skipping_line].skip = 1;
- ++skips;
-}
-
-/*
- *
- * ASSERTIONS
- *
- */
-
-/* Generic assert() just displays the failed condition. */
-int
-assertion_assert(const char *file, int line, int value,
- const char *condition, void *extra)
-{
- assertion_count(file, line);
- if (!value) {
- failure_start(file, line, "Assertion failed: %s", condition);
- failure_finish(extra);
- }
- return (value);
-}
-
-/* chdir() and report any errors */
-int
-assertion_chdir(const char *file, int line, const char *pathname)
-{
- assertion_count(file, line);
- if (chdir(pathname) == 0)
- return (1);
- failure_start(file, line, "chdir(\"%s\")", pathname);
- failure_finish(NULL);
- return (0);
-
-}
-
-/* Verify two integers are equal. */
-int
-assertion_equal_int(const char *file, int line,
- long long v1, const char *e1, long long v2, const char *e2, void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Utility to convert a single UTF-8 sequence.
- */
-static int
-_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
- static const char utf8_count[256] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
- 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
- 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
- };
- int ch;
- int cnt;
- uint32_t wc;
-
- *pwc = 0;
-
- /* Sanity check. */
- if (n == 0)
- return (0);
- /*
- * Decode 1-4 bytes depending on the value of the first byte.
- */
- ch = (unsigned char)*s;
- if (ch == 0)
- return (0); /* Standard: return 0 for end-of-string. */
- cnt = utf8_count[ch];
-
- /* Invalide sequence or there are not plenty bytes. */
- if (n < (size_t)cnt)
- return (-1);
-
- /* Make a Unicode code point from a single UTF-8 sequence. */
- switch (cnt) {
- case 1: /* 1 byte sequence. */
- *pwc = ch & 0x7f;
- return (cnt);
- case 2: /* 2 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
- return (cnt);
- case 3: /* 3 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x0f) << 12)
- | ((s[1] & 0x3f) << 6)
- | (s[2] & 0x3f);
- if (wc < 0x800)
- return (-1);/* Overlong sequence. */
- break;
- case 4: /* 4 bytes sequence. */
- if (n < 4)
- return (-1);
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- if ((s[3] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x07) << 18)
- | ((s[1] & 0x3f) << 12)
- | ((s[2] & 0x3f) << 6)
- | (s[3] & 0x3f);
- if (wc < 0x10000)
- return (-1);/* Overlong sequence. */
- break;
- default:
- return (-1);
- }
-
- /* The code point larger than 0x10FFFF is not leagal
- * Unicode values. */
- if (wc > 0x10FFFF)
- return (-1);
- /* Correctly gets a Unicode, returns used bytes. */
- *pwc = wc;
- return (cnt);
-}
-
-static void strdump(const char *e, const char *p, int ewidth, int utf8)
-{
- const char *q = p;
-
- logprintf(" %*s = ", ewidth, e);
- if (p == NULL) {
- logprintf("NULL\n");
- return;
- }
- logprintf("\"");
- while (*p != '\0') {
- unsigned int c = 0xff & *p++;
- switch (c) {
- case '\a': logprintf("\\a"); break;
- case '\b': logprintf("\\b"); break;
- case '\n': logprintf("\\n"); break;
- case '\r': logprintf("\\r"); break;
- default:
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else
- logprintf("\\x%02X", c);
- }
- }
- logprintf("\"");
- logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
-
- /*
- * If the current string is UTF-8, dump its code points.
- */
- if (utf8) {
- size_t len;
- uint32_t uc;
- int n;
- int cnt = 0;
-
- p = q;
- len = strlen(p);
- logprintf(" [");
- while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
- if (p != q)
- logprintf(" ");
- logprintf("%04X", uc);
- p += n;
- len -= n;
- cnt++;
- }
- logprintf("]");
- logprintf(" (count %d", cnt);
- if (n < 0) {
- logprintf(",unknown %d bytes", len);
- }
- logprintf(")");
-
- }
- logprintf("\n");
-}
-
-/* Verify two strings are equal, dump them if not. */
-int
-assertion_equal_string(const char *file, int line,
- const char *v1, const char *e1,
- const char *v2, const char *e2,
- void *extra, int utf8)
-{
- int l1, l2;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- l1 = (int)strlen(e1);
- l2 = (int)strlen(e2);
- if (l1 < l2)
- l1 = l2;
- strdump(e1, v1, l1, utf8);
- strdump(e2, v2, l1, utf8);
- failure_finish(extra);
- return (0);
-}
-
-static void
-wcsdump(const char *e, const wchar_t *w)
-{
- logprintf(" %s = ", e);
- if (w == NULL) {
- logprintf("(null)");
- return;
- }
- logprintf("\"");
- while (*w != L'\0') {
- unsigned int c = *w++;
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else if (c < 256)
- logprintf("\\x%02X", c);
- else if (c < 0x10000)
- logprintf("\\u%04X", c);
- else
- logprintf("\\U%08X", c);
- }
- logprintf("\"\n");
-}
-
-#ifndef HAVE_WCSCMP
-static int
-wcscmp(const wchar_t *s1, const wchar_t *s2)
-{
-
- while (*s1 == *s2++) {
- if (*s1++ == L'\0')
- return 0;
- }
- if (*s1 > *--s2)
- return 1;
- else
- return -1;
-}
-#endif
-
-/* Verify that two wide strings are equal, dump them if not. */
-int
-assertion_equal_wstring(const char *file, int line,
- const wchar_t *v1, const char *e1,
- const wchar_t *v2, const char *e2,
- void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- wcsdump(e1, v1);
- wcsdump(e2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
- * any bytes in p that differ from ref will be highlighted with '_'
- * before and after the hex value.
- */
-static void
-hexdump(const char *p, const char *ref, size_t l, size_t offset)
-{
- size_t i, j;
- char sep;
-
- if (p == NULL) {
- logprintf("(null)\n");
- return;
- }
- for(i=0; i < l; i+=16) {
- logprintf("%04x", (unsigned)(i + offset));
- sep = ' ';
- for (j = 0; j < 16 && i + j < l; j++) {
- if (ref != NULL && p[i + j] != ref[i + j])
- sep = '_';
- logprintf("%c%02x", sep, 0xff & (int)p[i+j]);
- if (ref != NULL && p[i + j] == ref[i + j])
- sep = ' ';
- }
- for (; j < 16; j++) {
- logprintf("%c ", sep);
- sep = ' ';
- }
- logprintf("%c", sep);
- for (j=0; j < 16 && i + j < l; j++) {
- int c = p[i + j];
- if (c >= ' ' && c <= 126)
- logprintf("%c", c);
- else
- logprintf(".");
- }
- logprintf("\n");
- }
-}
-
-/* Verify that two blocks of memory are the same, display the first
- * block of differences if they're not. */
-int
-assertion_equal_mem(const char *file, int line,
- const void *_v1, const char *e1,
- const void *_v2, const char *e2,
- size_t l, const char *ld, void *extra)
-{
- const char *v1 = (const char *)_v1;
- const char *v2 = (const char *)_v2;
- size_t offset;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
- return (1);
- if (v1 == NULL || v2 == NULL)
- return (0);
-
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" size %s = %d\n", ld, (int)l);
- /* Dump 48 bytes (3 lines) so that the first difference is
- * in the second line. */
- offset = 0;
- while (l > 64 && memcmp(v1, v2, 32) == 0) {
- /* Two lines agree, so step forward one line. */
- v1 += 16;
- v2 += 16;
- l -= 16;
- offset += 16;
- }
- logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 128 ? l : 128, offset);
- logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 128 ? l : 128, offset);
- logprintf("\n");
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that a block of memory is filled with the specified byte. */
-int
-assertion_memory_filled_with(const char *file, int line,
- const void *_v1, const char *vd,
- size_t l, const char *ld,
- char b, const char *bd, void *extra)
-{
- const char *v1 = (const char *)_v1;
- size_t c = 0;
- size_t i;
- (void)ld; /* UNUSED */
-
- assertion_count(file, line);
-
- for (i = 0; i < l; ++i) {
- if (v1[i] == b) {
- ++c;
- }
- }
- if (c == l)
- return (1);
-
- failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
- logprintf(" Only %d bytes were correct\n", (int)c);
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that the named file exists and is empty. */
-int
-assertion_empty_file(const char *filename, int line, const char *f1)
-{
- char buff[1024];
- struct stat st;
- ssize_t s;
- FILE *f;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0)
- return (1);
-
- failure_start(filename, line, "File should be empty: %s", f1);
- logprintf(" File size: %d\n", (int)st.st_size);
- logprintf(" Contents:\n");
- f = fopen(f1, "rb");
- if (f == NULL) {
- logprintf(" Unable to open %s\n", f1);
- } else {
- s = ((off_t)sizeof(buff) < st.st_size) ?
- (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
- s = fread(buff, 1, s, f);
- hexdump(buff, NULL, s, 0);
- fclose(f);
- }
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file exists and is not empty. */
-int
-assertion_non_empty_file(const char *filename, int line, const char *f1)
-{
- struct stat st;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0) {
- failure_start(filename, line, "File empty: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify that two files have the same contents. */
-/* TODO: hexdump the first bytes that actually differ. */
-int
-assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
-{
- char buff1[1024];
- char buff2[1024];
- FILE *f1, *f2;
- int n1, n2;
-
- assertion_count(filename, line);
-
- f1 = fopen(fn1, "rb");
- f2 = fopen(fn2, "rb");
- if (f1 == NULL || f2 == NULL) {
- if (f1) fclose(f1);
- if (f2) fclose(f2);
- return (0);
- }
- for (;;) {
- n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
- n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
- if (n1 != n2)
- break;
- if (n1 == 0 && n2 == 0) {
- fclose(f1);
- fclose(f2);
- return (1);
- }
- if (memcmp(buff1, buff2, n1) != 0)
- break;
- }
- fclose(f1);
- fclose(f2);
- failure_start(filename, line, "Files not identical");
- logprintf(" file1=\"%s\"\n", fn1);
- logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file does exist. */
-int
-assertion_file_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (!_access(f, 0))
- return (1);
-#else
- if (!access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file doesn't exist. */
-int
-assertion_file_not_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (_access(f, 0))
- return (1);
-#else
- if (access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should not exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Compare the contents of a file to a block of memory. */
-int
-assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
-{
- char *contents;
- FILE *f;
- int n;
-
- assertion_count(filename, line);
-
- f = fopen(fn, "rb");
- if (f == NULL) {
- failure_start(filename, line,
- "File should exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- contents = malloc(s * 2);
- n = (int)fread(contents, 1, s * 2, f);
- fclose(f);
- if (n == s && memcmp(buff, contents, s) == 0) {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "File contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
- hexdump(contents, buff, n > 512 ? 512 : n, 0);
- else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Check the contents of a text file, being tolerant of line endings. */
-int
-assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
-{
- char *contents;
- const char *btxt, *ftxt;
- FILE *f;
- int n, s;
-
- assertion_count(filename, line);
- f = fopen(fn, "r");
- if (f == NULL) {
- failure_start(filename, line,
- "File doesn't exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- s = (int)strlen(buff);
- contents = malloc(s * 2 + 128);
- n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
- if (n >= 0)
- contents[n] = '\0';
- fclose(f);
- /* Compare texts. */
- btxt = buff;
- ftxt = (const char *)contents;
- while (*btxt != '\0' && *ftxt != '\0') {
- if (*btxt == *ftxt) {
- ++btxt;
- ++ftxt;
- continue;
- }
- if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
- /* Pass over different new line characters. */
- ++btxt;
- ftxt += 2;
- continue;
- }
- break;
- }
- if (*btxt == '\0' && *ftxt == '\0') {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "Contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0) {
- hexdump(contents, buff, n, 0);
- logprintf(" expected\n", fn);
- hexdump(buff, contents, s, 0);
- } else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Verify that a text file contains the specified lines, regardless of order */
-/* This could be more efficient if we sorted both sets of lines, etc, but
- * since this is used only for testing and only ever deals with a dozen or so
- * lines at a time, this relatively crude approach is just fine. */
-int
-assertion_file_contains_lines_any_order(const char *file, int line,
- const char *pathname, const char *lines[])
-{
- char *buff;
- size_t buff_size;
- size_t expected_count, actual_count, i, j;
- char **expected = NULL;
- char *p, **actual = NULL;
- char c;
- int expected_failure = 0, actual_failure = 0;
-
- assertion_count(file, line);
-
- buff = slurpfile(&buff_size, "%s", pathname);
- if (buff == NULL) {
- failure_start(pathname, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- /* Make a copy of the provided lines and count up the expected
- * file size. */
- for (i = 0; lines[i] != NULL; ++i) {
- }
- expected_count = i;
- if (expected_count) {
- expected = malloc(sizeof(char *) * expected_count);
- if (expected == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (i = 0; lines[i] != NULL; ++i) {
- expected[i] = strdup(lines[i]);
- }
- }
-
- /* Break the file into lines */
- actual_count = 0;
- for (c = '\0', p = buff; p < buff + buff_size; ++p) {
- if (*p == '\x0d' || *p == '\x0a')
- *p = '\0';
- if (c == '\0' && *p != '\0')
- ++actual_count;
- c = *p;
- }
- if (actual_count) {
- actual = calloc(sizeof(char *), actual_count);
- if (actual == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (j = 0, p = buff; p < buff + buff_size;
- p += 1 + strlen(p)) {
- if (*p != '\0') {
- actual[j] = p;
- ++j;
- }
- }
- }
-
- /* Erase matching lines from both lists */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] == NULL)
- continue;
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] == NULL)
- continue;
- if (strcmp(expected[i], actual[j]) == 0) {
- free(expected[i]);
- expected[i] = NULL;
- actual[j] = NULL;
- break;
- }
- }
- }
-
- /* If there's anything left, it's a failure */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL)
- ++expected_failure;
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- ++actual_failure;
- }
- if (expected_failure == 0 && actual_failure == 0) {
- free(buff);
- free(expected);
- free(actual);
- return (1);
- }
- failure_start(file, line, "File doesn't match: %s", pathname);
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL) {
- logprintf(" Expected but not present: %s\n", expected[i]);
- free(expected[i]);
- }
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- logprintf(" Present but not expected: %s\n", actual[j]);
- }
- failure_finish(NULL);
- free(buff);
- free(expected);
- free(actual);
- return (0);
-}
-
-/* Test that two paths point to the same file. */
-/* As a side-effect, asserts that both files exist. */
-static int
-is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(path1, &bhfi1);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path1);
- failure_finish(NULL);
- return (0);
- }
- r = my_GetFileInformationByName(path2, &bhfi2);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path2);
- failure_finish(NULL);
- return (0);
- }
- return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
- && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
- && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
-#else
- struct stat st1, st2;
- int r;
-
- assertion_count(file, line);
- r = lstat(path1, &st1);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path1);
- failure_finish(NULL);
- return (0);
- }
- r = lstat(path2, &st2);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path2);
- failure_finish(NULL);
- return (0);
- }
- return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
-#endif
-}
-
-int
-assertion_is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-int
-assertion_is_not_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (!is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s should not be hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify a/b/mtime of 'pathname'. */
-/* If 'recent', verify that it's within last 10 seconds. */
-static int
-assertion_file_time(const char *file, int line,
- const char *pathname, long t, long nsec, char type, int recent)
-{
- long long filet, filet_nsec;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME (116444736000000000ULL)
- FILETIME fxtime, fbirthtime, fatime, fmtime;
- ULARGE_INTEGER wintm;
- HANDLE h;
- fxtime.dwLowDateTime = 0;
- fxtime.dwHighDateTime = 0;
-
- assertion_count(file, line);
- /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
- * a directory file. If not, CreateFile() will fail when
- * the pathname is a directory. */
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
- switch (type) {
- case 'a': fxtime = fatime; break;
- case 'b': fxtime = fbirthtime; break;
- case 'm': fxtime = fmtime; break;
- }
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't GetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- wintm.LowPart = fxtime.dwLowDateTime;
- wintm.HighPart = fxtime.dwHighDateTime;
- filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
- filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
- nsec = (nsec / 100) * 100; /* Round the request */
-#else
- struct stat st;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- switch (type) {
- case 'a': filet = st.st_atime; break;
- case 'm': filet = st.st_mtime; break;
- case 'b': filet = 0; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
-#if defined(__FreeBSD__)
- switch (type) {
- case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
- case 'b': filet = st.st_birthtime;
- filet_nsec = st.st_birthtimespec.tv_nsec; break;
- case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
- /* FreeBSD generally only stores to microsecond res, so round. */
- filet_nsec = (filet_nsec / 1000) * 1000;
- nsec = (nsec / 1000) * 1000;
-#else
- filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */
- if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */
-#if defined(__HAIKU__)
- if (type == 'a') return (1); /* Haiku doesn't have atime. */
-#endif
-#endif
-#endif
- if (recent) {
- /* Check that requested time is up-to-date. */
- time_t now = time(NULL);
- if (filet < now - 10 || filet > now + 1) {
- failure_start(file, line,
- "File %s has %ctime %lld, %lld seconds ago\n",
- pathname, type, filet, now - filet);
- failure_finish(NULL);
- return (0);
- }
- } else if (filet != t || filet_nsec != nsec) {
- failure_start(file, line,
- "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
- pathname, type, filet, filet_nsec, t, nsec);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify atime of 'pathname'. */
-int
-assertion_file_atime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'a', 0);
-}
-
-/* Verify atime of 'pathname' is up-to-date. */
-int
-assertion_file_atime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'a', 1);
-}
-
-/* Verify birthtime of 'pathname'. */
-int
-assertion_file_birthtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'b', 0);
-}
-
-/* Verify birthtime of 'pathname' is up-to-date. */
-int
-assertion_file_birthtime_recent(const char *file, int line,
- const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
-}
-
-/* Verify mtime of 'pathname'. */
-int
-assertion_file_mtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'm', 0);
-}
-
-/* Verify mtime of 'pathname' is up-to-date. */
-int
-assertion_file_mtime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'm', 1);
-}
-
-/* Verify number of links to 'pathname'. */
-int
-assertion_file_nlinks(const char *file, int line,
- const char *pathname, int nlinks)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(pathname, &bhfi);
- if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, bhfi.nNumberOfLinks, nlinks);
- failure_finish(NULL);
- return (0);
-#else
- struct stat st;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, st.st_nlink, nlinks);
- failure_finish(NULL);
- return (0);
-#endif
-}
-
-/* Verify size of 'pathname'. */
-int
-assertion_file_size(const char *file, int line, const char *pathname, long size)
-{
- int64_t filesize;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- {
- BY_HANDLE_FILE_INFORMATION bhfi;
- r = !my_GetFileInformationByName(pathname, &bhfi);
- filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow;
- }
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- filesize = st.st_size;
- }
-#endif
- if (r == 0 && filesize == size)
- return (1);
- failure_start(file, line, "File %s has size %ld, expected %ld",
- pathname, (long)filesize, (long)size);
- failure_finish(NULL);
- return (0);
-}
-
-/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
-int
-assertion_is_dir(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Dir should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISDIR(st.st_mode)) {
- failure_start(file, line, "%s is not a dir", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "Dir %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Verify that 'pathname' is a regular file. If 'mode' is >= 0,
- * verify that too. */
-int
-assertion_is_reg(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0 || !S_ISREG(st.st_mode)) {
- failure_start(file, line, "File should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "File %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Check whether 'pathname' is a symbolic link. If 'contents' is
- * non-NULL, verify that the symlink has those contents. */
-static int
-is_symlink(const char *file, int line,
- const char *pathname, const char *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)pathname; /* UNUSED */
- (void)contents; /* UNUSED */
- assertion_count(file, line);
- /* Windows sort-of has real symlinks, but they're only usable
- * by privileged users and are crippled even then, so there's
- * really not much point in bothering with this. */
- return (0);
-#else
- char buff[300];
- struct stat st;
- ssize_t linklen;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line,
- "Symlink should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISLNK(st.st_mode))
- return (0);
- if (contents == NULL)
- return (1);
- linklen = readlink(pathname, buff, sizeof(buff));
- if (linklen < 0) {
- failure_start(file, line, "Can't read symlink %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0)
- return (0);
- return (1);
-#endif
-}
-
-/* Assert that path is a symlink that (optionally) contains contents. */
-int
-assertion_is_symlink(const char *file, int line,
- const char *path, const char *contents)
-{
- if (is_symlink(file, line, path, contents))
- return (1);
- if (contents)
- failure_start(file, line, "File %s is not a symlink to %s",
- path, contents);
- else
- failure_start(file, line, "File %s is not a symlink", path);
- failure_finish(NULL);
- return (0);
-}
-
-
-/* Create a directory and report any errors. */
-int
-assertion_make_dir(const char *file, int line, const char *dirname, int mode)
-{
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
- if (0 == _mkdir(dirname))
- return (1);
-#else
- if (0 == mkdir(dirname, mode))
- return (1);
-#endif
- failure_start(file, line, "Could not create directory %s", dirname);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a file with the specified contents and report any failures. */
-int
-assertion_make_file(const char *file, int line,
- const char *path, int mode, int csize, const void *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* TODO: Rework this to set file mode as well. */
- FILE *f;
- (void)mode; /* UNUSED */
- assertion_count(file, line);
- f = fopen(path, "wb");
- if (f == NULL) {
- failure_start(file, line, "Could not create file %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (contents != NULL) {
- size_t wsize;
-
- if (csize < 0)
- wsize = strlen(contents);
- else
- wsize = (size_t)csize;
- if (wsize != fwrite(contents, 1, wsize, f)) {
- fclose(f);
- failure_start(file, line,
- "Could not write file %s", path);
- failure_finish(NULL);
- return (0);
- }
- }
- fclose(f);
- return (1);
-#else
- int fd;
- assertion_count(file, line);
- fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
- if (fd < 0) {
- failure_start(file, line, "Could not create %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (contents != NULL) {
- ssize_t wsize;
-
- if (csize < 0)
- wsize = (ssize_t)strlen(contents);
- else
- wsize = (ssize_t)csize;
- if (wsize != write(fd, contents, wsize)) {
- close(fd);
- failure_start(file, line,
- "Could not write to %s", path);
- failure_finish(NULL);
- return (0);
- }
- }
- close(fd);
- return (1);
-#endif
-}
-
-/* Create a hardlink and report any failures. */
-int
-assertion_make_hardlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
- int succeeded;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- succeeded = my_CreateHardLinkA(newpath, linkto);
-#elif HAVE_LINK
- succeeded = !link(linkto, newpath);
-#else
- succeeded = 0;
-#endif
- if (succeeded)
- return (1);
- failure_start(file, line, "Could not create hardlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a symlink and report any failures. */
-int
-assertion_make_symlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- int targetIsDir = 0; /* TODO: Fix this */
- assertion_count(file, line);
- if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
- return (1);
-#elif HAVE_SYMLINK
- assertion_count(file, line);
- if (0 == symlink(linkto, newpath))
- return (1);
-#endif
- failure_start(file, line, "Could not create symlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Set umask, report failures. */
-int
-assertion_umask(const char *file, int line, int mask)
-{
- assertion_count(file, line);
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- umask(mask);
- return (1);
-}
-
-/* Set times, report failures. */
-int
-assertion_utimes(const char *file, int line,
- const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
-{
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
- + (((nsec)/1000)*10))
- HANDLE h;
- ULARGE_INTEGER wintm;
- FILETIME fatime, fmtime;
- FILETIME *pat, *pmt;
-
- assertion_count(file, line);
- h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (at > 0 || at_nsec > 0) {
- wintm.QuadPart = WINTIME(at, at_nsec);
- fatime.dwLowDateTime = wintm.LowPart;
- fatime.dwHighDateTime = wintm.HighPart;
- pat = &fatime;
- } else
- pat = NULL;
- if (mt > 0 || mt_nsec > 0) {
- wintm.QuadPart = WINTIME(mt, mt_nsec);
- fmtime.dwLowDateTime = wintm.LowPart;
- fmtime.dwHighDateTime = wintm.HighPart;
- pmt = &fmtime;
- } else
- pmt = NULL;
- if (pat != NULL || pmt != NULL)
- r = SetFileTime(h, NULL, pat, pmt);
- else
- r = 1;
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't SetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#else /* defined(_WIN32) && !defined(__CYGWIN__) */
- struct stat st;
- struct timeval times[2];
-
-#if !defined(__FreeBSD__)
- mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
-#endif
- if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
- return (1);
-
- r = lstat(pathname, &st);
- if (r < 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (mt == 0 && mt_nsec == 0) {
- mt = st.st_mtime;
-#if defined(__FreeBSD__)
- mt_nsec = st.st_mtimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- mt_nsec = (mt_nsec / 1000) * 1000;
-#endif
- }
- if (at == 0 && at_nsec == 0) {
- at = st.st_atime;
-#if defined(__FreeBSD__)
- at_nsec = st.st_atimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- at_nsec = (at_nsec / 1000) * 1000;
-#endif
- }
-
- times[1].tv_sec = mt;
- times[1].tv_usec = mt_nsec / 1000;
-
- times[0].tv_sec = at;
- times[0].tv_usec = at_nsec / 1000;
-
-#ifdef HAVE_LUTIMES
- r = lutimes(pathname, times);
-#else
- r = utimes(pathname, times);
-#endif
- if (r < 0) {
- failure_start(file, line, "Can't utimes %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-}
-
-/* Set nodump, report failures. */
-int
-assertion_nodump(const char *file, int line, const char *pathname)
-{
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
- int r;
-
- assertion_count(file, line);
- r = chflags(pathname, UF_NODUMP);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
- int fd, r, flags;
-
- assertion_count(file, line);
- fd = open(pathname, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- failure_start(file, line, "Can't open %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't get flags %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- close(fd);
-#else
- (void)pathname; /* UNUSED */
- assertion_count(file, line);
-#endif
- return (1);
-}
-
-/*
- *
- * UTILITIES for use by tests.
- *
- */
-
-/*
- * Check whether platform supports symlinks. This is intended
- * for tests to use in deciding whether to bother testing symlink
- * support; if the platform doesn't support symlinks, there's no point
- * in checking whether the program being tested can create them.
- *
- * Note that the first time this test is called, we actually go out to
- * disk to create and verify a symlink. This is necessary because
- * symlink support is actually a property of a particular filesystem
- * and can thus vary between directories on a single system. After
- * the first call, this returns the cached result from memory, so it's
- * safe to call it as often as you wish.
- */
-int
-canSymlink(void)
-{
- /* Remember the test result */
- static int value = 0, tested = 0;
- if (tested)
- return (value);
-
- ++tested;
- assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
- /* Note: Cygwin has its own symlink() emulation that does not
- * use the Win32 CreateSymbolicLink() function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
- value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
- && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
-#elif HAVE_SYMLINK
- value = (0 == symlink("canSymlink.0", "canSymlink.1"))
- && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
-#endif
- return (value);
-}
-
-/* Platform-dependent options for hiding the output of a subcommand. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
-#else
-static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
-#endif
-/*
- * Can this platform run the bzip2 program?
- */
-int
-canBzip2(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the grzip program?
- */
-int
-canGrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("grzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the gzip program?
- */
-int
-canGzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("gzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lrzip program?
- */
-int
-canRunCommand(const char *cmd)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("%s %s", cmd, redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-int
-canLrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lrzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lz4 program?
- */
-int
-canLz4(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lz4 -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzip program?
- */
-int
-canLzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzma program?
- */
-int
-canLzma(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzma -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzop program?
- */
-int
-canLzop(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzop -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the xz program?
- */
-int
-canXz(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("xz -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this filesystem handle nodump flags.
- */
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-
-int
-canNodump(void)
-{
- const char *path = "cannodumptest";
- struct stat sb;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- if (chflags(path, UF_NODUMP) < 0)
- return (0);
- if (stat(path, &sb) < 0)
- return (0);
- if (sb.st_flags & UF_NODUMP)
- return (1);
- return (0);
-}
-
-#elif 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;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0)
- return (0);
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
- if (r < 0)
- return (0);
- close(fd);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0)
- return (0);
- close(fd);
- if (flags & EXT2_NODUMP_FL)
- return (1);
- return (0);
-}
-
-#else
-
-int
-canNodump()
-{
- return (0);
-}
-
-#endif
-
-/*
- * Sleep as needed; useful for verifying disk timestamp changes by
- * ensuring that the wall-clock time has actually changed before we
- * go back to re-read something from disk.
- */
-void
-sleepUntilAfter(time_t t)
-{
- while (t >= time(NULL))
-#if defined(_WIN32) && !defined(__CYGWIN__)
- Sleep(500);
-#else
- sleep(1);
-#endif
-}
-
-/*
- * Call standard system() call, but build up the command line using
- * sprintf() conventions.
- */
-int
-systemf(const char *fmt, ...)
-{
- char buff[8192];
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- if (verbosity > VERBOSITY_FULL)
- logprintf("Cmd: %s\n", buff);
- r = system(buff);
- va_end(ap);
- return (r);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-char *
-slurpfile(size_t * sizep, const char *fmt, ...)
-{
- char filename[8192];
- struct stat st;
- va_list ap;
- char *p;
- ssize_t bytes_read;
- FILE *f;
- int r;
-
- va_start(ap, fmt);
- vsprintf(filename, fmt, ap);
- va_end(ap);
-
- f = fopen(filename, "rb");
- if (f == NULL) {
- /* Note: No error; non-existent file is okay here. */
- return (NULL);
- }
- r = fstat(fileno(f), &st);
- if (r != 0) {
- logprintf("Can't stat file %s\n", filename);
- fclose(f);
- return (NULL);
- }
- p = malloc((size_t)st.st_size + 1);
- if (p == NULL) {
- logprintf("Can't allocate %ld bytes of memory to read file %s\n",
- (long int)st.st_size, filename);
- fclose(f);
- return (NULL);
- }
- bytes_read = fread(p, 1, (size_t)st.st_size, f);
- if (bytes_read < st.st_size) {
- logprintf("Can't read file %s\n", filename);
- fclose(f);
- free(p);
- return (NULL);
- }
- p[st.st_size] = '\0';
- if (sizep != NULL)
- *sizep = (size_t)st.st_size;
- fclose(f);
- return (p);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-void
-dumpfile(const char *filename, void *data, size_t len)
-{
- ssize_t bytes_written;
- FILE *f;
-
- f = fopen(filename, "wb");
- if (f == NULL) {
- logprintf("Can't open file %s for writing\n", filename);
- return;
- }
- bytes_written = fwrite(data, 1, len, f);
- if (bytes_written < (ssize_t)len)
- logprintf("Can't write file %s\n", filename);
- fclose(f);
-}
-
-/* Read a uuencoded file from the reference directory, decode, and
- * write the result into the current directory. */
-#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
-#define UUDECODE(c) (((c) - 0x20) & 0x3f)
-void
-extract_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
-
- sprintf(buff, "%s/%s.uu", refdir, name);
- in = fopen(buff, "r");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Read up to and including the 'begin' line. */
- for (;;) {
- if (fgets(buff, sizeof(buff), in) == NULL) {
- /* TODO: This is a failure. */
- return;
- }
- if (memcmp(buff, "begin ", 6) == 0)
- break;
- }
- /* Now, decode the rest and write it. */
- out = fopen(name, "wb");
- while (fgets(buff, sizeof(buff), in) != NULL) {
- char *p = buff;
- int bytes;
-
- if (memcmp(buff, "end", 3) == 0)
- break;
-
- bytes = UUDECODE(*p++);
- while (bytes > 0) {
- int n = 0;
- /* Write out 1-3 bytes from that. */
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- assert(VALID_UUDECODE(p[1]));
- n = UUDECODE(*p++) << 18;
- n |= UUDECODE(*p++) << 12;
- fputc(n >> 16, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++) << 6;
- fputc((n >> 8) & 0xFF, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++);
- fputc(n & 0xFF, out);
- --bytes;
- }
- }
- }
- fclose(out);
- fclose(in);
-}
-
-void
-copy_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
- size_t rbytes;
-
- sprintf(buff, "%s/%s", refdir, name);
- in = fopen(buff, "rb");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
- out = fopen(name, "wb");
- while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- if (fwrite(buff, 1, rbytes, out) != rbytes) {
- logprintf("Error: fwrite\n");
- break;
- }
- }
- fclose(out);
- fclose(in);
-}
-
-int
-is_LargeInode(const char *file)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- r = my_GetFileInformationByName(file, &bhfi);
- if (r != 0)
- return (0);
- return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
-#else
- struct stat st;
- int64_t ino;
-
- if (stat(file, &st) < 0)
- return (0);
- ino = (int64_t)st.st_ino;
- return (ino > 0xffffffff);
-#endif
-}
-
-void
-extract_reference_files(const char **names)
-{
- while (names && *names)
- extract_reference_file(*names++);
-}
-
-/*
- *
- * TEST management
- *
- */
-
-/*
- * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has
- * a line like
- * DEFINE_TEST(test_function)
- * for each test.
- */
-
-/* Use "list.h" to declare all of the test functions. */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void);
-#include "list.h"
-
-/* Use "list.h" to create a list of all tests (functions and names). */
-#undef DEFINE_TEST
-#define DEFINE_TEST(n) { n, #n, 0 },
-struct test_list_t tests[] = {
- #include "list.h"
-};
-
-/*
- * Summarize repeated failures in the just-completed test.
- */
-static void
-test_summarize(int failed, int skips_num)
-{
- unsigned int i;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY:
- printf(failed ? "E" : ".");
- fflush(stdout);
- break;
- case VERBOSITY_PASSFAIL:
- printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n");
- break;
- }
-
- log_console = (verbosity == VERBOSITY_LIGHT_REPORT);
-
- for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
- if (failed_lines[i].count > 1 && !failed_lines[i].skip)
- logprintf("%s:%d: Summary: Failed %d times\n",
- failed_filename, i, failed_lines[i].count);
- }
- /* Clear the failure history for the next file. */
- failed_filename = NULL;
- memset(failed_lines, 0, sizeof(failed_lines));
-}
-
-/*
- * Actually run a single test, with appropriate setup and cleanup.
- */
-static int
-test_run(int i, const char *tmpdir)
-{
- char workdir[1024];
- char logfilename[64];
- int failures_before = failures;
- int skips_before = skips;
- int oldumask;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
- break;
- case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-64s", i, tests[i].name);
- fflush(stdout);
- break;
- default: /* Title of test, details will follow */
- printf("%3d: %s\n", i, tests[i].name);
- }
-
- /* Chdir to the top-level work directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to top work dir %s\n", tmpdir);
- exit(1);
- }
- /* Create a log file for this test. */
- sprintf(logfilename, "%s.log", tests[i].name);
- logfile = fopen(logfilename, "w");
- fprintf(logfile, "%s\n\n", tests[i].name);
- /* Chdir() to a work dir for this specific test. */
- snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
- testworkdir = workdir;
- if (!assertMakeDir(testworkdir, 0755)
- || !assertChdir(testworkdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to work dir %s\n", testworkdir);
- exit(1);
- }
- /* Explicitly reset the locale before each test. */
- setlocale(LC_ALL, "C");
- /* Record the umask before we run the test. */
- umask(oldumask = umask(0));
- /*
- * Run the actual test.
- */
- (*tests[i].func)();
- /*
- * Clean up and report afterwards.
- */
- testworkdir = NULL;
- /* Restore umask */
- umask(oldumask);
- /* Reset locale. */
- setlocale(LC_ALL, "C");
- /* Reset directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n",
- tmpdir);
- exit(1);
- }
- /* Report per-test summaries. */
- tests[i].failures = failures - failures_before;
- test_summarize(tests[i].failures, skips - skips_before);
- /* Close the per-test log file. */
- fclose(logfile);
- logfile = NULL;
- /* If there were no failures, we can remove the work dir and logfile. */
- if (tests[i].failures == 0) {
- if (!keep_temp_files && assertChdir(tmpdir)) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure not to leave empty directories.
- * Sometimes a processing of closing files used by tests
- * is not done, then rmdir will be failed and it will
- * leave a empty test directory. So we should wait a few
- * seconds and retry rmdir. */
- int r, t;
- for (t = 0; t < 10; t++) {
- if (t > 0)
- Sleep(1000);
- r = systemf("rmdir /S /Q %s", tests[i].name);
- if (r == 0)
- break;
- }
- systemf("del %s", logfilename);
-#else
- systemf("rm -rf %s", tests[i].name);
- systemf("rm %s", logfilename);
-#endif
- }
- }
- /* Return appropriate status. */
- return (tests[i].failures);
-}
-
-/*
- *
- *
- * MAIN and support routines.
- *
- *
- */
-
-static void
-usage(const char *program)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i;
-
- printf("Usage: %s [options] <test> <test> ...\n", program);
- printf("Default is to run all tests.\n");
- printf("Otherwise, specify the numbers of the tests you wish to run.\n");
- printf("Options:\n");
- printf(" -d Dump core after any failure, for debugging.\n");
- printf(" -k Keep all temp files.\n");
- printf(" Default: temp files for successful tests deleted.\n");
-#ifdef PROGRAM
- printf(" -p <path> Path to executable to be tested.\n");
- printf(" Default: path taken from " ENVBASE " environment variable.\n");
-#endif
- printf(" -q Quiet.\n");
- printf(" -r <dir> Path to dir containing reference files.\n");
- printf(" Default: Current directory.\n");
- printf(" -u Keep running specifies tests until one fails.\n");
- printf(" -v Verbose.\n");
- printf("Available tests:\n");
- for (i = 0; i < limit; i++)
- printf(" %d: %s\n", i, tests[i].name);
- exit(1);
-}
-
-static char *
-get_refdir(const char *d)
-{
- size_t tried_size, buff_size;
- char *buff, *tried, *pwd = NULL, *p = NULL;
-
-#ifdef PATH_MAX
- buff_size = PATH_MAX;
-#else
- buff_size = 8192;
-#endif
- buff = calloc(buff_size, 1);
- if (buff == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* Allocate a buffer to hold the various directories we checked. */
- tried_size = buff_size * 2;
- tried = calloc(tried_size, 1);
- if (tried == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* If a dir was specified, try that */
- if (d != NULL) {
- pwd = NULL;
- snprintf(buff, buff_size, "%s", d);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- goto failure;
- }
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
- /* Look for a known file. */
- snprintf(buff, buff_size, "%s", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(LIBRARY)
- snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY);
-#else
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM);
-#endif
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(PROGRAM_ALIAS)
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-#endif
-
- if (memcmp(pwd, "/usr/obj", 8) == 0) {
- snprintf(buff, buff_size, "%s", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- }
-
-failure:
- printf("Unable to locate known reference file %s\n", KNOWNREF);
- printf(" Checked following directories:\n%s\n", tried);
- printf("Use -r option to specify full path to reference directory\n");
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
- DebugBreak();
-#endif
- exit(1);
-
-success:
- free(p);
- free(pwd);
- free(tried);
-
- /* Copy result into a fresh buffer to reduce memory usage. */
- p = strdup(buff);
- free(buff);
- return p;
-}
-
-int
-main(int argc, char **argv)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int test_set[sizeof(tests) / sizeof(tests[0])];
- int i = 0, j = 0, tests_run = 0, tests_failed = 0, option;
- time_t now;
- char *refdir_alloc = NULL;
- const char *progname;
- char **saved_argv;
- const char *tmp, *option_arg, *p;
- char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL;
- char tmpdir_timestamp[256];
-
- (void)argc; /* UNUSED */
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
- /* To stop to run the default invalid parameter handler. */
- _set_invalid_parameter_handler(invalid_parameter_handler);
- /* Disable annoying assertion message box. */
- _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-
- /*
- * Name of this program, used to build root of our temp directory
- * tree.
- */
- progname = p = argv[0];
- if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(testprogdir, progname);
- while (*p != '\0') {
- /* Support \ or / dir separators for Windows compat. */
- if (*p == '/' || *p == '\\')
- {
- progname = p + 1;
- i = j;
- }
- ++p;
- j++;
- }
- testprogdir[i] = '\0';
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (testprogdir[0] != '/' && testprogdir[0] != '\\' &&
- !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') ||
- (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) &&
- testprogdir[1] == ':' &&
- (testprogdir[2] == '/' || testprogdir[2] == '\\')))
-#else
- if (testprogdir[0] != '/')
-#endif
- {
- /* Fixup path for relative directories. */
- if ((testprogdir = (char *)realloc(testprogdir,
- strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir) + 1);
- memcpy(testprogdir, pwd, strlen(pwd));
- testprogdir[strlen(pwd)] = '/';
- }
-
-#ifdef PROGRAM
- /* Get the target program from environment, if available. */
- testprogfile = getenv(ENVBASE);
-#endif
-
- if (getenv("TMPDIR") != NULL)
- tmp = getenv("TMPDIR");
- else if (getenv("TMP") != NULL)
- tmp = getenv("TMP");
- else if (getenv("TEMP") != NULL)
- tmp = getenv("TEMP");
- else if (getenv("TEMPDIR") != NULL)
- tmp = getenv("TEMPDIR");
- else
- tmp = "/tmp";
-
- /* Allow -d to be controlled through the environment. */
- if (getenv(ENVBASE "_DEBUG") != NULL)
- dump_on_failure = 1;
-
- /* Allow -v to be controlled through the environment. */
- if (getenv("_VERBOSITY_LEVEL") != NULL)
- {
- vlevel = getenv("_VERBOSITY_LEVEL");
- verbosity = atoi(vlevel);
- if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL)
- {
- /* Unsupported verbosity levels are silently ignored */
- vlevel = NULL;
- verbosity = VERBOSITY_PASSFAIL;
- }
- }
-
- /* Get the directory holding test files from environment. */
- refdir = getenv(ENVBASE "_TEST_FILES");
-
- /*
- * Parse options, without using getopt(), which isn't available
- * on all platforms.
- */
- ++argv; /* Skip program name */
- while (*argv != NULL) {
- if (**argv != '-')
- break;
- p = *argv++;
- ++p; /* Skip '-' */
- while (*p != '\0') {
- option = *p++;
- option_arg = NULL;
- /* If 'opt' takes an argument, parse that. */
- if (option == 'p' || option == 'r') {
- if (*p != '\0')
- option_arg = p;
- else if (*argv == NULL) {
- fprintf(stderr,
- "Option -%c requires argument.\n",
- option);
- usage(progname);
- } else
- option_arg = *argv++;
- p = ""; /* End of this option word. */
- }
-
- /* Now, handle the option. */
- switch (option) {
- case 'd':
- dump_on_failure = 1;
- break;
- case 'k':
- keep_temp_files = 1;
- break;
- case 'p':
-#ifdef PROGRAM
- testprogfile = option_arg;
-#else
- fprintf(stderr, "-p option not permitted\n");
- usage(progname);
-#endif
- break;
- case 'q':
- if (!vlevel)
- verbosity--;
- break;
- case 'r':
- refdir = option_arg;
- break;
- case 'u':
- until_failure++;
- break;
- case 'v':
- if (!vlevel)
- verbosity++;
- break;
- default:
- fprintf(stderr, "Unrecognized option '%c'\n",
- option);
- usage(progname);
- }
- }
- }
-
- /*
- * Sanity-check that our options make sense.
- */
-#ifdef PROGRAM
- if (testprogfile == NULL)
- {
- if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
- strlen(PROGRAM) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(tmp2, testprogdir);
- strcat(tmp2, "/");
- strcat(tmp2, PROGRAM);
- testprogfile = tmp2;
- }
-
- {
- char *testprg;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Command.com sometimes rejects '/' separators. */
- testprg = strdup(testprogfile);
- for (i = 0; testprg[i] != '\0'; i++) {
- if (testprg[i] == '/')
- testprg[i] = '\\';
- }
- testprogfile = testprg;
-#endif
- /* Quote the name that gets put into shell command lines. */
- testprg = malloc(strlen(testprogfile) + 3);
- strcpy(testprg, "\"");
- strcat(testprg, testprogfile);
- strcat(testprg, "\"");
- testprog = testprg;
- }
-#endif
-
-#if !defined(_WIN32) && defined(SIGPIPE)
- { /* Ignore SIGPIPE signals */
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGPIPE, &sa, NULL);
- }
-#endif
-
- /*
- * Create a temp directory for the following tests.
- * Include the time the tests started as part of the name,
- * to make it easier to track the results of multiple tests.
- */
- now = time(NULL);
- for (i = 0; ; i++) {
- strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
- "%Y-%m-%dT%H.%M.%S",
- localtime(&now));
- sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname,
- tmpdir_timestamp, i);
- if (assertMakeDir(tmpdir,0755))
- break;
- if (i >= 999) {
- fprintf(stderr,
- "ERROR: Unable to create temp directory %s\n",
- tmpdir);
- exit(1);
- }
- }
-
- /*
- * If the user didn't specify a directory for locating
- * reference files, try to find the reference files in
- * the "usual places."
- */
- refdir = refdir_alloc = get_refdir(refdir);
-
- /*
- * Banner with basic information.
- */
- printf("\n");
- printf("If tests fail or crash, details will be in:\n");
- printf(" %s\n", tmpdir);
- printf("\n");
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("Reference files will be read from: %s\n", refdir);
-#ifdef PROGRAM
- printf("Running tests on: %s\n", testprog);
-#endif
- printf("Exercising: ");
- fflush(stdout);
- printf("%s\n", EXTRA_VERSION);
- } else {
- printf("Running ");
- fflush(stdout);
- }
-
- /*
- * Run some or all of the individual tests.
- */
- saved_argv = argv;
- do {
- argv = saved_argv;
- do {
- int test_num;
-
- test_num = get_test_set(test_set, limit, *argv, tests);
- if (test_num < 0) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- free(testprogdir);
- usage(progname);
- return (1);
- }
- for (i = 0; i < test_num; i++) {
- tests_run++;
- if (test_run(test_set[i], tmpdir)) {
- tests_failed++;
- if (until_failure)
- goto finish;
- }
- }
- if (*argv != NULL)
- argv++;
- } while (*argv != NULL);
- } while (until_failure);
-
-finish:
- /* Must be freed after all tests run */
- free(tmp2);
- free(testprogdir);
- free(pwd);
-
- /*
- * Report summary statistics.
- */
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("\n");
- printf("Totals:\n");
- printf(" Tests run: %8d\n", tests_run);
- printf(" Tests failed: %8d\n", tests_failed);
- printf(" Assertions checked:%8d\n", assertions);
- printf(" Assertions failed: %8d\n", failures);
- printf(" Skips reported: %8d\n", skips);
- }
- if (failures) {
- printf("\n");
- printf("Failing tests:\n");
- for (i = 0; i < limit; ++i) {
- if (tests[i].failures)
- printf(" %d: %s (%d failures)\n", i,
- tests[i].name, tests[i].failures);
- }
- printf("\n");
- printf("Details for failing tests: %s\n", tmpdir);
- printf("\n");
- } else {
- if (verbosity == VERBOSITY_SUMMARY_ONLY)
- printf("\n");
- printf("%d tests passed, no failures\n", tests_run);
- }
-
- free(refdir_alloc);
-
- /* If the final tmpdir is empty, we can remove it. */
- /* This should be the usual case when all tests succeed. */
- assertChdir("..");
- rmdir(tmpdir);
-
- return (tests_failed ? 1 : 0);
-}
diff --git a/archivers/libarchive/files/libarchive/test/read_open_memory.c b/archivers/libarchive/files/libarchive/test/read_open_memory.c
index f4162eb4bb4..2bb8d54751c 100644
--- a/archivers/libarchive/files/libarchive/test/read_open_memory.c
+++ b/archivers/libarchive/files/libarchive/test/read_open_memory.c
@@ -86,21 +86,7 @@ static int
read_open_memory_internal(struct archive *a, const void *buff,
size_t size, size_t read_size, int level)
{
- struct read_memory_data *mine;
-
- mine = (struct read_memory_data *)malloc(sizeof(*mine));
- if (mine == NULL) {
- archive_set_error(a, ENOMEM, "No memory");
- return (ARCHIVE_FATAL);
- }
- memset(mine, 0, sizeof(*mine));
- mine->start = mine->p = (const unsigned char *)buff;
- mine->end = mine->start + size;
- mine->read_size = read_size;
- mine->copy_buff_offset = 32;
- mine->copy_buff_size = read_size + mine->copy_buff_offset * 2;
- mine->copy_buff = malloc(mine->copy_buff_size);
- memset(mine->copy_buff, 0xA5, mine->copy_buff_size);
+ struct read_memory_data *mine = NULL;
switch (level) {
case 3:
@@ -109,6 +95,20 @@ read_open_memory_internal(struct archive *a, const void *buff,
archive_read_set_open_callback(a, memory_read_open);
archive_read_set_skip_callback(a, memory_read_skip);
case 1:
+ mine = malloc(sizeof(*mine));
+ if (mine == NULL) {
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ memset(mine, 0, sizeof(*mine));
+ mine->start = mine->p = (const unsigned char *)buff;
+ mine->end = mine->start + size;
+ mine->read_size = read_size;
+ mine->copy_buff_offset = 32;
+ mine->copy_buff_size = read_size + mine->copy_buff_offset * 2;
+ mine->copy_buff = malloc(mine->copy_buff_size);
+ memset(mine->copy_buff, 0xA5, mine->copy_buff_size);
+
archive_read_set_read_callback(a, memory_read);
archive_read_set_close_callback(a, memory_read_close);
archive_read_set_callback_data(a, mine);
@@ -213,7 +213,8 @@ memory_read_close(struct archive *a, void *client_data)
{
struct read_memory_data *mine = (struct read_memory_data *)client_data;
(void)a; /* UNUSED */
- free(mine->copy_buff);
+ if (mine != NULL)
+ free(mine->copy_buff);
free(mine);
return (ARCHIVE_OK);
}
diff --git a/archivers/libarchive/files/libarchive/test/test.h b/archivers/libarchive/files/libarchive/test/test.h
index 1117d6a7776..fd679f5f2ff 100644
--- a/archivers/libarchive/files/libarchive/test/test.h
+++ b/archivers/libarchive/files/libarchive/test/test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2006 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -21,335 +21,16 @@
* 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: head/lib/libarchive/test/test.h 201247 2009-12-30 05:59:21Z kientzle $
*/
/* Every test program should #include "test.h" as the first thing. */
-/*
- * The goal of this file (and the matching test.c) is to
- * simplify the very repetitive test-*.c test programs.
- */
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "config_freebsd.h"
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-/* Win32 can't run the 'configure' script. */
-#include "config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
-#include <sys/types.h> /* Windows requires this before sys/stat.h */
-#include <sys/stat.h>
-
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#define dirent direct
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <wchar.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-/*
- * System-specific tweaks. We really want to minimize these
- * as much as possible, since they make it harder to understand
- * the mainline code.
- */
-
-/* Windows (including Visual Studio and MinGW but not Cygwin) */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(__BORLANDC__)
-#undef chdir
-#define chdir _chdir
-#define strdup _strdup
-#endif
-#endif
-
-/* Visual Studio */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf sprintf_s
-#endif
-
-#if defined(__BORLANDC__)
-#pragma warn -8068 /* Constant out of range in comparison. */
-#endif
-
-/* Haiku OS and QNX */
-#if defined(__HAIKU__) || defined(__QNXNTO__)
-/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
-#include <stdint.h>
-#endif
-
-/* Get a real definition for __FBSDID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define it so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define __FBSDID(a) struct _undefined_hack
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * Redefine DEFINE_TEST for use in defining the test functions.
- */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void); void name(void)
-
-/* An implementation of the standard assert() macro */
-#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* chdir() and error if it fails */
-#define assertChdir(path) \
- assertion_chdir(__FILE__, __LINE__, path)
-/* Assert two integers are the same. Reports value of each one if not. */
-#define assertEqualInt(v1,v2) \
- assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* Assert two strings are the same. Reports value of each one if not. */
-#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
-#define assertEqualUTF8String(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
-/* As above, but v1 and v2 are wchar_t * */
-#define assertEqualWString(v1,v2) \
- assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* As above, but raw blocks of bytes. */
-#define assertEqualMem(v1, v2, l) \
- assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert that memory is full of a specified byte */
-#define assertMemoryFilledWith(v1, l, b) \
- assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
-/* Assert two files are the same. */
-#define assertEqualFile(f1, f2) \
- assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
-/* Assert that a file is empty. */
-#define assertEmptyFile(pathname) \
- assertion_empty_file(__FILE__, __LINE__, (pathname))
-/* Assert that a file is not empty. */
-#define assertNonEmptyFile(pathname) \
- assertion_non_empty_file(__FILE__, __LINE__, (pathname))
-#define assertFileAtime(pathname, sec, nsec) \
- assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileAtimeRecent(pathname) \
- assertion_file_atime_recent(__FILE__, __LINE__, pathname)
-#define assertFileBirthtime(pathname, sec, nsec) \
- assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileBirthtimeRecent(pathname) \
- assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists(pathname) \
- assertion_file_exists(__FILE__, __LINE__, pathname)
-/* Assert that a file exists. */
-#define assertFileNotExists(pathname) \
- assertion_file_not_exists(__FILE__, __LINE__, pathname)
-/* Assert that file contents match a string. */
-#define assertFileContents(data, data_size, pathname) \
- assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
-#define assertFileMtime(pathname, sec, nsec) \
- assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileMtimeRecent(pathname) \
- assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
-#define assertFileNLinks(pathname, nlinks) \
- assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
-#define assertFileSize(pathname, size) \
- assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertTextFileContents(text, pathname) \
- assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
-#define assertFileContainsLinesAnyOrder(pathname, lines) \
- assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
-#define assertIsDir(pathname, mode) \
- assertion_is_dir(__FILE__, __LINE__, pathname, mode)
-#define assertIsHardlink(path1, path2) \
- assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsNotHardlink(path1, path2) \
- assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsReg(pathname, mode) \
- assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
-/* Create a directory, report error if it fails. */
-#define assertMakeDir(dirname, mode) \
- assertion_make_dir(__FILE__, __LINE__, dirname, mode)
-#define assertMakeFile(path, mode, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
-#define assertMakeBinFile(path, mode, csize, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
-#define assertMakeHardlink(newfile, oldfile) \
- assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
-#define assertMakeSymlink(newfile, linkto) \
- assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
-#define assertNodump(path) \
- assertion_nodump(__FILE__, __LINE__, path)
-#define assertUmask(mask) \
- assertion_umask(__FILE__, __LINE__, mask)
-#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
- assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
-
-/*
- * This would be simple with C99 variadic macros, but I don't want to
- * require that. Instead, I insert a function call before each
- * skipping() call to pass the file and line information down. Crude,
- * but effective.
- */
-#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
-
-/* Function declarations. These are defined in test_utility.c. */
-void failure(const char *fmt, ...);
-int assertion_assert(const char *, int, int, const char *, void *);
-int assertion_chdir(const char *, int, const char *);
-int assertion_empty_file(const char *, int, const char *);
-int assertion_equal_file(const char *, int, const char *, const char *);
-int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
-int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
-int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int assertion_file_atime(const char *, int, const char *, long, long);
-int assertion_file_atime_recent(const char *, int, const char *);
-int assertion_file_birthtime(const char *, int, const char *, long, long);
-int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
-int assertion_file_contents(const char *, int, const void *, int, const char *);
-int assertion_file_exists(const char *, int, const char *);
-int assertion_file_mtime(const char *, int, const char *, long, long);
-int assertion_file_mtime_recent(const char *, int, const char *);
-int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, int, const char *);
-int assertion_file_size(const char *, int, const char *, long);
-int assertion_is_dir(const char *, int, const char *, int);
-int assertion_is_hardlink(const char *, int, const char *, const char *);
-int assertion_is_not_hardlink(const char *, int, const char *, const char *);
-int assertion_is_reg(const char *, int, const char *, int);
-int assertion_is_symlink(const char *, int, const char *, const char *);
-int assertion_make_dir(const char *, int, const char *, int);
-int assertion_make_file(const char *, int, const char *, int, int, const void *);
-int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
-int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_nodump(const char *, int, const char *);
-int assertion_non_empty_file(const char *, int, const char *);
-int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
-int assertion_umask(const char *, int, int);
-int assertion_utimes(const char *, int, const char *, long, long, long, long );
-
-void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
-
-/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
-
-/* Delay until time() returns a value after this. */
-void sleepUntilAfter(time_t);
-
-/* Return true if this platform can create symlinks. */
-int canSymlink(void);
-
-/* Return true if this platform can run the "bzip2" program. */
-int canBzip2(void);
-
-/* Return true if this platform can run the "grzip" program. */
-int canGrzip(void);
-
-/* Return true if this platform can run the "gzip" program. */
-int canGzip(void);
-
-/* Return true if this platform can run the specified command. */
-int canRunCommand(const char *);
-
-/* Return true if this platform can run the "lrzip" program. */
-int canLrzip(void);
-
-/* Return true if this platform can run the "lz4" program. */
-int canLz4(void);
-
-/* Return true if this platform can run the "lzip" program. */
-int canLzip(void);
-
-/* Return true if this platform can run the "lzma" program. */
-int canLzma(void);
-
-/* Return true if this platform can run the "lzop" program. */
-int canLzop(void);
-
-/* Return true if this platform can run the "xz" program. */
-int canXz(void);
-
-/* Return true if this filesystem can handle nodump flags. */
-int canNodump(void);
-
-/* Return true if the file has large i-node number(>0xffffffff). */
-int is_LargeInode(const char *);
-
-/* Suck file into string allocated via malloc(). Call free() when done. */
-/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
-char *slurpfile(size_t *, const char *fmt, ...);
-
-/* Dump block of bytes to a file. */
-void dumpfile(const char *filename, void *, size_t);
-
-/* Extracts named reference file to the current directory. */
-void extract_reference_file(const char *);
-/* Copies named reference file to the current directory. */
-void copy_reference_file(const char *);
-
-/* Extracts a list of files to the current directory.
- * List must be NULL terminated.
- */
-void extract_reference_files(const char **);
-
-/* Path to working directory for current test */
-extern const char *testworkdir;
-
-/*
- * Special interfaces for libarchive test harness.
- */
-
-#include "archive.h"
-#include "archive_entry.h"
-
-/* Special customized read-from-memory interface. */
-int read_open_memory(struct archive *, const void *, size_t, size_t);
-/* _minimal version exercises a slightly different set of libarchive APIs. */
-int read_open_memory_minimal(struct archive *, const void *, size_t, size_t);
-/* _seek version produces a seekable file. */
-int read_open_memory_seek(struct archive *, const void *, size_t, size_t);
-
-/* Versions of above that accept an archive argument for additional info. */
-#define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a))
-#define assertEqualIntA(a,v1,v2) \
- assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
-#define assertEqualStringA(a,v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a), 0)
+#define KNOWNREF "test_compat_gtar_1.tar.uu"
+#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
+#undef PROGRAM /* Testing a library, not a program. */
+#define LIBRARY "libarchive"
+#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x))
+#define EXTRA_ERRNO(x) archive_errno((struct archive *)(x))
+#define EXTRA_VERSION archive_version_details()
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
+#include "test_common.h"
diff --git a/archivers/libarchive/files/libarchive/test/test_acl_freebsd_nfs4.c b/archivers/libarchive/files/libarchive/test/test_acl_freebsd_nfs4.c
deleted file mode 100644
index fd2301d1f3d..00000000000
--- a/archivers/libarchive/files/libarchive/test/test_acl_freebsd_nfs4.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 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 "test.h"
-__FBSDID("$FreeBSD$");
-
-#if defined(__FreeBSD__) && __FreeBSD__ >= 8
-#define _ACL_PRIVATE
-#include <sys/acl.h>
-
-struct myacl_t {
- int type;
- int permset;
- int tag;
- int qual; /* GID or UID of user/group, depending on tag. */
- const char *name; /* Name of user/group, depending on tag. */
-};
-
-static struct myacl_t acls_reg[] = {
- /* For this test, we need the file owner to be able to read and write the ACL. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
-
- /* An entry for each type. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
- { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
-
- /* An entry for each permission. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
- ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
- ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
- ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
- ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
- ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
- ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
- ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
-
- /* One entry for each qualifier. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
-// { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
-// ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
-};
-
-
-static struct myacl_t acls_dir[] = {
- /* For this test, we need to be able to read and write the ACL. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
-
- /* An entry for each type. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
- { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
-
- /* An entry for each permission. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
- ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
- ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
- ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
- ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
- ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
- ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
- ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
- ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
- ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
-
- /* One entry with each inheritance value. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
-#if 0
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
- ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
- ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
-#endif
-
-#if 0
- /* FreeBSD does not support audit entries. */
- { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
- ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
- { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
- ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
- ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
-#endif
-
- /* One entry for each qualifier. */
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
- ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
-};
-
-static void
-set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
-{
- int i;
-
- archive_entry_acl_clear(ae);
- if (start > 0) {
- assertEqualInt(ARCHIVE_OK,
- archive_entry_acl_add_entry(ae,
- acls[0].type, acls[0].permset, acls[0].tag,
- acls[0].qual, acls[0].name));
- }
- for (i = start; i < end; i++) {
- assertEqualInt(ARCHIVE_OK,
- archive_entry_acl_add_entry(ae,
- acls[i].type, acls[i].permset, acls[i].tag,
- acls[i].qual, acls[i].name));
- }
-}
-
-static int
-acl_permset_to_bitmap(acl_permset_t opaque_ps)
-{
- static struct { int machine; int portable; } perms[] = {
- {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
- {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
- {ACL_READ, ARCHIVE_ENTRY_ACL_READ},
- {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
- {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
- {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
- {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
- {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
- {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
- {ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
- {ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
- {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
- {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
- {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
- {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
- {ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
- {ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
- {ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
- {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
- };
- int i, permset = 0;
-
- for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
- if (acl_get_perm_np(opaque_ps, perms[i].machine))
- permset |= perms[i].portable;
- return permset;
-}
-
-static int
-acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
-{
- static struct { int machine; int portable; } flags[] = {
- {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
- {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
- {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
- };
- int i, flagset = 0;
-
- for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
- if (acl_get_flag_np(opaque_fs, flags[i].machine))
- flagset |= flags[i].portable;
- return flagset;
-}
-
-static int
-acl_match(acl_entry_t aclent, struct myacl_t *myacl)
-{
- gid_t g, *gp;
- uid_t u, *up;
- acl_tag_t tag_type;
- acl_permset_t opaque_ps;
- acl_flagset_t opaque_fs;
- int perms;
-
- acl_get_tag_type(aclent, &tag_type);
-
- /* translate the silly opaque permset to a bitmap */
- acl_get_permset(aclent, &opaque_ps);
- acl_get_flagset_np(aclent, &opaque_fs);
- perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
- if (perms != myacl->permset)
- return (0);
-
- switch (tag_type) {
- case ACL_USER_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
- break;
- case ACL_USER:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
- return (0);
- up = acl_get_qualifier(aclent);
- u = *up;
- acl_free(up);
- if ((uid_t)myacl->qual != u)
- return (0);
- break;
- case ACL_GROUP_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
- break;
- case ACL_GROUP:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
- return (0);
- gp = acl_get_qualifier(aclent);
- g = *gp;
- acl_free(gp);
- if ((gid_t)myacl->qual != g)
- return (0);
- break;
- case ACL_MASK:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
- break;
- case ACL_EVERYONE:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
- break;
- }
- return (1);
-}
-
-static void
-compare_acls(acl_t acl, struct myacl_t *myacls, const char *filename, int start, int end)
-{
- int *marker;
- int entry_id = ACL_FIRST_ENTRY;
- int matched;
- int i, n;
- acl_entry_t acl_entry;
-
- n = end - start;
- marker = malloc(sizeof(marker[0]) * (n + 1));
- for (i = 0; i < n; i++)
- marker[i] = i + start;
- /* Always include the first ACE. */
- if (start > 0) {
- marker[n] = 0;
- ++n;
- }
-
- /*
- * Iterate over acls in system acl object, try to match each
- * one with an item in the myacls array.
- */
- while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
- /* After the first time... */
- entry_id = ACL_NEXT_ENTRY;
-
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (acl_match(acl_entry, &myacls[marker[i]])) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- failure("ACL entry on file %s that shouldn't be there", filename);
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry %d missing from %s: "
- "type=%d,permset=%x,tag=%d,qual=%d,name=``%s''\n",
- marker[i], filename,
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-
-static void
-compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
-{
- int *marker;
- int matched;
- int i, n;
- int type, permset, tag, qual;
- const char *name;
-
- /* Count ACL entries in myacls array and allocate an indirect array. */
- n = end - start;
- marker = malloc(sizeof(marker[0]) * (n + 1));
- for (i = 0; i < n; i++)
- marker[i] = i + start;
- /* Always include the first ACE. */
- if (start > 0) {
- marker[n] = 0;
- ++n;
- }
-
- /*
- * Iterate over acls in entry, try to match each
- * one with an item in the myacls array.
- */
- assertEqualInt(n, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- while (ARCHIVE_OK == archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
-
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (tag == myacls[marker[i]].tag
- && qual == myacls[marker[i]].qual
- && permset == myacls[marker[i]].permset
- && type == myacls[marker[i]].type) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- failure("ACL entry on file that shouldn't be there: "
- "type=%d,permset=%x,tag=%d,qual=%d",
- type,permset,tag,qual);
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry %d missing from %s: "
- "type=%d,permset=%x,tag=%d,qual=%d,name=``%s''\n",
- marker[i], filename,
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-#endif
-
-/*
- * Verify ACL restore-to-disk. This test is FreeBSD-specific.
- */
-
-DEFINE_TEST(test_acl_freebsd_nfs4)
-{
-#if !defined(__FreeBSD__)
- skipping("FreeBSD-specific NFS4 ACL restore test");
-#elif __FreeBSD__ < 8
- skipping("NFS4 ACLs supported only on FreeBSD 8.0 and later");
-#else
- char buff[64];
- struct stat st;
- struct archive *a;
- struct archive_entry *ae;
- int i, n;
- acl_t acl;
-
- /*
- * First, do a quick manual set/read of ACL data to
- * verify that the local filesystem does support ACLs.
- * If it doesn't, we'll simply skip the remaining tests.
- */
- acl = acl_from_text("owner@:rwxp::allow,group@:rwp:f:allow");
- assert((void *)acl != NULL);
- /* Create a test dir and try to set an ACL on it. */
- if (!assertMakeDir("pretest", 0755)) {
- acl_free(acl);
- return;
- }
-
- n = acl_set_file("pretest", ACL_TYPE_NFS4, acl);
- acl_free(acl);
- if (n != 0 && errno == EOPNOTSUPP) {
- skipping("NFS4 ACL tests require that NFS4 ACLs"
- " be enabled on the filesystem");
- return;
- }
- if (n != 0 && errno == EINVAL) {
- skipping("This filesystem does not support NFS4 ACLs");
- return;
- }
- failure("acl_set_file(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
-
- /* Create a write-to-disk object. */
- assert(NULL != (a = archive_write_disk_new()));
- archive_write_disk_set_options(a,
- ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
-
- /* Populate an archive entry with some metadata, including ACL info */
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "testall");
- 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);
- set_acls(ae, acls_reg, 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
-
- /* Write the entry to disk, including ACLs. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
-
- /* Likewise for a dir. */
- archive_entry_set_pathname(ae, "dirall");
- archive_entry_set_filetype(ae, AE_IFDIR);
- archive_entry_set_perm(ae, 0654);
- archive_entry_set_mtime(ae, 123456, 7890);
- set_acls(ae, acls_dir, 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
-
- for (i = 0; i < (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); ++i) {
- sprintf(buff, "dir%d", i);
- archive_entry_set_pathname(ae, buff);
- archive_entry_set_filetype(ae, AE_IFDIR);
- archive_entry_set_perm(ae, 0654);
- archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
- set_acls(ae, acls_dir, i, i + 1);
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
- }
-
- archive_entry_free(ae);
-
- /* Close the archive. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
-
- /* Verify the data on disk. */
- assertEqualInt(0, stat("testall", &st));
- assertEqualInt(st.st_mtime, 123456);
- acl = acl_get_file("testall", ACL_TYPE_NFS4);
- assert(acl != (acl_t)NULL);
- compare_acls(acl, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
- acl_free(acl);
-
- /* Verify single-permission dirs on disk. */
- for (i = 0; i < (int)(sizeof(acls_dir)/sizeof(acls_dir[0])); ++i) {
- sprintf(buff, "dir%d", i);
- assertEqualInt(0, stat(buff, &st));
- assertEqualInt(st.st_mtime, 123456 + i);
- acl = acl_get_file(buff, ACL_TYPE_NFS4);
- assert(acl != (acl_t)NULL);
- compare_acls(acl, acls_dir, buff, i, i + 1);
- acl_free(acl);
- }
-
- /* Verify "dirall" on disk. */
- assertEqualInt(0, stat("dirall", &st));
- assertEqualInt(st.st_mtime, 123456);
- acl = acl_get_file("dirall", ACL_TYPE_NFS4);
- assert(acl != (acl_t)NULL);
- compare_acls(acl, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- acl_free(acl);
-
- /* Read and compare ACL via archive_read_disk */
- a = archive_read_disk_new();
- assert(a != NULL);
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "testall");
- assertEqualInt(ARCHIVE_OK,
- archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_reg, "testall", 0, (int)(sizeof(acls_reg)/sizeof(acls_reg[0])));
- archive_entry_free(ae);
- assertEqualInt(ARCHIVE_OK, archive_read_free(a));
-
- /* Read and compare ACL via archive_read_disk */
- a = archive_read_disk_new();
- assert(a != NULL);
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "dirall");
- assertEqualInt(ARCHIVE_OK,
- archive_read_disk_entry_from_file(a, ae, -1, NULL));
- compare_entry_acls(ae, acls_dir, "dirall", 0, (int)(sizeof(acls_dir)/sizeof(acls_dir[0])));
- archive_entry_free(ae);
- assertEqualInt(ARCHIVE_OK, archive_read_free(a));
-#endif
-}
diff --git a/archivers/libarchive/files/libarchive/test/test_acl_freebsd_posix1e.c b/archivers/libarchive/files/libarchive/test/test_acl_freebsd_posix1e.c
deleted file mode 100644
index 36f9499f4c7..00000000000
--- a/archivers/libarchive/files/libarchive/test/test_acl_freebsd_posix1e.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*-
- * Copyright (c) 2003-2008 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 "test.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
-
-#if defined(__FreeBSD__) && __FreeBSD__ > 4
-#include <sys/acl.h>
-
-struct myacl_t {
- int type; /* Type of ACL: "access" or "default" */
- int permset; /* Permissions for this class of users. */
- int tag; /* Owner, User, Owning group, group, other, etc. */
- int qual; /* GID or UID of user/group, depending on tag. */
- const char *name; /* Name of user/group, depending on tag. */
-};
-
-static struct myacl_t acls2[] = {
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
- ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
- ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
- ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
- ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
- ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
- { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
- ARCHIVE_ENTRY_ACL_MASK, -1, "" },
- { 0, 0, 0, 0, NULL }
-};
-
-static void
-set_acls(struct archive_entry *ae, struct myacl_t *acls)
-{
- int i;
-
- archive_entry_acl_clear(ae);
- for (i = 0; acls[i].name != NULL; i++) {
- archive_entry_acl_add_entry(ae,
- acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
- acls[i].name);
- }
-}
-
-static int
-acl_match(acl_entry_t aclent, struct myacl_t *myacl)
-{
- gid_t g, *gp;
- uid_t u, *up;
- acl_tag_t tag_type;
- acl_permset_t opaque_ps;
- int permset = 0;
-
- acl_get_tag_type(aclent, &tag_type);
-
- /* translate the silly opaque permset to a bitmap */
- acl_get_permset(aclent, &opaque_ps);
- if (acl_get_perm_np(opaque_ps, ACL_EXECUTE))
- permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (acl_get_perm_np(opaque_ps, ACL_WRITE))
- permset |= ARCHIVE_ENTRY_ACL_WRITE;
- if (acl_get_perm_np(opaque_ps, ACL_READ))
- permset |= ARCHIVE_ENTRY_ACL_READ;
-
- if (permset != myacl->permset)
- return (0);
-
- switch (tag_type) {
- case ACL_USER_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
- break;
- case ACL_USER:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
- return (0);
- up = acl_get_qualifier(aclent);
- u = *up;
- acl_free(up);
- if ((uid_t)myacl->qual != u)
- return (0);
- break;
- case ACL_GROUP_OBJ:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
- break;
- case ACL_GROUP:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
- return (0);
- gp = acl_get_qualifier(aclent);
- g = *gp;
- acl_free(gp);
- if ((gid_t)myacl->qual != g)
- return (0);
- break;
- case ACL_MASK:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
- break;
- case ACL_OTHER:
- if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
- break;
- }
- return (1);
-}
-
-static void
-compare_acls(acl_t acl, struct myacl_t *myacls)
-{
- int *marker;
- int entry_id = ACL_FIRST_ENTRY;
- int matched;
- int i, n;
- acl_entry_t acl_entry;
-
- /* Count ACL entries in myacls array and allocate an indirect array. */
- for (n = 0; myacls[n].name != NULL; ++n)
- continue;
- if (n) {
- marker = malloc(sizeof(marker[0]) * n);
- if (marker == NULL)
- return;
- for (i = 0; i < n; i++)
- marker[i] = i;
- } else
- marker = NULL;
-
- /*
- * Iterate over acls in system acl object, try to match each
- * one with an item in the myacls array.
- */
- while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
- /* After the first time... */
- entry_id = ACL_NEXT_ENTRY;
-
- /* Search for a matching entry (tag and qualifier) */
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (acl_match(acl_entry, &myacls[marker[i]])) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
-
- /* TODO: Print out more details in this case. */
- failure("ACL entry on file that shouldn't be there");
- assert(matched == 1);
- }
-
- /* Dump entries in the myacls array that weren't in the system acl. */
- for (i = 0; i < n; ++i) {
- failure(" ACL entry missing from file: "
- "type=%d,permset=%d,tag=%d,qual=%d,name=``%s''\n",
- myacls[marker[i]].type, myacls[marker[i]].permset,
- myacls[marker[i]].tag, myacls[marker[i]].qual,
- myacls[marker[i]].name);
- assert(0); /* Record this as a failure. */
- }
- free(marker);
-}
-
-#endif
-
-
-/*
- * Verify ACL restore-to-disk. This test is FreeBSD-specific.
- */
-
-DEFINE_TEST(test_acl_freebsd_posix1e)
-{
-#if !defined(__FreeBSD__)
- skipping("FreeBSD-specific ACL restore test");
-#elif __FreeBSD__ < 5
- skipping("ACL restore supported only on FreeBSD 5.0 and later");
-#else
- struct stat st;
- struct archive *a;
- struct archive_entry *ae;
- int n, fd;
- acl_t acl;
-
- /*
- * First, do a quick manual set/read of ACL data to
- * verify that the local filesystem does support ACLs.
- * If it doesn't, we'll simply skip the remaining tests.
- */
- acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
- assert((void *)acl != NULL);
- /* Create a test file and try to set an ACL on it. */
- fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
- failure("Could not create test file?!");
- if (!assert(fd >= 0)) {
- acl_free(acl);
- return;
- }
-
- n = acl_set_fd(fd, acl);
- acl_free(acl);
- if (n != 0 && errno == EOPNOTSUPP) {
- close(fd);
- skipping("ACL tests require that ACL support be enabled on the filesystem");
- return;
- }
- if (n != 0 && errno == EINVAL) {
- close(fd);
- skipping("This filesystem does not support POSIX.1e ACLs");
- return;
- }
- failure("acl_set_fd(): errno = %d (%s)",
- errno, strerror(errno));
- assertEqualInt(0, n);
- close(fd);
-
- /* Create a write-to-disk object. */
- assert(NULL != (a = archive_write_disk_new()));
- archive_write_disk_set_options(a,
- ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
-
- /* Populate an archive entry with some metadata, including ACL info */
- ae = archive_entry_new();
- assert(ae != NULL);
- archive_entry_set_pathname(ae, "test0");
- archive_entry_set_mtime(ae, 123456, 7890);
- archive_entry_set_size(ae, 0);
- set_acls(ae, acls2);
- assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
- archive_entry_free(ae);
-
- /* Close the archive. */
- assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
-
- /* Verify the data on disk. */
- assertEqualInt(0, stat("test0", &st));
- assertEqualInt(st.st_mtime, 123456);
- acl = acl_get_file("test0", ACL_TYPE_ACCESS);
- assert(acl != (acl_t)NULL);
- compare_acls(acl, acls2);
- acl_free(acl);
-#endif
-}
diff --git a/archivers/libarchive/files/libarchive/test/test_acl_pax.c b/archivers/libarchive/files/libarchive/test/test_acl_pax.c
index 5150b11d63b..8566f55a51a 100644
--- a/archivers/libarchive/files/libarchive/test/test_acl_pax.c
+++ b/archivers/libarchive/files/libarchive/test/test_acl_pax.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,11 +24,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_pax.c 201247 2009-12-30 05:59:21Z kientzle $");
+__FBSDID("$FreeBSD$");
/*
* Exercise the system-independent portion of the ACL support.
- * Check that pax archive can save and restore ACL data.
+ * Check that pax archive can save and restore POSIX.1e ACL data.
*
* This should work on all systems, regardless of whether local
* filesystems support ACLs or not.
@@ -35,15 +36,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_pax.c 201247 2009-12-30 05
static unsigned char buff[16384];
-struct acl_t {
- int type; /* Type of ACL: "access" or "default" */
- int permset; /* Permissions for this class of users. */
- int tag; /* Owner, User, Owning group, group, other, etc. */
- int qual; /* GID or UID of user/group, depending on tag. */
- const char *name; /* Name of user/group, depending on tag. */
-};
-
-static struct acl_t acls0[] = {
+static struct archive_test_acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@@ -52,7 +45,7 @@ static struct acl_t acls0[] = {
ARCHIVE_ENTRY_ACL_OTHER, 0, "" },
};
-static struct acl_t acls1[] = {
+static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@@ -63,7 +56,7 @@ static struct acl_t acls1[] = {
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
-static struct acl_t acls2[] = {
+static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@@ -78,101 +71,149 @@ static struct acl_t acls2[] = {
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
-static void
-set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
-{
- int i;
-
- archive_entry_acl_clear(ae);
- for (i = 0; i < n; i++) {
- archive_entry_acl_add_entry(ae,
- acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
- acls[i].name);
- }
-}
+static struct archive_test_acl_t acls3[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
+};
-static int
-acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, const char *name)
-{
- if (type != acl->type)
- return (0);
- if (permset != acl->permset)
- return (0);
- if (tag != acl->tag)
- return (0);
- if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
- return (1);
- if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
- return (1);
- if (tag == ARCHIVE_ENTRY_ACL_OTHER)
- return (1);
- if (qual != acl->qual)
- return (0);
- if (name == NULL)
- return (acl->name == NULL || acl->name[0] == '\0');
- if (acl->name == NULL)
- return (name == NULL || name[0] == '\0');
- return (0 == strcmp(name, acl->name));
-}
+static struct archive_test_acl_t acls4[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
+ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
+ ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DENY,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_EXECUTE,
+ ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DENY,
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER,
+ ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
+};
-static void
-compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode)
-{
- int *marker = malloc(sizeof(marker[0]) * n);
- int i;
- int r;
- int type, permset, tag, qual;
- int matched;
- const char *name;
-
- for (i = 0; i < n; i++)
- marker[i] = i;
-
- while (0 == (r = archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name))) {
- for (i = 0, matched = 0; i < n && !matched; i++) {
- if (acl_match(&acls[marker[i]], type, permset,
- tag, qual, name)) {
- /* We found a match; remove it. */
- marker[i] = marker[n - 1];
- n--;
- matched = 1;
- }
- }
- if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
- if (!matched) printf("No match for user_obj perm\n");
- failure("USER_OBJ permset (%02o) != user mode (%02o)",
- permset, 07 & (mode >> 6));
- assert((permset << 6) == (mode & 0700));
- } else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
- if (!matched) printf("No match for group_obj perm\n");
- failure("GROUP_OBJ permset %02o != group mode %02o",
- permset, 07 & (mode >> 3));
- assert((permset << 3) == (mode & 0070));
- } else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
- if (!matched) printf("No match for other perm\n");
- failure("OTHER permset (%02o) != other mode (%02o)",
- permset, mode & 07);
- assert((permset << 0) == (mode & 0007));
- } else {
- failure("Could not find match for ACL "
- "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
- type, permset, tag, qual, name);
- assert(matched == 1);
- }
- }
- assertEqualInt(ARCHIVE_EOF, r);
- assert((mode_t)(mode & 0777) == (archive_entry_mode(ae) & 0777));
- failure("Could not find match for ACL "
- "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
- acls[marker[0]].type, acls[marker[0]].permset,
- acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
- assert(n == 0); /* Number of ACLs not matched should == 0 */
- free(marker);
-}
+static struct archive_test_acl_t acls5[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
+ { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
+ ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALARM,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
+ ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
+};
-DEFINE_TEST(test_acl_pax)
+DEFINE_TEST(test_acl_pax_posix1e)
{
struct archive *a;
struct archive_entry *ae;
@@ -197,23 +238,22 @@ DEFINE_TEST(test_acl_pax)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* Basic owner/owning group should just update mode bits. */
- set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
/* With any extended ACL entry, we should read back a full set. */
- set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
assertA(0 == archive_write_header(a, ae));
-
/* A more extensive set of ACLs. */
- set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertA(0 == archive_write_header(a, ae));
/*
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
- set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
archive_entry_free(ae);
@@ -227,13 +267,13 @@ DEFINE_TEST(test_acl_pax)
fclose(f);
/* Write out the reference data to a file for manual inspection. */
- extract_reference_file("test_acl_pax.tar");
- reference = slurpfile(&reference_size, "test_acl_pax.tar");
+ extract_reference_file("test_acl_pax_posix1e.tar");
+ reference = slurpfile(&reference_size, "test_acl_pax_posix1e.tar");
/* Assert that the generated data matches the built-in reference data.*/
- failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax.tar' reference file.");
+ failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file.");
assertEqualMem(buff, reference, reference_size);
- failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax.tar' reference file.");
+ failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file.");
assertEqualInt((int)used, reference_size);
free(reference);
@@ -255,15 +295,18 @@ DEFINE_TEST(test_acl_pax)
assertA(0 == archive_read_next_header(a, &ae));
failure("One extended ACL should flag all ACLs to be returned.");
assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0142);
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Third item has pretty extensive ACLs */
assertA(0 == archive_read_next_header(a, &ae));
- assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0543);
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
@@ -280,3 +323,93 @@ DEFINE_TEST(test_acl_pax)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
+
+DEFINE_TEST(test_acl_pax_nfs4)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+ size_t used;
+ FILE *f;
+ void *reference;
+ size_t reference_size;
+
+ /* Write an archive to memory. */
+ assert(NULL != (a = archive_write_new()));
+ assertA(0 == archive_write_set_format_pax(a));
+ assertA(0 == archive_write_add_filter_none(a));
+ assertA(0 == archive_write_set_bytes_per_block(a, 1));
+ assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
+ assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
+
+ /* Write a series of files to the archive with different ACL info. */
+
+ /* Create a simple archive_entry. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_pathname(ae, "file");
+ archive_entry_set_mode(ae, S_IFREG | 0777);
+
+ /* NFS4 ACLs mirroring 0754 file mode */
+ assertEntrySetAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]));
+ assertA(0 == archive_write_header(a, ae));
+
+ /* A more extensive set of NFS4 ACLs. */
+ assertEntrySetAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]));
+ assertA(0 == archive_write_header(a, ae));
+
+ /* Set with special (audit, alarm) NFS4 ACLs. */
+ assertEntrySetAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]));
+ assertA(0 == archive_write_header(a, ae));
+
+ archive_entry_free(ae);
+
+ /* Close out the archive. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+ /* Write out the data we generated to a file for manual inspection. */
+ assert(NULL != (f = fopen("testout", "wb")));
+ assertEqualInt(used, (size_t)fwrite(buff, 1, (unsigned int)used, f));
+ fclose(f);
+
+ /* Write out the reference data to a file for manual inspection. */
+ extract_reference_file("test_acl_pax_nfs4.tar");
+ reference = slurpfile(&reference_size, "test_acl_pax_nfs4.tar");
+
+ /* Assert that the generated data matches the built-in reference data.*/
+ failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file.");
+ assertEqualMem(buff, reference, reference_size);
+ failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file.");
+ assertEqualInt((int)used, reference_size);
+ free(reference);
+
+ /* Read back each entry and check that the ACL data is right. */
+ assert(NULL != (a = archive_read_new()));
+ assertA(0 == archive_read_support_format_all(a));
+ assertA(0 == archive_read_support_filter_all(a));
+ assertA(0 == archive_read_open_memory(a, buff, used));
+
+ /* First item has NFS4 ACLs mirroring file mode */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(3, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_ALLOW));
+ assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0);
+
+ /* Second item has has more fine-grained NFS4 ACLs */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4));
+ assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
+
+ /* Third item has has audit and alarm NFS4 ACLs */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4));
+ assertEntryCompareAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
+
+ /* Close the archive. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/archivers/libarchive/files/libarchive/test/test_acl_pax.tar.uu b/archivers/libarchive/files/libarchive/test/test_acl_pax.tar.uu
deleted file mode 100644
index 58d7b62463d..00000000000
--- a/archivers/libarchive/files/libarchive/test/test_acl_pax.tar.uu
+++ /dev/null
@@ -1,117 +0,0 @@
-begin 644 test_acl_pax.tar
-M9FEL90``````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````#`P,#$T,B``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`P
-M(#`P,#`P,#`P,#`P(#`Q,#`P-@`@,```````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````!U<W1A<@`P,```````
-M````````````````````````````````````````````````````````````
-M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````!087A(96%D97(O9FEL90``````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````,#`P,30R(``P,#`P,#`@`#`P
-M,#`P,"``,#`P,#`P,#`Q,3`@,#`P,#`P,#`P,#`@,#$Q-S8Q`"!X````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````'5S=&%R`#`P````````````````````````````````````````````
-M`````````````````````````````````````````#`P,#`P,"``,#`P,#`P
-M(```````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````#<R(%-#2$E,62YA
-M8VPN86-C97-S/75S97(Z.BTM>"QG<F]U<#HZ<BTM+&]T:&5R.CHM=RTL=7-E
-M<CIU<V5R-S<Z<BTM.C<W"@``````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````9FEL90``````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````#`P,#$T,B``,#`P,#`P(``P,#`P,#`@`#`P,#`P
-M,#`P,#`P(#`P,#`P,#`P,#`P(#`Q,#`P-@`@,```````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````````````!U<W1A<@`P
-M,```````````````````````````````````````````````````````````
-M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````!087A(96%D97(O9FEL90``````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````,#`P-30S(``P,#`P
-M,#`@`#`P,#`P,"``,#`P,#`P,#`Q-C$@,#`P,#`P,#`P,#`@,#$Q-S<T`"!X
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````'5S=&%R`#`P````````````````````````````````````
-M`````````````````````````````````````````````````#`P,#`P,"``
-M,#`P,#`P(```````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````````#$Q,R!3
-M0TA)3%DN86-L+F%C8V5S<SUU<V5R.CIR+7@L9W)O=7`Z.G(M+2QO=&AE<CHZ
-M+7=X+'5S97(Z=7-E<C<W.G(M+3HW-RQU<V5R.G5S97(W.#HM+2TZ-S@L9W)O
-M=7`Z9W)O=7`W.#IR=W@Z-S@*````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````9FEL90``````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````#`P,#4T,R``,#`P,#`P(``P,#`P,#`@
-M`#`P,#`P,#`P,#`P(#`P,#`P,#`P,#`P(#`Q,#`Q,P`@,```````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````````````````````!U
-M<W1A<@`P,```````````````````````````````````````````````````
-M```````````````````````````````````P,#`P,#`@`#`P,#`P,"``````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````!F:6QE````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````,#`P,30R
-M(``P,#`P,#`@`#`P,#`P,"``,#`P,#`P,#`P,#`@,#`P,#`P,#`P,#`@,#$P
-M,#`V`"`P````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````'5S=&%R`#`P````````````````````````````
-M`````````````````````````````````````````````````````````#`P
-M,#`P,"``,#`P,#`P(```````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-C````````````````````````````````````````````````
-`
-end
diff --git a/archivers/libarchive/files/libarchive/test/test_archive_api_feature.c b/archivers/libarchive/files/libarchive/test/test_archive_api_feature.c
index d551e6a01eb..60773ad04e5 100644
--- a/archivers/libarchive/files/libarchive/test/test_archive_api_feature.c
+++ b/archivers/libarchive/files/libarchive/test/test_archive_api_feature.c
@@ -42,8 +42,12 @@ DEFINE_TEST(test_archive_api_feature)
if (strlen(buff) < strlen(archive_version_string())) {
p = archive_version_string() + strlen(buff);
failure("Version string is: %s", archive_version_string());
- assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd');
- ++p;
+ if (p[0] == 'd'&& p[1] == 'e' && p[2] == 'v')
+ p += 3;
+ else {
+ assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd');
+ ++p;
+ }
failure("Version string is: %s", archive_version_string());
assert(*p == '\0');
}
diff --git a/archivers/libarchive/files/libarchive/test/test_archive_string.c b/archivers/libarchive/files/libarchive/test/test_archive_string.c
index 9e3f90702db..7fa743ba9ed 100644
--- a/archivers/libarchive/files/libarchive/test/test_archive_string.c
+++ b/archivers/libarchive/files/libarchive/test/test_archive_string.c
@@ -67,6 +67,8 @@ test_archive_string_ensure(void)
assert(&s == archive_string_ensure(&s, EXTENT + 1));
assertNonNULLString(0, 2 * EXTENT, s);
+
+ archive_string_free(&s);
}
static void
@@ -92,6 +94,8 @@ test_archive_strcat(void)
/* non-empty target, non-empty source */
assert(&s == archive_strcat(&s, "baz"));
assertExactString(8, EXTENT, "fubarbaz", s);
+
+ archive_string_free(&s);
}
static void
@@ -109,6 +113,8 @@ test_archive_strappend_char(void)
/* non-empty target */
archive_strappend_char(&s, 'Y');
assertExactString(2, EXTENT, "XY", s);
+
+ archive_string_free(&s);
}
/* archive_strnXXX() tests focus on length handling.
@@ -134,6 +140,8 @@ test_archive_strncat(void)
/* long read is ok too! */
assert(&s == archive_strncat(&s, "snafu", 8));
assertExactString(13, EXTENT, "snafubarsnafu", s);
+
+ archive_string_free(&s);
}
static void
@@ -155,6 +163,8 @@ test_archive_strncpy(void)
/* long read is ok too! */
assert(&s == archive_strncpy(&s, "snafu", 8));
assertExactString(5, EXTENT, "snafu", s);
+
+ archive_string_free(&s);
}
static void
@@ -176,6 +186,8 @@ test_archive_strcpy(void)
/* dirty target, empty source */
assert(&s == archive_strcpy(&s, ""));
assertExactString(0, EXTENT, "", s);
+
+ archive_string_free(&s);
}
static void
@@ -222,6 +234,11 @@ test_archive_string_concat(void)
archive_string_concat(&t, &s);
assertExactString(5, EXTENT, "snafu", s);
assertExactString(5, EXTENT, "snafu", t);
+
+ archive_string_free(&v);
+ archive_string_free(&u);
+ archive_string_free(&t);
+ archive_string_free(&s);
}
static void
@@ -274,6 +291,11 @@ test_archive_string_copy(void)
archive_string_copy(&t, &s);
assertExactString(5, EXTENT, "fubar", s);
assertExactString(5, EXTENT, "fubar", t);
+
+ archive_string_free(&v);
+ archive_string_free(&u);
+ archive_string_free(&t);
+ archive_string_free(&s);
}
static void
@@ -328,6 +350,8 @@ test_archive_string_sprintf(void)
archive_string_empty(&s);
archive_string_sprintf(&s, "%d", 1234567890);
assertExactString(10, 8 * EXTENT, "1234567890", s);
+
+ archive_string_free(&s);
}
DEFINE_TEST(test_archive_string)
diff --git a/archivers/libarchive/files/libarchive/test/test_compat_gtar.c b/archivers/libarchive/files/libarchive/test/test_compat_gtar.c
index 3d5e456e56e..70669244efb 100644
--- a/archivers/libarchive/files/libarchive/test/test_compat_gtar.c
+++ b/archivers/libarchive/files/libarchive/test/test_compat_gtar.c
@@ -106,10 +106,50 @@ test_compat_gtar_1(void)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
+/*
+ * test_compat_gtar_2.tar exercises reading of UID = 2097152 as base256
+ * and GID = 2097152 as octal without null terminator.
+ */
+static void
+test_compat_gtar_2(void)
+{
+ char name[] = "test_compat_gtar_2.tar";
+ struct archive_entry *ae;
+ struct archive *a;
+ int r;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ extract_reference_file(name);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
+
+ /* Read first entry. */
+ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
+ if (r != ARCHIVE_OK) {
+ archive_read_free(a);
+ return;
+ }
+
+ /* Check UID and GID */
+ assertEqualInt(2097152, archive_entry_uid(ae));
+ assertEqualInt(2097152, archive_entry_gid(ae));
+
+ /* Verify the end-of-archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify that the format detection worked. */
+ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
DEFINE_TEST(test_compat_gtar)
{
test_compat_gtar_1();
+ test_compat_gtar_2();
}
diff --git a/archivers/libarchive/files/libarchive/test/test_compat_solaris_tar_acl.c b/archivers/libarchive/files/libarchive/test/test_compat_solaris_tar_acl.c
index a0cf9a8ad8f..81597729067 100644
--- a/archivers/libarchive/files/libarchive/test/test_compat_solaris_tar_acl.c
+++ b/archivers/libarchive/files/libarchive/test/test_compat_solaris_tar_acl.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,104 +24,242 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/test/test_compat_solaris_tar_acl.c 201247 2009-12-30 05:59:21Z kientzle $");
+__FBSDID("$FreeBSD$");
/*
- * Exercise support for reading Solaris-style ACL data
- * from tar archives.
+ * Verify reading entries with POSIX.1e and NFSv4 ACLs from archives created
+ * with Solaris tar.
*
- * This should work on all systems, regardless of whether local
- * filesystems support ACLs or not.
+ * This should work on all systems, regardless of whether local filesystems
+ * support ACLs or not.
*/
+static struct archive_test_acl_t acls0[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
+ ARCHIVE_ENTRY_ACL_USER, 71, "lp" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER, 666, "666" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER, 1000, "1000" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_MASK, -1, ""},
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
+};
+
+static struct archive_test_acl_t acls1[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER, 2, "bin" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_GROUP, 3, "sys" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_MASK, -1, ""},
+ { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
+ ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
+};
+
+static struct archive_test_acl_t acls2[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, -1 ,"" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_USER, 2, "bin" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_GROUP, 3, "sys" },
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ,
+ ARCHIVE_ENTRY_ACL_MASK, -1, ""},
+ { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0,
+ ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
+};
+
+static struct archive_test_acl_t acls3[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_DENY,
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP, 12, "daemon" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP, 2, "bin" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER, 4, "adm" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
+};
+
+static struct archive_test_acl_t acls4[] = {
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
+ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
+ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
+ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
+ ARCHIVE_ENTRY_ACL_USER, 1100, "1100" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
+ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
+ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
+ ARCHIVE_ENTRY_ACL_GROUP, 4, "adm" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA |
+ ARCHIVE_ENTRY_ACL_DELETE_CHILD |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_EXECUTE |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
+ { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
+ ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
+};
+
DEFINE_TEST(test_compat_solaris_tar_acl)
{
+ char name[] = "test_compat_solaris_tar_acl.tar";
struct archive *a;
struct archive_entry *ae;
- const char *reference1 = "test_compat_solaris_tar_acl.tar";
- int type, permset, tag, qual;
- const char *name;
- /* Sample file generated on Solaris 10 */
- extract_reference_file(reference1);
+ /* Read archive file */
assert(NULL != (a = archive_read_new()));
- assertA(0 == archive_read_support_format_all(a));
- assertA(0 == archive_read_support_filter_all(a));
- assertA(0 == archive_read_open_filename(a, reference1, 512));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ extract_reference_file(name);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name,
+ 10240));
- /* Archive has 1 entry with some ACLs set on it. */
+ /* First item has access ACLs */
assertA(0 == archive_read_next_header(a, &ae));
+ failure("One extended ACL should flag all ACLs to be returned.");
+ assertEqualInt(7, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0644);
failure("Basic ACLs should set mode to 0644, not %04o",
archive_entry_mode(ae)&0777);
- assertEqualInt((archive_entry_mode(ae) & 0777), 0644);
- assertEqualInt(7, archive_entry_acl_reset(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(006, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_USER_OBJ, tag);
- assertEqualInt(-1, qual);
- assert(name == NULL);
-
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(004, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_GROUP_OBJ, tag);
- assertEqualInt(-1, qual);
- assert(name == NULL);
+ assert((archive_entry_mode(ae) & 0777) == 0644);
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(004, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_OTHER, tag);
- assertEqualInt(-1, qual);
- assert(name == NULL);
-
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(001, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
- assertEqualInt(71, qual);
- assertEqualString(name, "lp");
-
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(004, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
- assertEqualInt(666, qual);
- assertEqualString(name, "666");
-
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(007, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
- assertEqualInt(1000, qual);
- assertEqualString(name, "trasz");
+ /* Second item has default and access ACLs */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0750);
+ failure("Basic ACLs should set mode to 0750, not %04o",
+ archive_entry_mode(ae)&0777);
+ assert((archive_entry_mode(ae) & 0777) == 0750);
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0750);
- assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
- assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
- assertEqualInt(004, permset);
- assertEqualInt(ARCHIVE_ENTRY_ACL_MASK, tag);
- assertEqualInt(-1, qual);
- assertEqualString(name, NULL);
+ /* Third item has NFS4 ACLs */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(6, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4));
+ assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
- assertEqualInt(ARCHIVE_EOF, archive_entry_acl_next(ae,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- &type, &permset, &tag, &qual, &name));
+ /* Fourth item has NFS4 ACLs and inheritance flags */
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_acl_reset(ae,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4));
+ assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
diff --git a/archivers/libarchive/files/libarchive/test/test_fuzz.c b/archivers/libarchive/files/libarchive/test/test_fuzz.c
index 76fda6282fa..ce7b8663fae 100644
--- a/archivers/libarchive/files/libarchive/test/test_fuzz.c
+++ b/archivers/libarchive/files/libarchive/test/test_fuzz.c
@@ -104,29 +104,44 @@ test_fuzz(const struct files *filesets)
}
if (!assert(size < buffsize)) {
free(rawimage);
+ rawimage = NULL;
continue;
}
} else {
for (i = 0; filesets[n].names[i] != NULL; ++i)
{
+ char *newraw;
tmp = slurpfile(&size, filesets[n].names[i]);
- rawimage = (char *)realloc(rawimage, oldsize + size);
+ newraw = realloc(rawimage, oldsize + size);
+ if (!assert(newraw != NULL))
+ {
+ free(rawimage);
+ rawimage = NULL;
+ free(tmp);
+ continue;
+ }
+ rawimage = newraw;
memcpy(rawimage + oldsize, tmp, size);
oldsize += size;
size = oldsize;
free(tmp);
- if (!assert(rawimage != NULL))
- continue;
}
}
- if (size == 0)
+ if (size == 0) {
+ free(rawimage);
+ rawimage = NULL;
continue;
+ }
image = malloc(size);
assert(image != NULL);
if (image == NULL) {
free(rawimage);
+ rawimage = NULL;
return;
}
+
+ assert(rawimage != NULL);
+
srand((unsigned)time(NULL));
for (i = 0; i < 1000; ++i) {
@@ -158,6 +173,7 @@ test_fuzz(const struct files *filesets)
Sleep(100);
#endif
}
+ assert(f != NULL);
assertEqualInt((size_t)size, fwrite(image, 1, (size_t)size, f));
fclose(f);
@@ -191,7 +207,7 @@ test_fuzz(const struct files *filesets)
archive_read_close(a);
}
archive_read_free(a);
-}
+ }
free(image);
free(rawimage);
}
@@ -391,10 +407,12 @@ DEFINE_TEST(test_fuzz_tar)
"test_read_format_tar_empty_filename.tar",
NULL
};
+#if HAVE_LIBLZO2 && HAVE_LZO_LZO1X_H && HAVE_LZO_LZOCONF_H
static const char *fileset9[] = {
"test_compat_lzop_1.tar.lzo",
NULL
};
+#endif
static const struct files filesets[] = {
{0, fileset1}, /* Exercise bzip2 decompressor. */
{1, fileset1},
@@ -405,7 +423,9 @@ DEFINE_TEST(test_fuzz_tar)
{0, fileset6}, /* Exercise xz decompressor. */
{0, fileset7},
{0, fileset8},
+#if HAVE_LIBLZO2 && HAVE_LZO_LZO1X_H && HAVE_LZO_LZOCONF_H
{0, fileset9}, /* Exercise lzo decompressor. */
+#endif
{1, NULL}
};
test_fuzz(filesets);
diff --git a/archivers/libarchive/files/libarchive/test/test_pax_filename_encoding.c b/archivers/libarchive/files/libarchive/test/test_pax_filename_encoding.c
index 2d4515e1b3c..2fb7f452d54 100644
--- a/archivers/libarchive/files/libarchive/test/test_pax_filename_encoding.c
+++ b/archivers/libarchive/files/libarchive/test/test_pax_filename_encoding.c
@@ -347,7 +347,7 @@ DEFINE_TEST(test_pax_filename_encoding_KOI8R)
return;
}
- /* Check if the paltform completely supports the string conversion. */
+ /* Check if the platform completely supports the string conversion. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
@@ -394,7 +394,7 @@ DEFINE_TEST(test_pax_filename_encoding_CP1251)
return;
}
- /* Check if the paltform completely supports the string conversion. */
+ /* Check if the platform completely supports the string conversion. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
@@ -440,7 +440,7 @@ DEFINE_TEST(test_pax_filename_encoding_EUCJP)
return;
}
- /* Check if the paltform completely supports the string conversion. */
+ /* Check if the platform completely supports the string conversion. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
@@ -488,7 +488,7 @@ DEFINE_TEST(test_pax_filename_encoding_CP932)
return;
}
- /* Check if the paltform completely supports the string conversion. */
+ /* Check if the platform completely supports the string conversion. */
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
diff --git a/archivers/libarchive/files/libarchive/test/test_read_disk.c b/archivers/libarchive/files/libarchive/test/test_read_disk.c
index bd36c396a1a..43d7d86bab2 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_disk.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_disk.c
@@ -61,6 +61,7 @@ uname_lookup(void *d, int64_t u)
return ("NOTFOO");
}
+#if !defined(__CYGWIN__) && !defined(__HAIKU__)
/* We test GID lookup by looking up the name of group number zero and
* checking it against the following list. If your system uses a
* different conventional name for group number zero, please extend
@@ -71,13 +72,16 @@ static const char *zero_groups[] = {
"root", /* Linux */
"wheel" /* BSD */
};
+#endif
DEFINE_TEST(test_read_disk)
{
struct archive *a;
int gmagic = 0x13579, umagic = 0x1234;
+#if !defined(__CYGWIN__) && !defined(__HAIKU__)
const char *p;
size_t i;
+#endif
assert((a = archive_read_disk_new()) != NULL);
@@ -115,8 +119,6 @@ DEFINE_TEST(test_read_disk)
/* Some platforms don't have predictable names for
* uid=0, so we skip this part of the test. */
skipping("standard uname/gname lookup");
- i = 0;
- p = zero_groups[0]; /* avoid unused warnings */
#else
/* XXX Someday, we may need to generalize this the
* same way we generalized the group name check below.
diff --git a/archivers/libarchive/files/libarchive/test/test_read_disk_directory_traversals.c b/archivers/libarchive/files/libarchive/test/test_read_disk_directory_traversals.c
index c16b0c65311..fdbfbec91e9 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_disk_directory_traversals.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_disk_directory_traversals.c
@@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
#endif
/*
- * Test if the current filesytem is mounted with noatime option.
+ * Test if the current filesystem is mounted with noatime option.
*/
static int
atimeIsUpdated(void)
@@ -500,8 +500,8 @@ test_basic(void)
/*
* We should be on the initial directory where we performed
- * archive_read_disk_new() after we perfome archive_read_free()
- * even if we broke off the directory traversals.
+ * archive_read_disk_new() after we perform archive_read_free()
+ * even if we broke off the directory traversals.
*/
/* Save current working directory. */
@@ -1228,8 +1228,8 @@ test_restore_atime(void)
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
- * Test4: Traversals with archive_read_disk_set_atime_restored() and
- * archive_read_disk_honor_nodump().
+ * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
+ * ARCHIVE_READDISK_HONOR_NODUMP
*/
assertNodump("at/f1");
assertNodump("at/f2");
@@ -1320,13 +1320,16 @@ test_callbacks(void)
assertUtimes("cb", 886622, 0, 886622, 0);
assert((ae = archive_entry_new()) != NULL);
- if (assert((a = archive_read_disk_new()) != NULL)) {
+ assert((a = archive_read_disk_new()) != NULL);
+ if (a == NULL) {
archive_entry_free(ae);
return;
}
- if (assert((m = archive_match_new()) != NULL)) {
+ assert((m = archive_match_new()) != NULL);
+ if (m == NULL) {
archive_entry_free(ae);
archive_read_free(a);
+ archive_match_free(m);
return;
}
@@ -1376,6 +1379,10 @@ test_callbacks(void)
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ /* Reset name filter */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_disk_set_matching(a, NULL, NULL, NULL));
+
/*
* Test2: Traversals with a metadata filter.
*/
@@ -1393,7 +1400,7 @@ test_callbacks(void)
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
- failure("File 'cb/f1' should be exclueded");
+ failure("File 'cb/f1' should be excluded");
assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
@@ -1453,7 +1460,7 @@ test_nodump(void)
assert((a = archive_read_disk_new()) != NULL);
/*
- * Test1: Traversals without archive_read_disk_honor_nodump().
+ * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
@@ -1506,7 +1513,7 @@ test_nodump(void)
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
- * Test2: Traversals with archive_read_disk_honor_nodump().
+ * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
*/
assertUtimes("nd/f1", 886600, 0, 886600, 0);
assertUtimes("nd/f2", 886611, 0, 886611, 0);
@@ -1564,11 +1571,11 @@ DEFINE_TEST(test_read_disk_directory_traversals)
{
/* Basic test. */
test_basic();
- /* Test hybird mode; follow symlink initially, then not. */
+ /* Test hybrid mode; follow symlink initially, then not. */
test_symlink_hybrid();
- /* Test logcal mode; follow all symlinks. */
+ /* Test logical mode; follow all symlinks. */
test_symlink_logical();
- /* Test logcal mode; prevent loop in symlinks. */
+ /* Test logical mode; prevent loop in symlinks. */
test_symlink_logical_loop();
/* Test to restore atime. */
test_restore_atime();
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_7zip.c b/archivers/libarchive/files/libarchive/test/test_read_format_7zip.c
index 14447def898..1d1e4c75d2d 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_7zip.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_7zip.c
@@ -688,7 +688,7 @@ test_symname()
assertEqualInt(32, archive_read_data(a, buff, sizeof(buff)));
assertEqualMem(buff, "hellohellohello\nhellohellohello\n", 32);
- /* Verify symbolic-linke symlinkfile. */
+ /* Verify symbolic-link symlinkfile. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualInt((AE_IFLNK | 0755), archive_entry_mode(ae));
assertEqualString("symlinkfile", archive_entry_pathname(ae));
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_cpio_afio.c b/archivers/libarchive/files/libarchive/test/test_read_format_cpio_afio.c
index 16065eb0a51..95d3171e72c 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_cpio_afio.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_cpio_afio.c
@@ -27,7 +27,7 @@
__FBSDID("$FreeBSD$");
/*
-ecute the following to rebuild the data for this program:
+execute the following to rebuild the data for this program:
tail -n +33 test_read_format_cpio_afio.c | /bin/sh
# How to make a sample data.
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_isorr_bz2.c b/archivers/libarchive/files/libarchive/test/test_read_format_isorr_bz2.c
index d2dfa2e5f79..fb4f4a853ab 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_isorr_bz2.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_isorr_bz2.c
@@ -26,7 +26,7 @@
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_isorr_bz2.c 201247 2009-12-30 05:59:21Z kientzle $");
/*
-PLEASE use old cdrtools; mkisofs verion is 2.01.
+PLEASE use old cdrtools; mkisofs version is 2.01.
This version mkisofs made wrong "SL" System Use Entry of RRIP.
Execute the following command to rebuild the data for this program:
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_rar.c b/archivers/libarchive/files/libarchive/test/test_read_format_rar.c
index 587032309c4..6392d8f50ff 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_rar.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_rar.c
@@ -3603,7 +3603,7 @@ DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files)
assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff)));
/*
- * Eigth header.
+ * Eighth header.
*/
assertA(0 == archive_read_next_header(a, &ae));
assertEqualString("testdir/testsymlink6", archive_entry_pathname(ae));
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_raw.c b/archivers/libarchive/files/libarchive/test/test_read_format_raw.c
index 1310090cbc6..831bcec11de 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_raw.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_raw.c
@@ -35,6 +35,7 @@ DEFINE_TEST(test_read_format_raw)
struct archive *a;
const char *reffile1 = "test_read_format_raw.data";
const char *reffile2 = "test_read_format_raw.data.Z";
+ const char *reffile3 = "test_read_format_raw.bufr";
/* First, try pulling data out of an uninterpretable file. */
extract_reference_file(reffile1);
@@ -90,4 +91,30 @@ DEFINE_TEST(test_read_format_raw)
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+
+ /* Third, try with file which fooled us in past - appeared to be tar. */
+ extract_reference_file(reffile3);
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, reffile3, 1));
+
+ /* First (and only!) Entry */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("data", archive_entry_pathname(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
+ /* Most fields should be unset (unknown) */
+ assert(!archive_entry_size_is_set(ae));
+ assert(!archive_entry_atime_is_set(ae));
+ assert(!archive_entry_ctime_is_set(ae));
+ assert(!archive_entry_mtime_is_set(ae));
+
+ /* Test EOF */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip.c
index da5b13787ed..cea2676f3ea 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_zip.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip.c
@@ -126,6 +126,7 @@ test_basic(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
verify_basic(a, 0);
+ free(p);
}
/*
@@ -195,6 +196,7 @@ test_info_zip_ux(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108));
verify_info_zip_ux(a, 0);
+ free(p);
}
/*
@@ -258,6 +260,7 @@ test_extract_length_at_end(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108));
verify_extract_length_at_end(a, 0);
+ free(p);
}
static void
@@ -294,6 +297,8 @@ test_symlink(void)
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);
}
DEFINE_TEST(test_read_format_zip)
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip_comment_stored.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip_comment_stored.c
index d2b935de2d4..b92b2886cdd 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_zip_comment_stored.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_comment_stored.c
@@ -63,6 +63,8 @@ verify(const char *refname)
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
+
+ free(p);
}
DEFINE_TEST(test_read_format_zip_comment_stored)
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip_filename.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip_filename.c
index 93ba09b3ebb..4dd2e8ad6e8 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_zip_filename.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_filename.c
@@ -1116,7 +1116,7 @@ cleanup:
* - the filename of second file is stored in UTF-8.
*
* Whenever hdrcharset option is specified, we will correctly read the
- * filename of sencod file, which is stored in UTF-8.
+ * filename of second file, which is stored in UTF-8.
*/
DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2)
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_zip_mac_metadata.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip_mac_metadata.c
index 97aa427b034..99b7012328c 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_zip_mac_metadata.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_mac_metadata.c
@@ -112,4 +112,6 @@ DEFINE_TEST(test_read_format_zip_mac_metadata)
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_sfx.c b/archivers/libarchive/files/libarchive/test/test_read_format_zip_sfx.c
index d5992d39565..dc76ef9b382 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_zip_sfx.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_zip_sfx.c
@@ -60,4 +60,6 @@ DEFINE_TEST(test_read_format_zip_sfx)
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_sparse_basic.c b/archivers/libarchive/files/libarchive/test/test_sparse_basic.c
index 3cea4595c95..9d45f0fedc1 100644
--- a/archivers/libarchive/files/libarchive/test/test_sparse_basic.c
+++ b/archivers/libarchive/files/libarchive/test/test_sparse_basic.c
@@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$");
/*
* NOTE: On FreeBSD and Solaris, this test needs ZFS.
- * You may should perfom this test as
+ * You may perform this test as
* 'TMPDIR=<a directory on the ZFS> libarchive_test'.
*/
@@ -146,28 +146,14 @@ create_sparse_file(const char *path, const struct sparse *s)
#else
-#if defined(_PC_MIN_HOLE_SIZE)
-
-/*
- * FreeBSD and Solaris can detect 'hole' of a sparse file
- * through lseek(HOLE) on ZFS. (UFS does not support yet)
- */
-
-static int
-is_sparse_supported(const char *path)
-{
- return (pathconf(path, _PC_MIN_HOLE_SIZE) > 0);
-}
-
-#elif defined(__linux__)&& defined(HAVE_LINUX_FIEMAP_H)
-
+#if defined(HAVE_LINUX_FIEMAP_H)
/*
* FIEMAP, which can detect 'hole' of a sparse file, has
* been supported from 2.6.28
*/
static int
-is_sparse_supported(const char *path)
+is_sparse_supported_fiemap(const char *path)
{
const struct sparse sparse_file[] = {
/* This hole size is too small to create a sparse
@@ -198,7 +184,58 @@ is_sparse_supported(const char *path)
return (r >= 0);
}
-#else
+#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
+static int
+is_sparse_supported(const char *path)
+{
+ return is_sparse_supported_fiemap(path);
+}
+#endif
+#endif
+
+#if defined(_PC_MIN_HOLE_SIZE)
+
+/*
+ * FreeBSD and Solaris can detect 'hole' of a sparse file
+ * through lseek(HOLE) on ZFS. (UFS does not support yet)
+ */
+
+static int
+is_sparse_supported(const char *path)
+{
+ return (pathconf(path, _PC_MIN_HOLE_SIZE) > 0);
+}
+
+#elif defined(SEEK_HOLE) && defined(SEEK_DATA)
+
+static int
+is_sparse_supported(const char *path)
+{
+ const struct sparse sparse_file[] = {
+ /* This hole size is too small to create a sparse
+ * files for almost filesystem. */
+ { HOLE, 1024 }, { DATA, 10240 },
+ { END, 0 }
+ };
+ int fd, r;
+ const char *testfile = "can_sparse";
+
+ (void)path; /* UNUSED */
+ create_sparse_file(testfile, sparse_file);
+ fd = open(testfile, O_RDWR);
+ if (fd < 0)
+ return (0);
+ r = lseek(fd, 0, SEEK_HOLE);
+ close(fd);
+ unlink(testfile);
+#if defined(HAVE_LINUX_FIEMAP_H)
+ if (r < 0)
+ return (is_sparse_supported_fiemap(path));
+#endif
+ return (r >= 0);
+}
+
+#elif !defined(HAVE_LINUX_FIEMAP_H)
/*
* Other system may do not have the API such as lseek(HOLE),
diff --git a/archivers/libarchive/files/libarchive/test/test_write_disk_appledouble.c b/archivers/libarchive/files/libarchive/test/test_write_disk_appledouble.c
index 81032fca9cd..706794ab95b 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_disk_appledouble.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_disk_appledouble.c
@@ -144,7 +144,7 @@ DEFINE_TEST(test_write_disk_appledouble)
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("./file3", archive_entry_pathname(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
- /* Extract ._file3 which will be merged into file3 as medtadata. */
+ /* Extract ._file3 which will be merged into file3 as metadata. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("./._file3", archive_entry_pathname(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
@@ -203,7 +203,7 @@ DEFINE_TEST(test_write_disk_appledouble)
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("./file3", archive_entry_pathname(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
- /* Extract ._file3 which will be merged into file3 as medtadata. */
+ /* Extract ._file3 which will be merged into file3 as metadata. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("./._file3", archive_entry_pathname(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
diff --git a/archivers/libarchive/files/libarchive/test/test_write_filter_lzop.c b/archivers/libarchive/files/libarchive/test/test_write_filter_lzop.c
index a32932c6977..92db7bf3dc4 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_filter_lzop.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_filter_lzop.c
@@ -43,12 +43,12 @@ DEFINE_TEST(test_write_filter_lzop)
assert((a = archive_write_new()) != NULL);
r = archive_write_add_filter_lzop(a);
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
if (r != ARCHIVE_OK) {
if (canLzop() && r == ARCHIVE_WARN)
use_prog = 1;
else {
skipping("lzop writing not supported on this platform");
- assertEqualInt(ARCHIVE_OK, archive_write_free(a));
return;
}
}
@@ -92,7 +92,7 @@ DEFINE_TEST(test_write_filter_lzop)
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
r = archive_read_support_filter_lzop(a);
- if (r == ARCHIVE_WARN) {
+ if (r == ARCHIVE_WARN && !use_prog) {
skipping("Can't verify lzop writing by reading back;"
" lzop reading not fully supported on this platform");
} else {
@@ -212,7 +212,7 @@ DEFINE_TEST(test_write_filter_lzop)
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
r = archive_read_support_filter_lzop(a);
- if (r == ARCHIVE_WARN) {
+ if (r == ARCHIVE_WARN && !use_prog) {
skipping("lzop reading not fully supported on this platform");
} else {
assertEqualIntA(a, ARCHIVE_OK,
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_iso9660.c b/archivers/libarchive/files/libarchive/test/test_write_format_iso9660.c
index 1ea69a18359..e4e98bb95c2 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_format_iso9660.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_iso9660.c
@@ -117,8 +117,8 @@ DEFINE_TEST(test_write_format_iso9660)
*/
dirname[0] = '\0';
strcpy(dir, "/dir0");
- for (i = 0; i < 10; i++) {
- dir[4] = '0' + i;
+ for (i = 0; i < 13; i++) {
+ dir[4] = "0123456789ABCDEF"[i];
if (i == 0)
strcat(dirname, dir+1);
else
@@ -134,6 +134,19 @@ DEFINE_TEST(test_write_format_iso9660)
archive_entry_free(ae);
}
+ strcat(dirname, "/file");
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_atime(ae, 2, 20);
+ archive_entry_set_birthtime(ae, 3, 30);
+ archive_entry_set_ctime(ae, 4, 40);
+ archive_entry_set_mtime(ae, 5, 50);
+ archive_entry_copy_pathname(ae, dirname);
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_size(ae, 8);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
+
/*
* "dir0/dir1/file1" has 8 bytes of data.
*/
@@ -333,6 +346,45 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0555) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
* Read "hardlnk"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -386,6 +438,21 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file", archive_entry_pathname(ae));
+ assert((AE_IFREG | 0555) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -580,29 +647,65 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
- * Read "hardlnk"
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("hardlnk", archive_entry_pathname(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("file", archive_entry_pathname(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
- assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(8, archive_entry_size(ae));
assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
assertEqualMem(buff2, "12345678", 8);
/*
- * Read "file"
+ * Read "hardlnk"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("file", archive_entry_pathname(ae));
- assertEqualString("hardlnk", archive_entry_hardlink(ae));
+ assertEqualString("hardlnk", archive_entry_pathname(ae));
+ assertEqualString("file", archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualIntA(a, 0, archive_read_data(a, buff2, 10));
@@ -616,7 +719,7 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(5, archive_entry_ctime(ae));
assert(archive_entry_mtime_is_set(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- /* Trim lngname to 64 characters. */
+ /* Trim longname to 64 characters. */
longname[64] = '\0';
assertEqualString(longname, archive_entry_pathname(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
@@ -625,6 +728,22 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString(
+ "dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dirA/dirB/dirC/file",
+ archive_entry_pathname(ae));
+ assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -746,6 +865,42 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
+ * Read "rr_moved/dir7/dir8/dir9/dira"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "rr_moved/dir7/dir8/dir9/dira/dirB"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
+ * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString("RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC",
+ archive_entry_pathname(ae));
+ assert((S_IFDIR | 0700) == archive_entry_mode(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+
+ /*
* Read "dir0"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
@@ -827,33 +982,35 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualInt(2048, archive_entry_size(ae));
/*
- * Read "file"
+ * Read "hardlink"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
- assertEqualInt(0, archive_entry_birthtime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("FILE", archive_entry_pathname(ae));
+ assertEqualString("HARDLNK", archive_entry_pathname(ae));
+ assertEqualString(NULL, archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
- assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(8, archive_entry_size(ae));
assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
assertEqualMem(buff2, "12345678", 8);
/*
- * Read "hardlink"
+ * Read "file"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(0, archive_entry_birthtime(ae));
assertEqualInt(5, archive_entry_ctime(ae));
assertEqualInt(5, archive_entry_mtime(ae));
- assertEqualString("HARDLNK", archive_entry_pathname(ae));
- assertEqualString("FILE", archive_entry_hardlink(ae));
+ assertEqualString("FILE", archive_entry_pathname(ae));
+ assertEqualString("HARDLNK", archive_entry_hardlink(ae));
assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualIntA(a, 0, archive_read_data(a, buff2, 10));
+
/*
* Read longname
*/
@@ -871,6 +1028,22 @@ DEFINE_TEST(test_write_format_iso9660)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "rr_moved/dir7/dir8/dir9/dirA/dirB/dirC/file"
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(5, archive_entry_atime(ae));
+ assertEqualInt(5, archive_entry_ctime(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualString(
+ "RR_MOVED/DIR7/DIR8/DIR9/DIRA/DIRB/DIRC/FILE",
+ archive_entry_pathname(ae));
+ assert((AE_IFREG | 0400) == archive_entry_mode(ae));
+ assertEqualInt(1, archive_entry_nlink(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Read "dir0/dir1/file1"
*/
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_zip_empty.c b/archivers/libarchive/files/libarchive/test/test_write_format_zip_empty.c
index 2e3afec71fd..73a55731261 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_format_zip_empty.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_zip_empty.c
@@ -49,7 +49,7 @@ DEFINE_TEST(test_write_format_zip_empty)
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- /* Verify the correct format for an empy Zip archive. */
+ /* Verify the correct format for an empty Zip archive. */
assertEqualInt(used, 22);
assertEqualMem(buff,
"PK\005\006\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",