summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2008-02-11 00:31:09 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2008-02-11 00:31:09 +0000
commit8349d0ebaa6529a8bda62dbeec3edb6a70ff97b0 (patch)
treed495dce53e2594dbf992a0169d2a73a9e1608153 /lib
parentaf06cef1e44bdc5fe5b60018a24428a2d7908d9e (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/Makefile26
-rw-r--r--lib/libarchive/archive.h.in58
-rw-r--r--lib/libarchive/archive_entry.c31
-rw-r--r--lib/libarchive/archive_entry.h35
-rw-r--r--lib/libarchive/archive_entry_private.h2
-rw-r--r--lib/libarchive/archive_platform.h5
-rw-r--r--lib/libarchive/archive_read.c29
-rw-r--r--lib/libarchive/archive_read_extract.c10
-rw-r--r--lib/libarchive/archive_read_private.h3
-rw-r--r--lib/libarchive/archive_read_support_compression_none.c105
-rw-r--r--lib/libarchive/archive_read_support_format_all.c1
-rw-r--r--lib/libarchive/archive_read_support_format_ar.c8
-rw-r--r--lib/libarchive/archive_read_support_format_cpio.c184
-rw-r--r--lib/libarchive/archive_read_support_format_iso9660.c28
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c166
-rw-r--r--lib/libarchive/archive_read_support_format_zip.c155
-rw-r--r--lib/libarchive/archive_util.c2
-rw-r--r--lib/libarchive/archive_write_disk.c42
-rw-r--r--lib/libarchive/archive_write_set_compression_bzip2.c8
-rw-r--r--lib/libarchive/archive_write_set_compression_gzip.c8
-rw-r--r--lib/libarchive/archive_write_set_compression_none.c43
-rw-r--r--lib/libarchive/archive_write_set_format_ar.c28
-rw-r--r--lib/libarchive/archive_write_set_format_cpio.c1
-rw-r--r--lib/libarchive/archive_write_set_format_cpio_newc.c8
-rw-r--r--lib/libarchive/archive_write_set_format_pax.c13
-rw-r--r--lib/libarchive/archive_write_set_format_ustar.c13
-rw-r--r--lib/libarchive/filter_fork.c2
-rw-r--r--lib/libarchive/libarchive-formats.532
-rw-r--r--lib/libarchive/libarchive_internals.322
-rw-r--r--lib/libarchive/test/Makefile79
-rw-r--r--lib/libarchive/test/README12
-rw-r--r--lib/libarchive/test/main.c407
-rw-r--r--lib/libarchive/test/read_open_memory.c2
-rw-r--r--lib/libarchive/test/test.h104
-rw-r--r--lib/libarchive/test/test_compat_gtar_1.tgz.uu1
-rw-r--r--lib/libarchive/test/test_compat_zip_1.zip.uu1
-rw-r--r--lib/libarchive/test/test_read_format_cpio_odc.c2
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse.c699
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_13.tgz.uu1
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_17.tgz.uu1
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tgz.uu1
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tgz.uu1
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tgz.uu1
-rw-r--r--lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu1
-rw-r--r--lib/libarchive/test/test_read_format_isorr_bz2.c3
-rw-r--r--lib/libarchive/test/test_read_format_tar.c47
-rw-r--r--lib/libarchive/test/test_read_format_zip.c6
-rw-r--r--lib/libarchive/test/test_read_pax_truncated.c4
-rw-r--r--lib/libarchive/test/test_tar_filenames.c2
-rw-r--r--lib/libarchive/test/test_write_disk.c23
-rw-r--r--lib/libarchive/test/test_write_disk_perms.c33
-rw-r--r--lib/libarchive/test/test_write_format_cpio.c94
-rw-r--r--lib/libarchive/test/test_write_format_cpio_newc.c1
-rw-r--r--lib/libarchive/test/test_write_format_cpio_odc.c1
54 files changed, 1428 insertions, 1167 deletions
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 1ebc8e1b4612..bd59b2ae7aa4 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -9,22 +9,16 @@ LDADD= -lbz2 -lz
# Major: Bumped ONLY when API/ABI breakage happens (see SHLIB_MAJOR)
# Minor: Bumped when significant new features are added
# Revision: Bumped on any notable change
-VERSION= 2.2.4
-ARCHIVE_API_MAJOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/\..*//'
-ARCHIVE_API_MINOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/[0-9]*\.//' -e 's/\..*//'
-ARCHIVE_API_REV!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/.*\.//'
-
-# Can't use /usr/bin/printf to format the version stamp here, because
-# that's not available during installworld. Fortunately, awk is.
-ARCHIVE_VERSION_STAMP!= echo ${ARCHIVE_API_MAJOR} ${ARCHIVE_API_MINOR} ${ARCHIVE_API_REV} | awk '{printf("%d%03d%03d",$$1,$$2,$$3)}'
+# The useful version number (one integer, easy to compare)
+LIBARCHIVE_VERSION= 2004012
+# The pretty version string
+LIBARCHIVE_VERSION_STRING!= echo $$((${LIBARCHIVE_VERSION} / 1000000)).$$((${LIBARCHIVE_VERSION} / 1000 % 1000)).$$((${LIBARCHIVE_VERSION} % 1000))
# FreeBSD SHLIB_MAJOR value is managed as part of the FreeBSD system.
# It has no real relation to the version number above.
SHLIB_MAJOR= 4
-CFLAGS+= -DPACKAGE_NAME=\"lib${LIB}\"
-CFLAGS+= -DPACKAGE_VERSION=\"${VERSION}\"
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
CFLAGS+= -I${.OBJDIR}
@@ -37,11 +31,9 @@ INCS= archive.h archive_entry.h
# Note: FreeBSD has inttypes.h, so enable that include in archive.h.in
archive.h: archive.h.in Makefile
cat ${.CURDIR}/archive.h.in | sed \
- -e 's/@ARCHIVE_VERSION@/${VERSION}/g' \
+ -e 's/@LIBARCHIVE_VERSION@/${LIBARCHIVE_VERSION}/g' \
+ -e 's/@LIBARCHIVE_VERSION_STRING@/${LIBARCHIVE_VERSION_STRING}/g' \
-e 's/@SHLIB_MAJOR@/${SHLIB_MAJOR}/g' \
- -e 's/@ARCHIVE_API_MAJOR@/${ARCHIVE_API_MAJOR}/g' \
- -e 's/@ARCHIVE_API_MINOR@/${ARCHIVE_API_MINOR}/g' \
- -e 's/@ARCHIVE_VERSION_STAMP@/${ARCHIVE_VERSION_STAMP}/g' \
-e 's|@ARCHIVE_H_INCLUDE_INTTYPES_H@|#include <inttypes.h> /* For int64_t */|g' \
> archive.h
@@ -54,6 +46,8 @@ SRCS= archive.h \
archive_entry.c \
archive_entry_copy_stat.c \
archive_entry_stat.c \
+ archive_entry_strmode.c \
+ archive_entry_link_resolver.c \
archive_read.c \
archive_read_data_into_fd.c \
archive_read_extract.c \
@@ -72,6 +66,7 @@ SRCS= archive.h \
archive_read_support_format_cpio.c \
archive_read_support_format_empty.c \
archive_read_support_format_iso9660.c \
+ archive_read_support_format_mtree.c \
archive_read_support_format_tar.c \
archive_read_support_format_zip.c \
archive_string.c \
@@ -105,6 +100,7 @@ MAN= archive_entry.3 \
archive_util.3 \
archive_write.3 \
archive_write_disk.3 \
+ cpio.5 \
libarchive.3 \
libarchive-formats.5 \
tar.5
@@ -246,7 +242,7 @@ MLINKS+= archive_write_disk.3 archive_write_disk_set_standard_lookup.3
MLINKS+= archive_write_disk.3 archive_write_disk_set_user_lookup.3
MLINKS+= libarchive.3 archive.3
-test:
+check:
cd ${.CURDIR}/test && make test
.include <bsd.lib.mk>
diff --git a/lib/libarchive/archive.h.in b/lib/libarchive/archive.h.in
index bf90f4a53fd7..22e3888ec7d5 100644
--- a/lib/libarchive/archive.h.in
+++ b/lib/libarchive/archive.h.in
@@ -60,40 +60,10 @@ extern "C" {
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_LIBRARY_VERSION "libarchive @ARCHIVE_VERSION@"
+#define ARCHIVE_LIBRARY_VERSION "libarchive @LIBARCHIVE_VERSION_STRING@"
const char * archive_version(void);
/*
- * Major version number: If ARCHIVE_API_VERSION !=
- * archive_api_version(), then the library you were linked with is
- * using an incompatible API to the one you were compiled with. This
- * is almost certainly a fatal problem.
- */
-#define ARCHIVE_API_VERSION @ARCHIVE_API_MAJOR@
-int archive_api_version(void);
-
-/*
- * Minor version number: ARCHIVE_API_FEATURE is incremented with each
- * significant feature addition, so you can test (at compile or run
- * time) if a particular feature is implemented. It's no big deal if
- * ARCHIVE_API_FEATURE != archive_api_feature(), as long as both are
- * high enough to include the features you're relying on. Specific
- * values of FEATURE are documented here:
- *
- * 1 - Version tests are available.
- * 2 - archive_{read,write}_close available separately from _finish.
- * 3 - open_memory, open_memory2, open_FILE, open_fd available
- * 5 - archive_write_disk interface available
- *
- * Unfortunately, this count resets whenever ARCHIVE_API_VERSION changes,
- * making it awkward to use in practice. For that reason, it is deprecated
- * in favor of the more-accurate version stamp below. It will eventually
- * be removed.
- */
-#define ARCHIVE_API_FEATURE @ARCHIVE_API_MINOR@
-int archive_api_feature(void);
-
-/*
* The "version stamp" is a single integer that makes it easy to check
* the exact version: for version a.b.c, the version stamp is
* printf("%d%03d%03d",a,b,c). For example, version 2.12.108 has
@@ -102,16 +72,34 @@ int archive_api_feature(void);
* This was introduced with libarchive 1.9.0 in the libarchive 1.x family
* and libarchive 2.2.4 in the libarchive 2.x family. The following
* may be useful if you really want to do feature detection for earlier
- * libarchive versions:
+ * libarchive versions (which defined API_VERSION and API_FEATURE):
*
* #ifndef ARCHIVE_VERSION_STAMP
* #define ARCHIVE_VERSION_STAMP \
* (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
* #endif
*/
-#define ARCHIVE_VERSION_STAMP @ARCHIVE_VERSION_STAMP@
+#define ARCHIVE_VERSION_STAMP @LIBARCHIVE_VERSION@
int archive_version_stamp(void);
+/*
+ * Major version number: If ARCHIVE_API_VERSION !=
+ * archive_api_version(), then the library you were linked with is
+ * using an incompatible API to the one you were compiled with. This
+ * is almost certainly a fatal problem.
+ * This is deprecated and will be removed; use ARCHIVE_VERSION_STAMP
+ * instead.
+ */
+#define ARCHIVE_API_VERSION (ARCHIVE_VERSION_STAMP / 1000000)
+int archive_api_version(void);
+
+/*
+ * Minor version number. This is deprecated and will be removed.
+ * Use ARCHIVE_VERSION_STAMP to adapt to libarchive API variations.
+ */
+#define ARCHIVE_API_FEATURE ((ARCHIVE_VERSION_STAMP / 1000) % 1000)
+int archive_api_feature(void);
+
#define ARCHIVE_BYTES_PER_RECORD 512
#define ARCHIVE_DEFAULT_BYTES_PER_BLOCK 10240
@@ -218,6 +206,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FORMAT_AR 0x70000
#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1)
#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2)
+#define ARCHIVE_FORMAT_MTREE 0x80000
+#define ARCHIVE_FORMAT_MTREE_V1 (ARCHIVE_FORMAT_MTREE | 1)
+#define ARCHIVE_FORMAT_MTREE_V2 (ARCHIVE_FORMAT_MTREE | 2)
/*-
* Basic outline for reading an archive:
@@ -254,6 +245,7 @@ int archive_read_support_format_cpio(struct archive *);
int archive_read_support_format_empty(struct archive *);
int archive_read_support_format_gnutar(struct archive *);
int archive_read_support_format_iso9660(struct archive *);
+int archive_read_support_format_mtree(struct archive *);
int archive_read_support_format_tar(struct archive *);
int archive_read_support_format_zip(struct archive *);
diff --git a/lib/libarchive/archive_entry.c b/lib/libarchive/archive_entry.c
index 3f6984d72014..34c91162fc20 100644
--- a/lib/libarchive/archive_entry.c
+++ b/lib/libarchive/archive_entry.c
@@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
-# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
-# define makedev mkdev
-# endif
#else
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
@@ -74,6 +71,22 @@ __FBSDID("$FreeBSD$");
#undef max
#define max(a, b) ((a)>(b)?(a):(b))
+/* Play games to come up with a suitable makedev() definition. */
+#ifdef __QNXNTO__
+/* QNX. <sigh> */
+#include <sys/netmgr.h>
+#define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
+#elif defined makedev
+/* There's a "makedev" macro. */
+#define ae_makedev(maj, min) makedev((maj), (min))
+#elif defined mkdev || defined _WIN32 || defined __WIN32__
+/* Windows. <sigh> */
+#define ae_makedev(maj, min) mkdev((maj), (min))
+#else
+/* There's a "makedev" function. */
+#define ae_makedev(maj, min) makedev((maj), (min))
+#endif
+
static void aes_clean(struct aes *);
static void aes_copy(struct aes *dest, struct aes *src);
static const char * aes_get_mbs(struct aes *);
@@ -402,7 +415,7 @@ dev_t
archive_entry_dev(struct archive_entry *entry)
{
if (entry->ae_stat.aest_dev_is_broken_down)
- return makedev(entry->ae_stat.aest_devmajor,
+ return ae_makedev(entry->ae_stat.aest_devmajor,
entry->ae_stat.aest_devminor);
else
return (entry->ae_stat.aest_dev);
@@ -548,7 +561,7 @@ dev_t
archive_entry_rdev(struct archive_entry *entry)
{
if (entry->ae_stat.aest_rdev_is_broken_down)
- return makedev(entry->ae_stat.aest_rdevmajor,
+ return ae_makedev(entry->ae_stat.aest_rdevmajor,
entry->ae_stat.aest_rdevminor);
else
return (entry->ae_stat.aest_rdev);
@@ -780,6 +793,14 @@ archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
}
void
+archive_entry_set_perm(struct archive_entry *entry, mode_t p)
+{
+ entry->stat_valid = 0;
+ entry->ae_stat.aest_mode &= AE_IFMT;
+ entry->ae_stat.aest_mode |= ~AE_IFMT & p;
+}
+
+void
archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
{
entry->stat_valid = 0;
diff --git a/lib/libarchive/archive_entry.h b/lib/libarchive/archive_entry.h
index 2f18d31cac47..173fbc30474e 100644
--- a/lib/libarchive/archive_entry.h
+++ b/lib/libarchive/archive_entry.h
@@ -62,6 +62,7 @@ struct archive_entry;
#define AE_IFMT 0170000
#define AE_IFREG 0100000
#define AE_IFLNK 0120000
+#define AE_IFSOCK 0140000
#define AE_IFCHR 0020000
#define AE_IFBLK 0060000
#define AE_IFDIR 0040000
@@ -108,6 +109,7 @@ dev_t archive_entry_rdev(struct archive_entry *);
dev_t archive_entry_rdevmajor(struct archive_entry *);
dev_t archive_entry_rdevminor(struct archive_entry *);
int64_t archive_entry_size(struct archive_entry *);
+const char *archive_entry_strmode(struct archive_entry *);
const char *archive_entry_symlink(struct archive_entry *);
const wchar_t *archive_entry_symlink_w(struct archive_entry *);
uid_t archive_entry_uid(struct archive_entry *);
@@ -148,6 +150,7 @@ void archive_entry_set_nlink(struct archive_entry *, unsigned int);
void archive_entry_set_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
+void archive_entry_set_perm(struct archive_entry *, mode_t);
void archive_entry_set_rdev(struct archive_entry *, dev_t);
void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
@@ -260,11 +263,6 @@ int archive_entry_acl_count(struct archive_entry *, int want_type);
int __archive_entry_acl_parse_w(struct archive_entry *,
const wchar_t *, int type);
-
-#ifdef __cplusplus
-}
-#endif
-
/*
* extended attributes
*/
@@ -283,5 +281,32 @@ int archive_entry_xattr_reset(struct archive_entry *);
int archive_entry_xattr_next(struct archive_entry *,
const char **name, const void **value, size_t *);
+/*
+ * Utility to detect hardlinks.
+ *
+ * The 'struct archive_hardlink_lookup' is a cache of entry
+ * names and dev/ino numbers. Here's how to use it:
+ * 1. Create a lookup object with archive_hardlink_lookup_new()
+ * 2. Hand each archive_entry to archive_hardlink_lookup().
+ * That function will return NULL (this is not a hardlink to
+ * a previous entry) or the pathname of the first entry
+ * that matched this.
+ * 3. Use archive_hardlink_lookup_free() to release the cache.
+ *
+ * To make things more efficient, be sure that each entry has a valid
+ * nlinks value. The hardlink cache uses this to track when all links
+ * have been found. If the nlinks value is zero, it will keep every
+ * name in the cache indefinitely, which can use a lot of memory.
+ */
+struct archive_entry_linkresolver;
+
+struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
+void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
+const char *archive_entry_linkresolve(struct archive_entry_linkresolver *,
+ struct archive_entry *);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */
diff --git a/lib/libarchive/archive_entry_private.h b/lib/libarchive/archive_entry_private.h
index 34b8e2666367..33e9d78c59c4 100644
--- a/lib/libarchive/archive_entry_private.h
+++ b/lib/libarchive/archive_entry_private.h
@@ -149,6 +149,8 @@ struct archive_entry {
struct ae_xattr *xattr_head;
struct ae_xattr *xattr_p;
+
+ char strmode[11];
};
diff --git a/lib/libarchive/archive_platform.h b/lib/libarchive/archive_platform.h
index cd48a83fce67..3f232803a6f1 100644
--- a/lib/libarchive/archive_platform.h
+++ b/lib/libarchive/archive_platform.h
@@ -57,7 +57,8 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h> /* For __FBSDID */
#else
-#define __FBSDID(a) /* null */
+/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+#define __FBSDID(a) struct _undefined_hack
#endif
/* Try to get standard C99-style integer type definitions. */
@@ -122,4 +123,4 @@
#define ARCHIVE_ERRNO_MISC (-1)
#endif
-#endif /* !ARCHIVE_H_INCLUDED */
+#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c
index e0763f291e89..1028c5dc9b20 100644
--- a/lib/libarchive/archive_read.c
+++ b/lib/libarchive/archive_read.c
@@ -307,6 +307,18 @@ archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
archive_clear_error(&a->archive);
/*
+ * If no format has yet been chosen, choose one.
+ */
+ if (a->format == NULL) {
+ slot = choose_format(a);
+ if (slot < 0) {
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ a->format = &(a->formats[slot]);
+ }
+
+ /*
* If client didn't consume entire data, skip any remainder
* (This is especially important for GNU incremental directories.)
*/
@@ -324,12 +336,6 @@ archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
/* Record start-of-header. */
a->header_position = a->archive.file_position;
- slot = choose_format(a);
- if (slot < 0) {
- a->archive.state = ARCHIVE_STATE_FATAL;
- return (ARCHIVE_FATAL);
- }
- a->format = &(a->formats[slot]);
ret = (a->format->read_header)(a, entry);
/*
@@ -735,3 +741,14 @@ __archive_read_register_compression(struct archive_read *a,
__archive_errx(1, "Not enough slots for compression registration");
return (NULL); /* Never actually executed. */
}
+
+/* used internally to simplify read-ahead */
+const void *
+__archive_read_ahead(struct archive_read *a, size_t len)
+{
+ const void *h;
+
+ if ((a->decompressor->read_ahead)(a, &h, len) < (ssize_t)len)
+ return (NULL);
+ return (h);
+}
diff --git a/lib/libarchive/archive_read_extract.c b/lib/libarchive/archive_read_extract.c
index c69c34f1c5de..5eb0d36bef8c 100644
--- a/lib/libarchive/archive_read_extract.c
+++ b/lib/libarchive/archive_read_extract.c
@@ -67,6 +67,7 @@ get_extract(struct archive_read *a)
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (NULL);
}
+ memset(a->extract, 0, sizeof(*a->extract));
a->extract->ad = archive_write_disk_new();
if (a->extract->ad == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
@@ -130,11 +131,13 @@ archive_read_extract_set_progress_callback(struct archive *_a,
static int
copy_data(struct archive *ar, struct archive *aw)
{
- int r;
+ off_t offset;
const void *buff;
+ struct extract *extract;
size_t size;
- off_t offset;
+ int r;
+ extract = get_extract((struct archive_read *)ar);
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
@@ -149,6 +152,9 @@ copy_data(struct archive *ar, struct archive *aw)
"%s", archive_error_string(aw));
return (r);
}
+ if (extract->extract_progress)
+ (extract->extract_progress)
+ (extract->extract_progress_user_data);
}
}
diff --git a/lib/libarchive/archive_read_private.h b/lib/libarchive/archive_read_private.h
index f9b174984c1d..da9cfb544b64 100644
--- a/lib/libarchive/archive_read_private.h
+++ b/lib/libarchive/archive_read_private.h
@@ -173,4 +173,7 @@ struct decompressor_t
int (*bid)(const void *, size_t),
int (*init)(struct archive_read *, const void *, size_t));
+const void
+ *__archive_read_ahead(struct archive_read *, size_t);
+
#endif
diff --git a/lib/libarchive/archive_read_support_compression_none.c b/lib/libarchive/archive_read_support_compression_none.c
index 99586c064306..2b9d43fdff61 100644
--- a/lib/libarchive/archive_read_support_compression_none.c
+++ b/lib/libarchive/archive_read_support_compression_none.c
@@ -170,56 +170,45 @@ archive_decompressor_none_read_ahead(struct archive_read *a, const void **buff,
min = state->buffer_size;
/*
- * Try to satisfy the request directly from the client
- * buffer. We can do this if all of the data in the copy
- * buffer was copied from the current client buffer. This
- * also covers the case where the copy buffer is empty and
- * the client buffer has all the data we need.
+ * Keep pulling more data until we can satisfy the request.
*/
- if (state->client_total >= state->client_avail + state->avail
- && state->client_avail + state->avail >= min) {
- state->client_avail += state->avail;
- state->client_next -= state->avail;
- state->avail = 0;
- state->next = state->buffer;
- *buff = state->client_next;
- return (state->client_avail);
- }
+ for (;;) {
- /*
- * If we can't use client buffer, we'll have to use copy buffer.
- */
+ /*
+ * If we can satisfy from the copy buffer, we're done.
+ */
+ if (state->avail >= min) {
+ *buff = state->next;
+ return (state->avail);
+ }
- /* Move data forward in copy buffer if necessary. */
- if (state->next > state->buffer &&
- state->next + min > state->buffer + state->buffer_size) {
- if (state->avail > 0)
- memmove(state->buffer, state->next, state->avail);
- state->next = state->buffer;
- }
+ /*
+ * We can satisfy directly from client buffer if everything
+ * currently in the copy buffer is still in the client buffer.
+ */
+ if (state->client_total >= state->client_avail + state->avail
+ && state->client_avail + state->avail >= min) {
+ /* "Roll back" to client buffer. */
+ state->client_avail += state->avail;
+ state->client_next -= state->avail;
+ /* Copy buffer is now empty. */
+ state->avail = 0;
+ state->next = state->buffer;
+ /* Return data from client buffer. */
+ *buff = state->client_next;
+ return (state->client_avail);
+ }
- /* Collect data in copy buffer to fulfill request. */
- while (state->avail < min) {
- /* Copy data from client buffer to our copy buffer. */
- if (state->client_avail > 0) {
- /* First estimate: copy to fill rest of buffer. */
- size_t tocopy = (state->buffer + state->buffer_size)
- - (state->next + state->avail);
- /* Don't copy more than is available. */
- if (tocopy > state->client_avail)
- tocopy = state->client_avail;
- memcpy(state->next + state->avail, state->client_next,
- tocopy);
- state->client_next += tocopy;
- state->client_avail -= tocopy;
- state->avail += tocopy;
- } else {
- /* There is no more client data: fetch more. */
- /*
- * It seems to me that const void ** and const
- * char ** should be compatible, but they
- * aren't, hence the cast.
- */
+ /* Move data forward in copy buffer if necessary. */
+ if (state->next > state->buffer &&
+ state->next + min > state->buffer + state->buffer_size) {
+ if (state->avail > 0)
+ memmove(state->buffer, state->next, state->avail);
+ state->next = state->buffer;
+ }
+
+ /* If we've used up the client data, get more. */
+ if (state->client_avail <= 0) {
bytes_read = (a->client_reader)(&a->archive,
a->client_data, &state->client_buff);
if (bytes_read < 0) { /* Read error. */
@@ -232,17 +221,33 @@ archive_decompressor_none_read_ahead(struct archive_read *a, const void **buff,
state->client_total = state->client_avail = 0;
state->client_next = state->client_buff = NULL;
state->end_of_file = 1;
- break;
+ /* Return whatever we do have. */
+ *buff = state->next;
+ return (state->avail);
}
a->archive.raw_position += bytes_read;
state->client_total = bytes_read;
state->client_avail = state->client_total;
state->client_next = state->client_buff;
}
+ else
+ {
+ /* We can add client data to copy buffer. */
+ /* First estimate: copy to fill rest of buffer. */
+ size_t tocopy = (state->buffer + state->buffer_size)
+ - (state->next + state->avail);
+ /* Don't copy more than is available. */
+ if (tocopy > state->client_avail)
+ tocopy = state->client_avail;
+ memcpy(state->next + state->avail, state->client_next,
+ tocopy);
+ /* Remove this data from client buffer. */
+ state->client_next += tocopy;
+ state->client_avail -= tocopy;
+ /* add it to copy buffer. */
+ state->avail += tocopy;
+ }
}
-
- *buff = state->next;
- return (state->avail);
}
/*
diff --git a/lib/libarchive/archive_read_support_format_all.c b/lib/libarchive/archive_read_support_format_all.c
index d03f362b26b7..753a105e2592 100644
--- a/lib/libarchive/archive_read_support_format_all.c
+++ b/lib/libarchive/archive_read_support_format_all.c
@@ -35,6 +35,7 @@ archive_read_support_format_all(struct archive *a)
archive_read_support_format_cpio(a);
archive_read_support_format_empty(a);
archive_read_support_format_iso9660(a);
+ archive_read_support_format_mtree(a);
archive_read_support_format_tar(a);
archive_read_support_format_zip(a);
return (ARCHIVE_OK);
diff --git a/lib/libarchive/archive_read_support_format_ar.c b/lib/libarchive/archive_read_support_format_ar.c
index c7f4cae43fdd..0094a3481c6c 100644
--- a/lib/libarchive/archive_read_support_format_ar.c
+++ b/lib/libarchive/archive_read_support_format_ar.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include "archive_read_private.h"
struct ar {
- int bid;
off_t entry_bytes_remaining;
off_t entry_offset;
off_t entry_padding;
@@ -103,7 +102,6 @@ archive_read_support_format_ar(struct archive *_a)
return (ARCHIVE_FATAL);
}
memset(ar, 0, sizeof(*ar));
- ar->bid = -1;
ar->strtab = NULL;
r = __archive_read_register_format(a,
@@ -148,9 +146,6 @@ archive_read_format_ar_bid(struct archive_read *a)
ar = (struct ar *)(a->format->data);
- if (ar->bid > 0)
- return (ar->bid);
-
/*
* Verify the 8-byte file signature.
* TODO: Do we need to check more than this?
@@ -159,8 +154,7 @@ archive_read_format_ar_bid(struct archive_read *a)
if (bytes_read < 8)
return (-1);
if (strncmp((const char*)h, "!<arch>\n", 8) == 0) {
- ar->bid = 64;
- return (ar->bid);
+ return (64);
}
return (-1);
}
diff --git a/lib/libarchive/archive_read_support_format_cpio.c b/lib/libarchive/archive_read_support_format_cpio.c
index 7eccc8719b33..5cb5fe6bbb4d 100644
--- a/lib/libarchive/archive_read_support_format_cpio.c
+++ b/lib/libarchive/archive_read_support_format_cpio.c
@@ -118,6 +118,8 @@ static int archive_read_format_cpio_read_data(struct archive_read *,
static int archive_read_format_cpio_read_header(struct archive_read *,
struct archive_entry *);
static int be4(const unsigned char *);
+static int find_odc_header(struct archive_read *);
+static int find_newc_header(struct archive_read *);
static int header_bin_be(struct archive_read *, struct cpio *,
struct archive_entry *, size_t *, size_t *);
static int header_bin_le(struct archive_read *, struct cpio *,
@@ -126,6 +128,8 @@ static int header_newc(struct archive_read *, struct cpio *,
struct archive_entry *, size_t *, size_t *);
static int header_odc(struct archive_read *, struct cpio *,
struct archive_entry *, size_t *, size_t *);
+static int is_octal(const char *, size_t);
+static int is_hex(const char *, size_t);
static int le4(const unsigned char *);
static void record_hardlink(struct cpio *cpio, struct archive_entry *entry);
@@ -161,13 +165,14 @@ archive_read_support_format_cpio(struct archive *_a)
static int
archive_read_format_cpio_bid(struct archive_read *a)
{
- int bid, bytes_read;
+ int bytes_read;
const void *h;
const unsigned char *p;
struct cpio *cpio;
+ int bid;
cpio = (struct cpio *)(a->format->data);
- bid = 0;
+
bytes_read = (a->decompressor->read_ahead)(a, &h, 6);
/* Convert error code into error return. */
if (bytes_read < 0)
@@ -176,6 +181,7 @@ archive_read_format_cpio_bid(struct archive_read *a)
return (-1);
p = (const unsigned char *)h;
+ bid = 0;
if (memcmp(p, "070707", 6) == 0) {
/* ASCII cpio archive (odc, POSIX.1) */
cpio->read_header = header_odc;
@@ -231,7 +237,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
cpio = (struct cpio *)(a->format->data);
r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad));
- if (r != ARCHIVE_OK)
+ if (r < ARCHIVE_WARN)
return (r);
/* Read name from buffer. */
@@ -266,7 +272,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
/* Detect and record hardlinks to previously-extracted entries. */
record_hardlink(cpio, entry);
- return (ARCHIVE_OK);
+ return (r);
}
static int
@@ -306,6 +312,84 @@ archive_read_format_cpio_read_data(struct archive_read *a,
}
}
+/*
+ * Skip forward to the next cpio newc header by searching for the
+ * 07070[12] string. This should be generalized and merged with
+ * find_odc_header below.
+ */
+static int
+is_hex(const char *p, size_t len)
+{
+ while (len-- > 0) {
+ if ((*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'f')
+ || (*p >= 'A' && *p <= 'F'))
+ ++p;
+ else
+ return (0);
+ }
+ return (1);
+}
+
+static int
+find_newc_header(struct archive_read *a)
+{
+ const void *h;
+ const char *p, *q;
+ size_t skip, bytes, skipped = 0;
+
+ for (;;) {
+ bytes = (a->decompressor->read_ahead)(a, &h, 2048);
+ if (bytes < sizeof(struct cpio_newc_header))
+ return (ARCHIVE_FATAL);
+ p = h;
+ q = p + bytes;
+
+ /* Try the typical case first, then go into the slow search.*/
+ if (memcmp("07070", p, 5) == 0
+ && (p[5] == '1' || p[5] == '2')
+ && is_hex(p, sizeof(struct cpio_newc_header)))
+ return (ARCHIVE_OK);
+
+ /*
+ * Scan ahead until we find something that looks
+ * like an odc header.
+ */
+ while (p + sizeof(struct cpio_newc_header) < q) {
+ switch (p[5]) {
+ case '1':
+ case '2':
+ if (memcmp("07070", p, 5) == 0
+ && is_hex(p, sizeof(struct cpio_newc_header))) {
+ skip = p - (const char *)h;
+ (a->decompressor->consume)(a, skip);
+ skipped += skip;
+ if (skipped > 0) {
+ archive_set_error(&a->archive,
+ 0,
+ "Skipped %d bytes before "
+ "finding valid header",
+ (int)skipped);
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+ }
+ p += 2;
+ break;
+ case '0':
+ p++;
+ break;
+ default:
+ p += 6;
+ break;
+ }
+ }
+ skip = p - (const char *)h;
+ (a->decompressor->consume)(a, skip);
+ skipped += skip;
+ }
+}
+
static int
header_newc(struct archive_read *a, struct cpio *cpio,
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
@@ -313,6 +397,11 @@ header_newc(struct archive_read *a, struct cpio *cpio,
const void *h;
const struct cpio_newc_header *header;
size_t bytes;
+ int r;
+
+ r = find_newc_header(a);
+ if (r < ARCHIVE_WARN)
+ return (r);
/* Read fixed-size portion of header. */
bytes = (a->decompressor->read_ahead)(a, &h, sizeof(struct cpio_newc_header));
@@ -357,7 +446,81 @@ header_newc(struct archive_read *a, struct cpio *cpio,
archive_entry_set_size(entry, cpio->entry_bytes_remaining);
/* Pad file contents to a multiple of 4. */
cpio->entry_padding = 3 & -cpio->entry_bytes_remaining;
- return (ARCHIVE_OK);
+ return (r);
+}
+
+/*
+ * Skip forward to the next cpio odc header by searching for the
+ * 070707 string. This is a hand-optimized search that could
+ * probably be easily generalized to handle all character-based
+ * cpio variants.
+ */
+static int
+is_octal(const char *p, size_t len)
+{
+ while (len-- > 0) {
+ if (*p < '0' || *p > '7')
+ return (0);
+ ++p;
+ }
+ return (1);
+}
+
+static int
+find_odc_header(struct archive_read *a)
+{
+ const void *h;
+ const char *p, *q;
+ size_t skip, bytes, skipped = 0;
+
+ for (;;) {
+ bytes = (a->decompressor->read_ahead)(a, &h, 512);
+ if (bytes < sizeof(struct cpio_odc_header))
+ return (ARCHIVE_FATAL);
+ p = h;
+ q = p + bytes;
+
+ /* Try the typical case first, then go into the slow search.*/
+ if (memcmp("070707", p, 6) == 0
+ && is_octal(p, sizeof(struct cpio_odc_header)))
+ return (ARCHIVE_OK);
+
+ /*
+ * Scan ahead until we find something that looks
+ * like an odc header.
+ */
+ while (p + sizeof(struct cpio_odc_header) < q) {
+ switch (p[5]) {
+ case '7':
+ if (memcmp("070707", p, 6) == 0
+ && is_octal(p, sizeof(struct cpio_odc_header))) {
+ skip = p - (const char *)h;
+ (a->decompressor->consume)(a, skip);
+ skipped += skip;
+ if (skipped > 0) {
+ archive_set_error(&a->archive,
+ 0,
+ "Skipped %d bytes before "
+ "finding valid header",
+ (int)skipped);
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+ }
+ p += 2;
+ break;
+ case '0':
+ p++;
+ break;
+ default:
+ p += 6;
+ break;
+ }
+ }
+ skip = p - (const char *)h;
+ (a->decompressor->consume)(a, skip);
+ skipped += skip;
+ }
}
static int
@@ -365,12 +528,18 @@ header_odc(struct archive_read *a, struct cpio *cpio,
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
const void *h;
+ int r;
const struct cpio_odc_header *header;
size_t bytes;
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
a->archive.archive_format_name = "POSIX octet-oriented cpio";
+ /* Find the start of the next header. */
+ r = find_odc_header(a);
+ if (r < ARCHIVE_WARN)
+ return (r);
+
/* Read fixed-size portion of header. */
bytes = (a->decompressor->read_ahead)(a, &h, sizeof(struct cpio_odc_header));
if (bytes < sizeof(struct cpio_odc_header))
@@ -400,7 +569,7 @@ header_odc(struct archive_read *a, struct cpio *cpio,
atol8(header->c_filesize, sizeof(header->c_filesize));
archive_entry_set_size(entry, cpio->entry_bytes_remaining);
cpio->entry_padding = 0;
- return (ARCHIVE_OK);
+ return (r);
}
static int
@@ -574,7 +743,7 @@ record_hardlink(struct cpio *cpio, struct archive_entry *entry)
*/
for (le = cpio->links_head; le; le = le->next) {
if (le->dev == dev && le->ino == ino) {
- archive_entry_set_hardlink(entry, le->name);
+ archive_entry_copy_hardlink(entry, le->name);
if (--le->links <= 0) {
if (le->previous != NULL)
@@ -583,6 +752,7 @@ record_hardlink(struct cpio *cpio, struct archive_entry *entry)
le->next->previous = le->previous;
if (cpio->links_head == le)
cpio->links_head = le->next;
+ free(le->name);
free(le);
}
diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c
index 9e3785c53524..83e22875bded 100644
--- a/lib/libarchive/archive_read_support_format_iso9660.c
+++ b/lib/libarchive/archive_read_support_format_iso9660.c
@@ -181,6 +181,7 @@ struct file_info {
time_t mtime; /* File last modified time. */
time_t atime; /* File last accessed time. */
time_t ctime; /* File creation time. */
+ uint64_t rdev; /* Device number */
mode_t mode;
uid_t uid;
gid_t gid;
@@ -194,7 +195,6 @@ struct file_info {
struct iso9660 {
int magic;
#define ISO9660_MAGIC 0x96609660
- int bid; /* If non-zero, return this as our bid. */
struct archive_string pathname;
char seenRockridge; /* Set true if RR extensions are used. */
unsigned char suspOffset;
@@ -255,7 +255,6 @@ archive_read_support_format_iso9660(struct archive *_a)
}
memset(iso9660, 0, sizeof(*iso9660));
iso9660->magic = ISO9660_MAGIC;
- iso9660->bid = -1; /* We haven't yet bid. */
r = __archive_read_register_format(a,
iso9660,
@@ -280,12 +279,10 @@ archive_read_format_iso9660_bid(struct archive_read *a)
ssize_t bytes_read;
const void *h;
const unsigned char *p;
+ int bid;
iso9660 = (struct iso9660 *)(a->format->data);
- if (iso9660->bid >= 0)
- return (iso9660->bid);
-
/*
* Skip the first 32k (reserved area) and get the first
* 8 sectors of the volume descriptor table. Of course,
@@ -293,7 +290,7 @@ archive_read_format_iso9660_bid(struct archive_read *a)
*/
bytes_read = (a->decompressor->read_ahead)(a, &h, 32768 + 8*2048);
if (bytes_read < 32768 + 8*2048)
- return (iso9660->bid = -1);
+ return (-1);
p = (const unsigned char *)h;
/* Skip the reserved area. */
@@ -302,16 +299,15 @@ archive_read_format_iso9660_bid(struct archive_read *a)
/* Check each volume descriptor to locate the PVD. */
for (; bytes_read > 2048; bytes_read -= 2048, p += 2048) {
- iso9660->bid = isPVD(iso9660, p);
- if (iso9660->bid > 0)
- return (iso9660->bid);
+ bid = isPVD(iso9660, p);
+ if (bid > 0)
+ return (bid);
if (*p == '\177') /* End-of-volume-descriptor marker. */
break;
}
/* We didn't find a valid PVD; return a bid of zero. */
- iso9660->bid = 0;
- return (iso9660->bid);
+ return (0);
}
static int
@@ -365,6 +361,8 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_entry_set_mtime(entry, file->mtime, 0);
archive_entry_set_ctime(entry, file->ctime, 0);
archive_entry_set_atime(entry, file->atime, 0);
+ /* N.B.: Rock Ridge supports 64-bit device numbers. */
+ archive_entry_set_rdev(entry, (dev_t)file->rdev);
archive_entry_set_size(entry, iso9660->entry_bytes_remaining);
archive_string_empty(&iso9660->pathname);
archive_entry_set_pathname(entry,
@@ -680,6 +678,14 @@ parse_rockridge(struct iso9660 *iso9660, struct file_info *file,
*/
break;
}
+ if (p[0] == 'P' && p[1] == 'N' && version == 1) {
+ if (data_length == 16) {
+ file->rdev = toi(data,4);
+ file->rdev <<= 32;
+ file->rdev |= toi(data + 8, 4);
+ }
+ break;
+ }
if (p[0] == 'P' && p[1] == 'X' && version == 1) {
/*
* PX extension comprises:
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c
index 72d2e85adde7..9cfe0e762aa4 100644
--- a/lib/libarchive/archive_read_support_format_tar.c
+++ b/lib/libarchive/archive_read_support_format_tar.c
@@ -128,8 +128,8 @@ struct archive_entry_header_gnutar {
char isextended[1];
char realsize[12];
/*
- * GNU doesn't use POSIX 'prefix' field; they use the 'L' (longname)
- * entry instead.
+ * Old GNU format doesn't use POSIX 'prefix' field; they use
+ * the 'L' (longname) entry instead.
*/
};
@@ -164,7 +164,6 @@ struct tar {
struct sparse_block *sparse_last;
int64_t sparse_offset;
int64_t sparse_numbytes;
- int64_t sparse_realsize;
int sparse_gnu_major;
int sparse_gnu_minor;
char sparse_gnu_pending;
@@ -279,6 +278,8 @@ archive_read_format_tar_cleanup(struct archive_read *a)
archive_string_free(&tar->line);
archive_string_free(&tar->pax_global);
archive_string_free(&tar->pax_header);
+ archive_string_free(&tar->longname);
+ archive_string_free(&tar->longlink);
free(tar->pax_entry);
free(tar);
(a->format->data) = NULL;
@@ -294,24 +295,8 @@ archive_read_format_tar_bid(struct archive_read *a)
const void *h;
const struct archive_entry_header_ustar *header;
- /*
- * If we're already reading a non-tar file, don't
- * bother to bid.
- */
- if (a->archive.archive_format != 0 &&
- (a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) !=
- ARCHIVE_FORMAT_TAR)
- return (0);
bid = 0;
- /*
- * If we're already reading a tar format, start the bid at 1 as
- * a failsafe.
- */
- if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
- ARCHIVE_FORMAT_TAR)
- bid++;
-
/* Now let's look at the actual header and see if it matches. */
if (a->decompressor->read_ahead != NULL)
bytes_read = (a->decompressor->read_ahead)(a, &h, 512);
@@ -319,32 +304,18 @@ archive_read_format_tar_bid(struct archive_read *a)
bytes_read = 0; /* Empty file. */
if (bytes_read < 0)
return (ARCHIVE_FATAL);
- if (bytes_read == 0 && bid > 0) {
- /* An archive without a proper end-of-archive marker. */
- /* Hold our nose and bid 1 anyway. */
- return (1);
- }
- if (bytes_read < 512) {
- /* If it's a new archive, then just return a zero bid. */
- if (bid == 0)
- return (0);
- /*
- * If we already know this is a tar archive,
- * then we have a problem.
- */
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Truncated tar archive");
- return (ARCHIVE_FATAL);
- }
+ if (bytes_read < 512)
+ return (0);
/* If it's an end-of-archive mark, we can handle it. */
- if ((*(const char *)h) == 0 && archive_block_is_null((const unsigned char *)h)) {
- /* If it's a known tar file, end-of-archive is definite. */
- if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
- ARCHIVE_FORMAT_TAR)
- return (512);
- /* Empty archive? */
- return (1);
+ if ((*(const char *)h) == 0
+ && archive_block_is_null((const unsigned char *)h)) {
+ /*
+ * Usually, I bid the number of bits verified, but
+ * in this case, 4096 seems excessive so I picked 10 as
+ * an arbitrary but reasonable-seeming value.
+ */
+ return (10);
}
/* If it's not an end-of-archive mark, it must have a valid checksum.*/
@@ -441,7 +412,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
free(sp);
}
tar->sparse_last = NULL;
- tar->sparse_realsize = -1; /* Mark this as "unset" */
+ tar->realsize = -1; /* Mark this as "unset" */
r = tar_read_header(a, tar, entry);
@@ -452,8 +423,6 @@ archive_read_format_tar_read_header(struct archive_read *a,
if (tar->sparse_list == NULL)
gnu_add_sparse_entry(tar, 0, tar->entry_bytes_remaining);
- tar->realsize = archive_entry_size(entry);
-
if (r == ARCHIVE_OK) {
/*
* "Regular" entry with trailing '/' is really
@@ -581,16 +550,24 @@ tar_read_header(struct archive_read *a, struct tar *tar,
/* Read 512-byte header record */
bytes = (a->decompressor->read_ahead)(a, &h, 512);
- if (bytes < 512) {
+ if (bytes < 0)
+ return (bytes);
+ if (bytes == 0) {
/*
- * If we're here, it's becase the _bid function accepted
- * this file. So just call a short read end-of-archive
- * and be done with it.
+ * An archive that just ends without a proper
+ * end-of-archive marker. Yes, there are tar programs
+ * that do this; hold our nose and accept it.
*/
return (ARCHIVE_EOF);
}
+ if (bytes < 512) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated tar archive");
+ return (ARCHIVE_FATAL);
+ }
(a->decompressor->consume)(a, 512);
+
/* Check for end-of-archive mark. */
if (((*(const char *)h)==0) && archive_block_is_null((const unsigned char *)h)) {
/* Try to consume a second all-null record, as well. */
@@ -598,6 +575,10 @@ tar_read_header(struct archive_read *a, struct tar *tar,
if (bytes > 0)
(a->decompressor->consume)(a, bytes);
archive_set_error(&a->archive, 0, NULL);
+ if (a->archive.archive_format_name == NULL) {
+ a->archive.archive_format = ARCHIVE_FORMAT_TAR;
+ a->archive.archive_format_name = "tar";
+ }
return (ARCHIVE_EOF);
}
@@ -936,6 +917,7 @@ header_common(struct archive_read *a, struct tar *tar,
archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid)));
archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid)));
tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size));
+ tar->realsize = tar->entry_bytes_remaining;
archive_entry_set_size(entry, tar->entry_bytes_remaining);
archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
@@ -961,30 +943,46 @@ header_common(struct archive_read *a, struct tar *tar,
* A tricky point: Traditionally, tar readers have
* ignored the size field when reading hardlink
* entries, and some writers put non-zero sizes even
- * though the body is empty. POSIX.1-2001 broke with
- * this tradition by permitting hardlink entries to
- * store valid bodies in pax interchange format, but
- * not in ustar format. Since there is no hard and
- * fast way to distinguish pax interchange from
- * earlier archives (the 'x' and 'g' entries are
- * optional, after all), we need a heuristic. Here, I
- * use the bid function to test whether or not there's
- * a valid header following. Of course, if we know
- * this is pax interchange format, then we must obey
- * the size.
- *
- * This heuristic will only fail for a pax interchange
- * archive that is storing hardlink bodies, no pax
- * extended attribute entries have yet occurred, and
- * we encounter a hardlink entry for a file that is
- * itself an uncompressed tar archive.
+ * though the body is empty. POSIX blessed this
+ * convention in the 1988 standard, but broke with
+ * this tradition in 2001 by permitting hardlink
+ * entries to store valid bodies in pax interchange
+ * format, but not in ustar format. Since there is no
+ * hard and fast way to distinguish pax interchange
+ * from earlier archives (the 'x' and 'g' entries are
+ * optional, after all), we need a heuristic.
*/
- if (archive_entry_size(entry) > 0 &&
- a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
- archive_read_format_tar_bid(a) > 50) {
+ if (archive_entry_size(entry) == 0) {
+ /* If the size is already zero, we're done. */
+ } else if (a->archive.archive_format
+ == ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) {
+ /* Definitely pax extended; must obey hardlink size. */
+ } else if (a->archive.archive_format == ARCHIVE_FORMAT_TAR
+ || a->archive.archive_format == ARCHIVE_FORMAT_TAR_GNUTAR)
+ {
+ /* Old-style or GNU tar: we must ignore the size. */
+ archive_entry_set_size(entry, 0);
+ tar->entry_bytes_remaining = 0;
+ } else if (archive_read_format_tar_bid(a) > 50) {
+ /*
+ * We don't know if it's pax: If the bid
+ * function sees a valid ustar header
+ * immediately following, then let's ignore
+ * the hardlink size.
+ */
archive_entry_set_size(entry, 0);
tar->entry_bytes_remaining = 0;
}
+ /*
+ * TODO: There are still two cases I'd like to handle:
+ * = a ustar non-pax archive with a hardlink entry at
+ * end-of-archive. (Look for block of nulls following?)
+ * = a pax archive that has not seen any pax headers
+ * and has an entry which is a hardlink entry storing
+ * a body containing an uncompressed tar archive.
+ * The first is worth addressing; I don't see any reliable
+ * way to deal with the second possibility.
+ */
break;
case '2': /* Symlink */
archive_entry_set_filetype(entry, AE_IFLNK);
@@ -1367,9 +1365,10 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
tar->sparse_numbytes = -1;
}
}
- if (wcscmp(key, L"GNU.sparse.size") == 0)
- archive_entry_set_size(entry,
- tar_atol10(value, wcslen(value)));
+ if (wcscmp(key, L"GNU.sparse.size") == 0) {
+ tar->realsize = tar_atol10(value, wcslen(value));
+ archive_entry_set_size(entry, tar->realsize);
+ }
/* GNU "0.1" sparse pax format. */
if (wcscmp(key, L"GNU.sparse.map") == 0) {
@@ -1391,8 +1390,8 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
if (wcscmp(key, L"GNU.sparse.name") == 0)
archive_entry_copy_pathname_w(entry, value);
if (wcscmp(key, L"GNU.sparse.realsize") == 0) {
- tar->sparse_realsize = tar_atol10(value, wcslen(value));
- archive_entry_set_size(entry, tar->sparse_realsize);
+ tar->realsize = tar_atol10(value, wcslen(value));
+ archive_entry_set_size(entry, tar->realsize);
}
break;
case 'L':
@@ -1425,6 +1424,10 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
archive_entry_set_ino(entry, tar_atol10(value, wcslen(value)));
else if (wcscmp(key, L"SCHILY.nlink")==0)
archive_entry_set_nlink(entry, tar_atol10(value, wcslen(value)));
+ else if (wcscmp(key, L"SCHILY.realsize")==0) {
+ tar->realsize = tar_atol10(value, wcslen(value));
+ archive_entry_set_size(entry, tar->realsize);
+ }
break;
case 'a':
if (wcscmp(key, L"atime")==0) {
@@ -1481,12 +1484,14 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
* But, "size" is not necessarily the size of
* the file on disk; if this is a sparse file,
* the disk size may have already been set from
- * GNU.sparse.realsize.
+ * GNU.sparse.realsize or GNU.sparse.size or
+ * an old GNU header field or SCHILY.realsize
+ * or ....
*/
- if (tar->sparse_realsize < 0) {
+ if (tar->realsize < 0) {
archive_entry_set_size(entry,
tar->entry_bytes_remaining);
- tar->sparse_realsize
+ tar->realsize
= tar->entry_bytes_remaining;
}
}
@@ -1608,8 +1613,9 @@ header_gnutar(struct archive_read *a, struct tar *tar,
archive_entry_set_ctime(entry,
tar_atol(header->ctime, sizeof(header->ctime)), 0);
if (header->realsize[0] != 0) {
- archive_entry_set_size(entry,
- tar_atol(header->realsize, sizeof(header->realsize)));
+ tar->realsize
+ = tar_atol(header->realsize, sizeof(header->realsize));
+ archive_entry_set_size(entry, tar->realsize);
}
if (header->sparse[0].offset[0] != 0) {
diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c
index e9976779f407..d96bea621603 100644
--- a/lib/libarchive/archive_read_support_format_zip.c
+++ b/lib/libarchive/archive_read_support_format_zip.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_private.h"
+#include "archive_endian.h"
struct zip {
/* entry_bytes_remaining is the number of bytes we expect. */
@@ -121,11 +122,6 @@ static int archive_read_format_zip_read_data(struct archive_read *,
static int archive_read_format_zip_read_data_skip(struct archive_read *a);
static int archive_read_format_zip_read_header(struct archive_read *,
struct archive_entry *);
-static int i2(const char *);
-static int i4(const char *);
-static unsigned int u2(const char *);
-static unsigned int u4(const char *);
-static uint64_t u8(const char *);
static int zip_read_data_deflate(struct archive_read *a, const void **buff,
size_t *size, off_t *offset);
static int zip_read_data_none(struct archive_read *a, const void **buff,
@@ -166,38 +162,35 @@ archive_read_support_format_zip(struct archive *_a)
static int
archive_read_format_zip_bid(struct archive_read *a)
{
- int bytes_read;
int bid = 0;
- const void *h;
const char *p;
if (a->archive.archive_format == ARCHIVE_FORMAT_ZIP)
bid += 1;
- bytes_read = (a->decompressor->read_ahead)(a, &h, 4);
- if (bytes_read < 4)
- return (-1);
- p = (const char *)h;
+ if ((p = __archive_read_ahead(a, 4)) == NULL)
+ return (-1);
+ /*
+ * Bid of 30 here is: 16 bits for "PK",
+ * next 16-bit field has four options (-2 bits).
+ * 16 + 16-2 = 30.
+ */
if (p[0] == 'P' && p[1] == 'K') {
- bid += 16;
- if (p[2] == '\001' && p[3] == '\002')
- bid += 16;
- else if (p[2] == '\003' && p[3] == '\004')
- bid += 16;
- else if (p[2] == '\005' && p[3] == '\006')
- bid += 16;
- else if (p[2] == '\007' && p[3] == '\010')
- bid += 16;
+ if ((p[2] == '\001' && p[3] == '\002')
+ || (p[2] == '\003' && p[3] == '\004')
+ || (p[2] == '\005' && p[3] == '\006')
+ || (p[2] == '\007' && p[3] == '\010')
+ || (p[2] == '0' && p[3] == '0'))
+ return (30);
}
- return (bid);
+ return (0);
}
static int
archive_read_format_zip_read_header(struct archive_read *a,
struct archive_entry *entry)
{
- int bytes_read;
const void *h;
const char *signature;
struct zip *zip;
@@ -212,8 +205,7 @@ archive_read_format_zip_read_header(struct archive_read *a,
zip->end_of_entry_cleanup = 0;
zip->entry_uncompressed_bytes_read = 0;
zip->entry_compressed_bytes_read = 0;
- bytes_read = (a->decompressor->read_ahead)(a, &h, 4);
- if (bytes_read < 4)
+ if ((h = __archive_read_ahead(a, 4)) == NULL)
return (ARCHIVE_FATAL);
signature = (const char *)h;
@@ -223,6 +215,23 @@ archive_read_format_zip_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
+ /*
+ * "PK00" signature is used for "split" archives that
+ * only have a single segment. This means we can just
+ * skip the PK00; the first real file header should follow.
+ */
+ if (signature[2] == '0' && signature[3] == '0') {
+ (a->decompressor->consume)(a, 4);
+ if ((h = __archive_read_ahead(a, 4)) == NULL)
+ return (ARCHIVE_FATAL);
+ signature = (const char *)h;
+ if (signature[0] != 'P' || signature[1] != 'K') {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Bad ZIP file");
+ return (ARCHIVE_FATAL);
+ }
+ }
+
if (signature[2] == '\001' && signature[3] == '\002') {
/* Beginning of central directory. */
return (ARCHIVE_EOF);
@@ -260,21 +269,17 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
{
const struct zip_file_header *p;
const void *h;
- int bytes_read;
- bytes_read =
- (a->decompressor->read_ahead)(a, &h, sizeof(struct zip_file_header));
- if (bytes_read < (int)sizeof(struct zip_file_header)) {
+ if ((p = __archive_read_ahead(a, sizeof *p)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
}
- p = (const struct zip_file_header *)h;
zip->version = p->version[0];
zip->system = p->version[1];
- zip->flags = i2(p->flags);
- zip->compression = i2(p->compression);
+ zip->flags = le16dec(p->flags);
+ zip->compression = le16dec(p->compression);
if (zip->compression <
sizeof(compression_names)/sizeof(compression_names[0]))
zip->compression_name = compression_names[zip->compression];
@@ -286,25 +291,24 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
zip->mode = 0;
zip->uid = 0;
zip->gid = 0;
- zip->crc32 = i4(p->crc32);
- zip->filename_length = i2(p->filename_length);
- zip->extra_length = i2(p->extra_length);
- zip->uncompressed_size = u4(p->uncompressed_size);
- zip->compressed_size = u4(p->compressed_size);
+ zip->crc32 = le32dec(p->crc32);
+ zip->filename_length = le16dec(p->filename_length);
+ zip->extra_length = le16dec(p->extra_length);
+ zip->uncompressed_size = le32dec(p->uncompressed_size);
+ zip->compressed_size = le32dec(p->compressed_size);
(a->decompressor->consume)(a, sizeof(struct zip_file_header));
/* Read the filename. */
- bytes_read = (a->decompressor->read_ahead)(a, &h, zip->filename_length);
- if (bytes_read < zip->filename_length) {
+ if ((h = __archive_read_ahead(a, zip->filename_length)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
}
if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL)
__archive_errx(1, "Out of memory");
- archive_strncpy(&zip->pathname, (const char *)h, zip->filename_length);
+ archive_strncpy(&zip->pathname, h, zip->filename_length);
(a->decompressor->consume)(a, zip->filename_length);
archive_entry_set_pathname(entry, zip->pathname.s);
@@ -314,8 +318,7 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
zip->mode = AE_IFREG | 0777;
/* Read the extra data. */
- bytes_read = (a->decompressor->read_ahead)(a, &h, zip->extra_length);
- if (bytes_read < zip->extra_length) {
+ if ((h = __archive_read_ahead(a, zip->extra_length)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
@@ -386,21 +389,18 @@ archive_read_format_zip_read_data(struct archive_read *a,
if (zip->end_of_entry) {
if (!zip->end_of_entry_cleanup) {
if (zip->flags & ZIP_LENGTH_AT_END) {
- const void *h;
const char *p;
- int bytes_read =
- (a->decompressor->read_ahead)(a, &h, 16);
- if (bytes_read < 16) {
+
+ if ((p = __archive_read_ahead(a, 16)) == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP end-of-file record");
return (ARCHIVE_FATAL);
}
- p = (const char *)h;
- zip->crc32 = i4(p + 4);
- zip->compressed_size = u4(p + 8);
- zip->uncompressed_size = u4(p + 12);
- bytes_read = (a->decompressor->consume)(a, 16);
+ zip->crc32 = le32dec(p + 4);
+ zip->compressed_size = le32dec(p + 8);
+ zip->uncompressed_size = le32dec(p + 12);
+ (a->decompressor->consume)(a, 16);
}
/* Check file size, CRC against these values. */
@@ -695,37 +695,6 @@ archive_read_format_zip_cleanup(struct archive_read *a)
return (ARCHIVE_OK);
}
-static int
-i2(const char *p)
-{
- return ((0xff & (int)p[0]) + 256 * (0xff & (int)p[1]));
-}
-
-
-static int
-i4(const char *p)
-{
- return ((0xffff & i2(p)) + 0x10000 * (0xffff & i2(p+2)));
-}
-
-static unsigned int
-u2(const char *p)
-{
- return ((0xff & (unsigned int)p[0]) + 256 * (0xff & (unsigned int)p[1]));
-}
-
-static unsigned int
-u4(const char *p)
-{
- return u2(p) + 0x10000 * u2(p+2);
-}
-
-static uint64_t
-u8(const char *p)
-{
- return u4(p) + 0x100000000LL * u4(p+4);
-}
-
/*
* The extra data is stored as a list of
* id1+size1+data1 + id2+size2+data2 ...
@@ -738,8 +707,8 @@ process_extra(const void* extra, struct zip* zip)
const char *p = (const char *)extra;
while (offset < zip->extra_length - 4)
{
- unsigned short headerid = u2(p + offset);
- unsigned short datasize = u2(p + offset + 2);
+ unsigned short headerid = le16dec(p + offset);
+ unsigned short datasize = le16dec(p + offset + 2);
offset += 4;
if (offset + datasize > zip->extra_length)
break;
@@ -751,9 +720,9 @@ process_extra(const void* extra, struct zip* zip)
case 0x0001:
/* Zip64 extended information extra field. */
if (datasize >= 8)
- zip->uncompressed_size = u8(p + offset);
+ zip->uncompressed_size = le64dec(p + offset);
if (datasize >= 16)
- zip->compressed_size = u8(p + offset + 8);
+ zip->compressed_size = le64dec(p + offset + 8);
break;
case 0x5455:
{
@@ -765,12 +734,12 @@ process_extra(const void* extra, struct zip* zip)
if (flags & 0x01)
{
#ifdef DEBUG
- fprintf(stderr, "mtime: %d -> %d\n",
- zip->mtime, i4(p + offset));
+ fprintf(stderr, "mtime: %lld -> %d\n",
+ (long long)zip->mtime, le32dec(p + offset));
#endif
if (datasize < 4)
break;
- zip->mtime = i4(p + offset);
+ zip->mtime = le32dec(p + offset);
offset += 4;
datasize -= 4;
}
@@ -778,7 +747,7 @@ process_extra(const void* extra, struct zip* zip)
{
if (datasize < 4)
break;
- zip->atime = i4(p + offset);
+ zip->atime = le32dec(p + offset);
offset += 4;
datasize -= 4;
}
@@ -786,7 +755,7 @@ process_extra(const void* extra, struct zip* zip)
{
if (datasize < 4)
break;
- zip->ctime = i4(p + offset);
+ zip->ctime = le32dec(p + offset);
offset += 4;
datasize -= 4;
}
@@ -796,12 +765,12 @@ process_extra(const void* extra, struct zip* zip)
/* Info-ZIP Unix Extra Field (type 2) "Ux". */
#ifdef DEBUG
fprintf(stderr, "uid %d gid %d\n",
- i2(p + offset), i2(p + offset + 2));
+ le16dec(p + offset), le16dec(p + offset + 2));
#endif
if (datasize >= 2)
- zip->uid = i2(p + offset);
+ zip->uid = le16dec(p + offset);
if (datasize >= 4)
- zip->gid = i2(p + offset + 2);
+ zip->gid = le16dec(p + offset + 2);
break;
default:
break;
diff --git a/lib/libarchive/archive_util.c b/lib/libarchive/archive_util.c
index fbb0a9f60ca2..e80cabb642db 100644
--- a/lib/libarchive/archive_util.c
+++ b/lib/libarchive/archive_util.c
@@ -60,7 +60,7 @@ archive_version_stamp(void)
const char *
archive_version(void)
{
- return (PACKAGE_NAME " " PACKAGE_VERSION);
+ return (ARCHIVE_LIBRARY_VERSION);
}
int
diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c
index 435522ceac61..a941ab666e84 100644
--- a/lib/libarchive/archive_write_disk.c
+++ b/lib/libarchive/archive_write_disk.c
@@ -171,6 +171,8 @@ struct archive_write_disk {
int fd;
/* Current offset for writing data to the file. */
off_t offset;
+ /* Maximum size of file. */
+ off_t filesize;
/* Dir we were in before this restore; only for deep paths. */
int restore_pwd;
/* Mode we should use for this entry; affected by _PERM and umask. */
@@ -302,6 +304,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
a->offset = 0;
a->uid = a->user_uid;
a->mode = archive_entry_mode(a->entry);
+ a->filesize = archive_entry_size(a->entry);
archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
a->name = a->_name_data.s;
archive_clear_error(&a->archive);
@@ -421,6 +424,14 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
/* We've created the object and are ready to pour data into it. */
if (ret == ARCHIVE_OK)
a->archive.state = ARCHIVE_STATE_DATA;
+ /*
+ * If it's not open, tell our client not to try writing.
+ * In particular, dirs, links, etc, don't get written to.
+ */
+ if (a->fd < 0) {
+ archive_entry_set_size(entry, 0);
+ a->filesize = 0;
+ }
done:
/* Restore the user's umask before returning. */
umask(a->user_umask);
@@ -445,6 +456,7 @@ _archive_write_data_block(struct archive *_a,
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
ssize_t bytes_written = 0;
+ int r = ARCHIVE_OK;
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_disk_block");
@@ -464,7 +476,13 @@ _archive_write_data_block(struct archive *_a,
}
/* Write the data. */
- while (size > 0) {
+ while (size > 0 && a->offset < a->filesize) {
+ if ((off_t)(a->offset + size) > a->filesize) {
+ size = (size_t)(a->filesize - a->offset);
+ archive_set_error(&a->archive, errno,
+ "Write request too large");
+ r = ARCHIVE_WARN;
+ }
bytes_written = write(a->fd, buff, size);
if (bytes_written < 0) {
archive_set_error(&a->archive, errno, "Write failed");
@@ -473,13 +491,14 @@ _archive_write_data_block(struct archive *_a,
size -= bytes_written;
a->offset += bytes_written;
}
- return (ARCHIVE_OK);
+ return (r);
}
static ssize_t
_archive_write_data(struct archive *_a, const void *buff, size_t size)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ off_t offset;
int r;
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -487,10 +506,11 @@ _archive_write_data(struct archive *_a, const void *buff, size_t size)
if (a->fd < 0)
return (ARCHIVE_OK);
+ offset = a->offset;
r = _archive_write_data_block(_a, buff, size, a->offset);
if (r < ARCHIVE_OK)
return (r);
- return (size);
+ return (a->offset - offset);
}
static int
@@ -823,8 +843,20 @@ create_filesystem_object(struct archive_write_disk *a)
/* We identify hard/symlinks according to the link names. */
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
linkname = archive_entry_hardlink(a->entry);
- if (linkname != NULL)
- return link(linkname, a->name) ? errno : 0;
+ if (linkname != NULL) {
+ r = link(linkname, a->name) ? errno : 0;
+ /*
+ * New cpio and pax formats allow hardlink entries
+ * to carry data, so we may have to open the file
+ * for hardlink entries.
+ */
+ if (r == 0 && a->filesize > 0) {
+ a->fd = open(a->name, O_WRONLY | O_TRUNC);
+ if (a->fd < 0)
+ r = errno;
+ }
+ return (r);
+ }
linkname = archive_entry_symlink(a->entry);
if (linkname != NULL)
return symlink(linkname, a->name) ? errno : 0;
diff --git a/lib/libarchive/archive_write_set_compression_bzip2.c b/lib/libarchive/archive_write_set_compression_bzip2.c
index 58cd8a6536fc..1f59fca5ac93 100644
--- a/lib/libarchive/archive_write_set_compression_bzip2.c
+++ b/lib/libarchive/archive_write_set_compression_bzip2.c
@@ -320,6 +320,10 @@ drive_compressor(struct archive_write *a, struct private_data *state, int finish
state->stream.avail_out = bytes_written;
}
+ /* If there's nothing to do, we're done. */
+ if (!finishing && state->stream.avail_in == 0)
+ return (ARCHIVE_OK);
+
ret = BZ2_bzCompress(&(state->stream),
finishing ? BZ_FINISH : BZ_RUN);
@@ -339,7 +343,9 @@ drive_compressor(struct archive_write *a, struct private_data *state, int finish
/* Any other return value indicates an error */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_PROGRAMMER,
- "Bzip2 compression failed");
+ "Bzip2 compression failed;"
+ " BZ2_bzCompress() returned %d",
+ ret);
return (ARCHIVE_FATAL);
}
}
diff --git a/lib/libarchive/archive_write_set_compression_gzip.c b/lib/libarchive/archive_write_set_compression_gzip.c
index 8c6d427003d9..b2e4f80c61fd 100644
--- a/lib/libarchive/archive_write_set_compression_gzip.c
+++ b/lib/libarchive/archive_write_set_compression_gzip.c
@@ -378,6 +378,10 @@ drive_compressor(struct archive_write *a, struct private_data *state, int finish
state->stream.avail_out = bytes_written;
}
+ /* If there's nothing to do, we're done. */
+ if (!finishing && state->stream.avail_in == 0)
+ return (ARCHIVE_OK);
+
ret = deflate(&(state->stream),
finishing ? Z_FINISH : Z_NO_FLUSH );
@@ -396,7 +400,9 @@ drive_compressor(struct archive_write *a, struct private_data *state, int finish
default:
/* Any other return value indicates an error. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "GZip compression failed");
+ "GZip compression failed:"
+ " deflate() call returned status %d",
+ ret);
return (ARCHIVE_FATAL);
}
}
diff --git a/lib/libarchive/archive_write_set_compression_none.c b/lib/libarchive/archive_write_set_compression_none.c
index 1fc8f117ed7c..36828c28fa5e 100644
--- a/lib/libarchive/archive_write_set_compression_none.c
+++ b/lib/libarchive/archive_write_set_compression_none.c
@@ -151,11 +151,18 @@ archive_compressor_none_write(struct archive_write *a, const void *vbuff,
return (ARCHIVE_OK);
}
- while ((remaining > 0) || (state->avail == 0)) {
- /*
- * If we have a full output block, write it and reset the
- * output buffer.
- */
+ /* If the copy buffer isn't empty, try to fill it. */
+ if (state->avail < state->buffer_size) {
+ /* If buffer is not empty... */
+ /* ... copy data into buffer ... */
+ to_copy = (remaining > state->avail) ?
+ state->avail : remaining;
+ memcpy(state->next, buff, to_copy);
+ state->next += to_copy;
+ state->avail -= to_copy;
+ buff += to_copy;
+ remaining -= to_copy;
+ /* ... if it's full, write it out. */
if (state->avail == 0) {
bytes_written = (a->client_writer)(&a->archive,
a->client_data, state->buffer, state->buffer_size);
@@ -166,16 +173,26 @@ archive_compressor_none_write(struct archive_write *a, const void *vbuff,
state->next = state->buffer;
state->avail = state->buffer_size;
}
+ }
- /* Now we have space in the buffer; copy new data into it. */
- to_copy = (remaining > state->avail) ?
- state->avail : remaining;
- memcpy(state->next, buff, to_copy);
- state->next += to_copy;
- state->avail -= to_copy;
- buff += to_copy;
- remaining -= to_copy;
+ while (remaining > state->buffer_size) {
+ /* Write out full blocks directly to client. */
+ bytes_written = (a->client_writer)(&a->archive,
+ a->client_data, buff, state->buffer_size);
+ if (bytes_written <= 0)
+ return (ARCHIVE_FATAL);
+ a->archive.raw_position += bytes_written;
+ buff += bytes_written;
+ remaining -= bytes_written;
}
+
+ if (remaining > 0) {
+ /* Copy last bit into copy buffer. */
+ memcpy(state->next, buff, remaining);
+ state->next += remaining;
+ state->avail -= remaining;
+ }
+
a->archive.file_position += length;
return (ARCHIVE_OK);
}
diff --git a/lib/libarchive/archive_write_set_format_ar.c b/lib/libarchive/archive_write_set_format_ar.c
index 1b17282be1bc..6a223c3ae787 100644
--- a/lib/libarchive/archive_write_set_format_ar.c
+++ b/lib/libarchive/archive_write_set_format_ar.c
@@ -75,8 +75,9 @@ static int archive_write_ar_header(struct archive_write *,
static ssize_t archive_write_ar_data(struct archive_write *,
const void *buff, size_t s);
static int archive_write_ar_destroy(struct archive_write *);
+static int archive_write_ar_finish(struct archive_write *);
static int archive_write_ar_finish_entry(struct archive_write *);
-static const char *basename(const char *path);
+static const char *ar_basename(const char *path);
static int format_octal(int64_t v, char *p, int s);
static int format_decimal(int64_t v, char *p, int s);
@@ -126,7 +127,7 @@ archive_write_set_format_ar(struct archive_write *a)
a->format_write_header = archive_write_ar_header;
a->format_write_data = archive_write_ar_data;
- a->format_finish = NULL;
+ a->format_finish = archive_write_ar_finish;
a->format_destroy = archive_write_ar_destroy;
a->format_finish_entry = archive_write_ar_finish_entry;
return (ARCHIVE_OK);
@@ -192,11 +193,11 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
goto size;
}
- /*
+ /*
* Otherwise, entry is a normal archive member.
* Strip leading paths from filenames, if any.
*/
- if ((filename = basename(pathname)) == NULL) {
+ if ((filename = ar_basename(pathname)) == NULL) {
/* Reject filenames with trailing "/" */
archive_set_error(&a->archive, EINVAL,
"Invalid filename");
@@ -398,6 +399,23 @@ archive_write_ar_destroy(struct archive_write *a)
}
static int
+archive_write_ar_finish(struct archive_write *a)
+{
+ int ret;
+
+ /*
+ * If we haven't written anything yet, we need to write
+ * the ar global header now to make it a valid ar archive.
+ */
+ if (a->archive.file_position == 0) {
+ ret = (a->compressor.write)(a, "!<arch>\n", 8);
+ return (ret);
+ }
+
+ return (ARCHIVE_OK);
+}
+
+static int
archive_write_ar_finish_entry(struct archive_write *a)
{
struct ar_w *ar;
@@ -507,7 +525,7 @@ format_decimal(int64_t v, char *p, int s)
}
static const char *
-basename(const char *path)
+ar_basename(const char *path)
{
const char *endp, *startp;
diff --git a/lib/libarchive/archive_write_set_format_cpio.c b/lib/libarchive/archive_write_set_format_cpio.c
index ba23f3218055..631830e99cf8 100644
--- a/lib/libarchive/archive_write_set_format_cpio.c
+++ b/lib/libarchive/archive_write_set_format_cpio.c
@@ -228,6 +228,7 @@ archive_write_cpio_finish(struct archive_write *a)
cpio = (struct cpio *)a->format_data;
trailer = archive_entry_new();
+ /* nlink = 1 here for GNU cpio compat. */
archive_entry_set_nlink(trailer, 1);
archive_entry_set_pathname(trailer, "TRAILER!!!");
er = archive_write_cpio_header(a, trailer);
diff --git a/lib/libarchive/archive_write_set_format_cpio_newc.c b/lib/libarchive/archive_write_set_format_cpio_newc.c
index 37dd35af6313..6580b52faa34 100644
--- a/lib/libarchive/archive_write_set_format_cpio_newc.c
+++ b/lib/libarchive/archive_write_set_format_cpio_newc.c
@@ -176,9 +176,15 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
cpio->entry_bytes_remaining = archive_entry_size(entry);
cpio->padding = 3 & (-cpio->entry_bytes_remaining);
+
/* Write the symlink now. */
- if (p != NULL && *p != '\0')
+ if (p != NULL && *p != '\0') {
ret = (a->compressor.write)(a, p, strlen(p));
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ pad = 0x3 & -strlen(p);
+ ret = (a->compressor.write)(a, "\0\0\0", pad);
+ }
return (ret);
}
diff --git a/lib/libarchive/archive_write_set_format_pax.c b/lib/libarchive/archive_write_set_format_pax.c
index 0007e3a7c607..fbec7eb316c8 100644
--- a/lib/libarchive/archive_write_set_format_pax.c
+++ b/lib/libarchive/archive_write_set_format_pax.c
@@ -418,12 +418,15 @@ archive_write_pax_header(struct archive_write *a,
p = archive_entry_pathname(entry_original);
if (p[strlen(p) - 1] != '/') {
t = (char *)malloc(strlen(p) + 2);
- if (t != NULL) {
- strcpy(t, p);
- strcat(t, "/");
- archive_entry_copy_pathname(entry_original, t);
- free(t);
+ if (t == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate pax data");
+ return(ARCHIVE_FATAL);
}
+ strcpy(t, p);
+ strcat(t, "/");
+ archive_entry_copy_pathname(entry_original, t);
+ free(t);
}
break;
default:
diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c
index 390b1a0c5697..43b654345305 100644
--- a/lib/libarchive/archive_write_set_format_ustar.c
+++ b/lib/libarchive/archive_write_set_format_ustar.c
@@ -216,12 +216,15 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
p = archive_entry_pathname(entry);
if (p[strlen(p) - 1] != '/') {
t = (char *)malloc(strlen(p) + 2);
- if (t != NULL) {
- strcpy(t, p);
- strcat(t, "/");
- archive_entry_copy_pathname(entry, t);
- free(t);
+ if (t == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
}
+ strcpy(t, p);
+ strcat(t, "/");
+ archive_entry_copy_pathname(entry, t);
+ free(t);
}
}
diff --git a/lib/libarchive/filter_fork.c b/lib/libarchive/filter_fork.c
index a7ee48b46309..41c20f0b53bb 100644
--- a/lib/libarchive/filter_fork.c
+++ b/lib/libarchive/filter_fork.c
@@ -30,6 +30,8 @@ __FBSDID("$FreeBSD$");
#if defined(HAVE_POLL)
# if defined(HAVE_POLL_H)
# include <poll.h>
+# elif defined(HAVE_SYS_POLL_H)
+# include <sys/poll.h>
# endif
#elif defined(HAVE_SELECT)
# if defined(HAVE_SYS_SELECT_H)
diff --git a/lib/libarchive/libarchive-formats.5 b/lib/libarchive/libarchive-formats.5
index 52e2e366214b..7cc64ecb8182 100644
--- a/lib/libarchive/libarchive-formats.5
+++ b/lib/libarchive/libarchive-formats.5
@@ -74,6 +74,8 @@ It currently supports the most popular GNU extensions, including
modern long filename and linkname support, as well as atime and ctime data.
The libarchive library does not support multi-volume
archives, nor the old GNU long filename format.
+It can read GNU sparse file entries, including the new POSIX-based
+formats, but cannot write GNU sparse file entries.
.It Cm pax
The
.Xr libarchive 3
@@ -93,7 +95,7 @@ defined by Joerg Schilling's
.Dq star
archiver.
The libarchive library can read most of the SCHILY keys.
-It ignores any keywords that it does not understand.
+It silently ignores any keywords that it does not understand.
.It Cm restricted pax
The libarchive library can also write pax archives in which it
attempts to suppress the extended attributes entry whenever
@@ -139,19 +141,18 @@ In particular, it supports base-256 values in certain numeric fields.
This essentially removes the limitations on file size, modification time,
and device numbers.
.Pp
-The first tar program appeared in Sixth Edition Unix (circa 1976).
-This makes the tar format one of the oldest and most widely-supported
-archive formats.
+The first tar program appeared in Seventh Edition Unix in 1979.
The first official standard for the tar file format was the
.Dq ustar
(Unix Standard Tar) format defined by POSIX in 1988.
POSIX.1-2001 extended the ustar format to create the
.Dq pax interchange
format.
-There have also been many custom variations.
.Ss Cpio Formats
The libarchive library can read a number of common cpio variants and can write
.Dq odc
+and
+.Dq newc
format archives.
A cpio archive stores each entry as a fixed-size header followed
by a variable-length filename and variable-length data.
@@ -184,15 +185,26 @@ The SVR4 format can optionally include a CRC of the file
contents, although libarchive does not currently verify this CRC.
.El
.Pp
-Cpio is an old format that was widely used because of its simplicity
-and its support for very long filenames.
-Unfortunately, it has many limitations that make it unsuitable
+Cpio first appeared in PWB/UNIX 1.0, which was released within
+AT&T in 1977.
+PWB/UNIX 1.0 formed the basis of System III Unix, released outside
+of AT&T in 1981.
+This makes cpio older than tar, although cpio was not included
+in Version 7 AT&T Unix.
+As a result, the tar command became much better known in universities
+and research groups that used Version 7.
+The combination of the
+.Nm find
+and
+.Nm cpio
+utilities provided very precise control over file selection.
+Unfortunately, the format has many limitations that make it unsuitable
for widespread use.
Only the POSIX format permits files over 4GB, and its 18-bit
limit for most other fields makes it unsuitable for modern systems.
In addition, cpio formats only store numeric UID/GID values (not
usernames and group names), which can make it very difficult to correctly
-transfer archives across systems.
+transfer archives across systems with dissimilar user numbering.
.Ss Shar Formats
A
.Dq shell archive
@@ -255,4 +267,6 @@ Libarchive provides read and write support for both variants.
.Xr tar 1 ,
.Xr zip 1 ,
.Xr zlib 3 ,
+.Xr cpio 5 ,
+.Xr mtree 5 ,
.Xr tar 5
diff --git a/lib/libarchive/libarchive_internals.3 b/lib/libarchive/libarchive_internals.3
index c8f79ffac569..f050bfb5fdc7 100644
--- a/lib/libarchive/libarchive_internals.3
+++ b/lib/libarchive/libarchive_internals.3
@@ -96,12 +96,9 @@ When opening the archive, it reads an initial block of data
and offers it to each registered compression handler.
The one with the highest bid is initialized with the first block.
Similarly, the format handlers are polled to see which handler
-is the best for each header request.
-(Note that a single file can have entries handled by different
-format handlers;
-this allows a simple handler for a generic version of a format
-with more complex handlers implemented independently for
-extended sub-formats.)
+is the best for each archive.
+(Prior to 2.4.0, the format bidders were invoked for each
+entry, but this design hindered error recovery.)
.Ss I/O Layer and Client Callbacks
The read API goes to some lengths to be nice to clients.
As a result, there are few restrictions on the behavior of
@@ -116,6 +113,8 @@ In particular, blocks may be of different sizes.
The client skip callback returns the number of bytes actually
skipped, which may be much smaller than the skip requested.
The only requirement is that the skip not be larger.
+In particular, clients are allowed to return zero for any
+skip that they don't want to handle.
The skip callback must never be invoked with a negative value.
.Pp
Keep in mind that not all clients are reading from disk:
@@ -242,21 +241,12 @@ decompression method but not calling the
method.
This allows each bidder to look ahead in the input stream.
Bidders should not look further ahead than necessary, as long
-look aheads put pressure on the compression layer to buffer
+look aheads put pressure on the decompression layer to buffer
lots of data.
Most formats only require a few hundred bytes of look ahead;
look aheads of a few kilobytes are reasonable.
(The ISO9660 reader sometimes looks ahead by 48k, which
should be considered an upper limit.)
-Note that the bidder is invoked for every entry.
-For many formats, this is inappropriate; if you can only bid at
-the beginning of the file, store your bid value and check that
-each time your bid function is called.
-For example, the ISO9660 reader initializes a
-.Va bid
-value to -1 at registration time;
-each time the bid function is called, the bid value is returned
-immediately if it is zero or larger.
.It Read header
The header read is usually the most complex part of any format.
There are a few strategies worth mentioning:
diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile
index 6c1fb485d7d2..d55e2e6dfd4b 100644
--- a/lib/libarchive/test/Makefile
+++ b/lib/libarchive/test/Makefile
@@ -1,11 +1,34 @@
# $FreeBSD$
+# Where to find the libarchive sources
+LA_SRCDIR=${.CURDIR}/..
+.PATH: ${LA_SRCDIR}
+
+# Get a list of all libarchive source files
+LA_SRCS!=make -f ${LA_SRCDIR}/Makefile -V SRCS
+
+TESTFILES= \
+ test_compat_gtar_1.tgz \
+ test_compat_tar_hardlink_1.tar \
+ test_compat_zip_1.zip \
+ test_read_format_gtar_sparse_1_13.tgz \
+ test_read_format_gtar_sparse_1_17.tgz \
+ test_read_format_gtar_sparse_1_17_posix00.tgz \
+ test_read_format_gtar_sparse_1_17_posix01.tgz \
+ test_read_format_gtar_sparse_1_17_posix10.tgz \
+ test_read_format_gtar_sparse_1_17_posix10_modified.tar
+
TESTS= \
test_acl_basic.c \
test_acl_pax.c \
test_archive_api_feature.c \
test_bad_fd.c \
+ test_compat_gtar.c \
+ test_compat_tar_hardlink.c \
+ test_compat_zip.c \
+ test_empty_write.c \
test_entry.c \
+ test_entry_strmode.c \
test_read_compress_program.c \
test_read_data_large.c \
test_read_extract.c \
@@ -22,6 +45,7 @@ TESTS= \
test_read_format_gtar_sparse.c \
test_read_format_iso_gz.c \
test_read_format_isorr_bz2.c \
+ test_read_format_mtree.c \
test_read_format_pax_bz2.c \
test_read_format_tar.c \
test_read_format_tbz.c \
@@ -33,50 +57,75 @@ TESTS= \
test_read_position.c \
test_read_truncated.c \
test_tar_filenames.c \
+ test_tar_large.c \
test_write_compress_program.c \
test_write_disk.c \
+ test_write_disk_hardlink.c \
test_write_disk_perms.c \
test_write_disk_secure.c \
test_write_format_ar.c \
test_write_format_cpio.c \
+ test_write_format_cpio_odc.c \
+ test_write_format_cpio_newc.c \
test_write_format_cpio_empty.c \
test_write_format_shar_empty.c \
test_write_format_tar.c \
test_write_format_tar_empty.c \
test_write_open_memory.c
-SRCS= ${TESTS} \
+
+# Build the test program using all libarchive sources + the test sources.
+SRCS= ${LA_SRCS} \
+ ${TESTS} \
list.h \
main.c \
read_open_memory.c
-CLEANFILES+= list.h
+CLEANFILES+= list.h archive.h
NO_MAN=yes
PROG=libarchive_test
-DPADD=${LIBARCHIVE} ${LIBBZ2} ${LIBZ}
-LDADD= -larchive -lz -lbz2
+INTERNALPROG=yes # Don't install this; it's just for testing
+DPADD=${LIBBZ2} ${LIBZ}
+CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
+LDADD= -lz -lbz2
CFLAGS+= -static -g
CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -I${LA_SRCDIR}
+# Without this, libarchive source files find archive.h in LA_SRCDIR,
+# which may not be the same as archive.h in the test dir.
+CFLAGS+= -I-
# Uncomment to link against dmalloc
-#LDADD+= -L/usr/local/lib -ldmalloc
-#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
-#WARNS=6
+LDADD+= -L/usr/local/lib -ldmalloc
+CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+WARNS=6
-test: libarchive_test
- ./libarchive_test -k
+# Build libarchive_test and run it.
+check test: libarchive_test ${TESTFILES}
+ ./libarchive_test
+.for f in ${TESTFILES}
+${f}: ${f}.uu
+ uudecode -p ${.CURDIR}/${f}.uu >${f}
+.endfor
+
+INCS=archive.h list.h
+
+# Build archive.h, but in our .OBJDIR, not libarchive's
+# This keeps libarchive_test and libarchive builds completely separate.
+archive.h: ${LA_SRCDIR}/archive.h.in ${LA_SRCDIR}/Makefile
+ cd ${LA_SRCDIR} && unset MAKEOBJDIRPREFIX && MAKEOBJDIR=${.OBJDIR} make archive.h
+
+# list.h is just a list of all tests, as indicated by DEFINE_TEST macro lines
list.h: ${TESTS} Makefile
(cd ${.CURDIR}; cat ${TESTS}) | grep DEFINE_TEST > list.h
-clean:
- rm -f *.out
- rm -f *.o
- rm -f *.core
- rm -f *~
- rm -f list.h
+CLEANFILES += *.out *.o *.core *~ list.h archive.h ${TESTFILES}
+
+cleantest:
-chmod -R +w /tmp/libarchive_test.*
rm -rf /tmp/libarchive_test.*
diff --git a/lib/libarchive/test/README b/lib/libarchive/test/README
index 011aa8ec4721..0190b7c490ba 100644
--- a/lib/libarchive/test/README
+++ b/lib/libarchive/test/README
@@ -32,7 +32,11 @@ Each test function can rely on the following:
* The test function should use assert(), assertA() and similar macros
defined in test.h. If you need to add new macros of this form, feel
- free to do so.
+ free to do so. The current macro set includes assertEqualInt() and
+ assertEqualString() that print out additional detail about their
+ arguments if the assertion does fail. 'A' versions also accept
+ a struct archive * and display any error message from there on
+ failure.
* You are encouraged to document each assertion with a failure() call
just before the assert. The failure() function is a printf-like
@@ -43,7 +47,10 @@ Each test function can rely on the following:
assert(strcmp(buff1, buff2) == 0);
* Tests are encouraged to be economical with their memory and disk usage,
- though this is not essential.
+ though this is not essential. The test is occasionally run under
+ a memory debugger to try to locate memory leaks in the library;
+ as a result, tests should be careful to release any memory they
+ allocate.
* Disable tests on specific platforms as necessary. Please don't
use config.h to adjust feature requirements, as I want the tests
@@ -53,3 +60,4 @@ Each test function can rely on the following:
#if !defined(__PLATFORM) && !defined(__Platform2__)
assert(xxxx)
#endif
+
diff --git a/lib/libarchive/test/main.c b/lib/libarchive/test/main.c
index b64fe75614b8..ffe81cf30a51 100644
--- a/lib/libarchive/test/main.c
+++ b/lib/libarchive/test/main.c
@@ -24,6 +24,17 @@
*/
/*
+ * This same file is used pretty much verbatim for all test harnesses.
+ *
+ * The next line is used to define various environment variables, etc.
+ *
+ * The tar and cpio test harnesses are identical except for this line;
+ * the libarchive test harness omits some code that is needed only for
+ * testing standalone executables.
+ */
+#define PROGRAM "LIBARCHIVE"
+
+/*
* Various utility routines useful for test programs.
* Each test program is linked against this file.
*/
@@ -34,6 +45,18 @@
#include "test.h"
__FBSDID("$FreeBSD$");
+/*
+ * "list.h" is simply created by "grep DEFINE_TEST"; it has
+ * a line like
+ * DEFINE_TEST(test_function)
+ * for each test.
+ * Include it here with a suitable DEFINE_TEST to declare all of the
+ * test functions.
+ */
+#undef DEFINE_TEST
+#define DEFINE_TEST(name) void name(void);
+#include "list.h"
+
/* Interix doesn't define these in a standard header. */
#if __INTERIX__
extern char *optarg;
@@ -48,6 +71,8 @@ static int quiet_flag = 0;
static int failures = 0;
/* Cumulative count of skipped component tests. */
static int skips = 0;
+/* Cumulative count of assertions. */
+static int assertions = 0;
/*
* My own implementation of the standard assert() macro emits the
@@ -57,12 +82,10 @@ static int skips = 0;
* Emacs. ;-)
*
* It also supports a few special features specifically to simplify
- * libarchive test harnesses:
+ * test harnesses:
* failure(fmt, args) -- Stores a text string that gets
* printed if the following assertion fails, good for
* explaining subtle tests.
- * assertA(a, cond) -- If the test fails, also prints out any error
- * message stored in archive object 'a'.
*/
static char msg[4096];
@@ -76,12 +99,13 @@ static struct line {
int count;
} failed_lines[1000];
-
-/* Count this failure; return the number of previous failures. */
+/*
+ * Count this failure; return the number of previous failures.
+ */
static int
previous_failures(const char *filename, int line)
{
- int i;
+ unsigned int i;
int count;
if (failed_filename == NULL || strcmp(failed_filename, filename) != 0)
@@ -100,24 +124,30 @@ previous_failures(const char *filename, int line)
return (0);
}
}
+ return (0);
}
-/* Inform user that we're skipping a test. */
-static const char *skipped_filename;
-static int skipped_line;
-void skipping_setup(const char *filename, int line)
+/*
+ * Copy arguments into file-local variables.
+ */
+static const char *test_filename;
+static int test_line;
+static void *test_extra;
+void test_setup(const char *filename, int line)
{
- skipped_filename = filename;
- skipped_line = line;
+ test_filename = filename;
+ test_line = line;
}
+
+/*
+ * Inform user that we're skipping a test.
+ */
void
test_skipping(const char *fmt, ...)
{
- int i;
- int line = skipped_line;
va_list ap;
- if (previous_failures(skipped_filename, skipped_line))
+ if (previous_failures(test_filename, test_line))
return;
va_start(ap, fmt);
@@ -130,29 +160,30 @@ test_skipping(const char *fmt, ...)
/* Common handling of failed tests. */
static void
-test_failed(struct archive *a, int line)
+report_failure(void *extra)
{
- int i;
-
- failures ++;
-
if (msg[0] != '\0') {
fprintf(stderr, " Description: %s\n", msg);
msg[0] = '\0';
}
- if (a != NULL) {
- fprintf(stderr, " archive error: %s\n", archive_error_string(a));
+ if (extra != NULL) {
+ fprintf(stderr, " archive error: %s\n", archive_error_string((struct archive *)extra));
}
if (dump_on_failure) {
- fprintf(stderr, " *** forcing core dump so failure can be debugged ***\n");
+ fprintf(stderr,
+ " *** forcing core dump so failure can be debugged ***\n");
*(char *)(NULL) = 0;
exit(1);
}
}
-/* Summarize repeated failures in the just-completed test file. */
-int
+/*
+ * Summarize repeated failures in the just-completed test file.
+ * The reports above suppress multiple failures from the same source
+ * line; this reports on any tests that did fail multiple times.
+ */
+static int
summarize_comparator(const void *a0, const void *b0)
{
const struct line *a = a0, *b = b0;
@@ -165,10 +196,10 @@ summarize_comparator(const void *a0, const void *b0)
return (a->line - b->line);
}
-void
-summarize(const char *filename)
+static void
+summarize(void)
{
- int i;
+ unsigned int i;
qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]),
sizeof(failed_lines[0]), summarize_comparator);
@@ -196,35 +227,39 @@ failure(const char *fmt, ...)
/* Generic assert() just displays the failed condition. */
void
-test_assert(const char *file, int line, int value, const char *condition, struct archive *a)
+test_assert(const char *file, int line, int value, const char *condition, void *extra)
{
+ ++assertions;
if (value) {
msg[0] = '\0';
return;
}
+ failures ++;
if (previous_failures(file, line))
return;
fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
fprintf(stderr, " Condition: %s\n", condition);
- test_failed(a, line);
+ report_failure(extra);
}
/* assertEqualInt() displays the values of the two integers. */
void
test_assert_equal_int(const char *file, int line,
- int v1, const char *e1, int v2, const char *e2, struct archive *a)
+ int v1, const char *e1, int v2, const char *e2, void *extra)
{
+ ++assertions;
if (v1 == v2) {
msg[0] = '\0';
return;
}
+ failures ++;
if (previous_failures(file, line))
return;
fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
file, line);
fprintf(stderr, " %s=%d\n", e1, v1);
fprintf(stderr, " %s=%d\n", e2, v2);
- test_failed(a, line);
+ report_failure(extra);
}
/* assertEqualString() displays the values of the two strings. */
@@ -232,8 +267,9 @@ void
test_assert_equal_string(const char *file, int line,
const char *v1, const char *e1,
const char *v2, const char *e2,
- struct archive *a)
+ void *extra)
{
+ ++assertions;
if (v1 == NULL || v2 == NULL) {
if (v1 == v2) {
msg[0] = '\0';
@@ -243,13 +279,14 @@ test_assert_equal_string(const char *file, int line,
msg[0] = '\0';
return;
}
+ failures ++;
if (previous_failures(file, line))
return;
fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
file, line);
fprintf(stderr, " %s = \"%s\"\n", e1, v1);
fprintf(stderr, " %s = \"%s\"\n", e2, v2);
- test_failed(a, line);
+ report_failure(extra);
}
/* assertEqualWString() displays the values of the two strings. */
@@ -257,26 +294,222 @@ void
test_assert_equal_wstring(const char *file, int line,
const wchar_t *v1, const char *e1,
const wchar_t *v2, const char *e2,
- struct archive *a)
+ void *extra)
{
+ ++assertions;
if (wcscmp(v1, v2) == 0) {
msg[0] = '\0';
return;
}
+ failures ++;
if (previous_failures(file, line))
return;
fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
file, line);
fwprintf(stderr, L" %s = \"%ls\"\n", e1, v1);
fwprintf(stderr, L" %s = \"%ls\"\n", e2, v2);
- test_failed(a, line);
+ report_failure(extra);
+}
+
+/*
+ * 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;
+
+ for(i=0; i < l; i+=16) {
+ fprintf(stderr, "%04x", i + offset);
+ sep = ' ';
+ for (j = 0; j < 16 && i + j < l; j++) {
+ if (ref != NULL && p[i + j] != ref[i + j])
+ sep = '_';
+ fprintf(stderr, "%c%02x", sep, p[i+j]);
+ if (ref != NULL && p[i + j] == ref[i + j])
+ sep = ' ';
+ }
+ for (; j < 16; j++) {
+ fprintf(stderr, "%c ", sep);
+ sep = ' ';
+ }
+ fprintf(stderr, "%c", sep);
+ for (j=0; j < 16 && i + j < l; j++) {
+ int c = p[i + j];
+ if (c >= ' ' && c <= 126)
+ fprintf(stderr, "%c", c);
+ else
+ fprintf(stderr, ".");
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+/* assertEqualMem() displays the values of the two memory blocks. */
+/* TODO: For long blocks, hexdump the first bytes that actually differ. */
+void
+test_assert_equal_mem(const char *file, int line,
+ const char *v1, const char *e1,
+ const char *v2, const char *e2,
+ size_t l, const char *ld, void *extra)
+{
+ ++assertions;
+ if (v1 == NULL || v2 == NULL) {
+ if (v1 == v2) {
+ msg[0] = '\0';
+ return;
+ }
+ } else if (memcmp(v1, v2, l) == 0) {
+ msg[0] = '\0';
+ return;
+ }
+ failures ++;
+ if (previous_failures(file, line))
+ return;
+ fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
+ file, line);
+ fprintf(stderr, " size %s = %d\n", ld, (int)l);
+ fprintf(stderr, " Dump of %s\n", e1);
+ hexdump(v1, v2, l < 32 ? l : 32, 0);
+ fprintf(stderr, " Dump of %s\n", e2);
+ hexdump(v2, v1, l < 32 ? l : 32, 0);
+ fprintf(stderr, "\n");
+ report_failure(extra);
+}
+
+void
+test_assert_empty_file(const char *f1fmt, ...)
+{
+ char f1[1024];
+ struct stat st;
+ va_list ap;
+
+ va_start(ap, f1fmt);
+ vsprintf(f1, f1fmt, ap);
+ va_end(ap);
+
+ if (stat(f1, &st) != 0) {
+ fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
+ report_failure(NULL);
+ } else if (st.st_size > 0) {
+ fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
+ fprintf(stderr, " File size: %d\n", (int)st.st_size);
+ report_failure(NULL);
+ }
+}
+
+/* assertEqualFile() asserts that two files have the same contents. */
+/* TODO: hexdump the first bytes that actually differ. */
+void
+test_assert_equal_file(const char *f1, const char *f2pattern, ...)
+{
+ char f2[1024];
+ va_list ap;
+ char buff1[1024];
+ char buff2[1024];
+ int fd1, fd2;
+ int n1, n2;
+
+ va_start(ap, f2pattern);
+ vsprintf(f2, f2pattern, ap);
+ va_end(ap);
+
+ fd1 = open(f1, O_RDONLY);
+ fd2 = open(f2, O_RDONLY);
+ for (;;) {
+ n1 = read(fd1, buff1, sizeof(buff1));
+ n2 = read(fd2, buff2, sizeof(buff2));
+ if (n1 != n2)
+ break;
+ if (n1 == 0 && n2 == 0)
+ return;
+ if (memcmp(buff1, buff2, n1) != 0)
+ break;
+ }
+ fprintf(stderr, "%s:%d: Files are not identical\n", test_filename, test_line);
+ fprintf(stderr, " file1=\"%s\"\n", f1);
+ fprintf(stderr, " file2=\"%s\"\n", f2);
+ report_failure(test_extra);
+}
+
+
+/*
+ * 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);
+ 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;
+ int fd;
+ int r;
+
+ va_start(ap, fmt);
+ vsprintf(filename, fmt, ap);
+ va_end(ap);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ /* Note: No error; non-existent file is okay here. */
+ return (NULL);
+ }
+ r = fstat(fd, &st);
+ if (r != 0) {
+ fprintf(stderr, "Can't stat file %s\n", filename);
+ close(fd);
+ return (NULL);
+ }
+ p = malloc(st.st_size + 1);
+ if (p == NULL) {
+ fprintf(stderr, "Can't allocate %ld bytes of memory to read file %s\n", (long int)st.st_size, filename);
+ close(fd);
+ return (NULL);
+ }
+ bytes_read = read(fd, p, st.st_size);
+ if (bytes_read < st.st_size) {
+ fprintf(stderr, "Can't read file %s\n", filename);
+ close(fd);
+ free(p);
+ return (NULL);
+ }
+ p[st.st_size] = '\0';
+ if (sizep != NULL)
+ *sizep = (size_t)st.st_size;
+ close(fd);
+ return (p);
}
/*
* "list.h" is automatically generated; it just has a lot of lines like:
* DEFINE_TEST(function_name)
- * The common "test.h" includes it to declare all of the test functions.
- * We reuse it here to define a list of all tests to run.
+ * It's used above to declare all of the test functions.
+ * We reuse it here to define a list of all tests (functions and names).
*/
#undef DEFINE_TEST
#define DEFINE_TEST(n) { n, #n },
@@ -284,6 +517,12 @@ struct { void (*func)(void); const char *name; } tests[] = {
#include "list.h"
};
+/*
+ * Each test is run in a private work dir. Those work dirs
+ * do have consistent and predictable names, in case a group
+ * of tests need to collaborate. However, there is no provision
+ * for requiring that tests run in a certain order.
+ */
static int test_run(int i, const char *tmpdir)
{
int failures_before = failures;
@@ -307,29 +546,35 @@ static int test_run(int i, const char *tmpdir)
tests[i].name);
exit(1);
}
+ /* Chdir() to that work directory. */
if (chdir(tests[i].name)) {
fprintf(stderr,
"ERROR: Couldn't chdir to temp dir ``%s''\n",
tests[i].name);
exit(1);
}
+ /* Run the actual test. */
(*tests[i].func)();
- summarize(tests[i].name);
+ /* Summarize the results of this test. */
+ summarize();
+ /* Return appropriate status. */
return (failures == failures_before ? 0 : 1);
}
-static void usage(void)
+static void usage(const char *program)
{
static const int limit = sizeof(tests) / sizeof(tests[0]);
int i;
- printf("Usage: libarchive_test [options] <test> <test> ...\n");
+ 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(" -k Keep running after failures.\n");
printf(" Default: Core dump after any failure.\n");
printf(" -q Quiet.\n");
+ printf(" -r <dir> Path to dir containing reference files.\n");
+ printf(" Default: Current directory.\n");
printf("Available tests:\n");
for (i = 0; i < limit; i++)
printf(" %d: %s\n", i, tests[i].name);
@@ -341,19 +586,42 @@ int main(int argc, char **argv)
static const int limit = sizeof(tests) / sizeof(tests[0]);
int i, tests_run = 0, tests_failed = 0, opt;
time_t now;
+ char *refdir_alloc = NULL;
+ char *progname, *p;
char tmpdir[256];
+ char tmpdir_timestamp[256];
+
+ /*
+ * Name of this program, used to build root of our temp directory
+ * tree.
+ */
+ progname = p = argv[0];
+ while (*p != '\0') {
+ if (*p == '/')
+ progname = p + 1;
+ ++p;
+ }
+
+ /* Get the directory holding test files from environment. */
+ refdir = getenv(PROGRAM "_TEST_FILES");
- while ((opt = getopt(argc, argv, "kq")) != -1) {
+ /*
+ * Parse options.
+ */
+ while ((opt = getopt(argc, argv, "kqr:")) != -1) {
switch (opt) {
case 'k':
dump_on_failure = 0;
break;
case 'q':
- quiet_flag = 1;
+ quiet_flag++;
+ break;
+ case 'r':
+ refdir = optarg;
break;
case '?':
default:
- usage();
+ usage(progname);
}
}
argc -= optind;
@@ -366,10 +634,10 @@ int main(int argc, char **argv)
*/
now = time(NULL);
for (i = 0; i < 1000; i++) {
- strftime(tmpdir, sizeof(tmpdir),
- "/tmp/libarchive_test.%Y-%m-%dT%H.%M.%S",
+ strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
+ "%Y-%m-%dT%H.%M.%S",
localtime(&now));
- sprintf(tmpdir + strlen(tmpdir), "-%03d", i);
+ sprintf(tmpdir, "/tmp/%s.%s-%03d", progname, tmpdir_timestamp, i);
if (mkdir(tmpdir,0755) == 0)
break;
if (errno == EEXIST)
@@ -379,11 +647,32 @@ int main(int argc, char **argv)
exit(1);
}
+ /*
+ * If the user didn't specify a directory for locating
+ * reference files, use the current directory for that.
+ */
+ if (refdir == NULL) {
+ systemf("/bin/pwd > %s/refdir", tmpdir);
+ refdir = refdir_alloc = slurpfile(NULL, "%s/refdir", tmpdir);
+ p = refdir + strlen(refdir);
+ while (p[-1] == '\n') {
+ --p;
+ *p = '\0';
+ }
+ }
+
+ /*
+ * Banner with basic information.
+ */
if (!quiet_flag) {
- printf("Running libarchive tests in: %s\n", tmpdir);
+ printf("Running tests in: %s\n", tmpdir);
+ printf("Reference files will be read from: %s\n", refdir);
printf("Exercising %s\n", archive_version());
}
+ /*
+ * Run some or all of the individual tests.
+ */
if (argc == 0) {
/* Default: Run all tests. */
for (i = 0; i < limit; i++) {
@@ -396,7 +685,7 @@ int main(int argc, char **argv)
i = atoi(*argv);
if (**argv < '0' || **argv > '9' || i < 0 || i >= limit) {
printf("*** INVALID Test %s\n", *argv);
- usage();
+ usage(progname);
} else {
if (test_run(i, tmpdir))
tests_failed++;
@@ -405,10 +694,20 @@ int main(int argc, char **argv)
argv++;
}
}
- printf("\n");
- printf("%d of %d test groups reported failures\n",
- tests_failed, tests_run);
- printf(" Total of %d individual tests failed.\n", failures);
- printf(" Total of %d individual tests were skipped.\n", skips);
+
+ /*
+ * Report summary statistics.
+ */
+ if (!quiet_flag) {
+ printf("\n");
+ printf("%d of %d tests reported failures\n",
+ tests_failed, tests_run);
+ printf(" Total of %d assertions checked.\n", assertions);
+ printf(" Total of %d assertions failed.\n", failures);
+ printf(" Total of %d assertions skipped.\n", skips);
+ }
+
+ free(refdir_alloc);
+
return (tests_failed);
}
diff --git a/lib/libarchive/test/read_open_memory.c b/lib/libarchive/test/read_open_memory.c
index 6e1fc76794d7..63a7778c07ce 100644
--- a/lib/libarchive/test/read_open_memory.c
+++ b/lib/libarchive/test/read_open_memory.c
@@ -96,7 +96,7 @@ static ssize_t
memory_read(struct archive *a, void *client_data, const void **buff)
{
struct read_memory_data *mine = (struct read_memory_data *)client_data;
- ssize_t size;
+ size_t size;
(void)a; /* UNUSED */
size = mine->end - mine->buffer;
diff --git a/lib/libarchive/test/test.h b/lib/libarchive/test/test.h
index e867ea3600e6..3ec41eba7236 100644
--- a/lib/libarchive/test/test.h
+++ b/lib/libarchive/test/test.h
@@ -34,13 +34,13 @@
#define _FILE_OFFSET_BITS 64
-#include <archive.h>
-#include <archive_entry.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <wchar.h>
#ifdef USE_DMALLOC
@@ -69,52 +69,35 @@
#endif
/*
- * ARCHIVE_VERSION_STAMP first appeared in 1.9 and libarchive 2.2.4.
- * We can approximate it for earlier versions, though.
- * This is used to disable tests of features not present in the current
- * version.
- */
-#ifndef ARCHIVE_VERSION_STAMP
-#define ARCHIVE_VERSION_STAMP \
- (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
-#endif
-
-
-/*
- * "list.h" is simply created by "grep DEFINE_TEST"; it has
- * a line like
- * DEFINE_TEST(test_function)
- * for each test.
- * Include it here with a suitable DEFINE_TEST to declare all of the
- * test functions.
- */
-#define DEFINE_TEST(name) void name(void);
-#include "list.h"
-/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void)
+#define DEFINE_TEST(name) void name(void); void name(void)
/* An implementation of the standard assert() macro */
#define assert(e) test_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* As above, but reports any archive_error found in variable 'a' */
-#define assertA(e) test_assert(__FILE__, __LINE__, (e), #e, (a))
-/* Asserts that two integers are the same. Reports value of each one if not. */
-#define assertEqualIntA(a,v1,v2) \
- test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
+/* Assert two integers are the same. Reports value of each one if not. */
#define assertEqualInt(v1,v2) \
test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* Asserts that two strings are the same. Reports value of each one if not. */
-#define assertEqualStringA(a,v1,v2) \
- test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
+/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but raw blocks of bytes. */
+#define assertEqualMem(v1, v2, l) \
+ test_assert_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
+/* Assert two files are the same; allow printf-style expansion of second name.
+ * See below for comments about variable arguments here...
+ */
+#define assertEqualFile \
+ test_setup(__FILE__, __LINE__);test_assert_equal_file
+/* Assert that a file is empty; supports printf-style arguments. */
+#define assertEmptyFile \
+ test_setup(__FILE__, __LINE__);test_assert_empty_file
/*
* This would be simple with C99 variadic macros, but I don't want to
@@ -123,17 +106,58 @@
* but effective.
*/
#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
+ test_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
void failure(const char *fmt, ...);
-void skipping_setup(const char *, int);
+void test_setup(const char *, int);
void test_skipping(const char *fmt, ...);
-void test_assert(const char *, int, int, const char *, struct archive *);
-void test_assert_equal_int(const char *, int, int, const char *, int, const char *, struct archive *);
-void test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, struct archive *);
-void test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, struct archive *);
+void test_assert(const char *, int, int, const char *, void *);
+void test_assert_empty_file(const char *, ...);
+void test_assert_equal_file(const char *, const char *, ...);
+void test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *);
+void test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
+void test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
+void test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *);
+
+/* Like sprintf, then system() */
+int systemf(const char * fmt, ...);
+
+/* 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, ...);
+
+/*
+ * Global vars
+ */
+
+/* Directory holding reference files. */
+char *refdir;
+
+/*
+ * 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 *, void *, size_t, size_t);
-int read_open_memory(struct archive *, void *, size_t, size_t);
+
+/*
+ * ARCHIVE_VERSION_STAMP first appeared in 1.9 and libarchive 2.2.4.
+ * We can approximate it for earlier versions, though.
+ * This is used to disable tests of features not present in the current
+ * version.
+ */
+#ifndef ARCHIVE_VERSION_STAMP
+#define ARCHIVE_VERSION_STAMP \
+ (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
+#endif
+
+/* Versions of above that accept an archive argument for additional info. */
+#define assertA(e) test_assert(__FILE__, __LINE__, (e), #e, (a))
+#define assertEqualIntA(a,v1,v2) \
+ test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
+#define assertEqualStringA(a,v1,v2) \
+ test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
diff --git a/lib/libarchive/test/test_compat_gtar_1.tgz.uu b/lib/libarchive/test/test_compat_gtar_1.tgz.uu
index f088a4a5fe6a..5a8d51f5af84 100644
--- a/lib/libarchive/test/test_compat_gtar_1.tgz.uu
+++ b/lib/libarchive/test/test_compat_gtar_1.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_compat_gtar_1.tgz
M'XL(`,N`6T<``^W62PZ",!`&X!YE3@`SI:6Z<R^7\(&*+Q+%>'W+PJB)43=4
MJO^W:1.Z:#KYATG2)!T5]7Y95/N-Z@:UF)ZO7B9"-TPD[%@4%1W=Y\'IV$P.
diff --git a/lib/libarchive/test/test_compat_zip_1.zip.uu b/lib/libarchive/test/test_compat_zip_1.zip.uu
index e13a6cac29d9..1ed2d69966bf 100644
--- a/lib/libarchive/test/test_compat_zip_1.zip.uu
+++ b/lib/libarchive/test/test_compat_zip_1.zip.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_compat_zip_1.zip
M4$L#!!0`"``(``B$@S<````````````````4````345402U)3D8O34%.249%
M4U0N34;S3<S+3$LM+M$-2RTJSLS/LU(PU#/@Y7+,0Q)Q+$A,SDA5`(H!)<U!
diff --git a/lib/libarchive/test/test_read_format_cpio_odc.c b/lib/libarchive/test/test_read_format_cpio_odc.c
index de4d8d530980..6b758bb178f5 100644
--- a/lib/libarchive/test/test_read_format_cpio_odc.c
+++ b/lib/libarchive/test/test_read_format_cpio_odc.c
@@ -54,7 +54,7 @@ DEFINE_TEST(test_read_format_cpio_odc)
assertA(0 == archive_read_support_compression_all(a));
assertA(0 == archive_read_support_format_all(a));
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
- assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_POSIX);
assert(0 == archive_read_close(a));
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse.c b/lib/libarchive/test/test_read_format_gtar_sparse.c
index 66824d02f3ab..12bf23f6ab9c 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse.c
+++ b/lib/libarchive/test/test_read_format_gtar_sparse.c
@@ -29,7 +29,7 @@ __FBSDID("$FreeBSD$");
struct contents {
off_t o;
size_t s;
- char *d;
+ const char *d;
};
struct contents archive_contents_sparse[] = {
@@ -171,623 +171,6 @@ struct archive_contents {
{ NULL, NULL }
};
-
-/* Old GNU tar sparse format, as created by gtar 1.13 */
-static unsigned char archive_old_gtar_1_13[] = {
-31,139,8,0,30,'%',193,'F',0,3,237,215,'K','n',219,'H',20,133,'a',246,'N',
-180,129,6,170,'n',189,22,210,'+',208,' ',131,12,146,14,',','g',255,'}',201,
-192,142,17,29,'(','A',159,24,'l',160,255,207,3,219,'e',193,186,'$',127,241,
-'q',251,'r','}',186,'}',216,222,'U',169,165,204,222,183,'R','J',']',163,188,
-253,190,139,252,'u',171,'e',206,18,17,189,205,'m','_',')',177,']',254,'z',
-223,177,190,249,'z','{',190,'>',']','.',219,243,199,'O',15,'_',247,179,191,
-255,'k',251,'.','h',179,231,'>','z',221,'#',175,'?',231,'^',10,177,'^',219,
-':',188,172,239,'K',15,223,160,246,'o',175,250,253,211,'_',127,255,191,196,
-255,8,253,0,231,185,29,215,255,'x',215,247,'x','x',253,175,'=',218,221,245,
-'?','j',31,'\\',255,31,'\\',255,'[','o','j','}','E',233,'?',174,255,'Q',202,
-'X','u',212,213,212,'M',194,'~',167,213,'J',31,226,191,197,'\\','e',138,245,
-22,163,'/',181,158,27,161,182,162,'G',12,181,21,'}',214,170,182,'"','G',29,
-'w','[',177,175,143,'Y',213,156,'3','c','Q','s',206,209,170,154,'s',213,':',
-139,'Z',207,157,'-',230,220,227,157,'b',206,154,'{','-',196,156,185,15,218,
-20,'s',214,',','=',196,156,'5',223,'s',138,'9','k',180,213,196,156,'5','V',
-30,'O',177,190,'G',161,230,'l','+',214,'}',21,175,199,191,246,'V',155,154,
-183,207,181,212,188,'#','f','S',243,142,'c',171,239,215,'g','4','U','w',157,
-'3','T',221,'G',196,'j',191,230,'f',23,'1','g',228,';','w','1','g',148,172,
-'H',204,25,181,198,16,'s','F','~','F','T',191,217,196,'R',253,230,185,'j',
-170,'~',143,143,147,154,'3',15,'O','U','s',246,220,0,'5','g',238,132,'P',
-'s',246,'5',167,154,'s',180,161,250,141,177,218,'}',191,223,143,127,30,205,
-'P',29,31,31,127,'5',239,218,191,212,250,'<','6',227,199,245,150,19,'7','1',
-'o','+','3',255,145,'X',175,'Q','U',199,'-',247,210,'}',199,251,233,168,'N',
-213,239,'q',154,18,'s',182,204,189,171,'9','s',247,21,'5','g',198,219,213,
-156,'=',207,130,'j',206,145,225,169,'9',247,'U','5','g','^',247,'T',191,'/',
-167,211,251,245,181,134,154,'3',15,'s','U','s',230,'^',27,15,142,127,223,
-247,136,152,'7','?','<','U','u',220,'3','z',213,'q',207,15,180,234,248,'8',
-253,139,'y','{',134,'7',197,188,'=','s',12,177,'_',243,206,' ',239,'"',196,
-'z',207,'3',134,154,'3','?',133,170,223,'>',242,'D',172,230,28,'#','T',191,
-199,'e','J',205,'9','3','/','5','g','~','l',154,154,'s','e','0','b',206,177,
-167,'\'',230,28,185,'G','U',191,251,177,'W',253,142,'<',209,171,'~',143,203,
-233,131,227,'?',242,196,'t',127,215,176,175,175,'P',247,5,'#','s','Q',247,
-5,'#',195,'T',247,5,'#',15,180,234,'8','O',218,']','u',156,135,161,169,142,
-143,203,191,154,'s',238,'W',0,181,190,127,137,245,227,'f',232,205,'z',145,
-'7','F',248,'%','<',191,195,'A','?','p',208,15,28,244,3,7,253,192,'A','?',
-'p',184,253,208,31,28,244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,3,7,253,192,'A','?','p',208,15,
-28,'<',255,227,'L',244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,3,7,253,192,'A','?','p',208,15,
-28,'<',255,227,'L',244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,3,7,253,192,'A','?','p',208,15,
-28,'<',255,227,'L',244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,3,7,253,192,'A','?','p',208,15,
-28,'<',255,227,'L',244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,3,7,253,192,'A','?','p',208,15,
-28,'<',255,227,'L',244,3,7,253,192,'A','?','p',208,15,28,244,3,7,253,192,
-193,243,'?',206,'D','?','p',208,15,28,244,227,249,252,247,231,'?','o','_',
-174,'O',183,15,239,247,30,165,150,'2','{',223,'J',')','u',141,242,246,251,
-139,173,150,'9','K','D',244,'6',243,245,'5',127,218,'.',229,253,'F',250,238,
-235,237,249,250,'t',185,'l',207,31,'?','=','|',221,207,254,14,0,0,0,0,0,0,
-0,255,'1',255,0,178,'s',140,'2',0,240,0,0};
-
-/* Old GNU tar sparse format, as created by gtar 1.17 */
-static unsigned char archive_old_gtar_1_17[] = {
-31,139,8,0,30,'%',193,'F',0,3,237,215,']','r',19,'G',20,134,'a','e','\'',
-218,'@',170,186,'O',255,'-','$','+',208,5,23,'\\','@','(',203,236,'?','g',
-134,216,'8',232,139,160,248,'P','M',170,242,'>',20,'%',211,'6',214,153,158,
-'W','#',205,245,211,229,233,250,238,244,'P','%',205,222,183,199,186,'F','y',
-251,184,137,252,'{',170,'e',206,18,17,189,205,'S','~','w',197,'<',157,255,
-'x',236,'X','_','|',190,'>','_',158,206,231,211,243,251,15,'w',127,238,'{',
-223,255,'i',219,22,180,217,235,182,11,127,239,200,235,215,185,'K','!',214,
-'k',255,242,239,151,245,253,235,'{','O',240,250,31,'~',185,203,175,255,149,
-248,31,161,159,'c',']',247,235,127,'<',244,'9',238,'^',255,'k',143,'V',234,
-'?',175,255,17,'5',127,156,235,255,191,'^',255,'[',235,'M',173,175,'(',253,
-219,245,223,'J',25,171,142,186,182,'m','V',207,158,251,223,135,248,'m','1',
-'W',153,'b',189,197,232,'K',173,231,'A',168,163,232,17,'C',29,'E',159,181,
-170,163,200,'Q',199,205,'Q','l',235,'c','V','5',231,172,'}',168,'9',231,'h',
-'U',205,185,'j',157,'E',173,231,'f',139,'9',243,'a','N','1','g',205,']',11,
-'1','g',238,'A',155,'b',206,154,165,135,152,179,230,'s','N','1','g',141,182,
-154,152,179,198,202,243,')',214,183,'(',212,156,'m',197,186,173,226,245,252,
-215,222,'j','S',243,246,185,150,154,'w',196,'l','j',222,177,31,245,237,250,
-140,166,234,174,'s',134,170,'{',143,'X',237,'k',30,'v',17,'s','F','>','s',
-23,'s','F',201,138,196,156,'Q','k',12,'1','g',228,'k','D',245,155,'M',',',
-213,'o','^',171,166,234,'w',127,'9',169,'9',243,244,'T','5','g',207,3,'P',
-'s',230,'&',132,154,179,175,'9',213,156,163,13,213,'o',140,213,'n',251,253,
-'z',254,243,'l',134,234,'x',127,249,171,'y',215,246,'G',173,207,253,'0',190,
-']','o','9','q',19,243,182,'2',243,23,137,245,26,'U','u',220,'r',151,'n',
-';',222,'.','G','u',170,'~',247,203,148,152,179,'e',238,']',205,153,219,'W',
-212,156,25,'o','W','s',246,188,10,170,'9','G',134,167,230,220,'V',213,156,
-249,190,167,250,'}',185,156,222,174,175,'5',212,156,'y',154,171,154,'3','w',
-'m',220,'9',255,'}',219,17,'1','o',190,'x',170,234,184,'g',244,170,227,158,
-'/','h',213,241,'~',249,23,243,246,12,'o',138,'y','{',230,24,'b','_',243,
-147,'A','~',138,16,235,'=',175,24,'j',206,'|',21,170,'~',251,200,11,177,154,
-'s',140,'P',253,238,'o','S','j',206,153,'y',169,'9',243,'e',211,212,156,'+',
-131,17,'s',142,'-','=','1',231,200,29,'U',253,'n',231,'^',245,';',242,'B',
-175,250,221,223,'N',239,156,255,145,23,166,219,'O',13,219,250,10,245,185,
-'`','d','.',234,'s',193,200,'0',213,231,130,145,'\'','Z','u',156,23,237,174,
-':',206,211,208,'T',199,251,219,191,154,'s','n',239,0,'j','}',251,'#',214,
-247,15,'C','o',214,139,252,'`',132,31,194,253,27,28,244,3,7,253,192,'A','?',
-'p',208,15,28,244,3,135,219,15,253,193,'A','?','p',208,15,28,244,3,7,253,
-192,'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?','p',208,
-15,28,244,3,7,253,192,193,253,'?',142,'D','?','p',208,15,28,244,3,7,253,192,
-'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?','p',208,15,
-28,244,3,7,253,192,193,253,'?',142,'D','?','p',208,15,28,244,3,7,253,192,
-'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?','p',208,15,
-28,244,3,7,253,192,193,253,'?',142,'D','?','p',208,15,28,244,3,7,253,192,
-'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?','p',208,15,
-28,244,3,7,253,192,193,253,'?',142,'D','?','p',208,15,28,244,3,7,253,192,
-'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?','p',208,15,
-28,244,3,7,253,192,193,253,'?',142,'D','?','p',208,15,28,244,3,7,253,192,
-'A','?','p',208,15,28,220,255,227,'H',244,3,7,253,192,'A','?',158,143,127,
-'~',252,253,250,233,242,'t','}',247,184,231,'(','i',246,190,'=',214,'5',202,
-219,199,23,167,'Z',230,',',17,209,219,'<',149,'Z','#',234,233,'\\',30,'7',
-210,'W',159,175,207,151,167,243,249,244,252,254,195,221,159,251,222,247,1,
-0,0,0,0,0,0,0,248,15,249,11,162,'$',218,227,0,240,0,0};
-
-#if ARCHIVE_VERSION_STAMP >= 1009000
-/* libarchive < 1.9 does not support this. */
-/* GNU tar "posix" sparse format 0.0, as created by gtar 1.17 */
-static unsigned char archive_0_0_gtar_1_17[] = {
-31,139,8,0,31,'%',193,'F',0,3,237,217,207,'n',218,'X',20,199,'q',214,'<',
-5,'/','0',228,222,'s','}',255,'x',193,'z',186,26,'u',211,7,240,164,174,20,
-205,'$',169,'0',145,'2',243,244,'5','%',205,144,200,193,'p',14,141,203,232,
-251,217,'P','A',14,'8','9',191,'[',253,',',150,'W',31,155,199,15,'m',243,
-185,']','w',203,232,156,148,171,238,'k',179,238,218,217,249,184,'^',170,170,
-237,163,207,209,237,'?','~','W','9',153,'y',151,146,19,145,'*',228,153,243,
-161,'J','2','[','<',158,241,26,222,244,208,'m',154,'u',127,')',214,247,'y',
-250,']',158,31,'/',132,228,197,239,127,'|','Z',238,'v',190,236,'n',254,'m',
-'W',193,'W','1','K',153,'K',218,127,233,238,225,246,207,191,239,175,255,234,
-'V','a','.','e',255,149,251,'/','_',186,'v',179,170,'{','!',205,'_',190,225,
-'v',234,159,'M',219,173,162,151,185,212,3,'c',190,31,'+','Y','N',158,'{',
-190,202,'8','8',231,230,226,22,205,230,230,182,']','y','_',178,'K',193,'e',
-191,'}',238,250,229,'s','n','>',245,6,166,'u',246,195,'>','`',228,252,203,
-246,184,252,'w',254,'S',127,254,'}',14,'a',182,'x',151,'C',244,227,252,247,
-177,'8',248,'s','c',175,'_',232,249,183,'j',166,190,0,'\\','4',242,'3',173,
-229,'[',253,'O',206,247,25,135,255,255,247,193,247,157,239,'U',255,139,'1',
-210,255,222,195,203,'*',247,189,255,213,245,'n','/',3,149,'l','W',0,235,250,
-151,'h',128,178,157,'s',229,244,230,216,207,229,170,':','y',174,234,231,'R',
-'q','\'',207,197,237,156,'?',253,239,146,250,185,24,'O',255,187,148,']',2,
-'O',159,'S',238,175,30,223,'_','p','C','{','w',227,11,28,30,244,227,27,28,
-30,148,241,21,14,15,134,241,29,14,15,'V',227,'K',28,30,'L',227,'[','|','c',
-'p','|',141,195,131,'Y',187,199,162,221,'c',173,220,163,'8',229,30,197,'+',
-247,'(',162,220,163,'T',202,'=','J',165,220,163,'D',229,30,'%',')',247,'(',
-'Y',187,199,162,221,'c',173,220,'c','p',202,'=',6,'Q',238,'1',136,'r',143,
-'!','(',247,24,'*',229,30,'C','T',238,'1','$',229,30,'C',214,238,177,'(',
-247,248,'t',28,'O',191,212,202,')',247,'X',29,209,'o',134,7,143,'(','8',195,
-131,'G','4',156,225,193,'#','*',206,240,224,17,29,'g','x',240,136,146,'3',
-'<','x','D',203,'y','c','P',187,'G','m',207,137,218,158,19,181,'=','\'','j',
-'{','N',212,246,156,168,237,'9','Q',219,'s',162,182,231,'D','m',207,137,218,
-158,19,181,'=','\'','i','{','N',210,246,156,164,237,'9','I',219,'s',146,182,
-231,'$','m',207,'I',218,158,147,180,'=','\'','i','{','N',210,246,156,172,
-237,'9','Y',219,'s',178,182,231,'d','m',207,201,218,158,147,181,'=','\'',
-'k','{','N',214,246,156,172,237,'9','E',219,'s',138,182,231,20,'m',207,')',
-218,158,'S',180,'=',167,'h','{','N',209,246,156,162,237,'9','E',219,'s',138,
-182,231,20,'m',207,169,181,'=',167,214,246,156,'Z',219,'s','j','m',207,169,
-181,'=',167,214,246,156,'Z',219,'s','j','m',207,169,'G','z',142,175,3,'_',
-174,255,'_',236,150,'{',198,'/','{',6,28,252,254,199,'W',18,156,127,245,253,
-191,'8','I','|',255,127,9,248,254,22,22,228,7,22,228,7,22,228,7,22,228,7,
-22,228,7,22,214,252,144,'?','X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',
-144,31,'X',144,31,'X','p',255,143,')',145,31,'X',144,31,'X',144,31,'X',144,
-31,'X',144,31,'X',144,31,'X','p',255,143,')',145,31,'X',144,31,'X',144,31,
-'X',144,31,'X',144,31,'X',144,31,'X','p',255,143,')',145,31,'X',144,31,'X',
-144,31,'X',144,31,'X',144,31,'X',144,31,'X','p',255,143,')',145,31,'X',144,
-31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X','p',255,143,')',145,31,
-'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X','p',255,143,')',
-145,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X','p',255,
-143,')',145,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',
-'p',255,143,')',145,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,'X',144,
-31,'X','p',255,143,')',145,31,'X',144,31,'X',144,31,'X',144,31,'X',144,31,
-'X',144,31,'X','p',255,143,')',145,31,'X',144,31,'X',144,31,'X',144,31,'X',
-144,31,'X',144,31,'X','p',255,143,')',145,31,'X',144,31,'X',144,31,155,229,
-213,199,230,241,'C',219,'|','n',215,221,'2',':','\'',229,234,238,254,238,
-183,238,'k',179,238,218,'3','}',134,235,165,170,218,'>',250,28,221,254,227,
-'N',255,'o',239,'R','r','"','R',133,'<','s',190,146,232,'g',139,199,'3','}',
-254,'A',15,221,166,'Y',247,151,'b','}',159,167,'_',229,249,241,'B',136,'[',
-'4',155,155,219,'v',229,'}',201,'.',5,151,221,188,127,238,250,245,'s','S',
-'_','\'','~',142,179,31,246,1,163,231,223,237,159,255,212,159,127,137,210,
-159,255,'w','9','D','?',206,127,31,248,131,'?','7',246,250,133,158,127,0,
-0,0,0,0,0,0,0,0,0,0,0,0,192,'e',250,6,'X',180,13,'8',0,24,1,0};
-#endif
-
-#if ARCHIVE_VERSION_STAMP >= 1009000
-/* libarchive < 1.9 does not support this. */
-/* GNU tar "posix" sparse format 0.1, as created by gtar 1.17 */
-static unsigned char archive_0_1_gtar_1_17[] = {
-31,139,8,0,31,'%',193,'F',0,3,237,215,205,'n',26,'W',24,135,'q',214,'\\',
-5,23,224,194,249,'>','3',11,182,'m','V','U',164,170,23,'0','u','f','a','%',
-'v',',',198,150,172,'^','}',135,15,'\'',127,187,9,'T','z',137,167,'D',207,
-'o',195,4,'l','^','0',207,'!',231,',','W',239,187,167,'w','}',247,161,223,
-12,203,236,'\\',244,171,225,190,219,12,253,236,'|',220,168,164,180,189,245,
-'5',';',189,221,9,'9',204,188,'+',197,133,16,'R',172,'3',231,'c',202,'u',
-182,'x',':',227,'k',248,174,199,225,161,219,140,'/',197,250,'<',135,247,242,
-229,246,'B',132,186,248,237,247,'?',151,251,207,'|','9',220,252,221,175,163,
-31,255,250,161,153,135,162,15,221,'=',222,254,245,233,243,245,199,'a',29,
-'_','?',210,221,246,235,253,245,'<','{','}',228,182,187,'_',183,163,'X',174,
-178,15,'W','~',188,'l','j',216,']',31,134,'\\',185,'y','p',139,238,225,'f',
-'|',10,239,155,234,'J','t',213,'o',239,187,'~','y',159,155,'O',253,151,250,
-'9','-','W',227,231,245,199,238,227,250,245,230,'S',255,'C',190,2,'N',172,
-255,176,']','.','_',215,127,25,215,127,246,169,204,22,'o',178,136,158,215,
-255,152,219,209,159,';',245,248,133,174,127,171,'n',234,23,128,139,'F','?',
-211,'Z','~','o',255,23,206,'7',227,212,247,127,241,178,255,'K','n',187,255,
-203,'1',179,255,'{',11,161,249,215,254,175,'m','w',239,'`',220,133,213,'o',
-'o',0,219,246,245,'C','_','w',128,'a',238,'C','[',254,227,'&','0','l',175,
-']',179,223,16,142,215,'5',165,221,'u',26,175,'K',227,'v',215,'y','{',237,
-247,191,'[',198,235,156,247,191,219,236,255,206,251,'k','y',254,'V',158,223,
-';',25,224,189,'L',240,'A','F',248,'(','3','|',146,'!',190,200,20,'_',244,
-'m','T',157,211,232,156,'V',230,4,'\'','s',130,151,'9','!',200,156,144,'d',
-'N','H','2','\'','d',253,'{',21,153,19,170,206,'i','t','N','+','s',162,147,
-'9','1',200,156,24,'d','N',140,186,'9','O',250,193,'d',153,19,139,204,137,
-'U',231,'4','2',231,240,'v',220,225,31,'2','\'',233,231,159,'4',128,244,162,
-0,'M',' ','i',3,'I','#','H','Z','A',210,12,146,'v',144,181,131,172,29,'d',
-237,' ','k',7,'Y',';',200,218,'A',214,14,178,'v',144,181,131,172,29,20,237,
-160,'h',7,'E',';','(',218,'A',209,14,138,'v','P',180,131,162,29,20,237,160,
-'h',7,'U',';',168,218,'A',213,14,170,'v','P',181,131,170,29,'T',237,160,'j',
-7,'U',';','h',180,131,'F',';','h',180,131,'F',';','h',180,131,'F',';','h',
-180,131,230,197,151,193,139,'o',3,237,160,209,14,'Z',237,160,213,14,'Z',237,
-160,213,14,'Z',237,160,213,14,'Z',237,160,213,14,218,231,14,'|',27,255,231,
-231,219,'c',231,191,'s','m',1,142,254,255,239,'S',136,206,191,'>',255,133,
-228,'9',255,']',2,246,239,176,160,31,'X',208,15,',',232,7,22,244,3,11,250,
-129,133,181,31,250,131,5,253,192,130,'~','`','A','?',176,160,31,'X',208,15,
-',',232,7,22,156,255,'1','%',250,129,5,253,192,130,'~','`','A','?',176,160,
-31,'X',208,15,',','8',255,'c','J',244,3,11,250,129,5,253,192,130,'~','`',
-'A','?',176,160,31,'X','p',254,199,148,232,7,22,244,3,11,250,129,5,253,192,
-130,'~','`','A','?',176,224,252,143,')',209,15,',',232,7,22,244,3,11,250,
-129,5,253,192,130,'~','`',193,249,31,'S',162,31,'X',208,15,',',232,7,22,244,
-3,11,250,129,5,253,192,130,243,'?',166,'D','?',176,160,31,'X',208,15,',',
-232,7,22,244,3,11,250,129,5,231,127,'L',137,'~','`','A','?',176,160,31,'X',
-208,15,',',232,7,22,244,3,11,206,255,152,18,253,192,130,'~','`','A','?',176,
-160,31,'X',208,15,',',232,7,22,156,255,'1','%',250,129,5,253,192,130,'~',
-'`','A','?',176,160,31,'X',208,15,',','8',255,'c','J',244,3,11,250,129,5,
-253,192,130,'~','`','A','?',176,160,31,'X','p',254,199,148,232,7,22,244,3,
-11,250,177,'Y',174,222,'w','O',239,250,238,'C',191,25,150,217,185,232,'W',
-'w',159,239,'~',25,238,187,205,208,159,'i',134,27,149,148,182,183,190,'f',
-167,183,'{',227,181,'w',165,184,16,'B','J',227,253,'>',133,152,'g',139,167,
-'3',205,'?',234,'q','x',232,'6',227,'K',177,'>',207,225,173,'|',185,189,16,
-193,'-',186,135,155,219,'~',237,'}','S',']',137,174,186,249,'x',223,245,235,
-251,166,'~',157,248,'1',206,190,216,191,225,228,250,'w',178,254,'c',25,215,
-127,200,193,207,22,'o',178,136,158,215,255,24,252,209,159,';',245,248,133,
-174,127,0,0,0,0,0,240,243,251,7,233,'Q','N','O',0,240,0,0};
-#endif
-
-#if ARCHIVE_VERSION_STAMP >= 1009000
-/* libarchive < 1.9 does not support this. */
-/* GNU tar "posix" sparse format 1.0, as created by gtar 1.17 */
-static unsigned char archive_1_0_gtar_1_17[] = {
-31,139,8,0,' ','%',193,'F',0,3,237,215,205,'n',26,'I',20,134,'a',214,'\\',
-5,'7',16,168,255,234,'^','x',155,'d',21,'E',138,230,2,'Z','I','/',24,197,
-'N',4,142,'d',205,213,'O',1,182,245,217,178,'A',163,'C',220,131,242,'>',155,
-'n',183,'m',14,'?','o',161,174,229,234,243,'p',247,'q',28,190,141,155,237,
-'2',';',23,211,'j',251,'s',216,'l',199,217,249,184,166,164,180,';',250,154,
-157,30,247,130,207,'3',239,'J','q','!',132,148,218,'u',31,'S',142,179,197,
-221,25,159,195,171,'~','m','o',135,'M','{','*',214,199,185,127,'-',143,199,
-11,17,194,226,195,167,191,150,135,207,'|','y','=',252,253,'c','s',229,231,
-207,174,174,'o',218,'U','7',15,'E',175,222,12,215,227,213,225,'|',30,189,
-254,'f','3',14,223,183,235,127,198,171,232,'S',174,161,155,7,183,24,'n',215,
-237,207,189,239,170,'+',209,'U',191,187,246,245,233,'5','7',159,250,205,248,
-3,'-','W',237,131,251,178,255,220,222,175,191,143,191,229,'+',224,196,250,
-143,187,229,242,184,254,'c','i',235,'?',251,28,'f',139,'7','Y','D',15,235,
-191,181,'x',244,239,'N',253,254,'B',215,127,156,247,'M',',',243,236,195,220,
-183,211,174,134,253,249,195,218,'e','U',226,136,'a',234,'\'',128,139,'F',
-'?',211,'Z',190,'v',255,31,206,'7',227,244,253,127,'}','~',255,159,'c',229,
-254,255,'-',252,167,251,255,250,202,253,127,187,'[',8,'/','n',0,250,'~',255,
-'f',248,23,'v',0,129,29,192,255,193,177,251,255,'s','}',5,28,']',255,237,
-'6','3',':',255,252,254,'?',164,202,253,255,'[',232,251,215,'6',0,'a','w',
-238,186,195,'f',160,157,215,148,246,231,169,157,151,206,237,207,243,238,220,
-31,254,183,180,243,156,15,255,219,29,222,132,195,185,'<','~','/',143,239,
-157,12,240,'^','&',248,' ','#','|',148,25,'>',201,16,'_','d',138,'/',250,
-'2',170,206,233,'t','N','/','s',130,147,'9',193,203,156,16,'d','N','H','2',
-'\'','$',153,19,178,190,'_','E',230,132,170,'s',':',157,211,203,156,232,'d',
-'N',12,'2','\'',6,153,19,163,'n',204,146,'~','0','Y',230,196,'"','s','b',
-213,'9',157,204,185,127,'9',238,254,7,153,147,244,243,'O',26,'@','z','R',
-128,'&',144,180,129,164,17,'$',173,' ','i',6,'I',';',200,218,'A',214,14,178,
-'v',144,181,131,172,29,'d',237,' ','k',7,'Y',';',200,218,'A',214,14,138,'v',
-'P',180,131,162,29,20,237,160,'h',7,'E',';','(',218,'A',209,14,138,'v','P',
-180,131,170,29,'T',237,160,'j',7,'U',';',168,218,'A',213,14,170,'v','P',181,
-131,170,29,'t',218,'A',167,29,'t',218,'A',167,29,'t',218,'A',167,29,'t',218,
-'A',247,228,203,224,201,183,129,'v',208,'i',7,189,'v',208,'k',7,189,'v',208,
-'k',7,189,'v',208,'k',7,189,'v',208,'k',7,253,'C',7,190,143,220,'o','X',177,
-127,131,5,253,192,130,'~','`','A','?',176,160,31,'X',208,15,',',172,253,208,
-31,',',232,7,22,244,3,11,250,129,5,253,192,130,'~','`','A','?',176,'`',255,
-143,')',209,15,',',232,7,22,244,3,11,250,129,5,253,192,130,'~','`',193,254,
-31,'S',162,31,'X',208,15,',',232,7,22,244,3,11,250,129,5,253,192,130,253,
-'?',166,'D','?',176,160,31,'X',208,15,',',232,7,22,244,3,11,250,129,5,251,
-127,'L',137,'~','`','A','?',176,160,31,'X',208,15,',',232,7,22,244,3,11,246,
-255,152,18,253,192,130,'~','`','A','?',176,160,31,'X',208,15,',',232,7,22,
-236,255,'1','%',250,129,5,253,192,130,'~','`','A','?',176,160,31,'X',208,
-15,',',216,255,'c','J',244,3,11,250,129,5,253,192,130,'~','`','A','?',176,
-160,31,'X',176,255,199,148,232,7,22,244,3,11,250,129,5,253,192,130,'~','`',
-'A','?',176,'`',255,143,')',209,15,',',232,7,22,244,3,11,250,129,5,253,192,
-130,'~','`',193,254,31,'S',162,31,'X',208,15,',',232,7,22,244,3,11,250,129,
-5,253,192,130,253,'?',166,'D','?',176,160,31,'X',208,143,205,'r',245,'y',
-184,251,'8',14,223,198,205,'v',153,157,139,'i','u',243,227,230,221,246,231,
-176,217,142,'g',154,225,154,146,210,238,232,'k','v','z','<','h',231,222,149,
-226,'B',8,')',181,235,'>',133,'v','X',220,157,'i',254,'Q',191,182,183,195,
-166,'=',21,235,227,220,191,148,199,227,133,8,'n','1',220,174,175,199,'+',
-239,187,234,'J','t',213,205,219,181,175,207,175,'M',253,'<',241,'{',156,'}',
-177,191,224,228,250,'w',178,254,'c','i',235,'?',228,224,'g',139,'7','Y','D',
-15,235,191,5,127,244,239,'N',253,254,'B',215,'?',0,0,0,128,'?',199,191,200,
-'e','(',171,0,240,0,0};
-#endif
-
-
-/*
- * The following test archive is a little odd. First, it's uncompressed,
- * because that exercises some of the block reassembly code a little harder.
- * Second, it includes some leading comments prior to the sparse block
- * description. GNU tar doesn't do this, but I think it should, so I
- * want to ensure that libarchive correctly ignores such comments.
- */
-#if ARCHIVE_VERSION_STAMP >= 1009000
-
-/* Because it's uncompressed, I've made this archive a bit simpler. */
-struct archive_contents files_1_0b[] = {
- { "sparse", archive_contents_sparse },
- { "non-sparse", archive_contents_nonsparse },
- { NULL, NULL }
-};
-
-static unsigned char archive_1_0b[] = {
-'.','/','P','a','x','H','e','a','d','e','r','s','.','7','5','4','7','/','s',
-'p','a','r','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0','0','6','4','4',0,'0','0','0','1','7',
-'5','0',0,'0','0','0','1','7','5','0',0,'0','0','0','0','0','0','0','0','2',
-'1','5',0,'1','0','6','5','7','4','5','4','6','1','3',0,'0','1','3','4','2',
-'5',0,' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s',
-'t','a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,'0','0','0','0','0','0','0',0,'0','0','0','0','0','0','0',0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,'2','2',' ','G','N','U','.','s','p','a','r','s',
-'e','.','m','a','j','o','r','=','1',10,'2','2',' ','G','N','U','.','s','p',
-'a','r','s','e','.','m','i','n','o','r','=','0',10,'2','6',' ','G','N','U',
-'.','s','p','a','r','s','e','.','n','a','m','e','=','s','p','a','r','s','e',
-10,'3','1',' ','G','N','U','.','s','p','a','r','s','e','.','r','e','a','l',
-'s','i','z','e','=','3','1','4','5','7','2','8',10,'2','0',' ','a','t','i',
-'m','e','=','1','1','8','6','8','7','9','7','9','9',10,'2','0',' ','c','t',
-'i','m','e','=','1','1','8','6','8','7','9','5','2','8',10,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'.','/','G',
-'N','U','S','p','a','r','s','e','F','i','l','e','.','7','5','4','7','/','s',
-'p','a','r','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,'0','0','0','0','6','4','4',0,'0','0','0','1','7','5','0',
-0,'0','0','0','1','7','5','0',0,'0','0','0','0','0','0','0','3','0','0','0',
-0,'1','0','6','5','7','4','5','4','0','5','0',0,'0','1','5','1','1','2',0,
-' ','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a',
-'r',0,'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,'0','0','0','0','0','0','0',0,'0','0','0','0','0','0','0',0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-
-/* 32 added bytes containing extra comments at beginning of sparse block */
-'#','!','g','n','u','-','s','p','a','r','s','e','-','f','o','r','m','a',
-'t',10,'#','f','o','r','m','a','t',':','1','.','0',10,
-
-'3',10,'9','9','9','9','3','6',10,'5','1','2',
-10,'1','9','9','9','8','7','2',10,'5','1','2',10,'3','1','4','5','7','2',
-'8',10,'0',10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-
-/* 32 removed bytes to preserve alignment. */
-/* 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, */
-0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'a',0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'a',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'.','/','P','a',
-'x','H','e','a','d','e','r','s','.','7','5','4','7','/','n','o','n','-','s',
-'p','a','r','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,'0','0','0','0','6','4','4',0,'0','0','0','1','7','5','0',
-0,'0','0','0','1','7','5','0',0,'0','0','0','0','0','0','0','0','0','5','0',
-0,'1','0','6','5','7','4','5','4','6','1','3',0,'0','1','4','2','1','2',0,
-' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a',
-'r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
-'0','0','0','0','0',0,'0','0','0','0','0','0','0',0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,'2','0',' ','a','t','i','m','e','=','1','1','8','6','8','7',
-'9','7','9','9',10,'2','0',' ','c','t','i','m','e','=','1','1','8','6','8',
-'7','9','5','4','4',10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,'n','o','n','-','s','p','a','r','s','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,'0','0','0','0','6','4','4',0,'0','0','0','1','7','5','0',0,'0','0','0',
-'1','7','5','0',0,'0','0','0','0','0','0','0','0','0','0','1',0,'1','0','6',
-'5','7','4','5','4','0','7','0',0,'0','1','2','5','3','1',0,' ','0',0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,'0','0',
-'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'t',
-'i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
-'0','0','0','0','0',0,'0','0','0','0','0','0','0',0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,'a',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-#endif
-
/*
* A tricky piece of code that verifies the contents of a sparse
* archive entry against a description as defined at the top of this
@@ -795,29 +178,25 @@ static unsigned char archive_1_0b[] = {
*/
#define min(a,b) ((a) < (b) ? (a) : (b))
-/*
- * A convenience wrapper that adds the size of the buffer and the
- * name of the buffer to any call.
- */
-#define verify_archive(buffer, contents) \
- _verify_archive(buffer, sizeof(buffer), #buffer, contents)
-
static void
-_verify_archive(void *buffer, size_t length, const char *name,
- struct archive_contents *ac)
+verify_archive_file(const char *name, struct archive_contents *ac)
{
+ char path[512];
struct archive_entry *ae;
- struct archive *a;
int err;
/* data, size, offset of next expected block. */
struct contents expect;
/* data, size, offset of block read from archive. */
struct contents actual;
+ struct archive *a;
+
+ sprintf(path, "%s/%s", refdir, name);
assert((a = archive_read_new()) != NULL);
assert(0 == archive_read_support_compression_all(a));
assert(0 == archive_read_support_format_tar(a));
- assert(0 == read_open_memory(a, buffer, length, 3));
+ failure("Can't open %s", path);
+ assert(0 == archive_read_open_filename(a, path, 3));
while (ac->filename != NULL) {
struct contents *cts = ac->contents;
@@ -831,7 +210,7 @@ _verify_archive(void *buffer, size_t length, const char *name,
(const void **)&actual.d,
&actual.s, &actual.o))) {
while (actual.s > 0) {
- char c = *(char *)actual.d;
+ char c = *(const char *)actual.d;
if(actual.o < expect.o) {
/*
* Any byte before the expected
@@ -892,35 +271,51 @@ _verify_archive(void *buffer, size_t length, const char *name,
#endif
}
+
DEFINE_TEST(test_read_format_gtar_sparse)
{
- /*
- FILE *t = fopen("archive_1_0.tgz", "w");
- fwrite(archive_1_0, sizeof(archive_1_0), 1, t);
- fclose(t);
- */
-
- verify_archive(archive_old_gtar_1_13, files);
+ /* Two archives that use the "GNU tar sparse format". */
+ verify_archive_file("test_read_format_gtar_sparse_1_13.tgz", files);
+ verify_archive_file("test_read_format_gtar_sparse_1_17.tgz", files);
/*
- * libarchive < 1.9 doesn't support the newer sparse formats
- * from GNU tar 1.15 and 1.16.
+ * libarchive < 1.9 doesn't support the newer --posix sparse formats
+ * from GNU tar 1.15 and later.
*/
#if ARCHIVE_VERSION_STAMP < 1009000
- skipping("read support for GNUtar sparse format 0.0");
-#else
- verify_archive(archive_0_0_gtar_1_17, files);
-#endif
-#if ARCHIVE_VERSION_STAMP < 1009000
- skipping("read support for GNUtar sparse format 0.1");
+ skipping("read support for GNUtar --posix sparse formats");
#else
- verify_archive(archive_0_1_gtar_1_17, files);
-#endif
-#if ARCHIVE_VERSION_STAMP < 1009000
- skipping("read support for GNUtar sparse format 1.0");
-#else
- verify_archive(archive_1_0_gtar_1_17, files);
- verify_archive(archive_1_0b, files_1_0b);
+ /*
+ * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
+ */
+ verify_archive_file(
+ "test_read_format_gtar_sparse_1_17_posix00.tgz",
+ files);
+ /*
+ * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
+ */
+ verify_archive_file(
+ "test_read_format_gtar_sparse_1_17_posix01.tgz",
+ files);
+ /*
+ * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
+ */
+ verify_archive_file(
+ "test_read_format_gtar_sparse_1_17_posix10.tgz",
+ files);
+ /*
+ * The last test archive here is a little odd. First, it's
+ * uncompressed, because that exercises some of the block
+ * reassembly code a little harder. Second, it includes some
+ * leading comments prior to the sparse block description.
+ * GNU tar doesn't do this, but I think it should, so I want
+ * to ensure that libarchive correctly ignores such comments.
+ * Dump the file, looking for "#!gnu-sparse-format" starting
+ * at byte 0x600.
+ */
+ verify_archive_file(
+ "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
+ files);
#endif
}
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_13.tgz.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_13.tgz.uu
index a298e59fa08e..70198997e803 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_13.tgz.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_13.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_13.tgz
M'XL(`&&";$<``^W72VX;1Q2%X<Y.N($`=>NYD*Q``P\\L&.(\OYSNP/)LGE`
M!SDF.D#^SP,G94&\7?VS']<O3\_7#]M#E2AE]KZ54F*-\O[O7<W_W:*LUJ)$
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_17.tgz.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_17.tgz.uu
index 3f3127124a18..53889314ce24 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_17.tgz.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_17.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_17.tgz
M'XL(`&&";$<``^W776X3611%83,33Z"E>^[O0'H$?N"!!V@4A_GWJ8*$".\V
MK=Y8U1+KB\#H)L2G;BV77=?/EZ?K^]-#E31[WQYCC?+V<5/SSRG*:BU*1,_U
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tgz.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tgz.uu
index 41038960bc95..42ad82109b90 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tgz.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_17_posix00.tgz
M'XL(`&*";$<``^W9S6[;1A2&8:UU%;Z!RO/#^5MHW:R*;'H!K,,`06L[$&7`
M[=5W%#FN'(Q-Z1S5K-#W642!E&/3/M\$'\'5]<?^\</0?QHVX\KG&,KU^+7?
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tgz.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tgz.uu
index 6d7963ed4f90..a4191c3b20ed 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tgz.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_17_posix01.tgz
M'XL(`&*";$<``^W7WVX:1QB&<8ZY"B[`Q?/-OYT]X+3-416IZ@5L'0ZLQHX%
MMF3UZKN`';]V&SO21[PB>GXG;,#F`_,,F5F>?QSN/ZR'3^O-=IE:K7:^O1DV
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tgz.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tgz.uu
index c74c08fb3ede..bd121b08c969 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tgz.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tgz.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_17_posix10.tgz
M'XL(`&.";$<``^W7RV[;5A1&88WU%'J!RN=^&7B:9E0$*/H`1,*!B]@))`<P
M\O2A)#O];=@RBJV8$+*^"1G*T=9E'8%G??%AN'L_#I_&S78=6RGQ8OMUV&S'
diff --git a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu
index cf8fd77cc0ca..a0673de19d35 100644
--- a/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu
+++ b/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu
@@ -1,3 +1,4 @@
+$FreeBSD$
begin 644 test_read_format_gtar_sparse_1_17_posix10_modified.tar
M+B]087A(96%D97)S+C,X-C8S+W-P87)S90``````````````````````````
M````````````````````````````````````````````````````````````
diff --git a/lib/libarchive/test/test_read_format_isorr_bz2.c b/lib/libarchive/test/test_read_format_isorr_bz2.c
index a0859f9e1449..6f241eeb8962 100644
--- a/lib/libarchive/test/test_read_format_isorr_bz2.c
+++ b/lib/libarchive/test/test_read_format_isorr_bz2.c
@@ -110,6 +110,9 @@ DEFINE_TEST(test_read_format_isorr_bz2)
assertEqualInt(1, archive_entry_ctime(ae));
assertEqualInt(0, archive_entry_stat(ae)->st_nlink);
assertEqualInt(0, archive_entry_uid(ae));
+ assertEqualIntA(a, ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt(size, 0);
/* A directory. */
assert(0 == archive_read_next_header(a, &ae));
diff --git a/lib/libarchive/test/test_read_format_tar.c b/lib/libarchive/test/test_read_format_tar.c
index 8f8b83bcf543..bfe0b1388e2e 100644
--- a/lib/libarchive/test/test_read_format_tar.c
+++ b/lib/libarchive/test/test_read_format_tar.c
@@ -36,6 +36,52 @@ __FBSDID("$FreeBSD$");
* '2' is a symlink, '5' is a dir, etc.
*/
+/* Empty archive. */
+static unsigned char archiveEmpty[] = {
+ /* 512 zero bytes */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
+};
+
+static void verifyEmpty(void)
+{
+ struct archive_entry *ae;
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+ assertA(0 == archive_read_support_compression_all(a));
+ assertA(0 == archive_read_support_format_all(a));
+ assertA(0 == archive_read_open_memory(a, archiveEmpty, 512));
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
+ failure("512 zero bytes should be recognized as a tar archive.");
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR);
+
+ assert(0 == archive_read_close(a));
+#if ARCHIVE_API_VERSION > 1
+ assert(0 == archive_read_finish(a));
+#else
+ archive_read_finish(a);
+#endif
+}
+
/* Single entry with a hardlink. */
static unsigned char archive1[] = {
'h','a','r','d','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -411,6 +457,7 @@ static void verify(unsigned char *d, size_t s,
DEFINE_TEST(test_read_format_tar)
{
+ verifyEmpty();
verify(archive1, sizeof(archive1), verify1,
ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
verify(archive2, sizeof(archive2), verify2,
diff --git a/lib/libarchive/test/test_read_format_zip.c b/lib/libarchive/test/test_read_format_zip.c
index 96caf8593b0d..02592b4f6e98 100644
--- a/lib/libarchive/test/test_read_format_zip.c
+++ b/lib/libarchive/test/test_read_format_zip.c
@@ -48,6 +48,9 @@ DEFINE_TEST(test_read_format_zip)
struct archive_entry *ae;
struct archive *a;
char *buff[128];
+ const void *pv;
+ size_t s;
+ off_t o;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_compression_all(a));
@@ -57,6 +60,9 @@ DEFINE_TEST(test_read_format_zip)
assertEqualString("dir/", archive_entry_pathname(ae));
assertEqualInt(1179604249, archive_entry_mtime(ae));
assertEqualInt(0, archive_entry_size(ae));
+ assertEqualIntA(a, ARCHIVE_EOF,
+ archive_read_data_block(a, &pv, &s, &o));
+ assertEqualInt(s, 0);
assertA(0 == archive_read_next_header(a, &ae));
assertEqualString("file1", archive_entry_pathname(ae));
assertEqualInt(1179604289, archive_entry_mtime(ae));
diff --git a/lib/libarchive/test/test_read_pax_truncated.c b/lib/libarchive/test/test_read_pax_truncated.c
index 25db36114ce4..132c73315f52 100644
--- a/lib/libarchive/test/test_read_pax_truncated.c
+++ b/lib/libarchive/test/test_read_pax_truncated.c
@@ -29,9 +29,9 @@ DEFINE_TEST(test_read_pax_truncated)
{
struct archive_entry *ae;
struct archive *a;
- size_t used, i;
+ ssize_t used, i;
size_t buff_size = 1000000;
- size_t filedata_size = 100000;
+ ssize_t filedata_size = 100000;
char *buff = malloc(buff_size);
char *buff2 = malloc(buff_size);
char *filedata = malloc(filedata_size);
diff --git a/lib/libarchive/test/test_tar_filenames.c b/lib/libarchive/test/test_tar_filenames.c
index 1678f7a7ed8c..254917e5c80a 100644
--- a/lib/libarchive/test/test_tar_filenames.c
+++ b/lib/libarchive/test/test_tar_filenames.c
@@ -41,7 +41,7 @@ test_filename(const char *prefix, int dlen, int flen)
struct archive *a;
size_t used;
size_t prefix_length = 0;
- int i = 0;
+ unsigned i = 0;
if (prefix) {
strcpy(filename, prefix);
diff --git a/lib/libarchive/test/test_write_disk.c b/lib/libarchive/test/test_write_disk.c
index fb805ff8a393..ddad9b66273f 100644
--- a/lib/libarchive/test/test_write_disk.c
+++ b/lib/libarchive/test/test_write_disk.c
@@ -60,6 +60,24 @@ static void create_reg_file(struct archive_entry *ae, const char *msg)
/* Write the entry to disk. */
assert((ad = archive_write_disk_new()) != NULL);
failure("%s", msg);
+ /*
+ * A touchy API design issue: archive_write_data() does (as of
+ * 2.4.12) enforce the entry size as a limit on the data
+ * written to the file. This was not enforced prior to
+ * 2.4.12. The change was prompted by the refined
+ * hardlink-restore semantics introduced at that time. In
+ * short, libarchive needs to know whether a "hardlink entry"
+ * is going to overwrite the contents so that it can know
+ * whether or not to open the file for writing. This implies
+ * that there is a fundamental semantic difference between an
+ * entry with a zero size and one with a non-zero size in the
+ * case of hardlinks and treating the hardlink case
+ * differently from the regular file case is just asking for
+ * trouble. So, a zero size must always mean that no data
+ * will be accepted, which is consistent with the file size in
+ * the entry being a maximum size.
+ */
+ archive_entry_set_size(ae, sizeof(data));
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
@@ -92,6 +110,11 @@ static void create_reg_file2(struct archive_entry *ae, const char *msg)
/* Write the entry to disk. */
assert((ad = archive_write_disk_new()) != NULL);
failure("%s", msg);
+ /*
+ * See above for an explanation why this next call
+ * is necessary.
+ */
+ archive_entry_set_size(ae, datasize);
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
for (i = 0; i < datasize - 999; i += 1000) {
assertEqualIntA(ad, ARCHIVE_OK,
diff --git a/lib/libarchive/test/test_write_disk_perms.c b/lib/libarchive/test/test_write_disk_perms.c
index accd7541460d..2a5d5fdeb1f6 100644
--- a/lib/libarchive/test/test_write_disk_perms.c
+++ b/lib/libarchive/test/test_write_disk_perms.c
@@ -244,16 +244,18 @@ DEFINE_TEST(test_write_disk_perms)
failure("Opportunistic SUID failure shouldn't return error.");
assertEqualInt(0, archive_write_finish_entry(a));
- assert(archive_entry_clear(ae) != NULL);
- archive_entry_copy_pathname(ae, "file_bad_suid2");
- archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
- archive_entry_set_uid(ae, getuid() + 1);
- archive_write_disk_set_options(a,
- ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
- assertA(0 == archive_write_header(a, ae));
- /* Owner change should fail here. */
- failure("Non-opportunistic SUID failure should return error.");
- assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
+ if (getuid() != 0) {
+ assert(archive_entry_clear(ae) != NULL);
+ archive_entry_copy_pathname(ae, "file_bad_suid2");
+ archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
+ archive_entry_set_uid(ae, getuid() + 1);
+ archive_write_disk_set_options(a,
+ ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
+ assertA(0 == archive_write_header(a, ae));
+ /* Owner change should fail here. */
+ failure("Non-opportunistic SUID failure should return error.");
+ assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
+ }
/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
assert(archive_entry_clear(ae) != NULL);
@@ -403,10 +405,13 @@ DEFINE_TEST(test_write_disk_perms)
failure("file_bad_suid: st.st_mode=%o", st.st_mode);
assert((st.st_mode & 07777) == (0742));
- /* SUID bit should NOT have been set here. */
- assert(0 == stat("file_bad_suid2", &st));
- failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
- assert((st.st_mode & 07777) == (0742));
+ /* Some things don't fail if you're root, so suppress this. */
+ if (getuid() != 0) {
+ /* SUID bit should NOT have been set here. */
+ assert(0 == stat("file_bad_suid2", &st));
+ failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
+ assert((st.st_mode & 07777) == (0742));
+ }
/* SGID should be set here. */
assert(0 == stat("file_perm_sgid", &st));
diff --git a/lib/libarchive/test/test_write_format_cpio.c b/lib/libarchive/test/test_write_format_cpio.c
index 2ea40a36b445..5368e56b5153 100644
--- a/lib/libarchive/test/test_write_format_cpio.c
+++ b/lib/libarchive/test/test_write_format_cpio.c
@@ -37,6 +37,7 @@ test_format(int (*set_format)(struct archive *))
size_t used;
size_t buffsize = 1000000;
char *buff;
+ int damaged = 0;
buff = malloc(buffsize);
@@ -66,6 +67,41 @@ test_format(int (*set_format)(struct archive *))
archive_entry_free(ae);
assertA(8 == archive_write_data(a, "12345678", 9));
+ /*
+ * Write another file to it.
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(ae, 1, 10);
+ assert(1 == archive_entry_mtime(ae));
+ assert(10 == archive_entry_mtime_nsec(ae));
+ p = strdup("file2");
+ archive_entry_copy_pathname(ae, p);
+ strcpy(p, "XXXX");
+ free(p);
+ assertEqualString("file2", archive_entry_pathname(ae));
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ assert((S_IFREG | 0755) == archive_entry_mode(ae));
+ archive_entry_set_size(ae, 4);
+
+ assertA(0 == archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertA(4 == archive_write_data(a, "1234", 5));
+
+ /*
+ * Write a directory to it.
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(ae, 11, 110);
+ archive_entry_copy_pathname(ae, "dir");
+ archive_entry_set_mode(ae, S_IFDIR | 0755);
+ archive_entry_set_size(ae, 512);
+
+ assertA(0 == archive_write_header(a, ae));
+ assertEqualInt(0, archive_entry_size(ae));
+ archive_entry_free(ae);
+ assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));
+
+
/* Close out the archive. */
assertA(0 == archive_write_close(a));
#if ARCHIVE_API_VERSION > 1
@@ -75,6 +111,22 @@ test_format(int (*set_format)(struct archive *))
#endif
/*
+ * Damage the second entry to test the search-ahead recovery.
+ */
+ {
+ int i;
+ for (i = 80; i < 150; i++) {
+ if (memcmp(buff + i, "07070", 5) == 0) {
+ damaged = 1;
+ buff[i] = 'X';
+ break;
+ }
+ }
+ }
+ failure("Unable to locate the second header for damage-recovery test.");
+ assert(damaged = 1);
+
+ /*
* Now, read the data back.
*/
assert((a = archive_read_new()) != NULL);
@@ -82,21 +134,53 @@ test_format(int (*set_format)(struct archive *))
assertA(0 == archive_read_support_compression_all(a));
assertA(0 == archive_read_open_memory(a, buff, used));
- assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
- assert(1 == archive_entry_mtime(ae));
+ assertEqualInt(1, archive_entry_mtime(ae));
/* Not the same as above: cpio doesn't store hi-res times. */
assert(0 == archive_entry_mtime_nsec(ae));
assert(0 == archive_entry_atime(ae));
assert(0 == archive_entry_ctime(ae));
assertEqualString("file", archive_entry_pathname(ae));
- assert((S_IFREG | 0755) == archive_entry_mode(ae));
- assert(8 == archive_entry_size(ae));
+ assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
+ assertEqualInt(8, archive_entry_size(ae));
assertA(8 == archive_read_data(a, filedata, 10));
assert(0 == memcmp(filedata, "12345678", 8));
+ /*
+ * Read the second file back.
+ */
+ if (!damaged) {
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(1, archive_entry_mtime(ae));
+ /* Not the same as above: cpio doesn't store hi-res times. */
+ assert(0 == archive_entry_mtime_nsec(ae));
+ assert(0 == archive_entry_atime(ae));
+ assert(0 == archive_entry_ctime(ae));
+ assertEqualString("file2", archive_entry_pathname(ae));
+ assert((S_IFREG | 0755) == archive_entry_mode(ae));
+ assertEqualInt(4, archive_entry_size(ae));
+ assertEqualIntA(a, 4, archive_read_data(a, filedata, 10));
+ assert(0 == memcmp(filedata, "1234", 4));
+ }
+
+ /*
+ * Read the dir entry back.
+ */
+ assertEqualIntA(a,
+ damaged ? ARCHIVE_WARN : ARCHIVE_OK,
+ archive_read_next_header(a, &ae));
+ assertEqualInt(11, archive_entry_mtime(ae));
+ assert(0 == archive_entry_mtime_nsec(ae));
+ assert(0 == archive_entry_atime(ae));
+ assert(0 == archive_entry_ctime(ae));
+ assertEqualString("dir", archive_entry_pathname(ae));
+ assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae));
+ assertEqualInt(0, archive_entry_size(ae));
+ assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));
+
/* Verify the end of the archive. */
- assert(1 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, 1, archive_read_next_header(a, &ae));
assert(0 == archive_read_close(a));
#if ARCHIVE_API_VERSION > 1
assert(0 == archive_read_finish(a));
diff --git a/lib/libarchive/test/test_write_format_cpio_newc.c b/lib/libarchive/test/test_write_format_cpio_newc.c
index 9b16e47cceac..eec746ba6f4b 100644
--- a/lib/libarchive/test/test_write_format_cpio_newc.c
+++ b/lib/libarchive/test/test_write_format_cpio_newc.c
@@ -25,7 +25,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-
static int
is_hex(const char *p, size_t l)
{
diff --git a/lib/libarchive/test/test_write_format_cpio_odc.c b/lib/libarchive/test/test_write_format_cpio_odc.c
index 796dd7eace9a..94c027b6307b 100644
--- a/lib/libarchive/test/test_write_format_cpio_odc.c
+++ b/lib/libarchive/test/test_write_format_cpio_odc.c
@@ -25,7 +25,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-
static int
is_octal(const char *p, size_t l)
{