diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # libarchive
 
+# 3.0.5.0
+
+  * use libarchive-clib package
+
 # 3.0.4.2
 
   * Package bounds for Hackage
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -1,9 +1,8 @@
 module Main (main) where
 
 import           Codec.Archive
-import           Codec.Archive.Tar      (Entries (..), FormatError)
+import           Codec.Archive.Tar      (Entries, FormatError, GenEntries (..))
 import qualified Codec.Archive.Tar      as Tar
-import           Control.Monad          (void)
 import           Control.Monad.IO.Class (liftIO)
 import           Criterion.Main
 import qualified Data.ByteString.Lazy   as BSL
diff --git a/c/archive.h b/c/archive.h
deleted file mode 100644
--- a/c/archive.h
+++ /dev/null
@@ -1,1212 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $
- */
-
-#ifndef ARCHIVE_H_INCLUDED
-#define	ARCHIVE_H_INCLUDED
-
-/*
- * The version number is expressed as a single integer that makes it
- * easy to compare versions at build time: for version a.b.c, the
- * version number is printf("%d%03d%03d",a,b,c).  For example, if you
- * know your application requires version 2.12.108 or later, you can
- * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
- */
-/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define	ARCHIVE_VERSION_NUMBER 3007001
-
-#include <sys/stat.h>
-#include <stddef.h>  /* for wchar_t */
-#include <stdio.h> /* For FILE * */
-#include <time.h> /* For time_t */
-
-/*
- * Note: archive.h is for use outside of libarchive; the configuration
- * headers (config.h, archive_platform.h, etc.) are purely internal.
- * Do NOT use HAVE_XXX configuration macros to control the behavior of
- * this header!  If you must conditionalize, use predefined compiler and/or
- * platform macros.
- */
-#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
-# include <stdint.h>
-#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__) && !defined(__CLANG_INTTYPES_H)
-# include <inttypes.h>
-#endif
-
-/* Get appropriate definitions of 64-bit integer */
-#if !defined(__LA_INT64_T_DEFINED)
-/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */
-# if ARCHIVE_VERSION_NUMBER < 4000000
-#define __LA_INT64_T la_int64_t
-# endif
-#define __LA_INT64_T_DEFINED
-# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
-typedef __int64 la_int64_t;
-# else
-# include <unistd.h>  /* ssize_t */
-#  if defined(_SCO_DS) || defined(__osf__)
-typedef long long la_int64_t;
-#  else
-typedef int64_t la_int64_t;
-#  endif
-# endif
-#endif
-
-/* The la_ssize_t should match the type used in 'struct stat' */
-#if !defined(__LA_SSIZE_T_DEFINED)
-/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
-# if ARCHIVE_VERSION_NUMBER < 4000000
-#define __LA_SSIZE_T la_ssize_t
-# endif
-#define __LA_SSIZE_T_DEFINED
-# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
-#  if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
-typedef ssize_t la_ssize_t;
-#  elif defined(_WIN64)
-typedef __int64 la_ssize_t;
-#  else
-typedef long la_ssize_t;
-#  endif
-# else
-# include <unistd.h>  /* ssize_t */
-typedef ssize_t la_ssize_t;
-# endif
-#endif
-
-/* Large file support for Android */
-#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
-#include "android_lf.h"
-#endif
-
-/*
- * On Windows, define LIBARCHIVE_STATIC if you're building or using a
- * .lib.  The default here assumes you're building a DLL.  Only
- * libarchive source should ever define __LIBARCHIVE_BUILD.
- */
-#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
-# ifdef __LIBARCHIVE_BUILD
-#  ifdef __GNUC__
-#   define __LA_DECL	__attribute__((dllexport)) extern
-#  else
-#   define __LA_DECL	__declspec(dllexport)
-#  endif
-# else
-#  ifdef __GNUC__
-#   define __LA_DECL
-#  else
-#   define __LA_DECL	__declspec(dllimport)
-#  endif
-# endif
-#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
-#  define __LA_DECL __attribute__((visibility("default")))
-#else
-/* Static libraries or non-Windows needs no special declaration. */
-# define __LA_DECL
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__)
-#define	__LA_PRINTF(fmtarg, firstvararg) \
-	__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
-#else
-#define	__LA_PRINTF(fmtarg, firstvararg)	/* nothing */
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
-# define __LA_DEPRECATED __attribute__((deprecated))
-#else
-# define __LA_DEPRECATED
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The version number is provided as both a macro and a function.
- * The macro identifies the installed header; the function identifies
- * the library version (which may not be the same if you're using a
- * dynamically-linked version of the library).  Of course, if the
- * header and library are very different, you should expect some
- * strangeness.  Don't do that.
- */
-__LA_DECL int		archive_version_number(void);
-
-/*
- * Textual name/version of the library, useful for version displays.
- */
-#define	ARCHIVE_VERSION_ONLY_STRING "3.7.1"
-#define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
-__LA_DECL const char *	archive_version_string(void);
-
-/*
- * Detailed textual name/version of the library and its dependencies.
- * This has the form:
- *    "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..."
- * the list of libraries described here will vary depending on how
- * libarchive was compiled.
- */
-__LA_DECL const char *	archive_version_details(void);
-
-/*
- * Returns NULL if libarchive was compiled without the associated library.
- * Otherwise, returns the version number that libarchive was compiled
- * against.
- */
-__LA_DECL const char *  archive_zlib_version(void);
-__LA_DECL const char *  archive_liblzma_version(void);
-__LA_DECL const char *  archive_bzlib_version(void);
-__LA_DECL const char *  archive_liblz4_version(void);
-__LA_DECL const char *  archive_libzstd_version(void);
-
-/* Declare our basic types. */
-struct archive;
-struct archive_entry;
-
-/*
- * Error codes: Use archive_errno() and archive_error_string()
- * to retrieve details.  Unless specified otherwise, all functions
- * that return 'int' use these codes.
- */
-#define	ARCHIVE_EOF	  1	/* Found end of archive. */
-#define	ARCHIVE_OK	  0	/* Operation was successful. */
-#define	ARCHIVE_RETRY	(-10)	/* Retry might succeed. */
-#define	ARCHIVE_WARN	(-20)	/* Partial success. */
-/* For example, if write_header "fails", then you can't push data. */
-#define	ARCHIVE_FAILED	(-25)	/* Current operation cannot complete. */
-/* But if write_header is "fatal," then this archive is dead and useless. */
-#define	ARCHIVE_FATAL	(-30)	/* No more operations are possible. */
-
-/*
- * As far as possible, archive_errno returns standard platform errno codes.
- * Of course, the details vary by platform, so the actual definitions
- * here are stored in "archive_platform.h".  The symbols are listed here
- * for reference; as a rule, clients should not need to know the exact
- * platform-dependent error code.
- */
-/* Unrecognized or invalid file format. */
-/* #define	ARCHIVE_ERRNO_FILE_FORMAT */
-/* Illegal usage of the library. */
-/* #define	ARCHIVE_ERRNO_PROGRAMMER_ERROR */
-/* Unknown or unclassified error. */
-/* #define	ARCHIVE_ERRNO_MISC */
-
-/*
- * Callbacks are invoked to automatically read/skip/write/open/close the
- * archive. You can provide your own for complex tasks (like breaking
- * archives across multiple tapes) or use standard ones built into the
- * library.
- */
-
-/* Returns pointer and size of next block of data from archive. */
-typedef la_ssize_t	archive_read_callback(struct archive *,
-			    void *_client_data, const void **_buffer);
-
-/* Skips at most request bytes from archive and returns the skipped amount.
- * This may skip fewer bytes than requested; it may even skip zero bytes.
- * If you do skip fewer bytes than requested, libarchive will invoke your
- * read callback and discard data as necessary to make up the full skip.
- */
-typedef la_int64_t	archive_skip_callback(struct archive *,
-			    void *_client_data, la_int64_t request);
-
-/* Seeks to specified location in the file and returns the position.
- * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
- * Return ARCHIVE_FATAL if the seek fails for any reason.
- */
-typedef la_int64_t	archive_seek_callback(struct archive *,
-    void *_client_data, la_int64_t offset, int whence);
-
-/* Returns size actually written, zero on EOF, -1 on error. */
-typedef la_ssize_t	archive_write_callback(struct archive *,
-			    void *_client_data,
-			    const void *_buffer, size_t _length);
-
-typedef int	archive_open_callback(struct archive *, void *_client_data);
-
-typedef int	archive_close_callback(struct archive *, void *_client_data);
-
-typedef int	archive_free_callback(struct archive *, void *_client_data);
-
-/* Switches from one client data object to the next/prev client data object.
- * This is useful for reading from different data blocks such as a set of files
- * that make up one large file.
- */
-typedef int archive_switch_callback(struct archive *, void *_client_data1,
-			    void *_client_data2);
-
-/*
- * Returns a passphrase used for encryption or decryption, NULL on nothing
- * to do and give it up.
- */
-typedef const char *archive_passphrase_callback(struct archive *,
-			    void *_client_data);
-
-/*
- * Codes to identify various stream filters.
- */
-#define	ARCHIVE_FILTER_NONE	0
-#define	ARCHIVE_FILTER_GZIP	1
-#define	ARCHIVE_FILTER_BZIP2	2
-#define	ARCHIVE_FILTER_COMPRESS	3
-#define	ARCHIVE_FILTER_PROGRAM	4
-#define	ARCHIVE_FILTER_LZMA	5
-#define	ARCHIVE_FILTER_XZ	6
-#define	ARCHIVE_FILTER_UU	7
-#define	ARCHIVE_FILTER_RPM	8
-#define	ARCHIVE_FILTER_LZIP	9
-#define	ARCHIVE_FILTER_LRZIP	10
-#define	ARCHIVE_FILTER_LZOP	11
-#define	ARCHIVE_FILTER_GRZIP	12
-#define	ARCHIVE_FILTER_LZ4	13
-#define	ARCHIVE_FILTER_ZSTD	14
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-#define	ARCHIVE_COMPRESSION_NONE	ARCHIVE_FILTER_NONE
-#define	ARCHIVE_COMPRESSION_GZIP	ARCHIVE_FILTER_GZIP
-#define	ARCHIVE_COMPRESSION_BZIP2	ARCHIVE_FILTER_BZIP2
-#define	ARCHIVE_COMPRESSION_COMPRESS	ARCHIVE_FILTER_COMPRESS
-#define	ARCHIVE_COMPRESSION_PROGRAM	ARCHIVE_FILTER_PROGRAM
-#define	ARCHIVE_COMPRESSION_LZMA	ARCHIVE_FILTER_LZMA
-#define	ARCHIVE_COMPRESSION_XZ		ARCHIVE_FILTER_XZ
-#define	ARCHIVE_COMPRESSION_UU		ARCHIVE_FILTER_UU
-#define	ARCHIVE_COMPRESSION_RPM		ARCHIVE_FILTER_RPM
-#define	ARCHIVE_COMPRESSION_LZIP	ARCHIVE_FILTER_LZIP
-#define	ARCHIVE_COMPRESSION_LRZIP	ARCHIVE_FILTER_LRZIP
-#endif
-
-/*
- * Codes returned by archive_format.
- *
- * Top 16 bits identifies the format family (e.g., "tar"); lower
- * 16 bits indicate the variant.  This is updated by read_next_header.
- * Note that the lower 16 bits will often vary from entry to entry.
- * In some cases, this variation occurs as libarchive learns more about
- * the archive (for example, later entries might utilize extensions that
- * weren't necessary earlier in the archive; in this case, libarchive
- * will change the format code to indicate the extended format that
- * was used).  In other cases, it's because different tools have
- * modified the archive and so different parts of the archive
- * actually have slightly different formats.  (Both tar and cpio store
- * format codes in each entry, so it is quite possible for each
- * entry to be in a different format.)
- */
-#define	ARCHIVE_FORMAT_BASE_MASK		0xff0000
-#define	ARCHIVE_FORMAT_CPIO			0x10000
-#define	ARCHIVE_FORMAT_CPIO_POSIX		(ARCHIVE_FORMAT_CPIO | 1)
-#define	ARCHIVE_FORMAT_CPIO_BIN_LE		(ARCHIVE_FORMAT_CPIO | 2)
-#define	ARCHIVE_FORMAT_CPIO_BIN_BE		(ARCHIVE_FORMAT_CPIO | 3)
-#define	ARCHIVE_FORMAT_CPIO_SVR4_NOCRC		(ARCHIVE_FORMAT_CPIO | 4)
-#define	ARCHIVE_FORMAT_CPIO_SVR4_CRC		(ARCHIVE_FORMAT_CPIO | 5)
-#define	ARCHIVE_FORMAT_CPIO_AFIO_LARGE		(ARCHIVE_FORMAT_CPIO | 6)
-#define	ARCHIVE_FORMAT_CPIO_PWB			(ARCHIVE_FORMAT_CPIO | 7)
-#define	ARCHIVE_FORMAT_SHAR			0x20000
-#define	ARCHIVE_FORMAT_SHAR_BASE		(ARCHIVE_FORMAT_SHAR | 1)
-#define	ARCHIVE_FORMAT_SHAR_DUMP		(ARCHIVE_FORMAT_SHAR | 2)
-#define	ARCHIVE_FORMAT_TAR			0x30000
-#define	ARCHIVE_FORMAT_TAR_USTAR		(ARCHIVE_FORMAT_TAR | 1)
-#define	ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE	(ARCHIVE_FORMAT_TAR | 2)
-#define	ARCHIVE_FORMAT_TAR_PAX_RESTRICTED	(ARCHIVE_FORMAT_TAR | 3)
-#define	ARCHIVE_FORMAT_TAR_GNUTAR		(ARCHIVE_FORMAT_TAR | 4)
-#define	ARCHIVE_FORMAT_ISO9660			0x40000
-#define	ARCHIVE_FORMAT_ISO9660_ROCKRIDGE	(ARCHIVE_FORMAT_ISO9660 | 1)
-#define	ARCHIVE_FORMAT_ZIP			0x50000
-#define	ARCHIVE_FORMAT_EMPTY			0x60000
-#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_RAW			0x90000
-#define	ARCHIVE_FORMAT_XAR			0xA0000
-#define	ARCHIVE_FORMAT_LHA			0xB0000
-#define	ARCHIVE_FORMAT_CAB			0xC0000
-#define	ARCHIVE_FORMAT_RAR			0xD0000
-#define	ARCHIVE_FORMAT_7ZIP			0xE0000
-#define	ARCHIVE_FORMAT_WARC			0xF0000
-#define	ARCHIVE_FORMAT_RAR_V5			0x100000
-
-/*
- * Codes returned by archive_read_format_capabilities().
- *
- * This list can be extended with values between 0 and 0xffff.
- * The original purpose of this list was to let different archive
- * format readers expose their general capabilities in terms of
- * encryption.
- */
-#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
-#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0)  /* reader can detect encrypted data */
-#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1)  /* reader can detect encryptable metadata (pathname, mtime, etc.) */
-
-/*
- * Codes returned by archive_read_has_encrypted_entries().
- *
- * In case the archive does not support encryption detection at all
- * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
- * for some other reason (e.g. not enough bytes read) cannot say if
- * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
- * is returned.
- */
-#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
-#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
-
-/*-
- * Basic outline for reading an archive:
- *   1) Ask archive_read_new for an archive reader object.
- *   2) Update any global properties as appropriate.
- *      In particular, you'll certainly want to call appropriate
- *      archive_read_support_XXX functions.
- *   3) Call archive_read_open_XXX to open the archive
- *   4) Repeatedly call archive_read_next_header to get information about
- *      successive archive entries.  Call archive_read_data to extract
- *      data for entries of interest.
- *   5) Call archive_read_free to end processing.
- */
-__LA_DECL struct archive	*archive_read_new(void);
-
-/*
- * The archive_read_support_XXX calls enable auto-detect for this
- * archive handle.  They also link in the necessary support code.
- * For example, if you don't want bzlib linked in, don't invoke
- * support_compression_bzip2().  The "all" functions provide the
- * obvious shorthand.
- */
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_read_support_compression_all(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_compress(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_gzip(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_lzip(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_lzma(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_none(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_program(struct archive *,
-		     const char *command) __LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_program_signature
-		(struct archive *, const char *,
-		 const void * /* match */, size_t) __LA_DEPRECATED;
-
-__LA_DECL int archive_read_support_compression_rpm(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_uu(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_read_support_compression_xz(struct archive *)
-		__LA_DEPRECATED;
-#endif
-
-__LA_DECL int archive_read_support_filter_all(struct archive *);
-__LA_DECL int archive_read_support_filter_by_code(struct archive *, int);
-__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
-__LA_DECL int archive_read_support_filter_compress(struct archive *);
-__LA_DECL int archive_read_support_filter_gzip(struct archive *);
-__LA_DECL int archive_read_support_filter_grzip(struct archive *);
-__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
-__LA_DECL int archive_read_support_filter_lz4(struct archive *);
-__LA_DECL int archive_read_support_filter_lzip(struct archive *);
-__LA_DECL int archive_read_support_filter_lzma(struct archive *);
-__LA_DECL int archive_read_support_filter_lzop(struct archive *);
-__LA_DECL int archive_read_support_filter_none(struct archive *);
-__LA_DECL int archive_read_support_filter_program(struct archive *,
-		     const char *command);
-__LA_DECL int archive_read_support_filter_program_signature
-		(struct archive *, const char * /* cmd */,
-				    const void * /* match */, size_t);
-__LA_DECL int archive_read_support_filter_rpm(struct archive *);
-__LA_DECL int archive_read_support_filter_uu(struct archive *);
-__LA_DECL int archive_read_support_filter_xz(struct archive *);
-__LA_DECL int archive_read_support_filter_zstd(struct archive *);
-
-__LA_DECL int archive_read_support_format_7zip(struct archive *);
-__LA_DECL int archive_read_support_format_all(struct archive *);
-__LA_DECL int archive_read_support_format_ar(struct archive *);
-__LA_DECL int archive_read_support_format_by_code(struct archive *, int);
-__LA_DECL int archive_read_support_format_cab(struct archive *);
-__LA_DECL int archive_read_support_format_cpio(struct archive *);
-__LA_DECL int archive_read_support_format_empty(struct archive *);
-__LA_DECL int archive_read_support_format_gnutar(struct archive *);
-__LA_DECL int archive_read_support_format_iso9660(struct archive *);
-__LA_DECL int archive_read_support_format_lha(struct archive *);
-__LA_DECL int archive_read_support_format_mtree(struct archive *);
-__LA_DECL int archive_read_support_format_rar(struct archive *);
-__LA_DECL int archive_read_support_format_rar5(struct archive *);
-__LA_DECL int archive_read_support_format_raw(struct archive *);
-__LA_DECL int archive_read_support_format_tar(struct archive *);
-__LA_DECL int archive_read_support_format_warc(struct archive *);
-__LA_DECL int archive_read_support_format_xar(struct archive *);
-/* archive_read_support_format_zip() enables both streamable and seekable
- * zip readers. */
-__LA_DECL int archive_read_support_format_zip(struct archive *);
-/* Reads Zip archives as stream from beginning to end.  Doesn't
- * correctly handle SFX ZIP files or ZIP archives that have been modified
- * in-place. */
-__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
-/* Reads starting from central directory; requires seekable input. */
-__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
-
-/* Functions to manually set the format and filters to be used. This is
- * useful to bypass the bidding process when the format and filters to use
- * is known in advance.
- */
-__LA_DECL int archive_read_set_format(struct archive *, int);
-__LA_DECL int archive_read_append_filter(struct archive *, int);
-__LA_DECL int archive_read_append_filter_program(struct archive *,
-    const char *);
-__LA_DECL int archive_read_append_filter_program_signature
-    (struct archive *, const char *, const void * /* match */, size_t);
-
-/* Set various callbacks. */
-__LA_DECL int archive_read_set_open_callback(struct archive *,
-    archive_open_callback *);
-__LA_DECL int archive_read_set_read_callback(struct archive *,
-    archive_read_callback *);
-__LA_DECL int archive_read_set_seek_callback(struct archive *,
-    archive_seek_callback *);
-__LA_DECL int archive_read_set_skip_callback(struct archive *,
-    archive_skip_callback *);
-__LA_DECL int archive_read_set_close_callback(struct archive *,
-    archive_close_callback *);
-/* Callback used to switch between one data object to the next */
-__LA_DECL int archive_read_set_switch_callback(struct archive *,
-    archive_switch_callback *);
-
-/* This sets the first data object. */
-__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
-/* This sets data object at specified index */
-__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
-    unsigned int);
-/* This adds a data object at the specified index. */
-__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
-    unsigned int);
-/* This appends a data object to the end of list */
-__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
-/* This prepends a data object to the beginning of list */
-__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
-
-/* Opening freezes the callbacks. */
-__LA_DECL int archive_read_open1(struct archive *);
-
-/* Convenience wrappers around the above. */
-__LA_DECL int archive_read_open(struct archive *, void *_client_data,
-		     archive_open_callback *, archive_read_callback *,
-		     archive_close_callback *);
-__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
-		     archive_open_callback *, archive_read_callback *,
-		     archive_skip_callback *, archive_close_callback *);
-
-/*
- * A variety of shortcuts that invoke archive_read_open() with
- * canned callbacks suitable for common situations.  The ones that
- * accept a block size handle tape blocking correctly.
- */
-/* Use this if you know the filename.  Note: NULL indicates stdin. */
-__LA_DECL int archive_read_open_filename(struct archive *,
-		     const char *_filename, size_t _block_size);
-/* Use this for reading multivolume files by filenames.
- * NOTE: Must be NULL terminated. Sorting is NOT done. */
-__LA_DECL int archive_read_open_filenames(struct archive *,
-		     const char **_filenames, size_t _block_size);
-__LA_DECL int archive_read_open_filename_w(struct archive *,
-		     const wchar_t *_filename, size_t _block_size);
-/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
-__LA_DECL int archive_read_open_file(struct archive *,
-		     const char *_filename, size_t _block_size) __LA_DEPRECATED;
-/* Read an archive that's stored in memory. */
-__LA_DECL int archive_read_open_memory(struct archive *,
-		     const void * buff, size_t size);
-/* A more involved version that is only used for internal testing. */
-__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff,
-		     size_t size, size_t read_size);
-/* Read an archive that's already open, using the file descriptor. */
-__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
-		     size_t _block_size);
-/* Read an archive that's already open, using a FILE *. */
-/* Note: DO NOT use this with tape drives. */
-__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
-
-/* Parses and returns next entry header. */
-__LA_DECL int archive_read_next_header(struct archive *,
-		     struct archive_entry **);
-
-/* Parses and returns next entry header using the archive_entry passed in */
-__LA_DECL int archive_read_next_header2(struct archive *,
-		     struct archive_entry *);
-
-/*
- * Retrieve the byte offset in UNCOMPRESSED data where last-read
- * header started.
- */
-__LA_DECL la_int64_t		 archive_read_header_position(struct archive *);
-
-/*
- * Returns 1 if the archive contains at least one encrypted entry.
- * If the archive format not support encryption at all
- * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
- * If for any other reason (e.g. not enough data read so far)
- * we cannot say whether there are encrypted entries, then
- * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
- * In general, this function will return values below zero when the
- * reader is uncertain or totally incapable of encryption support.
- * When this function returns 0 you can be sure that the reader
- * supports encryption detection but no encrypted entries have
- * been found yet.
- *
- * NOTE: If the metadata/header of an archive is also encrypted, you
- * cannot rely on the number of encrypted entries. That is why this
- * function does not return the number of encrypted entries but#
- * just shows that there are some.
- */
-__LA_DECL int	archive_read_has_encrypted_entries(struct archive *);
-
-/*
- * Returns a bitmask of capabilities that are supported by the archive format reader.
- * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
- */
-__LA_DECL int		 archive_read_format_capabilities(struct archive *);
-
-/* Read data from the body of an entry.  Similar to read(2). */
-__LA_DECL la_ssize_t		 archive_read_data(struct archive *,
-				    void *, size_t);
-
-/* Seek within the body of an entry.  Similar to lseek(2). */
-__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int);
-
-/*
- * A zero-copy version of archive_read_data that also exposes the file offset
- * of each returned block.  Note that the client has no way to specify
- * the desired size of the block.  The API does guarantee that offsets will
- * be strictly increasing and that returned blocks will not overlap.
- */
-__LA_DECL int archive_read_data_block(struct archive *a,
-		    const void **buff, size_t *size, la_int64_t *offset);
-
-/*-
- * Some convenience functions that are built on archive_read_data:
- *  'skip': skips entire entry
- *  'into_buffer': writes data into memory buffer that you provide
- *  'into_fd': writes data to specified filedes
- */
-__LA_DECL int archive_read_data_skip(struct archive *);
-__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
-
-/*
- * Set read options.
- */
-/* Apply option to the format only. */
-__LA_DECL int archive_read_set_format_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option to the filter only. */
-__LA_DECL int archive_read_set_filter_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option to both the format and the filter. */
-__LA_DECL int archive_read_set_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option string to both the format and the filter. */
-__LA_DECL int archive_read_set_options(struct archive *_a,
-			    const char *opts);
-
-/*
- * Add a decryption passphrase.
- */
-__LA_DECL int archive_read_add_passphrase(struct archive *, const char *);
-__LA_DECL int archive_read_set_passphrase_callback(struct archive *,
-			    void *client_data, archive_passphrase_callback *);
-
-
-/*-
- * Convenience function to recreate the current entry (whose header
- * has just been read) on disk.
- *
- * This does quite a bit more than just copy data to disk. It also:
- *  - Creates intermediate directories as required.
- *  - Manages directory permissions:  non-writable directories will
- *    be initially created with write permission enabled; when the
- *    archive is closed, dir permissions are edited to the values specified
- *    in the archive.
- *  - Checks hardlinks:  hardlinks will not be extracted unless the
- *    linked-to file was also extracted within the same session. (TODO)
- */
-
-/* The "flags" argument selects optional behavior, 'OR' the flags you want. */
-
-/* Default: Do not try to set owner/group. */
-#define	ARCHIVE_EXTRACT_OWNER			(0x0001)
-/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
-#define	ARCHIVE_EXTRACT_PERM			(0x0002)
-/* Default: Do not restore mtime/atime. */
-#define	ARCHIVE_EXTRACT_TIME			(0x0004)
-/* Default: Replace existing files. */
-#define	ARCHIVE_EXTRACT_NO_OVERWRITE 		(0x0008)
-/* Default: Try create first, unlink only if create fails with EEXIST. */
-#define	ARCHIVE_EXTRACT_UNLINK			(0x0010)
-/* Default: Do not restore ACLs. */
-#define	ARCHIVE_EXTRACT_ACL			(0x0020)
-/* Default: Do not restore fflags. */
-#define	ARCHIVE_EXTRACT_FFLAGS			(0x0040)
-/* Default: Do not restore xattrs. */
-#define	ARCHIVE_EXTRACT_XATTR 			(0x0080)
-/* Default: Do not try to guard against extracts redirected by symlinks. */
-/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
-#define	ARCHIVE_EXTRACT_SECURE_SYMLINKS		(0x0100)
-/* Default: Do not reject entries with '..' as path elements. */
-#define	ARCHIVE_EXTRACT_SECURE_NODOTDOT		(0x0200)
-/* Default: Create parent directories as needed. */
-#define	ARCHIVE_EXTRACT_NO_AUTODIR		(0x0400)
-/* Default: Overwrite files, even if one on disk is newer. */
-#define	ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER	(0x0800)
-/* Detect blocks of 0 and write holes instead. */
-#define	ARCHIVE_EXTRACT_SPARSE			(0x1000)
-/* Default: Do not restore Mac extended metadata. */
-/* This has no effect except on Mac OS. */
-#define	ARCHIVE_EXTRACT_MAC_METADATA		(0x2000)
-/* Default: Use HFS+ compression if it was compressed. */
-/* This has no effect except on Mac OS v10.6 or later. */
-#define	ARCHIVE_EXTRACT_NO_HFS_COMPRESSION	(0x4000)
-/* Default: Do not use HFS+ compression if it was not compressed. */
-/* This has no effect except on Mac OS v10.6 or later. */
-#define	ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED	(0x8000)
-/* Default: Do not reject entries with absolute paths */
-#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
-/* Default: Do not clear no-change flags when unlinking object */
-#define	ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS	(0x20000)
-/* Default: Do not extract atomically (using rename) */
-#define	ARCHIVE_EXTRACT_SAFE_WRITES		(0x40000)
-
-__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
-		     int flags);
-__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
-		     struct archive * /* dest */);
-__LA_DECL void	 archive_read_extract_set_progress_callback(struct archive *,
-		     void (*_progress_func)(void *), void *_user_data);
-
-/* Record the dev/ino of a file that will not be written.  This is
- * generally set to the dev/ino of the archive being read. */
-__LA_DECL void		archive_read_extract_set_skip_file(struct archive *,
-		     la_int64_t, la_int64_t);
-
-/* Close the file and release most resources. */
-__LA_DECL int		 archive_read_close(struct archive *);
-/* Release all resources and destroy the object. */
-/* Note that archive_read_free will call archive_read_close for you. */
-__LA_DECL int		 archive_read_free(struct archive *);
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Synonym for archive_read_free() for backwards compatibility. */
-__LA_DECL int		 archive_read_finish(struct archive *) __LA_DEPRECATED;
-#endif
-
-/*-
- * To create an archive:
- *   1) Ask archive_write_new for an archive writer object.
- *   2) Set any global properties.  In particular, you should set
- *      the compression and format to use.
- *   3) Call archive_write_open to open the file (most people
- *       will use archive_write_open_file or archive_write_open_fd,
- *       which provide convenient canned I/O callbacks for you).
- *   4) For each entry:
- *      - construct an appropriate struct archive_entry structure
- *      - archive_write_header to write the header
- *      - archive_write_data to write the entry data
- *   5) archive_write_close to close the output
- *   6) archive_write_free to cleanup the writer and release resources
- */
-__LA_DECL struct archive	*archive_write_new(void);
-__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
-		     int bytes_per_block);
-__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
-/* XXX This is badly misnamed; suggestions appreciated. XXX */
-__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
-		     int bytes_in_last_block);
-__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
-
-/* The dev/ino of a file that won't be archived.  This is used
- * to avoid recursively adding an archive to itself. */
-__LA_DECL int archive_write_set_skip_file(struct archive *,
-    la_int64_t, la_int64_t);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_compress(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_gzip(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_lzip(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_lzma(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_none(struct archive *)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_program(struct archive *,
-		     const char *cmd) __LA_DEPRECATED;
-__LA_DECL int archive_write_set_compression_xz(struct archive *)
-		__LA_DEPRECATED;
-#endif
-
-/* A convenience function to set the filter based on the code. */
-__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
-__LA_DECL int archive_write_add_filter_by_name(struct archive *,
-		     const char *name);
-__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
-__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
-__LA_DECL int archive_write_add_filter_compress(struct archive *);
-__LA_DECL int archive_write_add_filter_grzip(struct archive *);
-__LA_DECL int archive_write_add_filter_gzip(struct archive *);
-__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
-__LA_DECL int archive_write_add_filter_lz4(struct archive *);
-__LA_DECL int archive_write_add_filter_lzip(struct archive *);
-__LA_DECL int archive_write_add_filter_lzma(struct archive *);
-__LA_DECL int archive_write_add_filter_lzop(struct archive *);
-__LA_DECL int archive_write_add_filter_none(struct archive *);
-__LA_DECL int archive_write_add_filter_program(struct archive *,
-		     const char *cmd);
-__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
-__LA_DECL int archive_write_add_filter_xz(struct archive *);
-__LA_DECL int archive_write_add_filter_zstd(struct archive *);
-
-
-/* A convenience function to set the format based on the code or name. */
-__LA_DECL int archive_write_set_format(struct archive *, int format_code);
-__LA_DECL int archive_write_set_format_by_name(struct archive *,
-		     const char *name);
-/* To minimize link pollution, use one or more of the following. */
-__LA_DECL int archive_write_set_format_7zip(struct archive *);
-__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
-__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
-__LA_DECL int archive_write_set_format_cpio(struct archive *);
-__LA_DECL int archive_write_set_format_cpio_bin(struct archive *);
-__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
-__LA_DECL int archive_write_set_format_cpio_odc(struct archive *);
-__LA_DECL int archive_write_set_format_cpio_pwb(struct archive *);
-__LA_DECL int archive_write_set_format_gnutar(struct archive *);
-__LA_DECL int archive_write_set_format_iso9660(struct archive *);
-__LA_DECL int archive_write_set_format_mtree(struct archive *);
-__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
-/* TODO: int archive_write_set_format_old_tar(struct archive *); */
-__LA_DECL int archive_write_set_format_pax(struct archive *);
-__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
-__LA_DECL int archive_write_set_format_raw(struct archive *);
-__LA_DECL int archive_write_set_format_shar(struct archive *);
-__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
-__LA_DECL int archive_write_set_format_ustar(struct archive *);
-__LA_DECL int archive_write_set_format_v7tar(struct archive *);
-__LA_DECL int archive_write_set_format_warc(struct archive *);
-__LA_DECL int archive_write_set_format_xar(struct archive *);
-__LA_DECL int archive_write_set_format_zip(struct archive *);
-__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename);
-__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
-__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
-__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
-/* Deprecated; use archive_write_open2 instead */
-__LA_DECL int archive_write_open(struct archive *, void *,
-		     archive_open_callback *, archive_write_callback *,
-		     archive_close_callback *);
-__LA_DECL int archive_write_open2(struct archive *, void *,
-		     archive_open_callback *, archive_write_callback *,
-		     archive_close_callback *, archive_free_callback *);
-__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
-__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
-__LA_DECL int archive_write_open_filename_w(struct archive *,
-		     const wchar_t *_file);
-/* A deprecated synonym for archive_write_open_filename() */
-__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
-		__LA_DEPRECATED;
-__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
-/* _buffSize is the size of the buffer, _used refers to a variable that
- * will be updated after each write into the buffer. */
-__LA_DECL int archive_write_open_memory(struct archive *,
-			void *_buffer, size_t _buffSize, size_t *_used);
-
-/*
- * Note that the library will truncate writes beyond the size provided
- * to archive_write_header or pad if the provided data is short.
- */
-__LA_DECL int archive_write_header(struct archive *,
-		     struct archive_entry *);
-__LA_DECL la_ssize_t	archive_write_data(struct archive *,
-			    const void *, size_t);
-
-/* This interface is currently only available for archive_write_disk handles.  */
-__LA_DECL la_ssize_t	 archive_write_data_block(struct archive *,
-				    const void *, size_t, la_int64_t);
-
-__LA_DECL int		 archive_write_finish_entry(struct archive *);
-__LA_DECL int		 archive_write_close(struct archive *);
-/* Marks the archive as FATAL so that a subsequent free() operation
- * won't try to close() cleanly.  Provides a fast abort capability
- * when the client discovers that things have gone wrong. */
-__LA_DECL int            archive_write_fail(struct archive *);
-/* This can fail if the archive wasn't already closed, in which case
- * archive_write_free() will implicitly call archive_write_close(). */
-__LA_DECL int		 archive_write_free(struct archive *);
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Synonym for archive_write_free() for backwards compatibility. */
-__LA_DECL int		 archive_write_finish(struct archive *) __LA_DEPRECATED;
-#endif
-
-/*
- * Set write options.
- */
-/* Apply option to the format only. */
-__LA_DECL int archive_write_set_format_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option to the filter only. */
-__LA_DECL int archive_write_set_filter_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option to both the format and the filter. */
-__LA_DECL int archive_write_set_option(struct archive *_a,
-			    const char *m, const char *o,
-			    const char *v);
-/* Apply option string to both the format and the filter. */
-__LA_DECL int archive_write_set_options(struct archive *_a,
-			    const char *opts);
-
-/*
- * Set a encryption passphrase.
- */
-__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p);
-__LA_DECL int archive_write_set_passphrase_callback(struct archive *,
-			    void *client_data, archive_passphrase_callback *);
-
-/*-
- * ARCHIVE_WRITE_DISK API
- *
- * To create objects on disk:
- *   1) Ask archive_write_disk_new for a new archive_write_disk object.
- *   2) Set any global properties.  In particular, you probably
- *      want to set the options.
- *   3) For each entry:
- *      - construct an appropriate struct archive_entry structure
- *      - archive_write_header to create the file/dir/etc on disk
- *      - archive_write_data to write the entry data
- *   4) archive_write_free to cleanup the writer and release resources
- *
- * In particular, you can use this in conjunction with archive_read()
- * to pull entries out of an archive and create them on disk.
- */
-__LA_DECL struct archive	*archive_write_disk_new(void);
-/* This file will not be overwritten. */
-__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
-    la_int64_t, la_int64_t);
-/* Set flags to control how the next item gets created.
- * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
-__LA_DECL int		 archive_write_disk_set_options(struct archive *,
-		     int flags);
-/*
- * The lookup functions are given uname/uid (or gname/gid) pairs and
- * return a uid (gid) suitable for this system.  These are used for
- * restoring ownership and for setting ACLs.  The default functions
- * are naive, they just return the uid/gid.  These are small, so reasonable
- * for applications that don't need to preserve ownership; they
- * are probably also appropriate for applications that are doing
- * same-system backup and restore.
- */
-/*
- * The "standard" lookup functions use common system calls to lookup
- * the uname/gname, falling back to the uid/gid if the names can't be
- * found.  They cache lookups and are reasonably fast, but can be very
- * large, so they are not used unless you ask for them.  In
- * particular, these match the specifications of POSIX "pax" and old
- * POSIX "tar".
- */
-__LA_DECL int	 archive_write_disk_set_standard_lookup(struct archive *);
-/*
- * If neither the default (naive) nor the standard (big) functions suit
- * your needs, you can write your own and register them.  Be sure to
- * include a cleanup function if you have allocated private data.
- */
-__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
-    void * /* private_data */,
-    la_int64_t (*)(void *, const char *, la_int64_t),
-    void (* /* cleanup */)(void *));
-__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
-    void * /* private_data */,
-    la_int64_t (*)(void *, const char *, la_int64_t),
-    void (* /* cleanup */)(void *));
-__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t);
-__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t);
-
-/*
- * ARCHIVE_READ_DISK API
- *
- * This is still evolving and somewhat experimental.
- */
-__LA_DECL struct archive *archive_read_disk_new(void);
-/* The names for symlink modes here correspond to an old BSD
- * command-line argument convention: -L, -P, -H */
-/* Follow all symlinks. */
-__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *);
-/* Follow no symlinks. */
-__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *);
-/* Follow symlink initially, then not. */
-__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *);
-/* TODO: Handle Linux stat32/stat64 ugliness. <sigh> */
-__LA_DECL int archive_read_disk_entry_from_file(struct archive *,
-    struct archive_entry *, int /* fd */, const struct stat *);
-/* Look up gname for gid or uname for uid. */
-/* Default implementations are very, very stupid. */
-__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t);
-__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t);
-/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
- * results for performance. */
-__LA_DECL int	archive_read_disk_set_standard_lookup(struct archive *);
-/* You can install your own lookups if you like. */
-__LA_DECL int	archive_read_disk_set_gname_lookup(struct archive *,
-    void * /* private_data */,
-    const char *(* /* lookup_fn */)(void *, la_int64_t),
-    void (* /* cleanup_fn */)(void *));
-__LA_DECL int	archive_read_disk_set_uname_lookup(struct archive *,
-    void * /* private_data */,
-    const char *(* /* lookup_fn */)(void *, la_int64_t),
-    void (* /* cleanup_fn */)(void *));
-/* Start traversal. */
-__LA_DECL int	archive_read_disk_open(struct archive *, const char *);
-__LA_DECL int	archive_read_disk_open_w(struct archive *, const wchar_t *);
-/*
- * Request that current entry be visited.  If you invoke it on every
- * directory, you'll get a physical traversal.  This is ignored if the
- * current entry isn't a directory or a link to a directory.  So, if
- * you invoke this on every returned path, you'll get a full logical
- * traversal.
- */
-__LA_DECL int	archive_read_disk_descend(struct archive *);
-__LA_DECL int	archive_read_disk_can_descend(struct archive *);
-__LA_DECL int	archive_read_disk_current_filesystem(struct archive *);
-__LA_DECL int	archive_read_disk_current_filesystem_is_synthetic(struct archive *);
-__LA_DECL int	archive_read_disk_current_filesystem_is_remote(struct archive *);
-/* Request that the access time of the entry visited by traversal be restored. */
-__LA_DECL int  archive_read_disk_set_atime_restored(struct archive *);
-/*
- * Set behavior. The "flags" argument selects optional behavior.
- */
-/* Request that the access time of the entry visited by traversal be restored.
- * This is the same as archive_read_disk_set_atime_restored. */
-#define	ARCHIVE_READDISK_RESTORE_ATIME		(0x0001)
-/* Default: Do not skip an entry which has nodump flags. */
-#define	ARCHIVE_READDISK_HONOR_NODUMP		(0x0002)
-/* Default: Skip a mac resource fork file whose prefix is "._" because of
- * using copyfile. */
-#define	ARCHIVE_READDISK_MAC_COPYFILE		(0x0004)
-/* Default: Traverse mount points. */
-#define	ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS	(0x0008)
-/* Default: Xattrs are read from disk. */
-#define	ARCHIVE_READDISK_NO_XATTR		(0x0010)
-/* Default: ACLs are read from disk. */
-#define	ARCHIVE_READDISK_NO_ACL			(0x0020)
-/* Default: File flags are read from disk. */
-#define	ARCHIVE_READDISK_NO_FFLAGS		(0x0040)
-/* Default: Sparse file information is read from disk. */
-#define	ARCHIVE_READDISK_NO_SPARSE		(0x0080)
-
-__LA_DECL int  archive_read_disk_set_behavior(struct archive *,
-		    int flags);
-
-/*
- * Set archive_match object that will be used in archive_read_disk to
- * know whether an entry should be skipped. The callback function
- * _excluded_func will be invoked when an entry is skipped by the result
- * of archive_match.
- */
-__LA_DECL int	archive_read_disk_set_matching(struct archive *,
-		    struct archive *_matching, void (*_excluded_func)
-		    (struct archive *, void *, struct archive_entry *),
-		    void *_client_data);
-__LA_DECL int	archive_read_disk_set_metadata_filter_callback(struct archive *,
-		    int (*_metadata_filter_func)(struct archive *, void *,
-		    	struct archive_entry *), void *_client_data);
-
-/* Simplified cleanup interface;
- * This calls archive_read_free() or archive_write_free() as needed. */
-__LA_DECL int	archive_free(struct archive *);
-
-/*
- * Accessor functions to read/set various information in
- * the struct archive object:
- */
-
-/* Number of filters in the current filter pipeline. */
-/* Filter #0 is the one closest to the format, -1 is a synonym for the
- * last filter, which is always the pseudo-filter that wraps the
- * client callbacks. */
-__LA_DECL int		 archive_filter_count(struct archive *);
-__LA_DECL la_int64_t	 archive_filter_bytes(struct archive *, int);
-__LA_DECL int		 archive_filter_code(struct archive *, int);
-__LA_DECL const char *	 archive_filter_name(struct archive *, int);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* These don't properly handle multiple filters, so are deprecated and
- * will eventually be removed. */
-/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
-__LA_DECL la_int64_t	 archive_position_compressed(struct archive *)
-				__LA_DEPRECATED;
-/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
-__LA_DECL la_int64_t	 archive_position_uncompressed(struct archive *)
-				__LA_DEPRECATED;
-/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
-__LA_DECL const char	*archive_compression_name(struct archive *)
-				__LA_DEPRECATED;
-/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
-__LA_DECL int		 archive_compression(struct archive *)
-				__LA_DEPRECATED;
-#endif
-
-__LA_DECL int		 archive_errno(struct archive *);
-__LA_DECL const char	*archive_error_string(struct archive *);
-__LA_DECL const char	*archive_format_name(struct archive *);
-__LA_DECL int		 archive_format(struct archive *);
-__LA_DECL void		 archive_clear_error(struct archive *);
-__LA_DECL void		 archive_set_error(struct archive *, int _err,
-			    const char *fmt, ...) __LA_PRINTF(3, 4);
-__LA_DECL void		 archive_copy_error(struct archive *dest,
-			    struct archive *src);
-__LA_DECL int		 archive_file_count(struct archive *);
-
-/*
- * ARCHIVE_MATCH API
- */
-__LA_DECL struct archive *archive_match_new(void);
-__LA_DECL int	archive_match_free(struct archive *);
-
-/*
- * Test if archive_entry is excluded.
- * This is a convenience function. This is the same as calling all
- * archive_match_path_excluded, archive_match_time_excluded
- * and archive_match_owner_excluded.
- */
-__LA_DECL int	archive_match_excluded(struct archive *,
-		    struct archive_entry *);
-
-/*
- * Test if pathname is excluded. The conditions are set by following functions.
- */
-__LA_DECL int	archive_match_path_excluded(struct archive *,
-		    struct archive_entry *);
-/* Control recursive inclusion of directory content when directory is included. Default on. */
-__LA_DECL int	archive_match_set_inclusion_recursion(struct archive *, int);
-/* Add exclusion pathname pattern. */
-__LA_DECL int	archive_match_exclude_pattern(struct archive *, const char *);
-__LA_DECL int	archive_match_exclude_pattern_w(struct archive *,
-		    const wchar_t *);
-/* Add exclusion pathname pattern from file. */
-__LA_DECL int	archive_match_exclude_pattern_from_file(struct archive *,
-		    const char *, int _nullSeparator);
-__LA_DECL int	archive_match_exclude_pattern_from_file_w(struct archive *,
-		    const wchar_t *, int _nullSeparator);
-/* Add inclusion pathname pattern. */
-__LA_DECL int	archive_match_include_pattern(struct archive *, const char *);
-__LA_DECL int	archive_match_include_pattern_w(struct archive *,
-		    const wchar_t *);
-/* Add inclusion pathname pattern from file. */
-__LA_DECL int	archive_match_include_pattern_from_file(struct archive *,
-		    const char *, int _nullSeparator);
-__LA_DECL int	archive_match_include_pattern_from_file_w(struct archive *,
-		    const wchar_t *, int _nullSeparator);
-/*
- * How to get statistic information for inclusion patterns.
- */
-/* Return the amount number of unmatched inclusion patterns. */
-__LA_DECL int	archive_match_path_unmatched_inclusions(struct archive *);
-/* Return the pattern of unmatched inclusion with ARCHIVE_OK.
- * Return ARCHIVE_EOF if there is no inclusion pattern. */
-__LA_DECL int	archive_match_path_unmatched_inclusions_next(
-		    struct archive *, const char **);
-__LA_DECL int	archive_match_path_unmatched_inclusions_next_w(
-		    struct archive *, const wchar_t **);
-
-/*
- * Test if a file is excluded by its time stamp.
- * The conditions are set by following functions.
- */
-__LA_DECL int	archive_match_time_excluded(struct archive *,
-		    struct archive_entry *);
-
-/*
- * Flags to tell a matching type of time stamps. These are used for
- * following functions.
- */
-/* Time flag: mtime to be tested. */
-#define ARCHIVE_MATCH_MTIME	(0x0100)
-/* Time flag: ctime to be tested. */
-#define ARCHIVE_MATCH_CTIME	(0x0200)
-/* Comparison flag: Match the time if it is newer than. */
-#define ARCHIVE_MATCH_NEWER	(0x0001)
-/* Comparison flag: Match the time if it is older than. */
-#define ARCHIVE_MATCH_OLDER	(0x0002)
-/* Comparison flag: Match the time if it is equal to. */
-#define ARCHIVE_MATCH_EQUAL	(0x0010)
-/* Set inclusion time. */
-__LA_DECL int	archive_match_include_time(struct archive *, int _flag,
-		    time_t _sec, long _nsec);
-/* Set inclusion time by a date string. */
-__LA_DECL int	archive_match_include_date(struct archive *, int _flag,
-		    const char *_datestr);
-__LA_DECL int	archive_match_include_date_w(struct archive *, int _flag,
-		    const wchar_t *_datestr);
-/* Set inclusion time by a particular file. */
-__LA_DECL int	archive_match_include_file_time(struct archive *,
-		    int _flag, const char *_pathname);
-__LA_DECL int	archive_match_include_file_time_w(struct archive *,
-		    int _flag, const wchar_t *_pathname);
-/* Add exclusion entry. */
-__LA_DECL int	archive_match_exclude_entry(struct archive *,
-		    int _flag, struct archive_entry *);
-
-/*
- * Test if a file is excluded by its uid ,gid, uname or gname.
- * The conditions are set by following functions.
- */
-__LA_DECL int	archive_match_owner_excluded(struct archive *,
-		    struct archive_entry *);
-/* Add inclusion uid, gid, uname and gname. */
-__LA_DECL int	archive_match_include_uid(struct archive *, la_int64_t);
-__LA_DECL int	archive_match_include_gid(struct archive *, la_int64_t);
-__LA_DECL int	archive_match_include_uname(struct archive *, const char *);
-__LA_DECL int	archive_match_include_uname_w(struct archive *,
-		    const wchar_t *);
-__LA_DECL int	archive_match_include_gname(struct archive *, const char *);
-__LA_DECL int	archive_match_include_gname_w(struct archive *,
-		    const wchar_t *);
-
-/* Utility functions */
-/* Convenience function to sort a NULL terminated list of strings */
-__LA_DECL int archive_utility_string_sort(char **);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* These are meaningless outside of this header. */
-#undef __LA_DECL
-
-#endif /* !ARCHIVE_H_INCLUDED */
diff --git a/c/archive_acl.c b/c/archive_acl.c
deleted file mode 100644
--- a/c/archive_acl.c
+++ /dev/null
@@ -1,2097 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#include "archive_acl_private.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-
-#undef max
-#define	max(a, b)	((a)>(b)?(a):(b))
-
-#ifndef HAVE_WMEMCMP
-/* Good enough for simple equality testing, but not for sorting. */
-#define wmemcmp(a,b,i)  memcmp((a), (b), (i) * sizeof(wchar_t))
-#endif
-
-static int	acl_special(struct archive_acl *acl,
-		    int type, int permset, int tag);
-static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
-		    int type, int permset, int tag, int id);
-static int	archive_acl_add_entry_len_l(struct archive_acl *acl,
-		    int type, int permset, int tag, int id, const char *name,
-		    size_t len, struct archive_string_conv *sc);
-static int	archive_acl_text_want_type(struct archive_acl *acl, int flags);
-static ssize_t	archive_acl_text_len(struct archive_acl *acl, int want_type,
-		    int flags, int wide, struct archive *a,
-		    struct archive_string_conv *sc);
-static int	isint_w(const wchar_t *start, const wchar_t *end, int *result);
-static int	ismode_w(const wchar_t *start, const wchar_t *end, int *result);
-static int	is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
-		    int *result);
-static int	is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
-		    int *result);
-static void	next_field_w(const wchar_t **wp, const wchar_t **start,
-		    const wchar_t **end, wchar_t *sep);
-static void	append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
-		    int tag, int flags, const wchar_t *wname, int perm, int id);
-static void	append_id_w(wchar_t **wp, int id);
-static int	isint(const char *start, const char *end, int *result);
-static int	ismode(const char *start, const char *end, int *result);
-static int	is_nfs4_flags(const char *start, const char *end,
-		    int *result);
-static int	is_nfs4_perms(const char *start, const char *end,
-		    int *result);
-static void	next_field(const char **p, const char **start,
-		    const char **end, char *sep);
-static void	append_entry(char **p, const char *prefix, int type,
-		    int tag, int flags, const char *name, int perm, int id);
-static void	append_id(char **p, int id);
-
-static const struct {
-	const int perm;
-	const char c;
-	const wchar_t wc;
-} nfsv4_acl_perm_map[] = {
-	{ ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r',
-	    L'r' },
-	{ ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w',
-	    L'w' },
-	{ ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' },
-	{ ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
-	    'p', L'p' },
-	{ ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' },
-	{ ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' },
-	{ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' },
-	{ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' },
-	{ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' },
-	{ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' },
-	{ ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' },
-	{ ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' },
-	{ ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' },
-	{ ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' }
-};
-
-static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) /
-    sizeof(nfsv4_acl_perm_map[0]));
-
-static const struct {
-	const int perm;
-	const char c;
-	const wchar_t wc;
-} nfsv4_acl_flag_map[] = {
-	{ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' },
-	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' }
-};
-
-static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) /
-    sizeof(nfsv4_acl_flag_map[0]));
-
-void
-archive_acl_clear(struct archive_acl *acl)
-{
-	struct archive_acl_entry *ap;
-
-	while (acl->acl_head != NULL) {
-		ap = acl->acl_head->next;
-		archive_mstring_clean(&acl->acl_head->name);
-		free(acl->acl_head);
-		acl->acl_head = ap;
-	}
-	free(acl->acl_text_w);
-	acl->acl_text_w = NULL;
-	free(acl->acl_text);
-	acl->acl_text = NULL;
-	acl->acl_p = NULL;
-	acl->acl_types = 0;
-	acl->acl_state = 0; /* Not counting. */
-}
-
-void
-archive_acl_copy(struct archive_acl *dest, struct archive_acl *src)
-{
-	struct archive_acl_entry *ap, *ap2;
-
-	archive_acl_clear(dest);
-
-	dest->mode = src->mode;
-	ap = src->acl_head;
-	while (ap != NULL) {
-		ap2 = acl_new_entry(dest,
-		    ap->type, ap->permset, ap->tag, ap->id);
-		if (ap2 != NULL)
-			archive_mstring_copy(&ap2->name, &ap->name);
-		ap = ap->next;
-	}
-}
-
-int
-archive_acl_add_entry(struct archive_acl *acl,
-    int type, int permset, int tag, int id, const char *name)
-{
-	struct archive_acl_entry *ap;
-
-	if (acl_special(acl, type, permset, tag) == 0)
-		return ARCHIVE_OK;
-	ap = acl_new_entry(acl, type, permset, tag, id);
-	if (ap == NULL) {
-		/* XXX Error XXX */
-		return ARCHIVE_FAILED;
-	}
-	if (name != NULL  &&  *name != '\0')
-		archive_mstring_copy_mbs(&ap->name, name);
-	else
-		archive_mstring_clean(&ap->name);
-	return ARCHIVE_OK;
-}
-
-int
-archive_acl_add_entry_w_len(struct archive_acl *acl,
-    int type, int permset, int tag, int id, const wchar_t *name, size_t len)
-{
-	struct archive_acl_entry *ap;
-
-	if (acl_special(acl, type, permset, tag) == 0)
-		return ARCHIVE_OK;
-	ap = acl_new_entry(acl, type, permset, tag, id);
-	if (ap == NULL) {
-		/* XXX Error XXX */
-		return ARCHIVE_FAILED;
-	}
-	if (name != NULL  &&  *name != L'\0' && len > 0)
-		archive_mstring_copy_wcs_len(&ap->name, name, len);
-	else
-		archive_mstring_clean(&ap->name);
-	return ARCHIVE_OK;
-}
-
-static int
-archive_acl_add_entry_len_l(struct archive_acl *acl,
-    int type, int permset, int tag, int id, const char *name, size_t len,
-    struct archive_string_conv *sc)
-{
-	struct archive_acl_entry *ap;
-	int r;
-
-	if (acl_special(acl, type, permset, tag) == 0)
-		return ARCHIVE_OK;
-	ap = acl_new_entry(acl, type, permset, tag, id);
-	if (ap == NULL) {
-		/* XXX Error XXX */
-		return ARCHIVE_FAILED;
-	}
-	if (name != NULL  &&  *name != '\0' && len > 0) {
-		r = archive_mstring_copy_mbs_len_l(&ap->name, name, len, sc);
-	} else {
-		r = 0;
-		archive_mstring_clean(&ap->name);
-	}
-	if (r == 0)
-		return (ARCHIVE_OK);
-	else if (errno == ENOMEM)
-		return (ARCHIVE_FATAL);
-	else
-		return (ARCHIVE_WARN);
-}
-
-/*
- * If this ACL entry is part of the standard POSIX permissions set,
- * store the permissions in the stat structure and return zero.
- */
-static int
-acl_special(struct archive_acl *acl, int type, int permset, int tag)
-{
-	if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
-	    && ((permset & ~007) == 0)) {
-		switch (tag) {
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			acl->mode &= ~0700;
-			acl->mode |= (permset & 7) << 6;
-			return (0);
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			acl->mode &= ~0070;
-			acl->mode |= (permset & 7) << 3;
-			return (0);
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			acl->mode &= ~0007;
-			acl->mode |= permset & 7;
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Allocate and populate a new ACL entry with everything but the
- * name.
- */
-static struct archive_acl_entry *
-acl_new_entry(struct archive_acl *acl,
-    int type, int permset, int tag, int id)
-{
-	struct archive_acl_entry *ap, *aq;
-
-	/* Type argument must be a valid NFS4 or POSIX.1e type.
-	 * The type must agree with anything already set and
-	 * the permset must be compatible. */
-	if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-		if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			return (NULL);
-		}
-		if (permset &
-		    ~(ARCHIVE_ENTRY_ACL_PERMS_NFS4
-			| ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4)) {
-			return (NULL);
-		}
-	} else	if (type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
-		if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
-			return (NULL);
-		}
-		if (permset & ~ARCHIVE_ENTRY_ACL_PERMS_POSIX1E) {
-			return (NULL);
-		}
-	} else {
-		return (NULL);
-	}
-
-	/* Verify the tag is valid and compatible with NFS4 or POSIX.1e. */
-	switch (tag) {
-	case ARCHIVE_ENTRY_ACL_USER:
-	case ARCHIVE_ENTRY_ACL_USER_OBJ:
-	case ARCHIVE_ENTRY_ACL_GROUP:
-	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-		/* Tags valid in both NFS4 and POSIX.1e */
-		break;
-	case ARCHIVE_ENTRY_ACL_MASK:
-	case ARCHIVE_ENTRY_ACL_OTHER:
-		/* Tags valid only in POSIX.1e. */
-		if (type & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
-			return (NULL);
-		}
-		break;
-	case ARCHIVE_ENTRY_ACL_EVERYONE:
-		/* Tags valid only in NFS4. */
-		if (type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			return (NULL);
-		}
-		break;
-	default:
-		/* No other values are valid. */
-		return (NULL);
-	}
-
-	free(acl->acl_text_w);
-	acl->acl_text_w = NULL;
-	free(acl->acl_text);
-	acl->acl_text = NULL;
-
-	/*
-	 * If there's a matching entry already in the list, overwrite it.
-	 * NFSv4 entries may be repeated and are not overwritten.
-	 *
-	 * TODO: compare names of no id is provided (needs more rework)
-	 */
-	ap = acl->acl_head;
-	aq = NULL;
-	while (ap != NULL) {
-		if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) &&
-		    ap->type == type && ap->tag == tag && ap->id == id) {
-			if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
-			    tag != ARCHIVE_ENTRY_ACL_GROUP)) {
-				ap->permset = permset;
-				return (ap);
-			}
-		}
-		aq = ap;
-		ap = ap->next;
-	}
-
-	/* Add a new entry to the end of the list. */
-	ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap));
-	if (ap == NULL)
-		return (NULL);
-	if (aq == NULL)
-		acl->acl_head = ap;
-	else
-		aq->next = ap;
-	ap->type = type;
-	ap->tag = tag;
-	ap->id = id;
-	ap->permset = permset;
-	acl->acl_types |= type;
-	return (ap);
-}
-
-/*
- * Return a count of entries matching "want_type".
- */
-int
-archive_acl_count(struct archive_acl *acl, int want_type)
-{
-	int count;
-	struct archive_acl_entry *ap;
-
-	count = 0;
-	ap = acl->acl_head;
-	while (ap != NULL) {
-		if ((ap->type & want_type) != 0)
-			count++;
-		ap = ap->next;
-	}
-
-	if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
-		count += 3;
-	return (count);
-}
-
-/*
- * Return a bitmask of stored ACL types in an ACL list
- */
-int
-archive_acl_types(struct archive_acl *acl)
-{
-	return (acl->acl_types);
-}
-
-/*
- * Prepare for reading entries from the ACL data.  Returns a count
- * of entries matching "want_type", or zero if there are no
- * non-extended ACL entries of that type.
- */
-int
-archive_acl_reset(struct archive_acl *acl, int want_type)
-{
-	int count, cutoff;
-
-	count = archive_acl_count(acl, want_type);
-
-	/*
-	 * If the only entries are the three standard ones,
-	 * then don't return any ACL data.  (In this case,
-	 * client can just use chmod(2) to set permissions.)
-	 */
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
-		cutoff = 3;
-	else
-		cutoff = 0;
-
-	if (count > cutoff)
-		acl->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
-	else
-		acl->acl_state = 0;
-	acl->acl_p = acl->acl_head;
-	return (count);
-}
-
-
-/*
- * Return the next ACL entry in the list.  Fake entries for the
- * standard permissions and include them in the returned list.
- */
-int
-archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type,
-    int *type, int *permset, int *tag, int *id, const char **name)
-{
-	*name = NULL;
-	*id = -1;
-
-	/*
-	 * The acl_state is either zero (no entries available), -1
-	 * (reading from list), or an entry type (retrieve that type
-	 * from ae_stat.aest_mode).
-	 */
-	if (acl->acl_state == 0)
-		return (ARCHIVE_WARN);
-
-	/* The first three access entries are special. */
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		switch (acl->acl_state) {
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			*permset = (acl->mode >> 6) & 7;
-			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-			*tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-			acl->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-			return (ARCHIVE_OK);
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			*permset = (acl->mode >> 3) & 7;
-			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-			*tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-			acl->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
-			return (ARCHIVE_OK);
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			*permset = acl->mode & 7;
-			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-			*tag = ARCHIVE_ENTRY_ACL_OTHER;
-			acl->acl_state = -1;
-			acl->acl_p = acl->acl_head;
-			return (ARCHIVE_OK);
-		default:
-			break;
-		}
-	}
-
-	while (acl->acl_p != NULL && (acl->acl_p->type & want_type) == 0)
-		acl->acl_p = acl->acl_p->next;
-	if (acl->acl_p == NULL) {
-		acl->acl_state = 0;
-		*type = 0;
-		*permset = 0;
-		*tag = 0;
-		*id = -1;
-		*name = NULL;
-		return (ARCHIVE_EOF); /* End of ACL entries. */
-	}
-	*type = acl->acl_p->type;
-	*permset = acl->acl_p->permset;
-	*tag = acl->acl_p->tag;
-	*id = acl->acl_p->id;
-	if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) {
-		if (errno == ENOMEM)
-			return (ARCHIVE_FATAL);
-		*name = NULL;
-	}
-	acl->acl_p = acl->acl_p->next;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Determine what type of ACL do we want
- */
-static int
-archive_acl_text_want_type(struct archive_acl *acl, int flags)
-{
-	int want_type;
-
-	/* Check if ACL is NFSv4 */
-	if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-		/* NFSv4 should never mix with POSIX.1e */
-		if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
-			return (0);
-		else
-			return (ARCHIVE_ENTRY_ACL_TYPE_NFS4);
-	}
-
-	/* Now deal with POSIX.1e ACLs */
-
-	want_type = 0;
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
-		want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-		want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-
-	/* By default we want both access and default ACLs */
-	if (want_type == 0)
-		return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E);
-
-	return (want_type);
-}
-
-/*
- * Calculate ACL text string length
- */
-static ssize_t
-archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
-    int wide, struct archive *a, struct archive_string_conv *sc) {
-	struct archive_acl_entry *ap;
-	const char *name;
-	const wchar_t *wname;
-	int count, idlen, tmp, r;
-	ssize_t length;
-	size_t len;
-
-	count = 0;
-	length = 0;
-	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
-		if ((ap->type & want_type) == 0)
-			continue;
-		/*
-		 * Filemode-mapping ACL entries are stored exclusively in
-		 * ap->mode so they should not be in the list
-		 */
-		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
-		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
-			continue;
-		count++;
-		if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
-		    && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-			length += 8; /* "default:" */
-		switch (ap->tag) {
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-				length += 6; /* "owner@" */
-				break;
-			}
-			/* FALLTHROUGH */
-		case ARCHIVE_ENTRY_ACL_USER:
-		case ARCHIVE_ENTRY_ACL_MASK:
-			length += 4; /* "user", "mask" */
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-				length += 6; /* "group@" */
-				break;
-			}
-			/* FALLTHROUGH */
-		case ARCHIVE_ENTRY_ACL_GROUP:
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			length += 5; /* "group", "other" */
-			break;
-		case ARCHIVE_ENTRY_ACL_EVERYONE:
-			length += 9; /* "everyone@" */
-			break;
-		}
-		length += 1; /* colon after tag */
-		if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
-			if (wide) {
-				r = archive_mstring_get_wcs(a, &ap->name,
-				    &wname);
-				if (r == 0 && wname != NULL)
-					length += wcslen(wname);
-				else if (r < 0 && errno == ENOMEM)
-					return (0);
-				else
-					length += sizeof(uid_t) * 3 + 1;
-			} else {
-				r = archive_mstring_get_mbs_l(a, &ap->name, &name,
-				    &len, sc);
-				if (r != 0)
-					return (0);
-				if (len > 0 && name != NULL)
-					length += len;
-				else
-					length += sizeof(uid_t) * 3 + 1;
-			}
-			length += 1; /* colon after user or group name */
-		} else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
-			length += 1; /* 2nd colon empty user,group or other */
-
-		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
-		    && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
-		    && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
-		    || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
-			/* Solaris has no colon after other: and mask: */
-			length = length - 1;
-		}
-
-		if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/* rwxpdDaARWcCos:fdinSFI:deny */
-			length += 27;
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
-				length += 1; /* allow, alarm, audit */
-		} else
-			length += 3; /* rwx */
-
-		if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
-		    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) {
-			length += 1; /* colon */
-			/* ID digit count */
-			idlen = 1;
-			tmp = ap->id;
-			while (tmp > 9) {
-				tmp = tmp / 10;
-				idlen++;
-			}
-			length += idlen;
-		}
-		length ++; /* entry separator */
-	}
-
-	/* Add filemode-mapping access entries to the length */
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
-			/* "user::rwx\ngroup::rwx\nother:rwx\n" */
-			length += 31;
-		} else {
-			/* "user::rwx\ngroup::rwx\nother::rwx\n" */
-			length += 32;
-		}
-	} else if (count == 0)
-		return (0);
-
-	/* The terminating character is included in count */
-	return (length);
-}
-
-/*
- * Generate a wide text version of the ACL. The flags parameter controls
- * the type and style of the generated ACL.
- */
-wchar_t *
-archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
-    struct archive *a)
-{
-	int count;
-	ssize_t length;
-	size_t len;
-	const wchar_t *wname;
-	const wchar_t *prefix;
-	wchar_t separator;
-	struct archive_acl_entry *ap;
-	int id, r, want_type;
-	wchar_t *wp, *ws;
-
-	want_type = archive_acl_text_want_type(acl, flags);
-
-	/* Both NFSv4 and POSIX.1 types found */
-	if (want_type == 0)
-		return (NULL);
-
-	if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
-		flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
-
-	length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
-
-	if (length == 0)
-		return (NULL);
-
-	if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
-		separator = L',';
-	else
-		separator = L'\n';
-
-	/* Now, allocate the string and actually populate it. */
-	wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t));
-	if (wp == NULL) {
-		if (errno == ENOMEM)
-			__archive_errx(1, "No memory");
-		return (NULL);
-	}
-	count = 0;
-
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
-		    acl->mode & 0700, -1);
-		*wp++ = separator;
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
-		    acl->mode & 0070, -1);
-		*wp++ = separator;
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
-		    acl->mode & 0007, -1);
-		count += 3;
-	}
-
-	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
-		if ((ap->type & want_type) == 0)
-			continue;
-		/*
-		 * Filemode-mapping ACL entries are stored exclusively in
-		 * ap->mode so they should not be in the list
-		 */
-		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
-		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
-			continue;
-		if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
-		    (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
-			prefix = L"default:";
-		else
-			prefix = NULL;
-		r = archive_mstring_get_wcs(a, &ap->name, &wname);
-		if (r == 0) {
-			if (count > 0)
-				*wp++ = separator;
-			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
-				id = ap->id;
-			else
-				id = -1;
-			append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
-			    wname, ap->permset, id);
-			count++;
-		} else if (r < 0 && errno == ENOMEM) {
-			free(ws);
-			return (NULL);
-		}
-	}
-
-	/* Add terminating character */
-	*wp++ = L'\0';
-
-	len = wcslen(ws);
-
-	if ((ssize_t)len > (length - 1))
-		__archive_errx(1, "Buffer overrun");
-
-	if (text_len != NULL)
-		*text_len = len;
-
-	return (ws);
-}
-
-static void
-append_id_w(wchar_t **wp, int id)
-{
-	if (id < 0)
-		id = 0;
-	if (id > 9)
-		append_id_w(wp, id / 10);
-	*(*wp)++ = L"0123456789"[id % 10];
-}
-
-static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
-    int tag, int flags, const wchar_t *wname, int perm, int id)
-{
-	int i;
-
-	if (prefix != NULL) {
-		wcscpy(*wp, prefix);
-		*wp += wcslen(*wp);
-	}
-	switch (tag) {
-	case ARCHIVE_ENTRY_ACL_USER_OBJ:
-		wname = NULL;
-		id = -1;
-		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			wcscpy(*wp, L"owner@");
-			break;
-		}
-		/* FALLTHROUGH */
-	case ARCHIVE_ENTRY_ACL_USER:
-		wcscpy(*wp, L"user");
-		break;
-	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-		wname = NULL;
-		id = -1;
-		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			wcscpy(*wp, L"group@");
-			break;
-		}
-		/* FALLTHROUGH */
-	case ARCHIVE_ENTRY_ACL_GROUP:
-		wcscpy(*wp, L"group");
-		break;
-	case ARCHIVE_ENTRY_ACL_MASK:
-		wcscpy(*wp, L"mask");
-		wname = NULL;
-		id = -1;
-		break;
-	case ARCHIVE_ENTRY_ACL_OTHER:
-		wcscpy(*wp, L"other");
-		wname = NULL;
-		id = -1;
-		break;
-	case ARCHIVE_ENTRY_ACL_EVERYONE:
-		wcscpy(*wp, L"everyone@");
-		wname = NULL;
-		id = -1;
-		break;
-	}
-	*wp += wcslen(*wp);
-	*(*wp)++ = L':';
-	if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
-	    tag == ARCHIVE_ENTRY_ACL_USER ||
-	    tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		if (wname != NULL) {
-			wcscpy(*wp, wname);
-			*wp += wcslen(*wp);
-		} else if (tag == ARCHIVE_ENTRY_ACL_USER
-		    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-			append_id_w(wp, id);
-			if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
-				id = -1;
-		}
-		/* Solaris style has no second colon after other and mask */
-		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
-		    || (tag != ARCHIVE_ENTRY_ACL_OTHER
-		    && tag != ARCHIVE_ENTRY_ACL_MASK))
-			*(*wp)++ = L':';
-	}
-	if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
-		/* POSIX.1e ACL perms */
-		*(*wp)++ = (perm & 0444) ? L'r' : L'-';
-		*(*wp)++ = (perm & 0222) ? L'w' : L'-';
-		*(*wp)++ = (perm & 0111) ? L'x' : L'-';
-	} else {
-		/* NFSv4 ACL perms */
-		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
-			if (perm & nfsv4_acl_perm_map[i].perm)
-				*(*wp)++ = nfsv4_acl_perm_map[i].wc;
-			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-				*(*wp)++ = L'-';
-		}
-		*(*wp)++ = L':';
-		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
-			if (perm & nfsv4_acl_flag_map[i].perm)
-				*(*wp)++ = nfsv4_acl_flag_map[i].wc;
-			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-				*(*wp)++ = L'-';
-		}
-		*(*wp)++ = L':';
-		switch (type) {
-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			wcscpy(*wp, L"allow");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			wcscpy(*wp, L"deny");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			wcscpy(*wp, L"audit");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			wcscpy(*wp, L"alarm");
-			break;
-		default:
-			break;
-		}
-		*wp += wcslen(*wp);
-	}
-	if (id != -1) {
-		*(*wp)++ = L':';
-		append_id_w(wp, id);
-	}
-}
-
-/*
- * Generate a text version of the ACL. The flags parameter controls
- * the type and style of the generated ACL.
- */
-char *
-archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
-    struct archive_string_conv *sc)
-{
-	int count;
-	ssize_t length;
-	size_t len;
-	const char *name;
-	const char *prefix;
-	char separator;
-	struct archive_acl_entry *ap;
-	int id, r, want_type;
-	char *p, *s;
-
-	want_type = archive_acl_text_want_type(acl, flags);
-
-	/* Both NFSv4 and POSIX.1 types found */
-	if (want_type == 0)
-		return (NULL);
-
-	if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
-		flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
-
-	length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc);
-
-	if (length == 0)
-		return (NULL);
-
-	if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
-		separator = ',';
-	else
-		separator = '\n';
-
-	/* Now, allocate the string and actually populate it. */
-	p = s = (char *)malloc(length * sizeof(char));
-	if (p == NULL) {
-		if (errno == ENOMEM)
-			__archive_errx(1, "No memory");
-		return (NULL);
-	}
-	count = 0;
-
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
-		    acl->mode & 0700, -1);
-		*p++ = separator;
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
-		    acl->mode & 0070, -1);
-		*p++ = separator;
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
-		    acl->mode & 0007, -1);
-		count += 3;
-	}
-
-	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
-		if ((ap->type & want_type) == 0)
-			continue;
-		/*
-		 * Filemode-mapping ACL entries are stored exclusively in
-		 * ap->mode so they should not be in the list
-		 */
-		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
-		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
-		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
-			continue;
-		if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
-		    (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
-			prefix = "default:";
-		else
-			prefix = NULL;
-		r = archive_mstring_get_mbs_l(
-		    NULL, &ap->name, &name, &len, sc);
-		if (r != 0) {
-			free(s);
-			return (NULL);
-		}
-		if (count > 0)
-			*p++ = separator;
-		if (name == NULL ||
-		    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
-			id = ap->id;
-		} else {
-			id = -1;
-		}
-		append_entry(&p, prefix, ap->type, ap->tag, flags, name,
-		    ap->permset, id);
-		count++;
-	}
-
-	/* Add terminating character */
-	*p++ = '\0';
-
-	len = strlen(s);
-
-	if ((ssize_t)len > (length - 1))
-		__archive_errx(1, "Buffer overrun");
-
-	if (text_len != NULL)
-		*text_len = len;
-
-	return (s);
-}
-
-static void
-append_id(char **p, int id)
-{
-	if (id < 0)
-		id = 0;
-	if (id > 9)
-		append_id(p, id / 10);
-	*(*p)++ = "0123456789"[id % 10];
-}
-
-static void
-append_entry(char **p, const char *prefix, int type,
-    int tag, int flags, const char *name, int perm, int id)
-{
-	int i;
-
-	if (prefix != NULL) {
-		strcpy(*p, prefix);
-		*p += strlen(*p);
-	}
-	switch (tag) {
-	case ARCHIVE_ENTRY_ACL_USER_OBJ:
-		name = NULL;
-		id = -1;
-		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			strcpy(*p, "owner@");
-			break;
-		}
-		/* FALLTHROUGH */
-	case ARCHIVE_ENTRY_ACL_USER:
-		strcpy(*p, "user");
-		break;
-	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-		name = NULL;
-		id = -1;
-		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			strcpy(*p, "group@");
-			break;
-		}
-		/* FALLTHROUGH */
-	case ARCHIVE_ENTRY_ACL_GROUP:
-		strcpy(*p, "group");
-		break;
-	case ARCHIVE_ENTRY_ACL_MASK:
-		strcpy(*p, "mask");
-		name = NULL;
-		id = -1;
-		break;
-	case ARCHIVE_ENTRY_ACL_OTHER:
-		strcpy(*p, "other");
-		name = NULL;
-		id = -1;
-		break;
-	case ARCHIVE_ENTRY_ACL_EVERYONE:
-		strcpy(*p, "everyone@");
-		name = NULL;
-		id = -1;
-		break;
-	}
-	*p += strlen(*p);
-	*(*p)++ = ':';
-	if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
-	    tag == ARCHIVE_ENTRY_ACL_USER ||
-	    tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		if (name != NULL) {
-			strcpy(*p, name);
-			*p += strlen(*p);
-		} else if (tag == ARCHIVE_ENTRY_ACL_USER
-		    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-			append_id(p, id);
-			if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
-				id = -1;
-		}
-		/* Solaris style has no second colon after other and mask */
-		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
-		    || (tag != ARCHIVE_ENTRY_ACL_OTHER
-		    && tag != ARCHIVE_ENTRY_ACL_MASK))
-			*(*p)++ = ':';
-	}
-	if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
-		/* POSIX.1e ACL perms */
-		*(*p)++ = (perm & 0444) ? 'r' : '-';
-		*(*p)++ = (perm & 0222) ? 'w' : '-';
-		*(*p)++ = (perm & 0111) ? 'x' : '-';
-	} else {
-		/* NFSv4 ACL perms */
-		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
-			if (perm & nfsv4_acl_perm_map[i].perm)
-				*(*p)++ = nfsv4_acl_perm_map[i].c;
-			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-				*(*p)++ = '-';
-		}
-		*(*p)++ = ':';
-		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
-			if (perm & nfsv4_acl_flag_map[i].perm)
-				*(*p)++ = nfsv4_acl_flag_map[i].c;
-			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
-				*(*p)++ = '-';
-		}
-		*(*p)++ = ':';
-		switch (type) {
-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			strcpy(*p, "allow");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			strcpy(*p, "deny");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			strcpy(*p, "audit");
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			strcpy(*p, "alarm");
-			break;
-		}
-		*p += strlen(*p);
-	}
-	if (id != -1) {
-		*(*p)++ = ':';
-		append_id(p, id);
-	}
-}
-
-/*
- * Parse a wide ACL text string.
- *
- * The want_type argument may be one of the following:
- * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
- * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
- *
- * POSIX.1e ACL entries prefixed with "default:" are treated as
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
- */
-int
-archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
-    int want_type)
-{
-	struct {
-		const wchar_t *start;
-		const wchar_t *end;
-	} field[6], name;
-
-	const wchar_t *s, *st;
-
-	int numfields, fields, n, r, sol, ret;
-	int type, types, tag, permset, id;
-	size_t len;
-	wchar_t sep;
-
-	ret = ARCHIVE_OK;
-	types = 0;
-
-	switch (want_type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
-		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-		__LA_FALLTHROUGH;
-	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-		numfields = 5;
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
-		numfields = 6;
-		break;
-	default:
-		return (ARCHIVE_FATAL);
-	}
-
-	while (text != NULL && *text != L'\0') {
-		/*
-		 * Parse the fields out of the next entry,
-		 * advance 'text' to start of next entry.
-		 */
-		fields = 0;
-		do {
-			const wchar_t *start, *end;
-			next_field_w(&text, &start, &end, &sep);
-			if (fields < numfields) {
-				field[fields].start = start;
-				field[fields].end = end;
-			}
-			++fields;
-		} while (sep == L':');
-
-		/* Set remaining fields to blank. */
-		for (n = fields; n < numfields; ++n)
-			field[n].start = field[n].end = NULL;
-
-		if (field[0].start != NULL && *(field[0].start) == L'#') {
-			/* Comment, skip entry */
-			continue;
-		}
-
-		n = 0;
-		sol = 0;
-		id = -1;
-		permset = 0;
-		name.start = name.end = NULL;
-
-		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/* POSIX.1e ACLs */
-			/*
-			 * Default keyword "default:user::rwx"
-			 * if found, we have one more field
-			 *
-			 * We also support old Solaris extension:
-			 * "defaultuser::rwx" is the default ACL corresponding
-			 * to "user::rwx", etc. valid only for first field
-			 */
-			s = field[0].start;
-			len = field[0].end - field[0].start;
-			if (*s == L'd' && (len == 1 || (len >= 7
-			    && wmemcmp((s + 1), L"efault", 6) == 0))) {
-				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-				if (len > 7)
-					field[0].start += 7;
-				else
-					n = 1;
-			} else
-				type = want_type;
-
-			/* Check for a numeric ID in field n+1 or n+3. */
-			isint_w(field[n + 1].start, field[n + 1].end, &id);
-			/* Field n+3 is optional. */
-			if (id == -1 && fields > n+3)
-				isint_w(field[n + 3].start, field[n + 3].end,
-				    &id);
-
-			tag = 0;
-			s = field[n].start;
-			st = field[n].start + 1;
-			len = field[n].end - field[n].start;
-
-			switch (*s) {
-			case L'u':
-				if (len == 1 || (len == 4
-				    && wmemcmp(st, L"ser", 3) == 0))
-					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				break;
-			case L'g':
-				if (len == 1 || (len == 5
-				    && wmemcmp(st, L"roup", 4) == 0))
-					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case L'o':
-				if (len == 1 || (len == 5
-				    && wmemcmp(st, L"ther", 4) == 0))
-					tag = ARCHIVE_ENTRY_ACL_OTHER;
-				break;
-			case L'm':
-				if (len == 1 || (len == 4
-				    && wmemcmp(st, L"ask", 3) == 0))
-					tag = ARCHIVE_ENTRY_ACL_MASK;
-				break;
-			default:
-					break;
-			}
-
-			switch (tag) {
-			case ARCHIVE_ENTRY_ACL_OTHER:
-			case ARCHIVE_ENTRY_ACL_MASK:
-				if (fields == (n + 2)
-				    && field[n + 1].start < field[n + 1].end
-				    && ismode_w(field[n + 1].start,
-				    field[n + 1].end, &permset)) {
-					/* This is Solaris-style "other:rwx" */
-					sol = 1;
-				} else if (fields == (n + 3) &&
-				    field[n + 1].start < field[n + 1].end) {
-					/* Invalid mask or other field */
-					ret = ARCHIVE_WARN;
-					continue;
-				}
-				break;
-			case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-				if (id != -1 ||
-				    field[n + 1].start < field[n + 1].end) {
-					name = field[n + 1];
-					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
-						tag = ARCHIVE_ENTRY_ACL_USER;
-					else
-						tag = ARCHIVE_ENTRY_ACL_GROUP;
-				}
-				break;
-			default:
-				/* Invalid tag, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-
-			/*
-			 * Without "default:" we expect mode in field 2
-			 * Exception: Solaris other and mask fields
-			 */
-			if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
-			    field[n + 2 - sol].end, &permset)) {
-				/* Invalid mode, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-		} else {
-			/* NFS4 ACLs */
-			s = field[0].start;
-			len = field[0].end - field[0].start;
-			tag = 0;
-
-			switch (len) {
-			case 4:
-				if (wmemcmp(s, L"user", 4) == 0)
-					tag = ARCHIVE_ENTRY_ACL_USER;
-				break;
-			case 5:
-				if (wmemcmp(s, L"group", 5) == 0)
-					tag = ARCHIVE_ENTRY_ACL_GROUP;
-				break;
-			case 6:
-				if (wmemcmp(s, L"owner@", 6) == 0)
-					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				else if (wmemcmp(s, L"group@", len) == 0)
-					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case 9:
-				if (wmemcmp(s, L"everyone@", 9) == 0)
-					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
-			default:
-				break;
-			}
-
-			if (tag == 0) {
-				/* Invalid tag, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
-			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
-				n = 1;
-				name = field[1];
-				isint_w(name.start, name.end, &id);
-			} else
-				n = 0;
-
-			if (!is_nfs4_perms_w(field[1 + n].start,
-			    field[1 + n].end, &permset)) {
-				/* Invalid NFSv4 perms, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			if (!is_nfs4_flags_w(field[2 + n].start,
-			    field[2 + n].end, &permset)) {
-				/* Invalid NFSv4 flags, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			s = field[3 + n].start;
-			len = field[3 + n].end - field[3 + n].start;
-			type = 0;
-			if (len == 4) {
-				if (wmemcmp(s, L"deny", 4) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-			} else if (len == 5) {
-				if (wmemcmp(s, L"allow", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-				else if (wmemcmp(s, L"audit", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
-				else if (wmemcmp(s, L"alarm", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
-			}
-			if (type == 0) {
-				/* Invalid entry type, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			isint_w(field[4 + n].start, field[4 + n].end, &id);
-		}
-
-		/* Add entry to the internal list. */
-		r = archive_acl_add_entry_w_len(acl, type, permset,
-		    tag, id, name.start, name.end - name.start);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if (r != ARCHIVE_OK)
-			ret = ARCHIVE_WARN;
-		types |= type;
-	}
-
-	/* Reset ACL */
-	archive_acl_reset(acl, types);
-
-	return (ret);
-}
-
-/*
- * Parse a string to a positive decimal integer.  Returns true if
- * the string is non-empty and consists only of decimal digits,
- * false otherwise.
- */
-static int
-isint_w(const wchar_t *start, const wchar_t *end, int *result)
-{
-	int n = 0;
-	if (start >= end)
-		return (0);
-	while (start < end) {
-		if (*start < L'0' || *start > L'9')
-			return (0);
-		if (n > (INT_MAX / 10) ||
-		    (n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) {
-			n = INT_MAX;
-		} else {
-			n *= 10;
-			n += *start - L'0';
-		}
-		start++;
-	}
-	*result = n;
-	return (1);
-}
-
-/*
- * Parse a string as a mode field.  Returns true if
- * the string is non-empty and consists only of mode characters,
- * false otherwise.
- */
-static int
-ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
-{
-	const wchar_t *p;
-
-	if (start >= end)
-		return (0);
-	p = start;
-	*permset = 0;
-	while (p < end) {
-		switch (*p++) {
-		case L'r': case L'R':
-			*permset |= ARCHIVE_ENTRY_ACL_READ;
-			break;
-		case L'w': case L'W':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE;
-			break;
-		case L'x': case L'X':
-			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
-			break;
-		case L'-':
-			break;
-		default:
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Parse a string as a NFS4 ACL permission field.
- * Returns true if the string is non-empty and consists only of NFS4 ACL
- * permission characters, false otherwise
- */
-static int
-is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
-{
-	const wchar_t *p = start;
-
-	while (p < end) {
-		switch (*p++) {
-		case L'r':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
-			break;
-		case L'w':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
-			break;
-		case L'x':
-			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
-			break;
-		case L'p':
-			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
-			break;
-		case L'D':
-			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
-			break;
-		case L'd':
-			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
-			break;
-		case L'a':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
-			break;
-		case L'A':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
-			break;
-		case L'R':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
-			break;
-		case L'W':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
-			break;
-		case L'c':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
-			break;
-		case L'C':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
-			break;
-		case L'o':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
-			break;
-		case L's':
-			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
-			break;
-		case L'-':
-			break;
-		default:
-			return(0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Parse a string as a NFS4 ACL flags field.
- * Returns true if the string is non-empty and consists only of NFS4 ACL
- * flag characters, false otherwise
- */
-static int
-is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
-{
-	const wchar_t *p = start;
-
-	while (p < end) {
-		switch(*p++) {
-		case L'f':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
-			break;
-		case L'd':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
-			break;
-		case L'i':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
-			break;
-		case L'n':
-			*permset |=
-			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
-			break;
-		case L'S':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
-			break;
-		case L'F':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
-			break;
-		case L'I':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
-			break;
-		case L'-':
-			break;
-		default:
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
- * to point to just after the separator.  *start points to the first
- * character of the matched text and *end just after the last
- * character of the matched identifier.  In particular *end - *start
- * is the length of the field body, not including leading or trailing
- * whitespace.
- */
-static void
-next_field_w(const wchar_t **wp, const wchar_t **start,
-    const wchar_t **end, wchar_t *sep)
-{
-	/* Skip leading whitespace to find start of field. */
-	while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
-		(*wp)++;
-	}
-	*start = *wp;
-
-	/* Scan for the separator. */
-	while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
-	    **wp != L'\n' && **wp != L'#') {
-		(*wp)++;
-	}
-	*sep = **wp;
-
-	/* Locate end of field, trim trailing whitespace if necessary */
-	if (*wp == *start) {
-		*end = *wp;
-	} else {
-		*end = *wp - 1;
-		while (**end == L' ' || **end == L'\t' || **end == L'\n') {
-			(*end)--;
-		}
-		(*end)++;
-	}
-
-	/* Handle in-field comments */
-	if (*sep == L'#') {
-		while (**wp != L'\0' && **wp != L',' && **wp != L'\n') {
-			(*wp)++;
-		}
-		*sep = **wp;
-	}
-
-	/* Adjust scanner location. */
-	if (**wp != L'\0')
-		(*wp)++;
-}
-
-/*
- * Parse an ACL text string.
- *
- * The want_type argument may be one of the following:
- * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
- * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
- *
- * POSIX.1e ACL entries prefixed with "default:" are treated as
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
- */
-int
-archive_acl_from_text_l(struct archive_acl *acl, const char *text,
-    int want_type, struct archive_string_conv *sc)
-{
-	struct {
-		const char *start;
-		const char *end;
-	} field[6], name;
-
-	const char *s, *st;
-	int numfields, fields, n, r, sol, ret;
-	int type, types, tag, permset, id;
-	size_t len;
-	char sep;
-
-	switch (want_type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
-		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-		__LA_FALLTHROUGH;
-	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-		numfields = 5;
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
-		numfields = 6;
-		break;
-	default:
-		return (ARCHIVE_FATAL);
-	}
-
-	ret = ARCHIVE_OK;
-	types = 0;
-
-	while (text != NULL &&  *text != '\0') {
-		/*
-		 * Parse the fields out of the next entry,
-		 * advance 'text' to start of next entry.
-		 */
-		fields = 0;
-		do {
-			const char *start, *end;
-			next_field(&text, &start, &end, &sep);
-			if (fields < numfields) {
-				field[fields].start = start;
-				field[fields].end = end;
-			}
-			++fields;
-		} while (sep == ':');
-
-		/* Set remaining fields to blank. */
-		for (n = fields; n < numfields; ++n)
-			field[n].start = field[n].end = NULL;
-
-		if (field[0].start != NULL && *(field[0].start) == '#') {
-			/* Comment, skip entry */
-			continue;
-		}
-
-		n = 0;
-		sol = 0;
-		id = -1;
-		permset = 0;
-		name.start = name.end = NULL;
-
-		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/* POSIX.1e ACLs */
-			/*
-			 * Default keyword "default:user::rwx"
-			 * if found, we have one more field
-			 *
-			 * We also support old Solaris extension:
-			 * "defaultuser::rwx" is the default ACL corresponding
-			 * to "user::rwx", etc. valid only for first field
-			 */
-			s = field[0].start;
-			len = field[0].end - field[0].start;
-			if (*s == 'd' && (len == 1 || (len >= 7
-			    && memcmp((s + 1), "efault", 6) == 0))) {
-				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-				if (len > 7)
-					field[0].start += 7;
-				else
-					n = 1;
-			} else
-				type = want_type;
-
-			/* Check for a numeric ID in field n+1 or n+3. */
-			isint(field[n + 1].start, field[n + 1].end, &id);
-			/* Field n+3 is optional. */
-			if (id == -1 && fields > (n + 3))
-				isint(field[n + 3].start, field[n + 3].end,
-				    &id);
-
-			tag = 0;
-			s = field[n].start;
-			st = field[n].start + 1;
-			len = field[n].end - field[n].start;
-
-			if (len == 0) {
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-
-			switch (*s) {
-			case 'u':
-				if (len == 1 || (len == 4
-				    && memcmp(st, "ser", 3) == 0))
-					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				break;
-			case 'g':
-				if (len == 1 || (len == 5
-				    && memcmp(st, "roup", 4) == 0))
-					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case 'o':
-				if (len == 1 || (len == 5
-				    && memcmp(st, "ther", 4) == 0))
-					tag = ARCHIVE_ENTRY_ACL_OTHER;
-				break;
-			case 'm':
-				if (len == 1 || (len == 4
-				    && memcmp(st, "ask", 3) == 0))
-					tag = ARCHIVE_ENTRY_ACL_MASK;
-				break;
-			default:
-					break;
-			}
-
-			switch (tag) {
-			case ARCHIVE_ENTRY_ACL_OTHER:
-			case ARCHIVE_ENTRY_ACL_MASK:
-				if (fields == (n + 2)
-				    && field[n + 1].start < field[n + 1].end
-				    && ismode(field[n + 1].start,
-				    field[n + 1].end, &permset)) {
-					/* This is Solaris-style "other:rwx" */
-					sol = 1;
-				} else if (fields == (n + 3) &&
-				    field[n + 1].start < field[n + 1].end) {
-					/* Invalid mask or other field */
-					ret = ARCHIVE_WARN;
-					continue;
-				}
-				break;
-			case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-				if (id != -1 ||
-				    field[n + 1].start < field[n + 1].end) {
-					name = field[n + 1];
-					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
-						tag = ARCHIVE_ENTRY_ACL_USER;
-					else
-						tag = ARCHIVE_ENTRY_ACL_GROUP;
-				}
-				break;
-			default:
-				/* Invalid tag, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-
-			/*
-			 * Without "default:" we expect mode in field 3
-			 * Exception: Solaris other and mask fields
-			 */
-			if (permset == 0 && !ismode(field[n + 2 - sol].start,
-			    field[n + 2 - sol].end, &permset)) {
-				/* Invalid mode, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-		} else {
-			/* NFS4 ACLs */
-			s = field[0].start;
-			len = field[0].end - field[0].start;
-			tag = 0;
-
-			switch (len) {
-			case 4:
-				if (memcmp(s, "user", 4) == 0)
-					tag = ARCHIVE_ENTRY_ACL_USER;
-				break;
-			case 5:
-				if (memcmp(s, "group", 5) == 0)
-					tag = ARCHIVE_ENTRY_ACL_GROUP;
-				break;
-			case 6:
-				if (memcmp(s, "owner@", 6) == 0)
-					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				else if (memcmp(s, "group@", 6) == 0)
-					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case 9:
-				if (memcmp(s, "everyone@", 9) == 0)
-					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
-				break;
-			default:
-				break;
-			}
-
-			if (tag == 0) {
-				/* Invalid tag, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
-			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
-				n = 1;
-				name = field[1];
-				isint(name.start, name.end, &id);
-			} else
-				n = 0;
-
-			if (!is_nfs4_perms(field[1 + n].start,
-			    field[1 + n].end, &permset)) {
-				/* Invalid NFSv4 perms, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			if (!is_nfs4_flags(field[2 + n].start,
-			    field[2 + n].end, &permset)) {
-				/* Invalid NFSv4 flags, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			s = field[3 + n].start;
-			len = field[3 + n].end - field[3 + n].start;
-			type = 0;
-			if (len == 4) {
-				if (memcmp(s, "deny", 4) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-			} else if (len == 5) {
-				if (memcmp(s, "allow", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-				else if (memcmp(s, "audit", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
-				else if (memcmp(s, "alarm", 5) == 0)
-					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
-			}
-			if (type == 0) {
-				/* Invalid entry type, skip entry */
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-			isint(field[4 + n].start, field[4 + n].end,
-			    &id);
-		}
-
-		/* Add entry to the internal list. */
-		r = archive_acl_add_entry_len_l(acl, type, permset,
-		    tag, id, name.start, name.end - name.start, sc);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if (r != ARCHIVE_OK)
-			ret = ARCHIVE_WARN;
-		types |= type;
-	}
-
-	/* Reset ACL */
-	archive_acl_reset(acl, types);
-
-	return (ret);
-}
-
-/*
- * Parse a string to a positive decimal integer.  Returns true if
- * the string is non-empty and consists only of decimal digits,
- * false otherwise.
- */
-static int
-isint(const char *start, const char *end, int *result)
-{
-	int n = 0;
-	if (start >= end)
-		return (0);
-	while (start < end) {
-		if (*start < '0' || *start > '9')
-			return (0);
-		if (n > (INT_MAX / 10) ||
-		    (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
-			n = INT_MAX;
-		} else {
-			n *= 10;
-			n += *start - '0';
-		}
-		start++;
-	}
-	*result = n;
-	return (1);
-}
-
-/*
- * Parse a string as a mode field.  Returns true if
- * the string is non-empty and consists only of mode characters,
- * false otherwise.
- */
-static int
-ismode(const char *start, const char *end, int *permset)
-{
-	const char *p;
-
-	if (start >= end)
-		return (0);
-	p = start;
-	*permset = 0;
-	while (p < end) {
-		switch (*p++) {
-		case 'r': case 'R':
-			*permset |= ARCHIVE_ENTRY_ACL_READ;
-			break;
-		case 'w': case 'W':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE;
-			break;
-		case 'x': case 'X':
-			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
-			break;
-		case '-':
-			break;
-		default:
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Parse a string as a NFS4 ACL permission field.
- * Returns true if the string is non-empty and consists only of NFS4 ACL
- * permission characters, false otherwise
- */
-static int
-is_nfs4_perms(const char *start, const char *end, int *permset)
-{
-	const char *p = start;
-
-	while (p < end) {
-		switch (*p++) {
-		case 'r':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
-			break;
-		case 'w':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
-			break;
-		case 'x':
-			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
-			break;
-		case 'p':
-			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
-			break;
-		case 'D':
-			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
-			break;
-		case 'd':
-			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
-			break;
-		case 'a':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
-			break;
-		case 'A':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
-			break;
-		case 'R':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
-			break;
-		case 'W':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
-			break;
-		case 'c':
-			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
-			break;
-		case 'C':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
-			break;
-		case 'o':
-			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
-			break;
-		case 's':
-			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
-			break;
-		case '-':
-			break;
-		default:
-			return(0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Parse a string as a NFS4 ACL flags field.
- * Returns true if the string is non-empty and consists only of NFS4 ACL
- * flag characters, false otherwise
- */
-static int
-is_nfs4_flags(const char *start, const char *end, int *permset)
-{
-	const char *p = start;
-
-	while (p < end) {
-		switch(*p++) {
-		case 'f':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
-			break;
-		case 'd':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
-			break;
-		case 'i':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
-			break;
-		case 'n':
-			*permset |=
-			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
-			break;
-		case 'S':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
-			break;
-		case 'F':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
-			break;
-		case 'I':
-			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
-			break;
-		case '-':
-			break;
-		default:
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
- * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
- * to point to just after the separator.  *start points to the first
- * character of the matched text and *end just after the last
- * character of the matched identifier.  In particular *end - *start
- * is the length of the field body, not including leading or trailing
- * whitespace.
- */
-static void
-next_field(const char **p, const char **start,
-    const char **end, char *sep)
-{
-	/* Skip leading whitespace to find start of field. */
-	while (**p == ' ' || **p == '\t' || **p == '\n') {
-		(*p)++;
-	}
-	*start = *p;
-
-	/* Scan for the separator. */
-	while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n' &&
-	    **p != '#') {
-		(*p)++;
-	}
-	*sep = **p;
-
-	/* Locate end of field, trim trailing whitespace if necessary */
-	if (*p == *start) {
-		*end = *p;
-	} else {
-		*end = *p - 1;
-		while (**end == ' ' || **end == '\t' || **end == '\n') {
-			(*end)--;
-		}
-		(*end)++;
-	}
-
-	/* Handle in-field comments */
-	if (*sep == '#') {
-		while (**p != '\0' && **p != ',' && **p != '\n') {
-			(*p)++;
-		}
-		*sep = **p;
-	}
-
-	/* Adjust scanner location. */
-	if (**p != '\0')
-		(*p)++;
-}
diff --git a/c/archive_acl_private.h b/c/archive_acl_private.h
deleted file mode 100644
--- a/c/archive_acl_private.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
-#define ARCHIVE_ACL_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include "archive_string.h"
-
-struct archive_acl_entry {
-	struct archive_acl_entry *next;
-	int	type;			/* E.g., access or default */
-	int	tag;			/* E.g., user/group/other/mask */
-	int	permset;		/* r/w/x bits */
-	int	id;			/* uid/gid for user/group */
-	struct archive_mstring name;		/* uname/gname */
-};
-
-struct archive_acl {
-	mode_t		mode;
-	struct archive_acl_entry	*acl_head;
-	struct archive_acl_entry	*acl_p;
-	int		 acl_state;	/* See acl_next for details. */
-	wchar_t		*acl_text_w;
-	char		*acl_text;
-	int		 acl_types;
-};
-
-void archive_acl_clear(struct archive_acl *);
-void archive_acl_copy(struct archive_acl *, struct archive_acl *);
-int archive_acl_count(struct archive_acl *, int);
-int archive_acl_types(struct archive_acl *);
-int archive_acl_reset(struct archive_acl *, int);
-int archive_acl_next(struct archive *, struct archive_acl *, int,
-    int *, int *, int *, int *, const char **);
-
-int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *);
-int archive_acl_add_entry_w_len(struct archive_acl *,
-    int, int, int, int, const wchar_t *, size_t);
-int archive_acl_add_entry_len(struct archive_acl *,
-    int, int, int, int, const char *, size_t);
-
-wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
-    struct archive *);
-char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
-    struct archive_string_conv *);
-
-/*
- * ACL text parser.
- */
-int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
-    int /* type */);
-int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
-    int /* type */, struct archive_string_conv *);
-
-#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/c/archive_blake2.h b/c/archive_blake2.h
deleted file mode 100644
--- a/c/archive_blake2.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
-   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
-   your option.  The terms of these licenses can be found at:
-
-   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
-   - OpenSSL license   : https://www.openssl.org/source/license.html
-   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
-
-   More information about the BLAKE2 hash function can be found at
-   https://blake2.net.
-*/
-
-#ifndef ARCHIVE_BLAKE2_H
-#define ARCHIVE_BLAKE2_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if defined(_MSC_VER)
-#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
-#elif defined(__GNUC__)
-#define BLAKE2_PACKED(x) x __attribute__((packed))
-#else
-#define BLAKE2_PACKED(x) _Pragma("pack 1") x _Pragma("pack 0")
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-  enum blake2s_constant
-  {
-    BLAKE2S_BLOCKBYTES = 64,
-    BLAKE2S_OUTBYTES   = 32,
-    BLAKE2S_KEYBYTES   = 32,
-    BLAKE2S_SALTBYTES  = 8,
-    BLAKE2S_PERSONALBYTES = 8
-  };
-
-  enum blake2b_constant
-  {
-    BLAKE2B_BLOCKBYTES = 128,
-    BLAKE2B_OUTBYTES   = 64,
-    BLAKE2B_KEYBYTES   = 64,
-    BLAKE2B_SALTBYTES  = 16,
-    BLAKE2B_PERSONALBYTES = 16
-  };
-
-  typedef struct blake2s_state__
-  {
-    uint32_t h[8];
-    uint32_t t[2];
-    uint32_t f[2];
-    uint8_t  buf[BLAKE2S_BLOCKBYTES];
-    size_t   buflen;
-    size_t   outlen;
-    uint8_t  last_node;
-  } blake2s_state;
-
-  typedef struct blake2b_state__
-  {
-    uint64_t h[8];
-    uint64_t t[2];
-    uint64_t f[2];
-    uint8_t  buf[BLAKE2B_BLOCKBYTES];
-    size_t   buflen;
-    size_t   outlen;
-    uint8_t  last_node;
-  } blake2b_state;
-
-  typedef struct blake2sp_state__
-  {
-    blake2s_state S[8][1];
-    blake2s_state R[1];
-    uint8_t       buf[8 * BLAKE2S_BLOCKBYTES];
-    size_t        buflen;
-    size_t        outlen;
-  } blake2sp_state;
-
-  typedef struct blake2bp_state__
-  {
-    blake2b_state S[4][1];
-    blake2b_state R[1];
-    uint8_t       buf[4 * BLAKE2B_BLOCKBYTES];
-    size_t        buflen;
-    size_t        outlen;
-  } blake2bp_state;
-
-  BLAKE2_PACKED(struct blake2s_param__
-  {
-    uint8_t  digest_length; /* 1 */
-    uint8_t  key_length;    /* 2 */
-    uint8_t  fanout;        /* 3 */
-    uint8_t  depth;         /* 4 */
-    uint32_t leaf_length;   /* 8 */
-    uint32_t node_offset;  /* 12 */
-    uint16_t xof_length;    /* 14 */
-    uint8_t  node_depth;    /* 15 */
-    uint8_t  inner_length;  /* 16 */
-    /* uint8_t  reserved[0]; */
-    uint8_t  salt[BLAKE2S_SALTBYTES]; /* 24 */
-    uint8_t  personal[BLAKE2S_PERSONALBYTES];  /* 32 */
-  });
-
-  typedef struct blake2s_param__ blake2s_param;
-
-  BLAKE2_PACKED(struct blake2b_param__
-  {
-    uint8_t  digest_length; /* 1 */
-    uint8_t  key_length;    /* 2 */
-    uint8_t  fanout;        /* 3 */
-    uint8_t  depth;         /* 4 */
-    uint32_t leaf_length;   /* 8 */
-    uint32_t node_offset;   /* 12 */
-    uint32_t xof_length;    /* 16 */
-    uint8_t  node_depth;    /* 17 */
-    uint8_t  inner_length;  /* 18 */
-    uint8_t  reserved[14];  /* 32 */
-    uint8_t  salt[BLAKE2B_SALTBYTES]; /* 48 */
-    uint8_t  personal[BLAKE2B_PERSONALBYTES];  /* 64 */
-  });
-
-  typedef struct blake2b_param__ blake2b_param;
-
-  typedef struct blake2xs_state__
-  {
-    blake2s_state S[1];
-    blake2s_param P[1];
-  } blake2xs_state;
-
-  typedef struct blake2xb_state__
-  {
-    blake2b_state S[1];
-    blake2b_param P[1];
-  } blake2xb_state;
-
-  /* Padded structs result in a compile-time error */
-  enum {
-    BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
-    BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
-  };
-
-  /* Streaming API */
-  int blake2s_init( blake2s_state *S, size_t outlen );
-  int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
-  int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
-  int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
-  int blake2s_final( blake2s_state *S, void *out, size_t outlen );
-
-  int blake2b_init( blake2b_state *S, size_t outlen );
-  int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
-  int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
-  int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
-  int blake2b_final( blake2b_state *S, void *out, size_t outlen );
-
-  int blake2sp_init( blake2sp_state *S, size_t outlen );
-  int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
-  int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
-  int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
-
-  int blake2bp_init( blake2bp_state *S, size_t outlen );
-  int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
-  int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
-  int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
-
-  /* Variable output length API */
-  int blake2xs_init( blake2xs_state *S, const size_t outlen );
-  int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
-  int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
-  int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
-
-  int blake2xb_init( blake2xb_state *S, const size_t outlen );
-  int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
-  int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
-  int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
-
-  /* Simple API */
-  int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-  int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-
-  int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-  int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-
-  int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-  int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-
-  /* This is simply an alias for blake2b */
-  int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
diff --git a/c/archive_blake2_impl.h b/c/archive_blake2_impl.h
deleted file mode 100644
--- a/c/archive_blake2_impl.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
-   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
-   your option.  The terms of these licenses can be found at:
-
-   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
-   - OpenSSL license   : https://www.openssl.org/source/license.html
-   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
-
-   More information about the BLAKE2 hash function can be found at
-   https://blake2.net.
-*/
-
-#ifndef ARCHIVE_BLAKE2_IMPL_H
-#define ARCHIVE_BLAKE2_IMPL_H
-
-#include <stdint.h>
-#include <string.h>
-
-#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
-  #if   defined(_MSC_VER)
-    #define BLAKE2_INLINE __inline
-  #elif defined(__GNUC__)
-    #define BLAKE2_INLINE __inline__
-  #else
-    #define BLAKE2_INLINE
-  #endif
-#else
-  #define BLAKE2_INLINE inline
-#endif
-
-static BLAKE2_INLINE uint32_t load32( const void *src )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  uint32_t w;
-  memcpy(&w, src, sizeof w);
-  return w;
-#else
-  const uint8_t *p = ( const uint8_t * )src;
-  return (( uint32_t )( p[0] ) <<  0) |
-         (( uint32_t )( p[1] ) <<  8) |
-         (( uint32_t )( p[2] ) << 16) |
-         (( uint32_t )( p[3] ) << 24) ;
-#endif
-}
-
-static BLAKE2_INLINE uint64_t load64( const void *src )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  uint64_t w;
-  memcpy(&w, src, sizeof w);
-  return w;
-#else
-  const uint8_t *p = ( const uint8_t * )src;
-  return (( uint64_t )( p[0] ) <<  0) |
-         (( uint64_t )( p[1] ) <<  8) |
-         (( uint64_t )( p[2] ) << 16) |
-         (( uint64_t )( p[3] ) << 24) |
-         (( uint64_t )( p[4] ) << 32) |
-         (( uint64_t )( p[5] ) << 40) |
-         (( uint64_t )( p[6] ) << 48) |
-         (( uint64_t )( p[7] ) << 56) ;
-#endif
-}
-
-static BLAKE2_INLINE uint16_t load16( const void *src )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  uint16_t w;
-  memcpy(&w, src, sizeof w);
-  return w;
-#else
-  const uint8_t *p = ( const uint8_t * )src;
-  return ( uint16_t )((( uint32_t )( p[0] ) <<  0) |
-                      (( uint32_t )( p[1] ) <<  8));
-#endif
-}
-
-static BLAKE2_INLINE void store16( void *dst, uint16_t w )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  memcpy(dst, &w, sizeof w);
-#else
-  uint8_t *p = ( uint8_t * )dst;
-  *p++ = ( uint8_t )w; w >>= 8;
-  *p++ = ( uint8_t )w;
-#endif
-}
-
-static BLAKE2_INLINE void store32( void *dst, uint32_t w )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  memcpy(dst, &w, sizeof w);
-#else
-  uint8_t *p = ( uint8_t * )dst;
-  p[0] = (uint8_t)(w >>  0);
-  p[1] = (uint8_t)(w >>  8);
-  p[2] = (uint8_t)(w >> 16);
-  p[3] = (uint8_t)(w >> 24);
-#endif
-}
-
-static BLAKE2_INLINE void store64( void *dst, uint64_t w )
-{
-#if defined(NATIVE_LITTLE_ENDIAN)
-  memcpy(dst, &w, sizeof w);
-#else
-  uint8_t *p = ( uint8_t * )dst;
-  p[0] = (uint8_t)(w >>  0);
-  p[1] = (uint8_t)(w >>  8);
-  p[2] = (uint8_t)(w >> 16);
-  p[3] = (uint8_t)(w >> 24);
-  p[4] = (uint8_t)(w >> 32);
-  p[5] = (uint8_t)(w >> 40);
-  p[6] = (uint8_t)(w >> 48);
-  p[7] = (uint8_t)(w >> 56);
-#endif
-}
-
-static BLAKE2_INLINE uint64_t load48( const void *src )
-{
-  const uint8_t *p = ( const uint8_t * )src;
-  return (( uint64_t )( p[0] ) <<  0) |
-         (( uint64_t )( p[1] ) <<  8) |
-         (( uint64_t )( p[2] ) << 16) |
-         (( uint64_t )( p[3] ) << 24) |
-         (( uint64_t )( p[4] ) << 32) |
-         (( uint64_t )( p[5] ) << 40) ;
-}
-
-static BLAKE2_INLINE void store48( void *dst, uint64_t w )
-{
-  uint8_t *p = ( uint8_t * )dst;
-  p[0] = (uint8_t)(w >>  0);
-  p[1] = (uint8_t)(w >>  8);
-  p[2] = (uint8_t)(w >> 16);
-  p[3] = (uint8_t)(w >> 24);
-  p[4] = (uint8_t)(w >> 32);
-  p[5] = (uint8_t)(w >> 40);
-}
-
-static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
-{
-  return ( w >> c ) | ( w << ( 32 - c ) );
-}
-
-static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
-{
-  return ( w >> c ) | ( w << ( 64 - c ) );
-}
-
-/* prevents compiler optimizing out memset() */
-static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
-{
-  static void *(__LA_LIBC_CC *const volatile memset_v)(void *, int, size_t) = &memset;
-  memset_v(v, 0, n);
-}
-
-#endif
diff --git a/c/archive_blake2s_ref.c b/c/archive_blake2s_ref.c
deleted file mode 100644
--- a/c/archive_blake2s_ref.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
-   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
-   your option.  The terms of these licenses can be found at:
-
-   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
-   - OpenSSL license   : https://www.openssl.org/source/license.html
-   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
-
-   More information about the BLAKE2 hash function can be found at
-   https://blake2.net.
-*/
-
-#include "archive_platform.h"
-
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "archive_blake2.h"
-#include "archive_blake2_impl.h"
-
-static const uint32_t blake2s_IV[8] =
-{
-  0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
-  0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
-};
-
-static const uint8_t blake2s_sigma[10][16] =
-{
-  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
-  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
-  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
-  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
-  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
-  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
-  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
-  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
-  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
-  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
-};
-
-static void blake2s_set_lastnode( blake2s_state *S )
-{
-  S->f[1] = (uint32_t)-1;
-}
-
-/* Some helper functions, not necessarily useful */
-static int blake2s_is_lastblock( const blake2s_state *S )
-{
-  return S->f[0] != 0;
-}
-
-static void blake2s_set_lastblock( blake2s_state *S )
-{
-  if( S->last_node ) blake2s_set_lastnode( S );
-
-  S->f[0] = (uint32_t)-1;
-}
-
-static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
-{
-  S->t[0] += inc;
-  S->t[1] += ( S->t[0] < inc );
-}
-
-static void blake2s_init0( blake2s_state *S )
-{
-  size_t i;
-  memset( S, 0, sizeof( blake2s_state ) );
-
-  for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
-}
-
-/* init2 xors IV with input parameter block */
-int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
-{
-  const unsigned char *p = ( const unsigned char * )( P );
-  size_t i;
-
-  blake2s_init0( S );
-
-  /* IV XOR ParamBlock */
-  for( i = 0; i < 8; ++i )
-    S->h[i] ^= load32( &p[i * 4] );
-
-  S->outlen = P->digest_length;
-  return 0;
-}
-
-
-/* Sequential blake2s initialization */
-int blake2s_init( blake2s_state *S, size_t outlen )
-{
-  blake2s_param P[1];
-
-  /* Move interval verification here? */
-  if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
-
-  P->digest_length = (uint8_t)outlen;
-  P->key_length    = 0;
-  P->fanout        = 1;
-  P->depth         = 1;
-  store32( &P->leaf_length, 0 );
-  store32( &P->node_offset, 0 );
-  store16( &P->xof_length, 0 );
-  P->node_depth    = 0;
-  P->inner_length  = 0;
-  /* memset(P->reserved, 0, sizeof(P->reserved) ); */
-  memset( P->salt,     0, sizeof( P->salt ) );
-  memset( P->personal, 0, sizeof( P->personal ) );
-  return blake2s_init_param( S, P );
-}
-
-int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
-{
-  blake2s_param P[1];
-
-  if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
-
-  if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
-
-  P->digest_length = (uint8_t)outlen;
-  P->key_length    = (uint8_t)keylen;
-  P->fanout        = 1;
-  P->depth         = 1;
-  store32( &P->leaf_length, 0 );
-  store32( &P->node_offset, 0 );
-  store16( &P->xof_length, 0 );
-  P->node_depth    = 0;
-  P->inner_length  = 0;
-  /* memset(P->reserved, 0, sizeof(P->reserved) ); */
-  memset( P->salt,     0, sizeof( P->salt ) );
-  memset( P->personal, 0, sizeof( P->personal ) );
-
-  if( blake2s_init_param( S, P ) < 0 ) return -1;
-
-  {
-    uint8_t block[BLAKE2S_BLOCKBYTES];
-    memset( block, 0, BLAKE2S_BLOCKBYTES );
-    memcpy( block, key, keylen );
-    blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
-    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
-  }
-  return 0;
-}
-
-#define G(r,i,a,b,c,d)                      \
-  do {                                      \
-    a = a + b + m[blake2s_sigma[r][2*i+0]]; \
-    d = rotr32(d ^ a, 16);                  \
-    c = c + d;                              \
-    b = rotr32(b ^ c, 12);                  \
-    a = a + b + m[blake2s_sigma[r][2*i+1]]; \
-    d = rotr32(d ^ a, 8);                   \
-    c = c + d;                              \
-    b = rotr32(b ^ c, 7);                   \
-  } while(0)
-
-#define ROUND(r)                    \
-  do {                              \
-    G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
-    G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
-    G(r,2,v[ 2],v[ 6],v[10],v[14]); \
-    G(r,3,v[ 3],v[ 7],v[11],v[15]); \
-    G(r,4,v[ 0],v[ 5],v[10],v[15]); \
-    G(r,5,v[ 1],v[ 6],v[11],v[12]); \
-    G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
-    G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
-  } while(0)
-
-static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
-{
-  uint32_t m[16];
-  uint32_t v[16];
-  size_t i;
-
-  for( i = 0; i < 16; ++i ) {
-    m[i] = load32( in + i * sizeof( m[i] ) );
-  }
-
-  for( i = 0; i < 8; ++i ) {
-    v[i] = S->h[i];
-  }
-
-  v[ 8] = blake2s_IV[0];
-  v[ 9] = blake2s_IV[1];
-  v[10] = blake2s_IV[2];
-  v[11] = blake2s_IV[3];
-  v[12] = S->t[0] ^ blake2s_IV[4];
-  v[13] = S->t[1] ^ blake2s_IV[5];
-  v[14] = S->f[0] ^ blake2s_IV[6];
-  v[15] = S->f[1] ^ blake2s_IV[7];
-
-  ROUND( 0 );
-  ROUND( 1 );
-  ROUND( 2 );
-  ROUND( 3 );
-  ROUND( 4 );
-  ROUND( 5 );
-  ROUND( 6 );
-  ROUND( 7 );
-  ROUND( 8 );
-  ROUND( 9 );
-
-  for( i = 0; i < 8; ++i ) {
-    S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
-  }
-}
-
-#undef G
-#undef ROUND
-
-int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
-{
-  const unsigned char * in = (const unsigned char *)pin;
-  if( inlen > 0 )
-  {
-    size_t left = S->buflen;
-    size_t fill = BLAKE2S_BLOCKBYTES - left;
-    if( inlen > fill )
-    {
-      S->buflen = 0;
-      memcpy( S->buf + left, in, fill ); /* Fill buffer */
-      blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
-      blake2s_compress( S, S->buf ); /* Compress */
-      in += fill; inlen -= fill;
-      while(inlen > BLAKE2S_BLOCKBYTES) {
-        blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
-        blake2s_compress( S, in );
-        in += BLAKE2S_BLOCKBYTES;
-        inlen -= BLAKE2S_BLOCKBYTES;
-      }
-    }
-    memcpy( S->buf + S->buflen, in, inlen );
-    S->buflen += inlen;
-  }
-  return 0;
-}
-
-int blake2s_final( blake2s_state *S, void *out, size_t outlen )
-{
-  uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
-  size_t i;
-
-  if( out == NULL || outlen < S->outlen )
-    return -1;
-
-  if( blake2s_is_lastblock( S ) )
-    return -1;
-
-  blake2s_increment_counter( S, ( uint32_t )S->buflen );
-  blake2s_set_lastblock( S );
-  memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
-  blake2s_compress( S, S->buf );
-
-  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
-    store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
-
-  memcpy( out, buffer, outlen );
-  secure_zero_memory(buffer, sizeof(buffer));
-  return 0;
-}
-
-int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
-{
-  blake2s_state S[1];
-
-  /* Verify parameters */
-  if ( NULL == in && inlen > 0 ) return -1;
-
-  if ( NULL == out ) return -1;
-
-  if ( NULL == key && keylen > 0) return -1;
-
-  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
-
-  if( keylen > BLAKE2S_KEYBYTES ) return -1;
-
-  if( keylen > 0 )
-  {
-    if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
-  }
-  else
-  {
-    if( blake2s_init( S, outlen ) < 0 ) return -1;
-  }
-
-  blake2s_update( S, ( const uint8_t * )in, inlen );
-  blake2s_final( S, out, outlen );
-  return 0;
-}
-
-#if defined(SUPERCOP)
-int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
-{
-  return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
-}
-#endif
-
-#if defined(BLAKE2S_SELFTEST)
-#include <string.h>
-#include "blake2-kat.h"
-int main( void )
-{
-  uint8_t key[BLAKE2S_KEYBYTES];
-  uint8_t buf[BLAKE2_KAT_LENGTH];
-  size_t i, step;
-
-  for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
-    key[i] = ( uint8_t )i;
-
-  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
-    buf[i] = ( uint8_t )i;
-
-  /* Test simple API */
-  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
-  {
-    uint8_t hash[BLAKE2S_OUTBYTES];
-    blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
-
-    if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
-    {
-      goto fail;
-    }
-  }
-
-  /* Test streaming API */
-  for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
-    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
-      uint8_t hash[BLAKE2S_OUTBYTES];
-      blake2s_state S;
-      uint8_t * p = buf;
-      size_t mlen = i;
-      int err = 0;
-
-      if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
-        goto fail;
-      }
-
-      while (mlen >= step) {
-        if ( (err = blake2s_update(&S, p, step)) < 0 ) {
-          goto fail;
-        }
-        mlen -= step;
-        p += step;
-      }
-      if ( (err = blake2s_update(&S, p, mlen)) < 0) {
-        goto fail;
-      }
-      if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
-        goto fail;
-      }
-
-      if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
-        goto fail;
-      }
-    }
-  }
-
-  puts( "ok" );
-  return 0;
-fail:
-  puts("error");
-  return -1;
-}
-#endif
diff --git a/c/archive_blake2sp_ref.c b/c/archive_blake2sp_ref.c
deleted file mode 100644
--- a/c/archive_blake2sp_ref.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
-   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
-   your option.  The terms of these licenses can be found at:
-
-   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
-   - OpenSSL license   : https://www.openssl.org/source/license.html
-   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
-
-   More information about the BLAKE2 hash function can be found at
-   https://blake2.net.
-*/
-
-#include "archive_platform.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#if defined(_OPENMP)
-#include <omp.h>
-#endif
-
-#include "archive_blake2.h"
-#include "archive_blake2_impl.h"
-
-#define PARALLELISM_DEGREE 8
-
-/*
-  blake2sp_init_param defaults to setting the expecting output length
-  from the digest_length parameter block field.
-
-  In some cases, however, we do not want this, as the output length
-  of these instances is given by inner_length instead.
-*/
-static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
-{
-  int err = blake2s_init_param(S, P);
-  S->outlen = P->inner_length;
-  return err;
-}
-
-static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )
-{
-  blake2s_param P[1];
-  P->digest_length = (uint8_t)outlen;
-  P->key_length = (uint8_t)keylen;
-  P->fanout = PARALLELISM_DEGREE;
-  P->depth = 2;
-  store32( &P->leaf_length, 0 );
-  store32( &P->node_offset, offset );
-  store16( &P->xof_length, 0 );
-  P->node_depth = 0;
-  P->inner_length = BLAKE2S_OUTBYTES;
-  memset( P->salt, 0, sizeof( P->salt ) );
-  memset( P->personal, 0, sizeof( P->personal ) );
-  return blake2sp_init_leaf_param( S, P );
-}
-
-static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
-{
-  blake2s_param P[1];
-  P->digest_length = (uint8_t)outlen;
-  P->key_length = (uint8_t)keylen;
-  P->fanout = PARALLELISM_DEGREE;
-  P->depth = 2;
-  store32( &P->leaf_length, 0 );
-  store32( &P->node_offset, 0 );
-  store16( &P->xof_length, 0 );
-  P->node_depth = 1;
-  P->inner_length = BLAKE2S_OUTBYTES;
-  memset( P->salt, 0, sizeof( P->salt ) );
-  memset( P->personal, 0, sizeof( P->personal ) );
-  return blake2s_init_param( S, P );
-}
-
-
-int blake2sp_init( blake2sp_state *S, size_t outlen )
-{
-  size_t i;
-
-  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
-
-  memset( S->buf, 0, sizeof( S->buf ) );
-  S->buflen = 0;
-  S->outlen = outlen;
-
-  if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
-    return -1;
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-    if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;
-
-  S->R->last_node = 1;
-  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
-  return 0;
-}
-
-int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
-{
-  size_t i;
-
-  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
-
-  if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
-
-  memset( S->buf, 0, sizeof( S->buf ) );
-  S->buflen = 0;
-  S->outlen = outlen;
-
-  if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
-    return -1;
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-    if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
-
-  S->R->last_node = 1;
-  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
-  {
-    uint8_t block[BLAKE2S_BLOCKBYTES];
-    memset( block, 0, BLAKE2S_BLOCKBYTES );
-    memcpy( block, key, keylen );
-
-    for( i = 0; i < PARALLELISM_DEGREE; ++i )
-      blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
-
-    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
-  }
-  return 0;
-}
-
-
-int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
-{
-  const unsigned char * in = (const unsigned char *)pin;
-  size_t left = S->buflen;
-  size_t fill = sizeof( S->buf ) - left;
-  size_t i;
-
-  if( left && inlen >= fill )
-  {
-    memcpy( S->buf + left, in, fill );
-
-    for( i = 0; i < PARALLELISM_DEGREE; ++i )
-      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
-
-    in += fill;
-    inlen -= fill;
-    left = 0;
-  }
-
-#if defined(_OPENMP)
-  #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
-#else
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-#endif
-  {
-#if defined(_OPENMP)
-    size_t      i = omp_get_thread_num();
-#endif
-    size_t inlen__ = inlen;
-    const unsigned char *in__ = ( const unsigned char * )in;
-    in__ += i * BLAKE2S_BLOCKBYTES;
-
-    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
-    {
-      blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
-      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
-      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
-    }
-  }
-
-  in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
-  inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
-
-  if( inlen > 0 )
-    memcpy( S->buf + left, in, inlen );
-
-  S->buflen = left + inlen;
-  return 0;
-}
-
-
-int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
-{
-  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
-  size_t i;
-
-  if(out == NULL || outlen < S->outlen) {
-    return -1;
-  }
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-  {
-    if( S->buflen > i * BLAKE2S_BLOCKBYTES )
-    {
-      size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
-
-      if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
-
-      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
-    }
-
-    blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
-  }
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-    blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
-
-  return blake2s_final( S->R, out, S->outlen );
-}
-
-
-int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
-{
-  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
-  blake2s_state S[PARALLELISM_DEGREE][1];
-  blake2s_state FS[1];
-  size_t i;
-
-  /* Verify parameters */
-  if ( NULL == in && inlen > 0 ) return -1;
-
-  if ( NULL == out ) return -1;
-
-  if ( NULL == key && keylen > 0) return -1;
-
-  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
-
-  if( keylen > BLAKE2S_KEYBYTES ) return -1;
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-    if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
-
-  S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
-
-  if( keylen > 0 )
-  {
-    uint8_t block[BLAKE2S_BLOCKBYTES];
-    memset( block, 0, BLAKE2S_BLOCKBYTES );
-    memcpy( block, key, keylen );
-
-    for( i = 0; i < PARALLELISM_DEGREE; ++i )
-      blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
-
-    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
-  }
-
-#if defined(_OPENMP)
-  #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
-#else
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-#endif
-  {
-#if defined(_OPENMP)
-    size_t      i = omp_get_thread_num();
-#endif
-    size_t inlen__ = inlen;
-    const unsigned char *in__ = ( const unsigned char * )in;
-    in__ += i * BLAKE2S_BLOCKBYTES;
-
-    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
-    {
-      blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
-      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
-      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
-    }
-
-    if( inlen__ > i * BLAKE2S_BLOCKBYTES )
-    {
-      const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
-      const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
-      blake2s_update( S[i], in__, len );
-    }
-
-    blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
-  }
-
-  if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
-    return -1;
-
-  FS->last_node = 1;
-
-  for( i = 0; i < PARALLELISM_DEGREE; ++i )
-    blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
-
-  return blake2s_final( FS, out, outlen );
-}
-
-
-
-#if defined(BLAKE2SP_SELFTEST)
-#include <string.h>
-#include "blake2-kat.h"
-int main( void )
-{
-  uint8_t key[BLAKE2S_KEYBYTES];
-  uint8_t buf[BLAKE2_KAT_LENGTH];
-  size_t i, step;
-
-  for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
-    key[i] = ( uint8_t )i;
-
-  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
-    buf[i] = ( uint8_t )i;
-
-  /* Test simple API */
-  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
-  {
-    uint8_t hash[BLAKE2S_OUTBYTES];
-    blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
-
-    if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
-    {
-      goto fail;
-    }
-  }
-
-  /* Test streaming API */
-  for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
-    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
-      uint8_t hash[BLAKE2S_OUTBYTES];
-      blake2sp_state S;
-      uint8_t * p = buf;
-      size_t mlen = i;
-      int err = 0;
-
-      if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
-        goto fail;
-      }
-
-      while (mlen >= step) {
-        if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
-          goto fail;
-        }
-        mlen -= step;
-        p += step;
-      }
-      if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
-        goto fail;
-      }
-      if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
-        goto fail;
-      }
-
-      if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
-        goto fail;
-      }
-    }
-  }
-
-  puts( "ok" );
-  return 0;
-fail:
-  puts("error");
-  return -1;
-}
-#endif
diff --git a/c/archive_check_magic.c b/c/archive_check_magic.c
deleted file mode 100644
--- a/c/archive_check_magic.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_check_magic.c 201089 2009-12-28 02:20:23Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
-#include <winbase.h>
-#endif
-
-#include "archive_private.h"
-
-static void
-errmsg(const char *m)
-{
-	size_t s = strlen(m);
-	ssize_t written;
-
-	while (s > 0) {
-		written = write(2, m, s);
-		if (written <= 0)
-			return;
-		m += written;
-		s -= written;
-	}
-}
-
-static __LA_DEAD void
-diediedie(void)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
-	/* Cause a breakpoint exception  */
-	DebugBreak();
-#endif
-	abort();        /* Terminate the program abnormally. */
-}
-
-static const char *
-state_name(unsigned s)
-{
-	switch (s) {
-	case ARCHIVE_STATE_NEW:		return ("new");
-	case ARCHIVE_STATE_HEADER:	return ("header");
-	case ARCHIVE_STATE_DATA:	return ("data");
-	case ARCHIVE_STATE_EOF:		return ("eof");
-	case ARCHIVE_STATE_CLOSED:	return ("closed");
-	case ARCHIVE_STATE_FATAL:	return ("fatal");
-	default:			return ("??");
-	}
-}
-
-static const char *
-archive_handle_type_name(unsigned m)
-{
-	switch (m) {
-	case ARCHIVE_WRITE_MAGIC:	return ("archive_write");
-	case ARCHIVE_READ_MAGIC:	return ("archive_read");
-	case ARCHIVE_WRITE_DISK_MAGIC:	return ("archive_write_disk");
-	case ARCHIVE_READ_DISK_MAGIC:	return ("archive_read_disk");
-	case ARCHIVE_MATCH_MAGIC:	return ("archive_match");
-	default:			return NULL;
-	}
-}
-
-
-static char *
-write_all_states(char *buff, unsigned int states)
-{
-	unsigned int lowbit;
-
-	buff[0] = '\0';
-
-	/* A trick for computing the lowest set bit. */
-	while ((lowbit = states & (1 + ~states)) != 0) {
-		states &= ~lowbit;		/* Clear the low bit. */
-		strcat(buff, state_name(lowbit));
-		if (states != 0)
-			strcat(buff, "/");
-	}
-	return buff;
-}
-
-/*
- * Check magic value and current state.
- *   Magic value mismatches are fatal and result in calls to abort().
- *   State mismatches return ARCHIVE_FATAL.
- *   Otherwise, returns ARCHIVE_OK.
- *
- * This is designed to catch serious programming errors that violate
- * the libarchive API.
- */
-int
-__archive_check_magic(struct archive *a, unsigned int magic,
-    unsigned int state, const char *function)
-{
-	char states1[64];
-	char states2[64];
-	const char *handle_type;
-
-	/*
-	 * If this isn't some form of archive handle,
-	 * then the library user has screwed up so bad that
-	 * we don't even have a reliable way to report an error.
-	 */
-	handle_type = archive_handle_type_name(a->magic);
-
-	if (!handle_type) {
-		errmsg("PROGRAMMER ERROR: Function ");
-		errmsg(function);
-		errmsg(" invoked with invalid archive handle.\n");
-		diediedie();
-	}
-
-	if (a->magic != magic) {
-		archive_set_error(a, -1,
-		    "PROGRAMMER ERROR: Function '%s' invoked"
-		    " on '%s' archive object, which is not supported.",
-		    function,
-		    handle_type);
-		a->state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-
-	if ((a->state & state) == 0) {
-		/* If we're already FATAL, don't overwrite the error. */
-		if (a->state != ARCHIVE_STATE_FATAL)
-			archive_set_error(a, -1,
-			    "INTERNAL ERROR: Function '%s' invoked with"
-			    " archive structure in state '%s',"
-			    " should be in state '%s'",
-			    function,
-			    write_all_states(states1, a->state),
-			    write_all_states(states2, state));
-		a->state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	return ARCHIVE_OK;
-}
diff --git a/c/archive_cmdline.c b/c/archive_cmdline.c
deleted file mode 100644
--- a/c/archive_cmdline.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA 
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_STRING_H
-#  include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_cmdline_private.h"
-#include "archive_string.h"
-
-static int cmdline_set_path(struct archive_cmdline *, const char *);
-static int cmdline_add_arg(struct archive_cmdline *, const char *);
-
-static ssize_t
-extract_quotation(struct archive_string *as, const char *p)
-{
-	const char *s;
-
-	for (s = p + 1; *s;) {
-		if (*s == '\\') {
-			if (s[1] != '\0') {
-				archive_strappend_char(as, s[1]);
-				s += 2;
-			} else
-				s++;
-		} else if (*s == '"')
-			break;
-		else {
-			archive_strappend_char(as, s[0]);
-			s++;
-		}
-	}
-	if (*s != '"')
-		return (ARCHIVE_FAILED);/* Invalid sequence. */
-	return ((ssize_t)(s + 1 - p));
-}
-
-static ssize_t
-get_argument(struct archive_string *as, const char *p)
-{
-	const char *s = p;
-
-	archive_string_empty(as);
-
-	/* Skip beginning space characters. */
-	while (*s != '\0' && *s == ' ')
-		s++;
-	/* Copy non-space characters. */
-	while (*s != '\0' && *s != ' ') {
-		if (*s == '\\') {
-			if (s[1] != '\0') {
-				archive_strappend_char(as, s[1]);
-				s += 2;
-			} else {
-				s++;/* Ignore this character.*/
-				break;
-			}
-		} else if (*s == '"') {
-			ssize_t q = extract_quotation(as, s);
-			if (q < 0)
-				return (ARCHIVE_FAILED);/* Invalid sequence. */
-			s += q;
-		} else {
-			archive_strappend_char(as, s[0]);
-			s++;
-		}
-	}
-	return ((ssize_t)(s - p));
-}
-
-/*
- * Set up command line arguments.
- * Returns ARCHIVE_OK if everything okey.
- * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
- * empty command line.
- * Returns ARCHIVE_FATAL if no memory.
- */
-int
-__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
-{
-	struct archive_string as;
-	const char *p;
-	ssize_t al;
-	int r;
-
-	archive_string_init(&as);
-
-	/* Get first argument as a command path. */
-	al = get_argument(&as, cmd);
-	if (al < 0) {
-		r = ARCHIVE_FAILED;/* Invalid sequence. */
-		goto exit_function;
-	}
-	if (archive_strlen(&as) == 0) {
-		r = ARCHIVE_FAILED;/* An empty command path. */
-		goto exit_function;
-	}
-	r = cmdline_set_path(data, as.s);
-	if (r != ARCHIVE_OK)
-		goto exit_function;
-	p = strrchr(as.s, '/');
-	if (p == NULL)
-		p = as.s;
-	else
-		p++;
-	r = cmdline_add_arg(data, p);
-	if (r != ARCHIVE_OK)
-		goto exit_function;
-	cmd += al;
-
-	for (;;) {
-		al = get_argument(&as, cmd);
-		if (al < 0) {
-			r = ARCHIVE_FAILED;/* Invalid sequence. */
-			goto exit_function;
-		}
-		if (al == 0)
-			break;
-		cmd += al;
-		if (archive_strlen(&as) == 0 && *cmd == '\0')
-			break;
-		r = cmdline_add_arg(data, as.s);
-		if (r != ARCHIVE_OK)
-			goto exit_function;
-	}
-	r = ARCHIVE_OK;
-exit_function:
-	archive_string_free(&as);
-	return (r);
-}
-
-/*
- * Set the program path.
- */
-static int
-cmdline_set_path(struct archive_cmdline *data, const char *path)
-{
-	char *newptr;
-
-	newptr = realloc(data->path, strlen(path) + 1);
-	if (newptr == NULL)
-		return (ARCHIVE_FATAL);
-	data->path = newptr;
-	strcpy(data->path, path);
-	return (ARCHIVE_OK);
-}
-
-/*
- * Add a argument for the program.
- */
-static int
-cmdline_add_arg(struct archive_cmdline *data, const char *arg)
-{
-	char **newargv;
-
-	if (data->path == NULL)
-		return (ARCHIVE_FAILED);
-
-	newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
-	if (newargv == NULL)
-		return (ARCHIVE_FATAL);
-	data->argv = newargv;
-	data->argv[data->argc] = strdup(arg);
-	if (data->argv[data->argc] == NULL)
-		return (ARCHIVE_FATAL);
-	/* Set the terminator of argv. */
-	data->argv[++data->argc] = NULL;
-	return (ARCHIVE_OK);
-}
-
-struct archive_cmdline *
-__archive_cmdline_allocate(void)
-{
-	return (struct archive_cmdline *)
-		calloc(1, sizeof(struct archive_cmdline));
-}
-
-/*
- * Release the resources.
- */
-int
-__archive_cmdline_free(struct archive_cmdline *data)
-{
-
-	if (data) {
-		free(data->path);
-		if (data->argv != NULL) {
-			int i;
-			for (i = 0; data->argv[i] != NULL; i++)
-				free(data->argv[i]);
-			free(data->argv);
-		}
-		free(data);
-	}
-	return (ARCHIVE_OK);
-}
-
diff --git a/c/archive_cmdline_private.h b/c/archive_cmdline_private.h
deleted file mode 100644
--- a/c/archive_cmdline_private.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_CMDLINE_PRIVATE_H
-#define ARCHIVE_CMDLINE_PRIVATE_H
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-struct archive_cmdline {
-        char            *path;
-        char            **argv;
-        int              argc;
-};
-
-struct archive_cmdline *__archive_cmdline_allocate(void);
-int __archive_cmdline_parse(struct archive_cmdline *, const char *);
-int __archive_cmdline_free(struct archive_cmdline *);
-
-#endif
diff --git a/c/archive_crc32.h b/c/archive_crc32.h
deleted file mode 100644
--- a/c/archive_crc32.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 2009 Joerg  Sonnenberger
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_crc32.h 201102 2009-12-28 03:11:36Z kientzle $
- */
-
-#ifndef ARCHIVE_CRC32_H
-#define ARCHIVE_CRC32_H
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-/*
- * When zlib is unavailable, we should still be able to validate
- * uncompressed zip archives.  That requires us to be able to compute
- * the CRC32 check value.  This is a drop-in compatible replacement
- * for crc32() from zlib.  It's slower than the zlib implementation,
- * but still pretty fast: This runs about 300MB/s on my 3GHz P4
- * compared to about 800MB/s for the zlib implementation.
- */
-static unsigned long
-crc32(unsigned long crc, const void *_p, size_t len)
-{
-	unsigned long crc2, b, i;
-	const unsigned char *p = _p;
-	static volatile int crc_tbl_inited = 0;
-	static unsigned long crc_tbl[256];
-
-	if (!crc_tbl_inited) {
-		for (b = 0; b < 256; ++b) {
-			crc2 = b;
-			for (i = 8; i > 0; --i) {
-				if (crc2 & 1)
-					crc2 = (crc2 >> 1) ^ 0xedb88320UL;
-				else    
-					crc2 = (crc2 >> 1);
-			}
-			crc_tbl[b] = crc2;
-		}
-		crc_tbl_inited = 1;
-	}
-
-	crc = crc ^ 0xffffffffUL;
-	/* A use of this loop is about 20% - 30% faster than
-	 * no use version in any optimization option of gcc.  */
-	for (;len >= 8; len -= 8) {
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-	}
-	while (len--)
-		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-	return (crc ^ 0xffffffffUL);
-}
-
-#endif
diff --git a/c/archive_cryptor.c b/c/archive_cryptor.c
deleted file mode 100644
--- a/c/archive_cryptor.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*-
-* Copyright (c) 2014 Michihiro NAKAJIMA
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "archive_platform.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include "archive.h"
-#include "archive_cryptor_private.h"
-
-/*
- * On systems that do not support any recognized crypto libraries,
- * this file will normally define no usable symbols.
- *
- * But some compilers and linkers choke on empty object files, so
- * define a public symbol that will always exist.  This could
- * be removed someday if this file gains another always-present
- * symbol definition.
- */
-int __libarchive_cryptor_build_hack(void) {
-	return 0;
-}
-
-#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
-
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len)
-{
-	CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
-	    pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
-	    derived_key, derived_key_len);
-	return 0;
-}
-
-#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#ifdef _MSC_VER
-#pragma comment(lib, "Bcrypt.lib")
-#endif
-
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-	size_t salt_len, unsigned rounds, uint8_t *derived_key,
-	size_t derived_key_len)
-{
-	NTSTATUS status;
-	BCRYPT_ALG_HANDLE hAlg;
-
-	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
-		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
-	if (!BCRYPT_SUCCESS(status))
-		return -1;
-
-	status = BCryptDeriveKeyPBKDF2(hAlg,
-		(PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
-		(PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
-		(PUCHAR)derived_key, (ULONG)derived_key_len, 0);
-
-	BCryptCloseAlgorithmProvider(hAlg, 0);
-
-	return (BCRYPT_SUCCESS(status)) ? 0: -1;
-}
-
-#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_PKCS5_H)
-
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len)
-{
-	mbedtls_md_context_t ctx;
-	const mbedtls_md_info_t *info;
-	int ret;
-
-	mbedtls_md_init(&ctx);
-	info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
-	if (info == NULL) {
-		mbedtls_md_free(&ctx);
-		return (-1);
-	}
-	ret = mbedtls_md_setup(&ctx, info, 1);
-	if (ret != 0) {
-		mbedtls_md_free(&ctx);
-		return (-1);
-	}
-	ret = mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)pw,
-	    pw_len, salt, salt_len, rounds, derived_key_len, derived_key);
-
-	mbedtls_md_free(&ctx);
-	return (ret);
-}
-
-#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
-
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len) {
-	pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
-	    salt_len, salt, derived_key_len, derived_key);
-	return 0;
-}
-
-#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
-
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len) {
-
-	PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
-	    derived_key_len, derived_key);
-	return 0;
-}
-
-#else
-
-/* Stub */
-static int
-pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len) {
-	(void)pw; /* UNUSED */
-	(void)pw_len; /* UNUSED */
-	(void)salt; /* UNUSED */
-	(void)salt_len; /* UNUSED */
-	(void)rounds; /* UNUSED */
-	(void)derived_key; /* UNUSED */
-	(void)derived_key_len; /* UNUSED */
-	return -1; /* UNSUPPORTED */
-}
-
-#endif
-
-#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
-# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
-#  define kCCAlgorithmAES kCCAlgorithmAES128
-# endif
-
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	CCCryptorStatus r;
-
-	ctx->key_len = key_len;
-	memcpy(ctx->key, key, key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	ctx->encr_pos = AES_BLOCK_SIZE;
-	r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
-	    ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
-	return (r == kCCSuccess)? 0: -1;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-	CCCryptorRef ref = ctx->ctx;
-	CCCryptorStatus r;
-
-	r = CCCryptorReset(ref, NULL);
-	if (r != kCCSuccess && r != kCCUnimplemented)
-		return -1;
-	r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
-	    AES_BLOCK_SIZE, NULL);
-	return (r == kCCSuccess)? 0: -1;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-	memset(ctx->key, 0, ctx->key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	return 0;
-}
-
-#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	BCRYPT_ALG_HANDLE hAlg;
-	BCRYPT_KEY_HANDLE hKey;
-	DWORD keyObj_len, aes_key_len;
-	PBYTE keyObj;
-	ULONG result;
-	NTSTATUS status;
-	BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
-
-	ctx->hAlg = NULL;
-	ctx->hKey = NULL;
-	ctx->keyObj = NULL;
-	switch (key_len) {
-	case 16: aes_key_len = 128; break;
-	case 24: aes_key_len = 192; break;
-	case 32: aes_key_len = 256; break;
-	default: return -1;
-	}
-	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
-		MS_PRIMITIVE_PROVIDER, 0);
-	if (!BCRYPT_SUCCESS(status))
-		return -1;
-	status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
-		sizeof(key_lengths), &result, 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	if (key_lengths.dwMinLength > aes_key_len
-		|| key_lengths.dwMaxLength < aes_key_len) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
-		sizeof(keyObj_len), &result, 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
-	if (keyObj == NULL) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
-		(PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		HeapFree(GetProcessHeap(), 0, keyObj);
-		return -1;
-	}
-	status = BCryptGenerateSymmetricKey(hAlg, &hKey,
-		keyObj, keyObj_len,
-		(PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		HeapFree(GetProcessHeap(), 0, keyObj);
-		return -1;
-	}
-
-	ctx->hAlg = hAlg;
-	ctx->hKey = hKey;
-	ctx->keyObj = keyObj;
-	ctx->keyObj_len = keyObj_len;
-	ctx->encr_pos = AES_BLOCK_SIZE;
-
-	return 0;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-	NTSTATUS status;
-	ULONG result;
-
-	status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
-		NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
-		&result, 0);
-	return BCRYPT_SUCCESS(status) ? 0 : -1;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-
-	if (ctx->hAlg != NULL) {
-		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
-		ctx->hAlg = NULL;
-		BCryptDestroyKey(ctx->hKey);
-		ctx->hKey = NULL;
-		HeapFree(GetProcessHeap(), 0, ctx->keyObj);
-		ctx->keyObj = NULL;
-	}
-	memset(ctx, 0, sizeof(*ctx));
-	return 0;
-}
-
-#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H)
-
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	mbedtls_aes_init(&ctx->ctx);
-	ctx->key_len = key_len;
-	memcpy(ctx->key, key, key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	ctx->encr_pos = AES_BLOCK_SIZE;
-	return 0;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-	if (mbedtls_aes_setkey_enc(&ctx->ctx, ctx->key,
-	    ctx->key_len * 8) != 0)
-		return (-1);
-	if (mbedtls_aes_crypt_ecb(&ctx->ctx, MBEDTLS_AES_ENCRYPT, ctx->nonce,
-	    ctx->encr_buf) != 0)
-		return (-1);
-	return 0;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-	mbedtls_aes_free(&ctx->ctx);
-	memset(ctx, 0, sizeof(*ctx));
-	return 0;
-}
-
-#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
-
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	ctx->key_len = key_len;
-	memcpy(ctx->key, key, key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	ctx->encr_pos = AES_BLOCK_SIZE;
-	memset(&ctx->ctx, 0, sizeof(ctx->ctx));
-	return 0;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-#if NETTLE_VERSION_MAJOR < 3
-	aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
-	aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
-#else
-	switch(ctx->key_len) {
-	case AES128_KEY_SIZE:
-		aes128_set_encrypt_key(&ctx->ctx.c128, ctx->key);
-		aes128_encrypt(&ctx->ctx.c128, AES_BLOCK_SIZE, ctx->encr_buf,
-		    ctx->nonce);
-		break;
-	case AES192_KEY_SIZE:
-		aes192_set_encrypt_key(&ctx->ctx.c192, ctx->key);
-		aes192_encrypt(&ctx->ctx.c192, AES_BLOCK_SIZE, ctx->encr_buf,
-		    ctx->nonce);
-		break;
-	case AES256_KEY_SIZE:
-		aes256_set_encrypt_key(&ctx->ctx.c256, ctx->key);
-		aes256_encrypt(&ctx->ctx.c256, AES_BLOCK_SIZE, ctx->encr_buf,
-		    ctx->nonce);
-		break;
-	default:
-		return -1;
-		break;
-	}
-#endif
-	return 0;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-	memset(ctx, 0, sizeof(*ctx));
-	return 0;
-}
-
-#elif defined(HAVE_LIBCRYPTO)
-
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
-		return -1;
-
-	switch (key_len) {
-	case 16: ctx->type = EVP_aes_128_ecb(); break;
-	case 24: ctx->type = EVP_aes_192_ecb(); break;
-	case 32: ctx->type = EVP_aes_256_ecb(); break;
-	default: ctx->type = NULL; return -1;
-	}
-
-	ctx->key_len = key_len;
-	memcpy(ctx->key, key, key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	ctx->encr_pos = AES_BLOCK_SIZE;
-	return 0;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-	int outl = 0;
-	int r;
-
-	r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL);
-	if (r == 0)
-		return -1;
-	r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
-	    AES_BLOCK_SIZE);
-	if (r == 0 || outl != AES_BLOCK_SIZE)
-		return -1;
-	return 0;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-	EVP_CIPHER_CTX_free(ctx->ctx);
-	memset(ctx->key, 0, ctx->key_len);
-	memset(ctx->nonce, 0, sizeof(ctx->nonce));
-	return 0;
-}
-
-#else
-
-#define ARCHIVE_CRYPTOR_STUB
-/* Stub */
-static int
-aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	(void)ctx; /* UNUSED */
-	(void)key; /* UNUSED */
-	(void)key_len; /* UNUSED */
-	return -1;
-}
-
-static int
-aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return -1;
-}
-
-static int
-aes_ctr_release(archive_crypto_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return 0;
-}
-
-#endif
-
-#ifdef ARCHIVE_CRYPTOR_STUB
-static int
-aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
-    size_t in_len, uint8_t * const out, size_t *out_len)
-{
-	(void)ctx; /* UNUSED */
-	(void)in; /* UNUSED */
-	(void)in_len; /* UNUSED */
-	(void)out; /* UNUSED */
-	(void)out_len; /* UNUSED */
-	aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
-	return -1;
-}
-
-#else
-static void
-aes_ctr_increase_counter(archive_crypto_ctx *ctx)
-{
-	uint8_t *const nonce = ctx->nonce;
-	int j;
-
-	for (j = 0; j < 8; j++) {
-		if (++nonce[j])
-			break;
-	}
-}
-
-static int
-aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
-    size_t in_len, uint8_t * const out, size_t *out_len)
-{
-	uint8_t *const ebuf = ctx->encr_buf;
-	unsigned pos = ctx->encr_pos;
-	unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
-	unsigned i;
-
-	for (i = 0; i < max; ) {
-		if (pos == AES_BLOCK_SIZE) {
-			aes_ctr_increase_counter(ctx);
-			if (aes_ctr_encrypt_counter(ctx) != 0)
-				return -1;
-			while (max -i >= AES_BLOCK_SIZE) {
-				for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
-					out[i+pos] = in[i+pos] ^ ebuf[pos];
-				i += AES_BLOCK_SIZE;
-				aes_ctr_increase_counter(ctx);
-				if (aes_ctr_encrypt_counter(ctx) != 0)
-					return -1;
-			}
-			pos = 0;
-			if (i >= max)
-				break;
-		}
-		out[i] = in[i] ^ ebuf[pos++];
-		i++;
-	}
-	ctx->encr_pos = pos;
-	*out_len = i;
-
-	return 0;
-}
-#endif /* ARCHIVE_CRYPTOR_STUB */
-
-
-const struct archive_cryptor __archive_cryptor =
-{
-  &pbkdf2_sha1,
-  &aes_ctr_init,
-  &aes_ctr_update,
-  &aes_ctr_release,
-  &aes_ctr_init,
-  &aes_ctr_update,
-  &aes_ctr_release,
-};
diff --git a/c/archive_cryptor_private.h b/c/archive_cryptor_private.h
deleted file mode 100644
--- a/c/archive_cryptor_private.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*-
-* Copyright (c) 2014 Michihiro NAKAJIMA
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
-#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-/*
- * On systems that do not support any recognized crypto libraries,
- * the archive_cryptor.c file will normally define no usable symbols.
- *
- * But some compilers and linkers choke on empty object files, so
- * define a public symbol that will always exist.  This could
- * be removed someday if this file gains another always-present
- * symbol definition.
- */
-int __libarchive_cryptor_build_hack(void);
-
-#ifdef __APPLE__
-# include <AvailabilityMacros.h>
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
-#  define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
-# endif
-#endif
-
-#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
-#include <CommonCrypto/CommonCryptor.h>
-#include <CommonCrypto/CommonKeyDerivation.h>
-#define AES_BLOCK_SIZE	16
-#define AES_MAX_KEY_SIZE kCCKeySizeAES256
-
-typedef struct {
-	CCCryptorRef	ctx;
-	uint8_t		key[AES_MAX_KEY_SIZE];
-	unsigned	key_len;
-	uint8_t		nonce[AES_BLOCK_SIZE];
-	uint8_t		encr_buf[AES_BLOCK_SIZE];
-	unsigned	encr_pos;
-} archive_crypto_ctx;
-
-#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#include <bcrypt.h>
-
-/* Common in other bcrypt implementations, but missing from VS2008. */
-#ifndef BCRYPT_SUCCESS
-#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
-#endif
-
-#define AES_MAX_KEY_SIZE 32
-#define AES_BLOCK_SIZE 16
-typedef struct {
-	BCRYPT_ALG_HANDLE hAlg;
-	BCRYPT_KEY_HANDLE hKey;
-	PBYTE		keyObj;
-	DWORD		keyObj_len;
-	uint8_t		nonce[AES_BLOCK_SIZE];
-	uint8_t		encr_buf[AES_BLOCK_SIZE];
-	unsigned	encr_pos;
-} archive_crypto_ctx;
-
-#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H)
-#include <mbedtls/aes.h>
-#include <mbedtls/md.h>
-#include <mbedtls/pkcs5.h>
-
-#define AES_MAX_KEY_SIZE 32
-#define AES_BLOCK_SIZE 16
-
-typedef struct {
-	mbedtls_aes_context	ctx;
-	uint8_t		key[AES_MAX_KEY_SIZE];
-	unsigned	key_len;
-	uint8_t		nonce[AES_BLOCK_SIZE];
-	uint8_t		encr_buf[AES_BLOCK_SIZE];
-	unsigned	encr_pos;
-} archive_crypto_ctx;
-
-#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
-#if defined(HAVE_NETTLE_PBKDF2_H)
-#include <nettle/pbkdf2.h>
-#endif
-#include <nettle/aes.h>
-#include <nettle/version.h>
-
-typedef struct {
-#if NETTLE_VERSION_MAJOR < 3
-	struct aes_ctx	ctx;
-#else
-	union {
-		struct aes128_ctx c128;
-		struct aes192_ctx c192;
-		struct aes256_ctx c256;
-	}		ctx;
-#endif
-	uint8_t		key[AES_MAX_KEY_SIZE];
-	unsigned	key_len;
-	uint8_t		nonce[AES_BLOCK_SIZE];
-	uint8_t		encr_buf[AES_BLOCK_SIZE];
-	unsigned	encr_pos;
-} archive_crypto_ctx;
-
-#elif defined(HAVE_LIBCRYPTO)
-#include "archive_openssl_evp_private.h"
-#define AES_BLOCK_SIZE	16
-#define AES_MAX_KEY_SIZE 32
-
-typedef struct {
-	EVP_CIPHER_CTX	*ctx;
-	const EVP_CIPHER *type;
-	uint8_t		key[AES_MAX_KEY_SIZE];
-	unsigned	key_len;
-	uint8_t		nonce[AES_BLOCK_SIZE];
-	uint8_t		encr_buf[AES_BLOCK_SIZE];
-	unsigned	encr_pos;
-} archive_crypto_ctx;
-
-#else
-
-#define AES_BLOCK_SIZE	16
-#define AES_MAX_KEY_SIZE 32
-typedef int archive_crypto_ctx;
-
-#endif
-
-/* defines */
-#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\
-  __archive_cryptor.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)
-
-#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \
-  __archive_cryptor.decrypto_aes_ctr_init(ctx, key, key_len)
-#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
-  __archive_cryptor.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
-#define archive_decrypto_aes_ctr_release(ctx) \
-  __archive_cryptor.decrypto_aes_ctr_release(ctx)
-
-#define archive_encrypto_aes_ctr_init(ctx, key, key_len) \
-  __archive_cryptor.encrypto_aes_ctr_init(ctx, key, key_len)
-#define archive_encrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
-  __archive_cryptor.encrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
-#define archive_encrypto_aes_ctr_release(ctx) \
-  __archive_cryptor.encrypto_aes_ctr_release(ctx)
-
-/* Minimal interface to cryptographic functionality for internal use in
- * libarchive */
-struct archive_cryptor
-{
-  /* PKCS5 PBKDF2 HMAC-SHA1 */
-  int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt,
-    size_t salt_len, unsigned rounds, uint8_t *derived_key,
-    size_t derived_key_len);
-  /* AES CTR mode(little endian version) */
-  int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
-  int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
-    size_t, uint8_t *, size_t *);
-  int (*decrypto_aes_ctr_release)(archive_crypto_ctx *);
-  int (*encrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
-  int (*encrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
-    size_t, uint8_t *, size_t *);
-  int (*encrypto_aes_ctr_release)(archive_crypto_ctx *);
-};
-
-extern const struct archive_cryptor __archive_cryptor;
-
-#endif
diff --git a/c/archive_digest.c b/c/archive_digest.c
deleted file mode 100644
--- a/c/archive_digest.c
+++ /dev/null
@@ -1,1565 +0,0 @@
-/*-
-* Copyright (c) 2003-2007 Tim Kientzle
-* Copyright (c) 2011 Andres Mejia
-* Copyright (c) 2011 Michihiro NAKAJIMA
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "archive_platform.h"
-
-#include "archive.h"
-#include "archive_digest_private.h"
-
-/* In particular, force the configure probe to break if it tries
- * to test a combination of OpenSSL and libmd. */
-#if defined(ARCHIVE_CRYPTO_OPENSSL) && defined(ARCHIVE_CRYPTO_LIBMD)
-#error Cannot use both OpenSSL and libmd.
-#endif
-
-/* Common in other bcrypt implementations, but missing from VS2008. */
-#ifndef BCRYPT_SUCCESS
-#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
-#endif
-
-/*
- * Message digest functions for Windows platform.
- */
-#if defined(ARCHIVE_CRYPTO_MD5_WIN)    ||\
-	defined(ARCHIVE_CRYPTO_SHA1_WIN)   ||\
-	defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
-	defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
-	defined(ARCHIVE_CRYPTO_SHA512_WIN)
-
-/*
- * Initialize a Message digest.
- */
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-static int
-win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
-{
-	NTSTATUS status;
-	ctx->valid = 0;
-
-	status = BCryptOpenAlgorithmProvider(&ctx->hAlg, algo, NULL, 0);
-	if (!BCRYPT_SUCCESS(status))
-		return (ARCHIVE_FAILED);
-	status = BCryptCreateHash(ctx->hAlg, &ctx->hHash, NULL, 0, NULL, 0, 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
-		return (ARCHIVE_FAILED);
-	}
-
-	ctx->valid = 1;
-	return (ARCHIVE_OK);
-}
-#else
-static int
-win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
-{
-
-	ctx->valid = 0;
-	if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
-	    prov, CRYPT_VERIFYCONTEXT)) {
-		if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
-			return (ARCHIVE_FAILED);
-		if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
-		    prov, CRYPT_NEWKEYSET))
-			return (ARCHIVE_FAILED);
-	}
-
-	if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) {
-		CryptReleaseContext(ctx->cryptProv, 0);
-		return (ARCHIVE_FAILED);
-	}
-
-	ctx->valid = 1;
-	return (ARCHIVE_OK);
-}
-#endif
-
-/*
- * Update a Message digest.
- */
-static int
-win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
-{
-
-	if (!ctx->valid)
-		return (ARCHIVE_FAILED);
-
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	BCryptHashData(ctx->hHash,
-		      (PUCHAR)(uintptr_t)buf,
-		      len, 0);
-#else
-	CryptHashData(ctx->hash,
-		      (unsigned char *)(uintptr_t)buf,
-		      (DWORD)len, 0);
-#endif
-	return (ARCHIVE_OK);
-}
-
-static int
-win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
-{
-#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
-	DWORD siglen = (DWORD)bufsize;
-#endif
-
-	if (!ctx->valid)
-		return (ARCHIVE_FAILED);
-
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0);
-	BCryptDestroyHash(ctx->hHash);
-	BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
-#else
-	CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
-	CryptDestroyHash(ctx->hash);
-	CryptReleaseContext(ctx->cryptProv, 0);
-#endif
-	ctx->valid = 0;
-	return (ARCHIVE_OK);
-}
-
-#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */
-
-
-/* MD5 implementations */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  MD5Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  MD5Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  MD5Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  MD5Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  MD5Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  MD5Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  CC_MD5_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  CC_MD5_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  CC_MD5_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  mbedtls_md5_init(ctx);
-  if (mbedtls_md5_starts_ret(ctx) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  if (mbedtls_md5_finish_ret(ctx, md) == 0) {
-    mbedtls_md5_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_md5_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  md5_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  md5_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  md5_digest(ctx, MD5_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_md5()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
-   * this is meant to cope with that. Real fix is probably to fix
-   * archive_write_set_format_xar.c
-   */
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-  return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
-#else
-  return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
-#endif
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 16, ctx));
-}
-
-#else
-
-static int
-__archive_md5init(archive_md5_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* RIPEMD160 implementations */
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-  RMD160Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  RMD160Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-  RMD160Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-  RIPEMD160_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  RIPEMD160_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-  RIPEMD160_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-  mbedtls_ripemd160_init(ctx);
-  if (mbedtls_ripemd160_starts_ret(ctx) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-  if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
-    mbedtls_ripemd160_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_ripemd160_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-  ripemd160_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  ripemd160_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-  ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_ripemd160()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#else
-
-static int
-__archive_ripemd160init(archive_rmd160_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* SHA1 implementations */
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  SHA1Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA1Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  SHA1Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  SHA1_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA1_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  SHA1_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  CC_SHA1_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  CC_SHA1_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  CC_SHA1_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  mbedtls_sha1_init(ctx);
-  if (mbedtls_sha1_starts_ret(ctx) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
-    mbedtls_sha1_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_sha1_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  sha1_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  sha1_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  sha1_digest(ctx, SHA1_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_sha1()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
-   * this is meant to cope with that. Real fix is probably to fix
-   * archive_write_set_format_xar.c
-   */
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-  return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
-#else
-  return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
-#endif
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 20, ctx));
-}
-
-#else
-
-static int
-__archive_sha1init(archive_sha1_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* SHA256 implementations */
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  SHA256_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA256_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  SHA256_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  SHA256Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA256Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  SHA256Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  SHA256Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA256Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  SHA256Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  SHA256_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA256_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  SHA256_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  CC_SHA256_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  CC_SHA256_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  CC_SHA256_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  mbedtls_sha256_init(ctx);
-  if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
-    mbedtls_sha256_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_sha256_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  sha256_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  sha256_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  sha256_digest(ctx, SHA256_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_sha256()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-  return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
-#else
-  return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
-#endif
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 32, ctx));
-}
-
-#else
-
-static int
-__archive_sha256init(archive_sha256_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* SHA384 implementations */
-#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  SHA384_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA384_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  SHA384_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  SHA384Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA384Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  SHA384Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  SHA384Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA384Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  SHA384Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  CC_SHA384_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  CC_SHA384_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  CC_SHA384_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  mbedtls_sha512_init(ctx);
-  if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
-    mbedtls_sha512_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_sha512_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  sha384_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  sha384_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  sha384_digest(ctx, SHA384_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_sha384()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-  return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
-#else
-  return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
-#endif
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 48, ctx));
-}
-
-#else
-
-static int
-__archive_sha384init(archive_sha384_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* SHA512 implementations */
-#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  SHA512_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA512_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  SHA512_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  SHA512Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA512Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  SHA512Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  SHA512Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA512Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  SHA512Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  SHA512_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  SHA512_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  SHA512_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  CC_SHA512_Init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  CC_SHA512_Update(ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  CC_SHA512_Final(md, ctx);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  mbedtls_sha512_init(ctx);
-  if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
-    return (ARCHIVE_OK);
-  else
-    return (ARCHIVE_FATAL);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
-    mbedtls_sha512_free(ctx);
-    return (ARCHIVE_OK);
-  } else {
-    mbedtls_sha512_free(ctx);
-    return (ARCHIVE_FATAL);
-  }
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  sha512_init(ctx);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  sha512_update(ctx, insize, indata);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  sha512_digest(ctx, SHA512_DIGEST_SIZE, md);
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-  if ((*ctx = EVP_MD_CTX_new()) == NULL)
-	return (ARCHIVE_FAILED);
-  if (!EVP_DigestInit(*ctx, EVP_sha512()))
-	return (ARCHIVE_FAILED);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  EVP_DigestUpdate(*ctx, indata, insize);
-  return (ARCHIVE_OK);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  if (*ctx) {
-    EVP_DigestFinal(*ctx, md, NULL);
-    EVP_MD_CTX_free(*ctx);
-    *ctx = NULL;
-  }
-  return (ARCHIVE_OK);
-}
-
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-  return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
-#else
-  return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
-#endif
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 64, ctx));
-}
-
-#else
-
-static int
-__archive_sha512init(archive_sha512_ctx *ctx)
-{
-	(void)ctx; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-	(void)ctx; /* UNUSED */
-	(void)indata; /* UNUSED */
-	(void)insize; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-	(void)ctx; /* UNUSED */
-	(void)md; /* UNUSED */
-	return (ARCHIVE_FAILED);
-}
-
-#endif
-
-/* NOTE: Message Digest functions are set based on availability and by the
- * following order of preference.
- * 1. libc
- * 2. libc2
- * 3. libc3
- * 4. libSystem
- * 5. Nettle
- * 6. OpenSSL
- * 7. libmd
- * 8. Windows API
- */
-const struct archive_digest __archive_digest =
-{
-/* MD5 */
-  &__archive_md5init,
-  &__archive_md5update,
-  &__archive_md5final,
-
-/* RIPEMD160 */
-  &__archive_ripemd160init,
-  &__archive_ripemd160update,
-  &__archive_ripemd160final,
-
-/* SHA1 */
-  &__archive_sha1init,
-  &__archive_sha1update,
-  &__archive_sha1final,
-
-/* SHA256 */
-  &__archive_sha256init,
-  &__archive_sha256update,
-  &__archive_sha256final,
-
-/* SHA384 */
-  &__archive_sha384init,
-  &__archive_sha384update,
-  &__archive_sha384final,
-
-/* SHA512 */
-  &__archive_sha512init,
-  &__archive_sha512update,
-  &__archive_sha512final
-};
diff --git a/c/archive_digest_private.h b/c/archive_digest_private.h
deleted file mode 100644
--- a/c/archive_digest_private.h
+++ /dev/null
@@ -1,426 +0,0 @@
-/*-
-* Copyright (c) 2003-2007 Tim Kientzle
-* Copyright (c) 2011 Andres Mejia
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef ARCHIVE_DIGEST_PRIVATE_H_INCLUDED
-#define ARCHIVE_DIGEST_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED
-#error "Should have include config.h first!"
-#endif
-
-/*
- * Crypto support in various Operating Systems:
- *
- * NetBSD:
- * - MD5 and SHA1 in libc: without _ after algorithm name
- * - SHA2 in libc: with _ after algorithm name
- *
- * OpenBSD:
- * - MD5, SHA1 and SHA2 in libc: without _ after algorithm name
- * - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name
- *
- * DragonFly and FreeBSD:
- * - MD5 libmd: without _ after algorithm name
- * - SHA1, SHA256 and SHA512 in libmd: with _ after algorithm name
- *
- * Mac OS X (10.4 and later):
- * - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name
- *
- * OpenSSL:
- * - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name
- *
- * Windows:
- * - MD5, SHA1 and SHA2 in archive_crypto.c using Windows crypto API
- */
-
-/* libc crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
-#include <md5.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
-#include <rmd160.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
-#include <sha1.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
-#include <sha2.h>
-#endif
-
-/* libmd crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_RMD160_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
-#define	ARCHIVE_CRYPTO_LIBMD 1
-#endif
-
-#if defined(ARCHIVE_CRYPTO_MD5_LIBMD)
-#include <md5.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
-#include <ripemd.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
-#include <sha.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
-#include <sha256.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
-#include <sha512.h>
-#endif
-
-/* libSystem crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
-#include <CommonCrypto/CommonDigest.h>
-#endif
-
-/* mbed TLS crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
-#include <mbedtls/md5.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
-#include <mbedtls/ripemd160.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
-#include <mbedtls/sha1.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
-#include <mbedtls/sha256.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
-#include <mbedtls/sha512.h>
-#endif
-
-/* Nettle crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_NETTLE)
-#include <nettle/md5.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
-#include <nettle/ripemd160.h>
-#endif
-#if defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
-#include <nettle/sha.h>
-#endif
-
-/* OpenSSL crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
-#define	ARCHIVE_CRYPTO_OPENSSL 1
-#include "archive_openssl_evp_private.h"
-#endif
-
-/* Windows crypto headers */
-#if defined(ARCHIVE_CRYPTO_MD5_WIN)    ||\
-  defined(ARCHIVE_CRYPTO_SHA1_WIN)   ||\
-  defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_WIN)
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-/* don't use bcrypt when XP needs to be supported */
-#include <bcrypt.h>
-typedef struct {
-  int   valid;
-  BCRYPT_ALG_HANDLE  hAlg;
-  BCRYPT_HASH_HANDLE hHash;
-} Digest_CTX;
-#else
-#include <windows.h>
-#include <wincrypt.h>
-typedef struct {
-  int   valid;
-  HCRYPTPROV  cryptProv;
-  HCRYPTHASH  hash;
-} Digest_CTX;
-#endif
-#endif
-
-/* typedefs */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
-typedef MD5_CTX archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
-typedef MD5_CTX archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
-typedef CC_MD5_CTX archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
-typedef mbedtls_md5_context archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
-typedef struct md5_ctx archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
-typedef EVP_MD_CTX *archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
-typedef Digest_CTX archive_md5_ctx;
-#else
-typedef unsigned char archive_md5_ctx;
-#endif
-
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
-typedef RMD160_CTX archive_rmd160_ctx;
-#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
-typedef RIPEMD160_CTX archive_rmd160_ctx;
-#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
-typedef mbedtls_ripemd160_context archive_rmd160_ctx;
-#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
-typedef struct ripemd160_ctx archive_rmd160_ctx;
-#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
-typedef EVP_MD_CTX *archive_rmd160_ctx;
-#else
-typedef unsigned char archive_rmd160_ctx;
-#endif
-
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
-typedef SHA1_CTX archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
-typedef SHA1_CTX archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
-typedef CC_SHA1_CTX archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
-typedef mbedtls_sha1_context archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
-typedef struct sha1_ctx archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
-typedef EVP_MD_CTX *archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
-typedef Digest_CTX archive_sha1_ctx;
-#else
-typedef unsigned char archive_sha1_ctx;
-#endif
-
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
-typedef SHA256_CTX archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
-typedef SHA256_CTX archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
-typedef SHA2_CTX archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
-typedef SHA256_CTX archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
-typedef CC_SHA256_CTX archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
-typedef mbedtls_sha256_context archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
-typedef struct sha256_ctx archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
-typedef EVP_MD_CTX *archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
-typedef Digest_CTX archive_sha256_ctx;
-#else
-typedef unsigned char archive_sha256_ctx;
-#endif
-
-#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
-typedef SHA384_CTX archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
-typedef SHA384_CTX archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
-typedef SHA2_CTX archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
-typedef CC_SHA512_CTX archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
-typedef mbedtls_sha512_context archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
-typedef struct sha384_ctx archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
-typedef EVP_MD_CTX *archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
-typedef Digest_CTX archive_sha384_ctx;
-#else
-typedef unsigned char archive_sha384_ctx;
-#endif
-
-#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
-typedef SHA512_CTX archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
-typedef SHA512_CTX archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
-typedef SHA2_CTX archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
-typedef SHA512_CTX archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
-typedef CC_SHA512_CTX archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
-typedef mbedtls_sha512_context archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
-typedef struct sha512_ctx archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
-typedef EVP_MD_CTX *archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
-typedef Digest_CTX archive_sha512_ctx;
-#else
-typedef unsigned char archive_sha512_ctx;
-#endif
-
-/* defines */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_MD5_LIBMD) ||	\
-  defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_MD5_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_MD5_WIN)
-#define ARCHIVE_HAS_MD5
-#endif
-#define archive_md5_init(ctx)\
-  __archive_digest.md5init(ctx)
-#define archive_md5_final(ctx, md)\
-  __archive_digest.md5final(ctx, md)
-#define archive_md5_update(ctx, buf, n)\
-  __archive_digest.md5update(ctx, buf, n)
-
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
-#define ARCHIVE_HAS_RMD160
-#endif
-#define archive_rmd160_init(ctx)\
-  __archive_digest.rmd160init(ctx)
-#define archive_rmd160_final(ctx, md)\
-  __archive_digest.rmd160final(ctx, md)
-#define archive_rmd160_update(ctx, buf, n)\
-  __archive_digest.rmd160update(ctx, buf, n)
-
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||	\
-  defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA1_WIN)
-#define ARCHIVE_HAS_SHA1
-#endif
-#define archive_sha1_init(ctx)\
-  __archive_digest.sha1init(ctx)
-#define archive_sha1_final(ctx, md)\
-  __archive_digest.sha1final(ctx, md)
-#define archive_sha1_update(ctx, buf, n)\
-  __archive_digest.sha1update(ctx, buf, n)
-
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA256_WIN)
-#define ARCHIVE_HAS_SHA256
-#endif
-#define archive_sha256_init(ctx)\
-  __archive_digest.sha256init(ctx)
-#define archive_sha256_final(ctx, md)\
-  __archive_digest.sha256final(ctx, md)
-#define archive_sha256_update(ctx, buf, n)\
-  __archive_digest.sha256update(ctx, buf, n)
-
-#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA384_WIN)
-#define ARCHIVE_HAS_SHA384
-#endif
-#define archive_sha384_init(ctx)\
-  __archive_digest.sha384init(ctx)
-#define archive_sha384_final(ctx, md)\
-  __archive_digest.sha384final(ctx, md)
-#define archive_sha384_update(ctx, buf, n)\
-  __archive_digest.sha384update(ctx, buf, n)
-
-#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBC3) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBMD) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_NETTLE) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) ||\
-  defined(ARCHIVE_CRYPTO_SHA512_WIN)
-#define ARCHIVE_HAS_SHA512
-#endif
-#define archive_sha512_init(ctx)\
-  __archive_digest.sha512init(ctx)
-#define archive_sha512_final(ctx, md)\
-  __archive_digest.sha512final(ctx, md)
-#define archive_sha512_update(ctx, buf, n)\
-  __archive_digest.sha512update(ctx, buf, n)
-
-/* Minimal interface to digest functionality for internal use in libarchive */
-struct archive_digest
-{
-  /* Message Digest */
-  int (*md5init)(archive_md5_ctx *ctx);
-  int (*md5update)(archive_md5_ctx *, const void *, size_t);
-  int (*md5final)(archive_md5_ctx *, void *);
-  int (*rmd160init)(archive_rmd160_ctx *);
-  int (*rmd160update)(archive_rmd160_ctx *, const void *, size_t);
-  int (*rmd160final)(archive_rmd160_ctx *, void *);
-  int (*sha1init)(archive_sha1_ctx *);
-  int (*sha1update)(archive_sha1_ctx *, const void *, size_t);
-  int (*sha1final)(archive_sha1_ctx *, void *);
-  int (*sha256init)(archive_sha256_ctx *);
-  int (*sha256update)(archive_sha256_ctx *, const void *, size_t);
-  int (*sha256final)(archive_sha256_ctx *, void *);
-  int (*sha384init)(archive_sha384_ctx *);
-  int (*sha384update)(archive_sha384_ctx *, const void *, size_t);
-  int (*sha384final)(archive_sha384_ctx *, void *);
-  int (*sha512init)(archive_sha512_ctx *);
-  int (*sha512update)(archive_sha512_ctx *, const void *, size_t);
-  int (*sha512final)(archive_sha512_ctx *, void *);
-};
-
-extern const struct archive_digest __archive_digest;
-
-#endif
diff --git a/c/archive_disk_acl_darwin.c b/c/archive_disk_acl_darwin.c
deleted file mode 100644
--- a/c/archive_disk_acl_darwin.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*-
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#if ARCHIVE_ACL_DARWIN
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_MEMBERSHIP_H
-#include <membership.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_ACL_H
-#define _ACL_PRIVATE /* For debugging */
-#include <sys/acl.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-#include "archive_write_disk_private.h"
-
-typedef struct {
-	const int a_perm;	/* Libarchive permission or flag */
-	const int p_perm;	/* Platform permission or flag */
-} acl_perm_map_t;
-
-static const acl_perm_map_t acl_nfs4_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
-#if HAVE_DECL_ACL_SYNCHRONIZE
-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
-#endif
-};
-
-static const int acl_nfs4_perm_map_size =
-    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
-
-static const acl_perm_map_t acl_nfs4_flag_map[] = {
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
-};
-
-static const int acl_nfs4_flag_map_size =
-    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
-
-static int translate_guid(struct archive *a, acl_entry_t acl_entry,
-    int *ae_id, int *ae_tag, const char **ae_name)
-{
-	void *q;
-	uid_t ugid;
-	int r, idtype;
-
-	q = acl_get_qualifier(acl_entry);
-	if (q == NULL)
-		return (1);
-	r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
-	if (r != 0) {
-		acl_free(q);
-		return (1);
-	}
-	if (idtype == ID_TYPE_UID) {
-		*ae_tag = ARCHIVE_ENTRY_ACL_USER;
-		*ae_id = ugid;
-		*ae_name = archive_read_disk_uname(a, *ae_id);
-	} else if (idtype == ID_TYPE_GID) {
-		*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-		*ae_id = ugid;
-		*ae_name = archive_read_disk_gname(a, *ae_id);
-	} else
-		r = 1;
-
-	acl_free(q);
-	return (r);
-}
-
-static void
-add_trivial_nfs4_acl(struct archive_entry *entry)
-{
-	mode_t mode;
-	int i;
-	const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
-	const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
-	    ARCHIVE_ENTRY_ACL_APPEND_DATA;
-	const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
-	const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
-	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
-	    ARCHIVE_ENTRY_ACL_READ_ACL |
-	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
-	const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
-	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
-	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
-	    ARCHIVE_ENTRY_ACL_WRITE_OWNER;
-
-	struct {
-	    const int type;
-	    const int tag;
-	    int permset;
-	} tacl_entry[] = {
-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
-	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
-	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
-	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
-	};
-
-	mode = archive_entry_mode(entry);
-
-	/* Permissions for everyone@ */
-	if (mode & 0004)
-		tacl_entry[5].permset |= rperm;
-	if (mode & 0002)
-		tacl_entry[5].permset |= wperm;
-	if (mode & 0001)
-		tacl_entry[5].permset |= eperm;
-
-	/* Permissions for group@ */
-	if (mode & 0040)
-		tacl_entry[4].permset |= rperm;
-	else if (mode & 0004)
-		tacl_entry[2].permset |= rperm;
-	if (mode & 0020)
-		tacl_entry[4].permset |= wperm;
-	else if (mode & 0002)
-		tacl_entry[2].permset |= wperm;
-	if (mode & 0010)
-		tacl_entry[4].permset |= eperm;
-	else if (mode & 0001)
-		tacl_entry[2].permset |= eperm;
-
-	/* Permissions for owner@ */
-	if (mode & 0400) {
-		tacl_entry[3].permset |= rperm;
-		if (!(mode & 0040) && (mode & 0004))
-			tacl_entry[0].permset |= rperm;
-	} else if ((mode & 0040) || (mode & 0004))
-		tacl_entry[1].permset |= rperm;
-	if (mode & 0200) {
-		tacl_entry[3].permset |= wperm;
-		if (!(mode & 0020) && (mode & 0002))
-			tacl_entry[0].permset |= wperm;
-	} else if ((mode & 0020) || (mode & 0002))
-		tacl_entry[1].permset |= wperm;
-	if (mode & 0100) {
-		tacl_entry[3].permset |= eperm;
-		if (!(mode & 0010) && (mode & 0001))
-			tacl_entry[0].permset |= eperm;
-	} else if ((mode & 0010) || (mode & 0001))
-		tacl_entry[1].permset |= eperm;
-
-	for (i = 0; i < 6; i++) {
-		if (tacl_entry[i].permset != 0) {
-			archive_entry_acl_add_entry(entry,
-			    tacl_entry[i].type, tacl_entry[i].permset,
-			    tacl_entry[i].tag, -1, NULL);
-		}
-	}
-
-	return;
-}
-
-static int
-translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, acl_t acl)
-{
-	acl_tag_t	 acl_tag;
-	acl_flagset_t	 acl_flagset;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-	int		 i, entry_acl_type;
-	int		 r, s, ae_id, ae_tag, ae_perm;
-	const char	*ae_name;
-
-	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
-	if (s == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to get first ACL entry");
-		return (ARCHIVE_WARN);
-	}
-
-	while (s == 0) {
-		ae_id = -1;
-		ae_name = NULL;
-		ae_perm = 0;
-
-		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL tag type");
-			return (ARCHIVE_WARN);
-		}
-		switch (acl_tag) {
-		case ACL_EXTENDED_ALLOW:
-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-			r = translate_guid(&a->archive, acl_entry,
-			    &ae_id, &ae_tag, &ae_name);
-			break;
-		case ACL_EXTENDED_DENY:
-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-			r = translate_guid(&a->archive, acl_entry,
-			    &ae_id, &ae_tag, &ae_name);
-			break;
-		default:
-			/* Skip types that libarchive can't support. */
-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-			continue;
-		}
-
-		/* Skip if translate_guid() above failed */
-		if (r != 0) {
-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-			continue;
-		}
-
-		/*
-		 * Libarchive stores "flag" (NFSv4 inheritance bits)
-		 * in the ae_perm bitmap.
-		 *
-		 * acl_get_flagset_np() fails with non-NFSv4 ACLs
-		 */
-		if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get flagset from a NFSv4 ACL entry");
-			return (ARCHIVE_WARN);
-		}
-		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-			r = acl_get_flag_np(acl_flagset,
-			    acl_nfs4_flag_map[i].p_perm);
-			if (r == -1) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to check flag in a NFSv4 "
-				    "ACL flagset");
-				return (ARCHIVE_WARN);
-			} else if (r)
-				ae_perm |= acl_nfs4_flag_map[i].a_perm;
-		}
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL permission set");
-			return (ARCHIVE_WARN);
-		}
-
-		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
-			/*
-			 * acl_get_perm() is spelled differently on different
-			 * platforms; see above.
-			 */
-			r = acl_get_perm_np(acl_permset,
-			    acl_nfs4_perm_map[i].p_perm);
-			if (r == -1) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to check permission in an ACL "
-				    "permission set");
-				return (ARCHIVE_WARN);
-			} else if (r)
-				ae_perm |= acl_nfs4_perm_map[i].a_perm;
-		}
-
-#if !HAVE_DECL_ACL_SYNCHRONIZE
-		/* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
-		ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
-#endif
-
-		archive_entry_acl_add_entry(entry, entry_acl_type,
-					    ae_perm, ae_tag,
-					    ae_id, ae_name);
-
-		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-set_acl(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl,
-    int ae_requested_type, const char *tname)
-{
-	acl_t		 acl;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-	acl_flagset_t	 acl_flagset;
-	int		 ret;
-	int		 ae_type, ae_permset, ae_tag, ae_id;
-	uuid_t		 ae_uuid;
-	uid_t		 ae_uid;
-	gid_t		 ae_gid;
-	const char	*ae_name;
-	int		 entries;
-	int		 i;
-
-	ret = ARCHIVE_OK;
-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
-	if (entries == 0)
-		return (ARCHIVE_OK);
-
-	if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-		errno = ENOENT;
-		archive_set_error(a, errno, "Unsupported ACL type");
-		return (ARCHIVE_FAILED);
-	}
-
-	acl = acl_init(entries);
-	if (acl == (acl_t)NULL) {
-		archive_set_error(a, errno,
-		    "Failed to initialize ACL working storage");
-		return (ARCHIVE_FAILED);
-	}
-
-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		/*
-		 * Mac OS doesn't support NFSv4 ACLs for
-		 * owner@, group@ and everyone@.
-		 * We skip any of these ACLs found.
-		 */
-		if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
-		    ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
-		    ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
-			continue;
-
-		if (acl_create_entry(&acl, &acl_entry) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to create a new ACL entry");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		switch (ae_type) {
-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
-			break;
-		default:
-			/* We don't support any other types on MacOS */
-			continue;
-		}
-
-		switch (ae_tag) {
-		case ARCHIVE_ENTRY_ACL_USER:
-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
-				continue;
-			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
-				continue;
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP:
-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
-				continue;
-			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
-				continue;
-			break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL tag");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to get ACL permission set");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-		if (acl_clear_perms(acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to clear ACL permissions");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
-			if (ae_permset & acl_nfs4_perm_map[i].a_perm) {
-				if (acl_add_perm(acl_permset,
-				    acl_nfs4_perm_map[i].p_perm) != 0) {
-					archive_set_error(a, errno,
-					    "Failed to add ACL permission");
-					ret = ARCHIVE_FAILED;
-					goto exit_free;
-				}
-			}
-		}
-
-		/*
-		 * acl_get_flagset_np() fails with non-NFSv4 ACLs
-		 */
-		if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to get flagset from an NFSv4 ACL entry");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-		if (acl_clear_flags_np(acl_flagset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to clear flags from an NFSv4 ACL flagset");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-			if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
-				if (acl_add_flag_np(acl_flagset,
-				    acl_nfs4_flag_map[i].p_perm) != 0) {
-					archive_set_error(a, errno,
-					    "Failed to add flag to "
-					    "NFSv4 ACL flagset");
-					ret = ARCHIVE_FAILED;
-					goto exit_free;
-				}
-			}
-		}
-	}
-
-	if (fd >= 0) {
-		if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0)
-			ret = ARCHIVE_OK;
-		else {
-			if (errno == EOPNOTSUPP) {
-				/* Filesystem doesn't support ACLs */
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(a, errno,
-				    "Failed to set acl on fd: %s", tname);
-				ret = ARCHIVE_WARN;
-			}
-		}
-	} else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) {
-		if (errno == EOPNOTSUPP) {
-			/* Filesystem doesn't support ACLs */
-			ret = ARCHIVE_OK;
-		} else {
-			archive_set_error(a, errno, "Failed to set acl: %s",
-			    tname);
-			ret = ARCHIVE_WARN;
-		}
-	}
-exit_free:
-	acl_free(acl);
-	return (ret);
-}
-
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	const char	*accpath;
-	acl_t		acl;
-	int		r;
-
-	accpath = NULL;
-
-	if (*fd < 0) {
-		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (accpath == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	archive_entry_acl_clear(entry);
-
-	acl = NULL;
-
-	if (*fd >= 0)
-		acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED);
-	else if (!a->follow_symlinks)
-		acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED);
-	else
-		acl = acl_get_file(accpath, ACL_TYPE_EXTENDED);
-
-	if (acl != NULL) {
-		r = translate_acl(a, entry, acl);
-		acl_free(acl);
-		acl = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate NFSv4 ACLs");
-		}
-
-		/*
-		 * Because Mac OS doesn't support owner@, group@ and everyone@
-		 * ACLs we need to add NFSv4 ACLs mirroring the file mode to
-		 * the archive entry. Otherwise extraction on non-Mac platforms
-		 * would lead to an invalid file mode.
-		 */
-		if ((archive_entry_acl_types(entry) &
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
-			add_trivial_nfs4_acl(entry);
-
-		return (r);
-	}
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode)
-{
-	int		ret = ARCHIVE_OK;
-
-	(void)mode;	/* UNUSED */
-
-	if ((archive_acl_types(abstract_acl) &
-	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-		ret = set_acl(a, fd, name, abstract_acl,
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
-	}
-	return (ret);
-}
-#endif	/* ARCHIVE_ACL_DARWIN */
diff --git a/c/archive_disk_acl_freebsd.c b/c/archive_disk_acl_freebsd.c
deleted file mode 100644
--- a/c/archive_disk_acl_freebsd.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#if ARCHIVE_ACL_FREEBSD
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_ACL_H
-#define _ACL_PRIVATE /* For debugging */
-#include <sys/acl.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-#include "archive_write_disk_private.h"
-
-typedef struct {
-	const int a_perm;	/* Libarchive permission or flag */
-	const int p_perm;	/* Platform permission or flag */
-} acl_perm_map_t;
-
-static const acl_perm_map_t acl_posix_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
-	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-};
-
-static const int acl_posix_perm_map_size =
-    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-static const acl_perm_map_t acl_nfs4_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
-};
-
-static const int acl_nfs4_perm_map_size =
-    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
-
-static const acl_perm_map_t acl_nfs4_flag_map[] = {
-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
-#ifdef ACL_ENTRY_INHERITED
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
-#endif
-};
-
-static const int acl_nfs4_flag_map_size =
-    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
-#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
-
-static int
-translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
-{
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	int brand;
-	acl_flagset_t	 acl_flagset;
-	acl_entry_type_t acl_type;
-#endif
-	acl_tag_t	 acl_tag;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-	int		 i, entry_acl_type, perm_map_size;
-	const acl_perm_map_t	*perm_map;
-	int		 r, s, ae_id, ae_tag, ae_perm;
-	void		*q;
-	const char	*ae_name;
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
-	// Make sure the "brand" on this ACL is consistent
-	// with the default_entry_acl_type bits provided.
-	if (acl_get_brand_np(acl, &brand) != 0) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to read ACL brand");
-		return (ARCHIVE_WARN);
-	}
-	switch (brand) {
-	case ACL_BRAND_POSIX:
-		switch (default_entry_acl_type) {
-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid ACL entry type for POSIX.1e ACL");
-			return (ARCHIVE_WARN);
-		}
-		break;
-	case ACL_BRAND_NFS4:
-		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid ACL entry type for NFSv4 ACL");
-			return (ARCHIVE_WARN);
-		}
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Unknown ACL brand");
-		return (ARCHIVE_WARN);
-	}
-#endif
-
-	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
-	if (s == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to get first ACL entry");
-		return (ARCHIVE_WARN);
-	}
-
-	while (s == 1) {
-		ae_id = -1;
-		ae_name = NULL;
-		ae_perm = 0;
-
-		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL tag type");
-			return (ARCHIVE_WARN);
-		}
-		switch (acl_tag) {
-		case ACL_USER:
-			q = acl_get_qualifier(acl_entry);
-			if (q != NULL) {
-				ae_id = (int)*(uid_t *)q;
-				acl_free(q);
-				ae_name = archive_read_disk_uname(&a->archive,
-				    ae_id);
-			}
-			ae_tag = ARCHIVE_ENTRY_ACL_USER;
-			break;
-		case ACL_GROUP:
-			q = acl_get_qualifier(acl_entry);
-			if (q != NULL) {
-				ae_id = (int)*(gid_t *)q;
-				acl_free(q);
-				ae_name = archive_read_disk_gname(&a->archive,
-				    ae_id);
-			}
-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-			break;
-		case ACL_MASK:
-			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
-			break;
-		case ACL_USER_OBJ:
-			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-			break;
-		case ACL_GROUP_OBJ:
-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-			break;
-		case ACL_OTHER:
-			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
-			break;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		case ACL_EVERYONE:
-			ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
-			break;
-#endif
-		default:
-			/* Skip types that libarchive can't support. */
-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-			continue;
-		}
-
-		// XXX acl_type maps to allow/deny/audit/YYYY bits
-		entry_acl_type = default_entry_acl_type;
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/*
-			 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
-			 */
-			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
-				archive_set_error(&a->archive, errno, "Failed "
-				    "to get ACL type from a NFSv4 ACL entry");
-				return (ARCHIVE_WARN);
-			}
-			switch (acl_type) {
-			case ACL_ENTRY_TYPE_ALLOW:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-				break;
-			case ACL_ENTRY_TYPE_DENY:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-				break;
-			case ACL_ENTRY_TYPE_AUDIT:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
-				break;
-			case ACL_ENTRY_TYPE_ALARM:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
-				break;
-			default:
-				archive_set_error(&a->archive, errno,
-				    "Invalid NFSv4 ACL entry type");
-				return (ARCHIVE_WARN);
-			}
-
-			/*
-			 * Libarchive stores "flag" (NFSv4 inheritance bits)
-			 * in the ae_perm bitmap.
-			 *
-			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
-			 */
-			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to get flagset from a NFSv4 "
-				    "ACL entry");
-				return (ARCHIVE_WARN);
-			}
-			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-				r = acl_get_flag_np(acl_flagset,
-				    acl_nfs4_flag_map[i].p_perm);
-				if (r == -1) {
-					archive_set_error(&a->archive, errno,
-					    "Failed to check flag in a NFSv4 "
-					    "ACL flagset");
-					return (ARCHIVE_WARN);
-				} else if (r)
-					ae_perm |= acl_nfs4_flag_map[i].a_perm;
-			}
-		}
-#endif
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL permission set");
-			return (ARCHIVE_WARN);
-		}
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			perm_map_size = acl_nfs4_perm_map_size;
-			perm_map = acl_nfs4_perm_map;
-		} else {
-#endif
-			perm_map_size = acl_posix_perm_map_size;
-			perm_map = acl_posix_perm_map;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		}
-#endif
-
-		for (i = 0; i < perm_map_size; ++i) {
-			r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
-			if (r == -1) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to check permission in an ACL "
-				    "permission set");
-				return (ARCHIVE_WARN);
-			} else if (r)
-				ae_perm |= perm_map[i].a_perm;
-		}
-
-		archive_entry_acl_add_entry(entry, entry_acl_type,
-					    ae_perm, ae_tag,
-					    ae_id, ae_name);
-
-		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-		if (s == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get next ACL entry");
-			return (ARCHIVE_WARN);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-set_acl(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode,
-    int ae_requested_type, const char *tname)
-{
-	int		 acl_type = 0;
-	acl_t		 acl;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	acl_flagset_t	 acl_flagset;
-	int		 r;
-#endif
-	int		 ret;
-	int		 ae_type, ae_permset, ae_tag, ae_id;
-	int		 perm_map_size;
-	const acl_perm_map_t	*perm_map;
-	uid_t		 ae_uid;
-	gid_t		 ae_gid;
-	const char	*ae_name;
-	int		 entries;
-	int		 i;
-
-	ret = ARCHIVE_OK;
-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
-	if (entries == 0)
-		return (ARCHIVE_OK);
-
-
-	switch (ae_requested_type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-		acl_type = ACL_TYPE_ACCESS;
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-		acl_type = ACL_TYPE_DEFAULT;
-		break;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
-		acl_type = ACL_TYPE_NFS4;
-		break;
-#endif
-	default:
-		errno = ENOENT;
-		archive_set_error(a, errno, "Unsupported ACL type");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
-		errno = EINVAL;
-		archive_set_error(a, errno,
-		    "Cannot set default ACL on non-directory");
-		return (ARCHIVE_WARN);
-	}
-
-	acl = acl_init(entries);
-	if (acl == (acl_t)NULL) {
-		archive_set_error(a, errno,
-		    "Failed to initialize ACL working storage");
-		return (ARCHIVE_FAILED);
-	}
-
-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		if (acl_create_entry(&acl, &acl_entry) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to create a new ACL entry");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-		switch (ae_tag) {
-		case ARCHIVE_ENTRY_ACL_USER:
-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			acl_set_tag_type(acl_entry, ACL_USER);
-			acl_set_qualifier(acl_entry, &ae_uid);
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP:
-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			acl_set_tag_type(acl_entry, ACL_GROUP);
-			acl_set_qualifier(acl_entry, &ae_gid);
-			break;
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
-			break;
-		case ARCHIVE_ENTRY_ACL_MASK:
-			acl_set_tag_type(acl_entry, ACL_MASK);
-			break;
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			acl_set_tag_type(acl_entry, ACL_OTHER);
-			break;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		case ARCHIVE_ENTRY_ACL_EVERYONE:
-			acl_set_tag_type(acl_entry, ACL_EVERYONE);
-			break;
-#endif
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL tag");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		r = 0;
-		switch (ae_type) {
-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			r = acl_set_entry_type_np(acl_entry,
-			    ACL_ENTRY_TYPE_ALLOW);
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			r = acl_set_entry_type_np(acl_entry,
-			    ACL_ENTRY_TYPE_DENY);
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			r = acl_set_entry_type_np(acl_entry,
-			    ACL_ENTRY_TYPE_AUDIT);
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			r = acl_set_entry_type_np(acl_entry,
-			    ACL_ENTRY_TYPE_ALARM);
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-			// These don't translate directly into the system ACL.
-			break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL entry type");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		if (r != 0) {
-			archive_set_error(a, errno,
-			    "Failed to set ACL entry type");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-#endif
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to get ACL permission set");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-		if (acl_clear_perms(acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to clear ACL permissions");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			perm_map_size = acl_nfs4_perm_map_size;
-			perm_map = acl_nfs4_perm_map;
-		} else {
-#endif
-			perm_map_size = acl_posix_perm_map_size;
-			perm_map = acl_posix_perm_map;
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		}
-#endif
-
-		for (i = 0; i < perm_map_size; ++i) {
-			if (ae_permset & perm_map[i].a_perm) {
-				if (acl_add_perm(acl_permset,
-				    perm_map[i].p_perm) != 0) {
-					archive_set_error(a, errno,
-					    "Failed to add ACL permission");
-					ret = ARCHIVE_FAILED;
-					goto exit_free;
-				}
-			}
-		}
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/*
-			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
-			 */
-			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
-				archive_set_error(a, errno,
-				    "Failed to get flagset from an NFSv4 "
-				    "ACL entry");
-				ret = ARCHIVE_FAILED;
-				goto exit_free;
-			}
-			if (acl_clear_flags_np(acl_flagset) != 0) {
-				archive_set_error(a, errno,
-				    "Failed to clear flags from an NFSv4 "
-				    "ACL flagset");
-				ret = ARCHIVE_FAILED;
-				goto exit_free;
-			}
-			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
-					if (acl_add_flag_np(acl_flagset,
-					    acl_nfs4_flag_map[i].p_perm) != 0) {
-						archive_set_error(a, errno,
-						    "Failed to add flag to "
-						    "NFSv4 ACL flagset");
-						ret = ARCHIVE_FAILED;
-						goto exit_free;
-					}
-				}
-			}
-		}
-#endif
-	}
-
-	/* Try restoring the ACL through 'fd' if we can. */
-	if (fd >= 0) {
-		if (acl_set_fd_np(fd, acl, acl_type) == 0)
-			ret = ARCHIVE_OK;
-		else {
-			if (errno == EOPNOTSUPP) {
-				/* Filesystem doesn't support ACLs */
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(a, errno,
-				    "Failed to set acl on fd: %s", tname);
-				ret = ARCHIVE_WARN;
-			}
-		}
-	}
-#if HAVE_ACL_SET_LINK_NP
-	else if (acl_set_link_np(name, acl_type, acl) != 0)
-#else
-	/* FreeBSD older than 8.0 */
-	else if (S_ISLNK(mode)) {
-	    /* acl_set_file() follows symbolic links, skip */
-	    ret = ARCHIVE_OK;
-	} else if (acl_set_file(name, acl_type, acl) != 0)
-#endif
-	{
-		if (errno == EOPNOTSUPP) {
-			/* Filesystem doesn't support ACLs */
-			ret = ARCHIVE_OK;
-		} else {
-			archive_set_error(a, errno, "Failed to set acl: %s",
-			    tname);
-			ret = ARCHIVE_WARN;
-		}
-	}
-exit_free:
-	acl_free(acl);
-	return (ret);
-}
-
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	const char	*accpath;
-	acl_t		acl;
-	int		r;
-
-	accpath = NULL;
-
-	if (*fd < 0) {
-		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (accpath == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	archive_entry_acl_clear(entry);
-
-	acl = NULL;
-
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	/* Try NFSv4 ACL first. */
-	if (*fd >= 0)
-		acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
-	else if (!a->follow_symlinks)
-		acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
-	else
-		acl = acl_get_file(accpath, ACL_TYPE_NFS4);
-
-	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
-		acl_free(acl);
-		acl = NULL;
-		return (ARCHIVE_OK);
-	}
-
-	if (acl != NULL) {
-		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
-		acl_free(acl);
-		acl = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate NFSv4 ACLs");
-		}
-
-		return (r);
-	}
-#endif
-
-	/* Retrieve access ACL from file. */
-	if (*fd >= 0)
-		acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
-#if HAVE_ACL_GET_LINK_NP
-	else if (!a->follow_symlinks)
-		acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
-#else
-	else if ((!a->follow_symlinks)
-	    && (archive_entry_filetype(entry) == AE_IFLNK))
-		/* We can't get the ACL of a symlink, so we assume it can't
-		   have one. */
-		acl = NULL;
-#endif
-	else
-		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
-
-#if HAVE_ACL_IS_TRIVIAL_NP
-	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
-		acl_free(acl);
-		acl = NULL;
-	}
-#endif
-
-	if (acl != NULL) {
-		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
-		acl_free(acl);
-		acl = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate access ACLs");
-			return (r);
-		}
-	}
-
-	/* Only directories can have default ACLs. */
-	if (S_ISDIR(archive_entry_mode(entry))) {
-		if (*fd >= 0)
-			acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
-		else
-			acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
-		if (acl != NULL) {
-			r = translate_acl(a, entry, acl,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
-			acl_free(acl);
-			if (r != ARCHIVE_OK) {
-				archive_set_error(&a->archive, errno,
-				    "Couldn't translate default ACLs");
-				return (r);
-			}
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode)
-{
-	int		ret = ARCHIVE_OK;
-
-	(void)mode;	/* UNUSED */
-
-	if ((archive_acl_types(abstract_acl)
-	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
-		if ((archive_acl_types(abstract_acl)
-		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-			ret = set_acl(a, fd, name, abstract_acl, mode,
-			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
-			if (ret != ARCHIVE_OK)
-				return (ret);
-		}
-		if ((archive_acl_types(abstract_acl)
-		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-			ret = set_acl(a, fd, name, abstract_acl, mode,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
-
-		/* Simultaneous POSIX.1e and NFSv4 is not supported */
-		return (ret);
-	}
-#if ARCHIVE_ACL_FREEBSD_NFS4
-	else if ((archive_acl_types(abstract_acl) &
-	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-		ret = set_acl(a, fd, name, abstract_acl, mode,
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
-	}
-#endif
-	return (ret);
-}
-#endif	/* ARCHIVE_ACL_FREEBSD */
diff --git a/c/archive_disk_acl_linux.c b/c/archive_disk_acl_linux.c
deleted file mode 100644
--- a/c/archive_disk_acl_linux.c
+++ /dev/null
@@ -1,760 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_ACL_LIBACL_H
-#include <acl/libacl.h>
-#endif
-#ifdef HAVE_SYS_ACL_H
-#include <sys/acl.h>
-#endif
-#ifdef HAVE_SYS_RICHACL_H
-#include <sys/richacl.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-#include "archive_write_disk_private.h"
-
-typedef struct {
-	const int a_perm;	/* Libarchive permission or flag */
-	const int p_perm;	/* Platform permission or flag */
-} acl_perm_map_t;
-
-#if ARCHIVE_ACL_LIBACL
-static const acl_perm_map_t acl_posix_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
-	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-};
-
-static const int acl_posix_perm_map_size =
-    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
-#endif /* ARCHIVE_ACL_LIBACL */
-
-#if ARCHIVE_ACL_LIBRICHACL
-static const acl_perm_map_t acl_nfs4_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
-	{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
-};
-
-static const int acl_nfs4_perm_map_size =
-    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
-
-static const acl_perm_map_t acl_nfs4_flag_map[] = {
-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
-};
-
-static const int acl_nfs4_flag_map_size =
-    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
-#endif /* ARCHIVE_ACL_LIBRICHACL */
-
-#if ARCHIVE_ACL_LIBACL
-/*
- * Translate POSIX.1e ACLs into libarchive internal structure
- */
-static int
-translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
-{
-	acl_tag_t	 acl_tag;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-	int		 i, entry_acl_type;
-	int		 r, s, ae_id, ae_tag, ae_perm;
-	void		*q;
-	const char	*ae_name;
-
-	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
-	if (s == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to get first ACL entry");
-		return (ARCHIVE_WARN);
-	}
-
-	while (s == 1) {
-		ae_id = -1;
-		ae_name = NULL;
-		ae_perm = 0;
-
-		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL tag type");
-			return (ARCHIVE_WARN);
-		}
-		switch (acl_tag) {
-		case ACL_USER:
-			q = acl_get_qualifier(acl_entry);
-			if (q != NULL) {
-				ae_id = (int)*(uid_t *)q;
-				acl_free(q);
-				ae_name = archive_read_disk_uname(&a->archive,
-				    ae_id);
-			}
-			ae_tag = ARCHIVE_ENTRY_ACL_USER;
-			break;
-		case ACL_GROUP:
-			q = acl_get_qualifier(acl_entry);
-			if (q != NULL) {
-				ae_id = (int)*(gid_t *)q;
-				acl_free(q);
-				ae_name = archive_read_disk_gname(&a->archive,
-				    ae_id);
-			}
-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-			break;
-		case ACL_MASK:
-			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
-			break;
-		case ACL_USER_OBJ:
-			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-			break;
-		case ACL_GROUP_OBJ:
-			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-			break;
-		case ACL_OTHER:
-			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
-			break;
-		default:
-			/* Skip types that libarchive can't support. */
-			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-			continue;
-		}
-
-		// XXX acl_type maps to allow/deny/audit/YYYY bits
-		entry_acl_type = default_entry_acl_type;
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get ACL permission set");
-			return (ARCHIVE_WARN);
-		}
-
-		for (i = 0; i < acl_posix_perm_map_size; ++i) {
-			r = acl_get_perm(acl_permset,
-			    acl_posix_perm_map[i].p_perm);
-			if (r == -1) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to check permission in an ACL "
-				    "permission set");
-				return (ARCHIVE_WARN);
-			} else if (r)
-				ae_perm |= acl_posix_perm_map[i].a_perm;
-		}
-
-		archive_entry_acl_add_entry(entry, entry_acl_type,
-					    ae_perm, ae_tag,
-					    ae_id, ae_name);
-
-		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
-		if (s == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get next ACL entry");
-			return (ARCHIVE_WARN);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-#endif /* ARCHIVE_ACL_LIBACL */
-
-#if ARCHIVE_ACL_LIBRICHACL
-/*
- * Translate RichACL into libarchive internal ACL
- */
-static int
-translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,
-    struct richacl *richacl)
-{
-	int ae_id, ae_tag, ae_perm;
-	int entry_acl_type, i;
-	const char *ae_name;
-
-	struct richace *richace;
-
-	richacl_for_each_entry(richace, richacl) {
-		ae_name = NULL;
-		ae_tag = 0;
-		ae_perm = 0;
-		ae_id = -1;
-
-		switch (richace->e_type) {
-		case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-			break;
-		case RICHACE_ACCESS_DENIED_ACE_TYPE:
-			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-			break;
-		default: /* Unknown entry type, skip */
-			continue;
-		}
-
-		/* Unsupported */
-		if (richace->e_flags & RICHACE_UNMAPPED_WHO)
-			continue;
-
-		if (richace->e_flags & RICHACE_SPECIAL_WHO) {
-			switch (richace->e_id) {
-			case RICHACE_OWNER_SPECIAL_ID:
-				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				break;
-			case RICHACE_GROUP_SPECIAL_ID:
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case RICHACE_EVERYONE_SPECIAL_ID:
-				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
-				break;
-			default: /* Unknown special ID type */
-				continue;
-			}
-		} else {
-			ae_id = richace->e_id;
-			if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-				ae_name = archive_read_disk_gname(&a->archive,
-				    (gid_t)(richace->e_id));
-			} else {
-				ae_tag = ARCHIVE_ENTRY_ACL_USER;
-				ae_name = archive_read_disk_uname(&a->archive,
-				    (uid_t)(richace->e_id));
-			}
-		}
-		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-			if ((richace->e_flags &
-			    acl_nfs4_flag_map[i].p_perm) != 0)
-				ae_perm |= acl_nfs4_flag_map[i].a_perm;
-		}
-		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
-			if ((richace->e_mask &
-			    acl_nfs4_perm_map[i].p_perm) != 0)
-				ae_perm |=
-				    acl_nfs4_perm_map[i].a_perm;
-		}
-
-		archive_entry_acl_add_entry(entry, entry_acl_type,
-		    ae_perm, ae_tag, ae_id, ae_name);
-	}
-	return (ARCHIVE_OK);
-}
-#endif	/* ARCHIVE_ACL_LIBRICHACL */
-
-#if ARCHIVE_ACL_LIBRICHACL
-static int
-_richacl_mode_to_mask(short mode)
-{
-	int mask = 0;
-
-	if (mode & S_IROTH)
-		mask |= RICHACE_POSIX_MODE_READ;
-	if (mode & S_IWOTH)
-		mask |= RICHACE_POSIX_MODE_WRITE;
-	if (mode & S_IXOTH)
-		mask |= RICHACE_POSIX_MODE_EXEC;
-
-	return (mask);
-}
-
-static void
-_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)
-{
-	richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);
-	richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);
-	richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);
-}
-#endif /* ARCHIVE_ACL_LIBRICHACL */
-
-#if ARCHIVE_ACL_LIBRICHACL
-static int
-set_richacl(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode,
-    int ae_requested_type, const char *tname)
-{
-	int		 ae_type, ae_permset, ae_tag, ae_id;
-	uid_t		 ae_uid;
-	gid_t		 ae_gid;
-	const char	*ae_name;
-	int		 entries;
-	int		 i;
-	int		 ret;
-	int		 e = 0;
-	struct richacl  *richacl = NULL;
-	struct richace  *richace;
-
-	ret = ARCHIVE_OK;
-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
-	if (entries == 0)
-		return (ARCHIVE_OK);
-
-	if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-		errno = ENOENT;
-		archive_set_error(a, errno, "Unsupported ACL type");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (S_ISLNK(mode)) {
-		/* Linux does not support RichACLs on symbolic links */
-		return (ARCHIVE_OK);
-	}
-
-	richacl = richacl_alloc(entries);
-	if (richacl == NULL) {
-		archive_set_error(a, errno,
-			"Failed to initialize RichACL working storage");
-		return (ARCHIVE_FAILED);
-	}
-
-	e = 0;
-
-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		richace = &(richacl->a_entries[e]);
-
-		richace->e_flags = 0;
-		richace->e_mask = 0;
-
-		switch (ae_tag) {
-		case ARCHIVE_ENTRY_ACL_USER:
-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			richace->e_id = ae_uid;
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP:
-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			richace->e_id = ae_gid;
-			richace->e_flags |= RICHACE_IDENTIFIER_GROUP;
-			break;
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			richace->e_flags |= RICHACE_SPECIAL_WHO;
-			richace->e_id = RICHACE_OWNER_SPECIAL_ID;
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			richace->e_flags |= RICHACE_SPECIAL_WHO;
-			richace->e_id = RICHACE_GROUP_SPECIAL_ID;
-			break;
-		case ARCHIVE_ENTRY_ACL_EVERYONE:
-			richace->e_flags |= RICHACE_SPECIAL_WHO;
-			richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;
-			break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL tag");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		switch (ae_type) {
-			case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-				richace->e_type =
-				    RICHACE_ACCESS_ALLOWED_ACE_TYPE;
-				break;
-			case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-				richace->e_type =
-				    RICHACE_ACCESS_DENIED_ACE_TYPE;
-				break;
-			case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-				break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL entry type");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
-			if (ae_permset & acl_nfs4_perm_map[i].a_perm)
-				richace->e_mask |= acl_nfs4_perm_map[i].p_perm;
-		}
-
-		for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-			if (ae_permset &
-			    acl_nfs4_flag_map[i].a_perm)
-				richace->e_flags |= acl_nfs4_flag_map[i].p_perm;
-		}
-	e++;
-	}
-
-	/* Fill RichACL masks */
-	_richacl_mode_to_masks(richacl, mode);
-
-	if (fd >= 0) {
-		if (richacl_set_fd(fd, richacl) == 0)
-			ret = ARCHIVE_OK;
-		else {
-			if (errno == EOPNOTSUPP) {
-				/* Filesystem doesn't support ACLs */
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(a, errno,
-				    "Failed to set richacl on fd: %s", tname);
-				ret = ARCHIVE_WARN;
-			}
-		}
-	} else if (richacl_set_file(name, richacl) != 0) {
-		if (errno == EOPNOTSUPP) {
-			/* Filesystem doesn't support ACLs */
-			ret = ARCHIVE_OK;
-		} else {
-			archive_set_error(a, errno, "Failed to set richacl: %s",
-			    tname);
-			ret = ARCHIVE_WARN;
-		}
-	}
-exit_free:
-	richacl_free(richacl);
-	return (ret);
-}
-#endif /* ARCHIVE_ACL_RICHACL */
-
-#if ARCHIVE_ACL_LIBACL
-static int
-set_acl(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode,
-    int ae_requested_type, const char *tname)
-{
-	int		 acl_type = 0;
-	int		 ae_type, ae_permset, ae_tag, ae_id;
-	uid_t		 ae_uid;
-	gid_t		 ae_gid;
-	const char	*ae_name;
-	int		 entries;
-	int		 i;
-	int		 ret;
-	acl_t		 acl = NULL;
-	acl_entry_t	 acl_entry;
-	acl_permset_t	 acl_permset;
-
-	ret = ARCHIVE_OK;
-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
-	if (entries == 0)
-		return (ARCHIVE_OK);
-
-	switch (ae_requested_type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-		acl_type = ACL_TYPE_ACCESS;
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-		acl_type = ACL_TYPE_DEFAULT;
-		break;
-	default:
-		errno = ENOENT;
-		archive_set_error(a, errno, "Unsupported ACL type");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (S_ISLNK(mode)) {
-		/* Linux does not support ACLs on symbolic links */
-		return (ARCHIVE_OK);
-	}
-
-	if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
-		errno = EINVAL;
-		archive_set_error(a, errno,
-		    "Cannot set default ACL on non-directory");
-		return (ARCHIVE_WARN);
-	}
-
-	acl = acl_init(entries);
-	if (acl == (acl_t)NULL) {
-		archive_set_error(a, errno,
-		    "Failed to initialize ACL working storage");
-		return (ARCHIVE_FAILED);
-	}
-
-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-
-		if (acl_create_entry(&acl, &acl_entry) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to create a new ACL entry");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		switch (ae_tag) {
-		case ARCHIVE_ENTRY_ACL_USER:
-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			acl_set_tag_type(acl_entry, ACL_USER);
-			acl_set_qualifier(acl_entry, &ae_uid);
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP:
-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			acl_set_tag_type(acl_entry, ACL_GROUP);
-			acl_set_qualifier(acl_entry, &ae_gid);
-			break;
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
-			break;
-		case ARCHIVE_ENTRY_ACL_MASK:
-			acl_set_tag_type(acl_entry, ACL_MASK);
-			break;
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			acl_set_tag_type(acl_entry, ACL_OTHER);
-			break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL tag");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to get ACL permission set");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-		if (acl_clear_perms(acl_permset) != 0) {
-			archive_set_error(a, errno,
-			    "Failed to clear ACL permissions");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		for (i = 0; i < acl_posix_perm_map_size; ++i) {
-			if (ae_permset & acl_posix_perm_map[i].a_perm) {
-				if (acl_add_perm(acl_permset,
-				    acl_posix_perm_map[i].p_perm) != 0) {
-					archive_set_error(a, errno,
-					    "Failed to add ACL permission");
-					ret = ARCHIVE_FAILED;
-					goto exit_free;
-				}
-			}
-		}
-
-	}
-
-	if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
-		if (acl_set_fd(fd, acl) == 0)
-			ret = ARCHIVE_OK;
-		else {
-			if (errno == EOPNOTSUPP) {
-				/* Filesystem doesn't support ACLs */
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(a, errno,
-				    "Failed to set acl on fd: %s", tname);
-				ret = ARCHIVE_WARN;
-			}
-		}
-	} else if (acl_set_file(name, acl_type, acl) != 0) {
-		if (errno == EOPNOTSUPP) {
-			/* Filesystem doesn't support ACLs */
-			ret = ARCHIVE_OK;
-		} else {
-			archive_set_error(a, errno, "Failed to set acl: %s",
-			    tname);
-			ret = ARCHIVE_WARN;
-		}
-	}
-exit_free:
-	acl_free(acl);
-	return (ret);
-}
-#endif /* ARCHIVE_ACL_LIBACL */
-
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	const char	*accpath;
-	int		r;
-#if ARCHIVE_ACL_LIBACL
-	acl_t		acl;
-#endif
-#if ARCHIVE_ACL_LIBRICHACL
-	struct richacl *richacl;
-	mode_t		mode;
-#endif
-
-	accpath = NULL;
-	r = ARCHIVE_OK;
-
-	/* For default ACLs we need reachable accpath */
-	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
-		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (accpath == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	archive_entry_acl_clear(entry);
-
-#if ARCHIVE_ACL_LIBACL
-	acl = NULL;
-#endif
-#if ARCHIVE_ACL_LIBRICHACL
-	richacl = NULL;
-#endif
-
-#if ARCHIVE_ACL_LIBRICHACL
-	/* Try NFSv4 ACL first. */
-	if (*fd >= 0)
-		richacl = richacl_get_fd(*fd);
-	else if ((!a->follow_symlinks)
-	    && (archive_entry_filetype(entry) == AE_IFLNK))
-		/* We can't get the ACL of a symlink, so we assume it can't
-		   have one */
-		richacl = NULL;
-	else
-		richacl = richacl_get_file(accpath);
-
-	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	if (richacl != NULL) {
-		mode = archive_entry_mode(entry);
-		if (richacl_equiv_mode(richacl, &mode) == 0) {
-			richacl_free(richacl);
-			richacl = NULL;
-			return (ARCHIVE_OK);
-		}
-	}
-
-	if (richacl != NULL) {
-		r = translate_richacl(a, entry, richacl);
-		richacl_free(richacl);
-		richacl = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			"Couldn't translate NFSv4 ACLs");
-		}
-
-		return (r);
-	}
-#endif	/* ARCHIVE_ACL_LIBRICHACL */
-
-#if ARCHIVE_ACL_LIBACL
-	/* Retrieve access ACL from file. */
-	if (*fd >= 0)
-		acl = acl_get_fd(*fd);
-	else if ((!a->follow_symlinks)
-	    && (archive_entry_filetype(entry) == AE_IFLNK))
-		/* We can't get the ACL of a symlink, so we assume it can't
-		   have one. */
-		acl = NULL;
-	else
-		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
-
-	if (acl != NULL) {
-		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
-		acl_free(acl);
-		acl = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate access ACLs");
-			return (r);
-		}
-	}
-
-	/* Only directories can have default ACLs. */
-	if (S_ISDIR(archive_entry_mode(entry))) {
-		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
-		if (acl != NULL) {
-			r = translate_acl(a, entry, acl,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
-			acl_free(acl);
-			if (r != ARCHIVE_OK) {
-				archive_set_error(&a->archive, errno,
-				    "Couldn't translate default ACLs");
-				return (r);
-			}
-		}
-	}
-#endif	/* ARCHIVE_ACL_LIBACL */
-	return (r);
-}
-
-int
-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode)
-{
-	int		ret = ARCHIVE_OK;
-
-#if !ARCHIVE_ACL_LIBRICHACL
-	(void)mode;	/* UNUSED */
-#endif
-
-#if ARCHIVE_ACL_LIBRICHACL
-	if ((archive_acl_types(abstract_acl)
-	    & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-		ret = set_richacl(a, fd, name, abstract_acl, mode,
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
-	}
-#if ARCHIVE_ACL_LIBACL
-	else
-#endif
-#endif	/* ARCHIVE_ACL_LIBRICHACL */
-#if ARCHIVE_ACL_LIBACL
-	if ((archive_acl_types(abstract_acl)
-	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
-		if ((archive_acl_types(abstract_acl)
-		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-			ret = set_acl(a, fd, name, abstract_acl, mode,
-			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
-			if (ret != ARCHIVE_OK)
-				return (ret);
-		}
-		if ((archive_acl_types(abstract_acl)
-		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-			ret = set_acl(a, fd, name, abstract_acl, mode,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
-	}
-#endif	/* ARCHIVE_ACL_LIBACL */
-	return (ret);
-}
-#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */
diff --git a/c/archive_disk_acl_sunos.c b/c/archive_disk_acl_sunos.c
deleted file mode 100644
--- a/c/archive_disk_acl_sunos.c
+++ /dev/null
@@ -1,824 +0,0 @@
-/*-
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#if ARCHIVE_ACL_SUNOS
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_ACL_H
-#define _ACL_PRIVATE /* For debugging */
-#include <sys/acl.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-#include "archive_write_disk_private.h"
-
-typedef struct {
-	const int a_perm;	/* Libarchive permission or flag */
-	const int p_perm;	/* Platform permission or flag */
-} acl_perm_map_t;
-
-static const acl_perm_map_t acl_posix_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
-	{ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
-	{ARCHIVE_ENTRY_ACL_READ, S_IROTH }
-};
-
-static const int acl_posix_perm_map_size =
-    (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-static const acl_perm_map_t acl_nfs4_perm_map[] = {
-	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
-	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
-	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
-	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
-	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
-	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
-	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
-	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
-	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
-	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
-	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
-	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
-	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
-};
-
-static const int acl_nfs4_perm_map_size =
-    (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
-
-static const acl_perm_map_t acl_nfs4_flag_map[] = {
-	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
-	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
-	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
-#ifdef ACE_INHERITED_ACE
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
-#endif
-};
-
-const int acl_nfs4_flag_map_size =
-    (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
-
-#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
-
-static void *
-sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
-{
-	int cnt, cntcmd;
-	size_t size;
-	void *aclp;
-
-	if (cmd == GETACL) {
-		cntcmd = GETACLCNT;
-		size = sizeof(aclent_t);
-	}
-#if ARCHIVE_ACL_SUNOS_NFS4
-	else if (cmd == ACE_GETACL) {
-		cntcmd = ACE_GETACLCNT;
-		size = sizeof(ace_t);
-	}
-#endif
-	else {
-		errno = EINVAL;
-		*aclcnt = -1;
-		return (NULL);
-	}
-
-	aclp = NULL;
-	cnt = -2;
-
-	while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
-		if (path != NULL)
-			cnt = acl(path, cntcmd, 0, NULL);
-		else
-			cnt = facl(fd, cntcmd, 0, NULL);
-
-		if (cnt > 0) {
-			if (aclp == NULL)
-				aclp = malloc(cnt * size);
-			else
-				aclp = realloc(NULL, cnt * size);
-			if (aclp != NULL) {
-				if (path != NULL)
-					cnt = acl(path, cmd, cnt, aclp);
-				else
-					cnt = facl(fd, cmd, cnt, aclp);
-			}
-		} else {
-			free(aclp);
-			aclp = NULL;
-			break;
-		}
-	}
-
-	*aclcnt = cnt;
-	return (aclp);
-}
-
-/*
- * Check if acl is trivial
- * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
- */
-static int
-sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
-    int is_dir, int *trivialp)
-{
-#if ARCHIVE_ACL_SUNOS_NFS4
-	int i, p;
-	const uint32_t rperm = ACE_READ_DATA;
-	const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
-	const uint32_t eperm = ACE_EXECUTE;
-	const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
-	    ACE_READ_ACL | ACE_SYNCHRONIZE;
-	const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
-	    ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
-
-	ace_t *ace;
-	ace_t tace[6];
-#endif
-
-	if (aclp == NULL || trivialp == NULL)
-		return (-1);
-
-	*trivialp = 0;
-
-	/*
-	 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
-	 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
-	 * including mask.
-	 */
-	if (!is_nfs4) {
-		if (aclcnt == 4)
-			*trivialp = 1;
-		return (0);
-	}
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-	/*
-	 * Continue with checking NFSv4 ACLs
-	 *
-	 * Create list of trivial ace's to be compared
-	 */
-
-	/* owner@ allow pre */
-	tace[0].a_flags = ACE_OWNER;
-	tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
-	tace[0].a_access_mask = 0;
-
-	/* owner@ deny */
-	tace[1].a_flags = ACE_OWNER;
-	tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
-	tace[1].a_access_mask = 0;
-
-	/* group@ deny */
-	tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
-	tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
-	tace[2].a_access_mask = 0;
-
-	/* owner@ allow */
-	tace[3].a_flags = ACE_OWNER;
-	tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
-	tace[3].a_access_mask = ownset;
-
-	/* group@ allow */
-	tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
-	tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
-	tace[4].a_access_mask = pubset;
-
-	/* everyone@ allow */
-	tace[5].a_flags = ACE_EVERYONE;
-	tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
-	tace[5].a_access_mask = pubset;
-
-	/* Permissions for everyone@ */
-	if (mode & 0004)
-		tace[5].a_access_mask |= rperm;
-	if (mode & 0002)
-		tace[5].a_access_mask |= wperm;
-	if (mode & 0001)
-		tace[5].a_access_mask |= eperm;
-
-	/* Permissions for group@ */
-	if (mode & 0040)
-		tace[4].a_access_mask |= rperm;
-	else if (mode & 0004)
-		tace[2].a_access_mask |= rperm;
-	if (mode & 0020)
-		tace[4].a_access_mask |= wperm;
-	else if (mode & 0002)
-		tace[2].a_access_mask |= wperm;
-	if (mode & 0010)
-		tace[4].a_access_mask |= eperm;
-	else if (mode & 0001)
-		tace[2].a_access_mask |= eperm;
-
-	/* Permissions for owner@ */
-	if (mode & 0400) {
-		tace[3].a_access_mask |= rperm;
-		if (!(mode & 0040) && (mode & 0004))
-			tace[0].a_access_mask |= rperm;
-	} else if ((mode & 0040) || (mode & 0004))
-		tace[1].a_access_mask |= rperm;
-	if (mode & 0200) {
-		tace[3].a_access_mask |= wperm;
-		if (!(mode & 0020) && (mode & 0002))
-			tace[0].a_access_mask |= wperm;
-	} else if ((mode & 0020) || (mode & 0002))
-		tace[1].a_access_mask |= wperm;
-	if (mode & 0100) {
-		tace[3].a_access_mask |= eperm;
-		if (!(mode & 0010) && (mode & 0001))
-			tace[0].a_access_mask |= eperm;
-	} else if ((mode & 0010) || (mode & 0001))
-		tace[1].a_access_mask |= eperm;
-
-	/* Check if the acl count matches */
-	p = 3;
-	for (i = 0; i < 3; i++) {
-		if (tace[i].a_access_mask != 0)
-			p++;
-	}
-	if (aclcnt != p)
-		return (0);
-
-	p = 0;
-	for (i = 0; i < 6; i++) {
-		if (tace[i].a_access_mask != 0) {
-			ace = &((ace_t *)aclp)[p];
-			/*
-			 * Illumos added ACE_DELETE_CHILD to write perms for
-			 * directories. We have to check against that, too.
-			 */
-			if (ace->a_flags != tace[i].a_flags ||
-			    ace->a_type != tace[i].a_type ||
-			    (ace->a_access_mask != tace[i].a_access_mask &&
-			    (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
-			    ace->a_access_mask !=
-			    (tace[i].a_access_mask | ACE_DELETE_CHILD))))
-				return (0);
-			p++;
-		}
-	}
-
-	*trivialp = 1;
-#else	/* !ARCHIVE_ACL_SUNOS_NFS4 */
-	(void)is_dir;	/* UNUSED */
-	(void)aclp;	/* UNUSED */
-#endif	/* !ARCHIVE_ACL_SUNOS_NFS4 */
-	return (0);
-}
-
-/*
- * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
- */
-static int
-translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, void *aclp, int aclcnt,
-    int default_entry_acl_type)
-{
-	int e, i;
-	int ae_id, ae_tag, ae_perm;
-	int entry_acl_type;
-	const char *ae_name;
-	aclent_t *aclent;
-#if ARCHIVE_ACL_SUNOS_NFS4
-	ace_t *ace;
-#endif
-
-	if (aclcnt <= 0)
-		return (ARCHIVE_OK);
-
-	for (e = 0; e < aclcnt; e++) {
-		ae_name = NULL;
-		ae_tag = 0;
-		ae_perm = 0;
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-		if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			ace = &((ace_t *)aclp)[e];
-			ae_id = ace->a_who;
-
-			switch(ace->a_type) {
-			case ACE_ACCESS_ALLOWED_ACE_TYPE:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
-				break;
-			case ACE_ACCESS_DENIED_ACE_TYPE:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
-				break;
-			case ACE_SYSTEM_AUDIT_ACE_TYPE:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-				break;
-			case ACE_SYSTEM_ALARM_ACE_TYPE:
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
-				break;
-			default:
-				/* Unknown entry type, skip */
-				continue;
-			}
-
-			if ((ace->a_flags & ACE_OWNER) != 0)
-				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-			else if ((ace->a_flags & ACE_GROUP) != 0)
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-			else if ((ace->a_flags & ACE_EVERYONE) != 0)
-				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
-			else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-				ae_name = archive_read_disk_gname(&a->archive,
-				    ae_id);
-			} else {
-				ae_tag = ARCHIVE_ENTRY_ACL_USER;
-				ae_name = archive_read_disk_uname(&a->archive,
-				    ae_id);
-			}
-
-			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-				if ((ace->a_flags &
-				    acl_nfs4_flag_map[i].p_perm) != 0)
-					ae_perm |= acl_nfs4_flag_map[i].a_perm;
-			}
-
-			for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
-				if ((ace->a_access_mask &
-				    acl_nfs4_perm_map[i].p_perm) != 0)
-					ae_perm |= acl_nfs4_perm_map[i].a_perm;
-			}
-		} else
-#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
-		if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
-			aclent = &((aclent_t *)aclp)[e];
-			if ((aclent->a_type & ACL_DEFAULT) != 0)
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-			else
-				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-			ae_id = aclent->a_id;
-
-			switch(aclent->a_type) {
-			case DEF_USER:
-			case USER:
-				ae_name = archive_read_disk_uname(&a->archive,
-				    ae_id);
-				ae_tag = ARCHIVE_ENTRY_ACL_USER;
-				break;
-			case DEF_GROUP:
-			case GROUP:
-				ae_name = archive_read_disk_gname(&a->archive,
-				    ae_id);
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
-				break;
-			case DEF_CLASS_OBJ:
-			case CLASS_OBJ:
-				ae_tag = ARCHIVE_ENTRY_ACL_MASK;
-				break;
-			case DEF_USER_OBJ:
-			case USER_OBJ:
-				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-				break;
-			case DEF_GROUP_OBJ:
-			case GROUP_OBJ:
-				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-				break;
-			case DEF_OTHER_OBJ:
-			case OTHER_OBJ:
-				ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
-				break;
-			default:
-				/* Unknown tag type, skip */
-				continue;
-			}
-
-			for (i = 0; i < acl_posix_perm_map_size; ++i) {
-				if ((aclent->a_perm &
-				    acl_posix_perm_map[i].p_perm) != 0)
-					ae_perm |= acl_posix_perm_map[i].a_perm;
-			}
-		} else
-			return (ARCHIVE_WARN);
-
-		archive_entry_acl_add_entry(entry, entry_acl_type,
-		    ae_perm, ae_tag, ae_id, ae_name);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-set_acl(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode,
-    int ae_requested_type, const char *tname)
-{
-	aclent_t	 *aclent;
-#if ARCHIVE_ACL_SUNOS_NFS4
-	ace_t		 *ace;
-#endif
-	int		 cmd, e, r;
-	void		 *aclp;
-	int		 ret;
-	int		 ae_type, ae_permset, ae_tag, ae_id;
-	int		 perm_map_size;
-	const acl_perm_map_t	*perm_map;
-	uid_t		 ae_uid;
-	gid_t		 ae_gid;
-	const char	*ae_name;
-	int		 entries;
-	int		 i;
-
-	ret = ARCHIVE_OK;
-	entries = archive_acl_reset(abstract_acl, ae_requested_type);
-	if (entries == 0)
-		return (ARCHIVE_OK);
-
-	switch (ae_requested_type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
-		cmd = SETACL;
-		aclp = malloc(entries * sizeof(aclent_t));
-		break;
-#if ARCHIVE_ACL_SUNOS_NFS4
-	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
-		cmd = ACE_SETACL;
-		aclp = malloc(entries * sizeof(ace_t));
-
-		break;
-#endif
-	default:
-		errno = ENOENT;
-		archive_set_error(a, errno, "Unsupported ACL type");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (aclp == NULL) {
-		archive_set_error(a, errno,
-		    "Can't allocate memory for acl buffer");
-		return (ARCHIVE_FAILED);
-	}
-
-        if (S_ISLNK(mode)) {
-                /* Skip ACLs on symbolic links */
-		ret = ARCHIVE_OK;
-		goto exit_free;
-        }
-
-	e = 0;
-
-	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
-		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		aclent = NULL;
-#if ARCHIVE_ACL_SUNOS_NFS4
-		ace = NULL;
-#endif
-		if (cmd == SETACL) {
-			aclent = &((aclent_t *)aclp)[e];
-			aclent->a_id = -1;
-			aclent->a_type = 0;
-			aclent->a_perm = 0;
-		}
-#if ARCHIVE_ACL_SUNOS_NFS4
-		else {	/* cmd == ACE_SETACL */
-			ace = &((ace_t *)aclp)[e];
-			ace->a_who = -1;
-			ace->a_access_mask = 0;
-			ace->a_flags = 0;
-		}
-#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
-
-		switch (ae_tag) {
-		case ARCHIVE_ENTRY_ACL_USER:
-			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			if (aclent != NULL) {
-				aclent->a_id = ae_uid;
-				aclent->a_type |= USER;
-			}
-#if ARCHIVE_ACL_SUNOS_NFS4
-			else {
-				ace->a_who = ae_uid;
-			}
-#endif
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP:
-			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			if (aclent != NULL) {
-				aclent->a_id = ae_gid;
-				aclent->a_type |= GROUP;
-			}
-#if ARCHIVE_ACL_SUNOS_NFS4
-			else {
-				ace->a_who = ae_gid;
-				ace->a_flags |= ACE_IDENTIFIER_GROUP;
-			}
-#endif
-			break;
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			if (aclent != NULL)
-				aclent->a_type |= USER_OBJ;
-#if ARCHIVE_ACL_SUNOS_NFS4
-			else {
-				ace->a_flags |= ACE_OWNER;
-			}
-#endif
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			if (aclent != NULL)
-				aclent->a_type |= GROUP_OBJ;
-#if ARCHIVE_ACL_SUNOS_NFS4
-			else {
-				ace->a_flags |= ACE_GROUP;
-				ace->a_flags |= ACE_IDENTIFIER_GROUP;
-			}
-#endif
-			break;
-		case ARCHIVE_ENTRY_ACL_MASK:
-			if (aclent != NULL)
-				aclent->a_type |= CLASS_OBJ;
-			break;
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			if (aclent != NULL)
-				aclent->a_type |= OTHER_OBJ;
-			break;
-#if ARCHIVE_ACL_SUNOS_NFS4
-		case ARCHIVE_ENTRY_ACL_EVERYONE:
-			if (ace != NULL)
-				ace->a_flags |= ACE_EVERYONE;
-			break;
-#endif
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL tag");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		r = 0;
-		switch (ae_type) {
-#if ARCHIVE_ACL_SUNOS_NFS4
-		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			if (ace != NULL)
-				ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
-			else
-				r = -1;
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			if (ace != NULL)
-				ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
-			else
-				r = -1;
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			if (ace != NULL)
-				ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
-			else
-				r = -1;
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			if (ace != NULL)
-				ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
-			else
-				r = -1;
-			break;
-#endif
-		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-			if (aclent == NULL)
-				r = -1;
-			break;
-		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-			if (aclent != NULL)
-				aclent->a_type |= ACL_DEFAULT;
-			else
-				r = -1;
-			break;
-		default:
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unsupported ACL entry type");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-		if (r != 0) {
-			errno = EINVAL;
-			archive_set_error(a, errno,
-			    "Failed to set ACL entry type");
-			ret = ARCHIVE_FAILED;
-			goto exit_free;
-		}
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			perm_map_size = acl_nfs4_perm_map_size;
-			perm_map = acl_nfs4_perm_map;
-		} else {
-#endif
-			perm_map_size = acl_posix_perm_map_size;
-			perm_map = acl_posix_perm_map;
-#if ARCHIVE_ACL_SUNOS_NFS4
-		}
-#endif
-		for (i = 0; i < perm_map_size; ++i) {
-			if (ae_permset & perm_map[i].a_perm) {
-#if ARCHIVE_ACL_SUNOS_NFS4
-				if (ae_requested_type ==
-				    ARCHIVE_ENTRY_ACL_TYPE_NFS4)
-					ace->a_access_mask |=
-					    perm_map[i].p_perm;
-				else
-#endif
-					aclent->a_perm |= perm_map[i].p_perm;
-			}
-		}
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
-				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
-					ace->a_flags |=
-					    acl_nfs4_flag_map[i].p_perm;
-				}
-			}
-		}
-#endif
-	e++;
-	}
-
-	/* Try restoring the ACL through 'fd' if we can. */
-	if (fd >= 0) {
-		if (facl(fd, cmd, entries, aclp) == 0)
-			ret = ARCHIVE_OK;
-		else {
-			if (errno == EOPNOTSUPP) {
-				/* Filesystem doesn't support ACLs */
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(a, errno,
-				    "Failed to set acl on fd: %s", tname);
-				ret = ARCHIVE_WARN;
-			}
-		}
-	} else if (acl(name, cmd, entries, aclp) != 0) {
-		if (errno == EOPNOTSUPP) {
-			/* Filesystem doesn't support ACLs */
-			ret = ARCHIVE_OK;
-		} else {
-			archive_set_error(a, errno, "Failed to set acl: %s",
-			    tname);
-			ret = ARCHIVE_WARN;
-		}
-	}
-exit_free:
-	free(aclp);
-	return (ret);
-}
-
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	const char	*accpath;
-	void		*aclp;
-	int		aclcnt;
-	int		r;
-
-	accpath = NULL;
-
-	if (*fd < 0) {
-		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (accpath == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	archive_entry_acl_clear(entry);
-
-	aclp = NULL;
-
-#if ARCHIVE_ACL_SUNOS_NFS4
-	if (*fd >= 0)
-		aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
-	else if ((!a->follow_symlinks)
-	    && (archive_entry_filetype(entry) == AE_IFLNK))
-		/* We can't get the ACL of a symlink, so we assume it can't
-		   have one. */
-		aclp = NULL;
-	else
-		aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
-
-	if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
-	    archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
-	    &r) == 0 && r == 1) {
-		free(aclp);
-		aclp = NULL;
-		return (ARCHIVE_OK);
-	}
-
-	if (aclp != NULL) {
-		r = translate_acl(a, entry, aclp, aclcnt,
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4);
-		free(aclp);
-		aclp = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate NFSv4 ACLs");
-		}
-		return (r);
-	}
-#endif	/* ARCHIVE_ACL_SUNOS_NFS4 */
-
-	/* Retrieve POSIX.1e ACLs from file. */
-	if (*fd >= 0)
-		aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
-	else if ((!a->follow_symlinks)
-	    && (archive_entry_filetype(entry) == AE_IFLNK))
-		/* We can't get the ACL of a symlink, so we assume it can't
-		   have one. */
-		aclp = NULL;
-	else
-		aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
-
-	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
-	    archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
-	    &r) == 0 && r == 1) {
-		free(aclp);
-		aclp = NULL;
-	}
-
-	if (aclp != NULL)
-	{
-		r = translate_acl(a, entry, aclp, aclcnt,
-		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
-		free(aclp);
-		aclp = NULL;
-
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't translate access ACLs");
-			return (r);
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode)
-{
-	int		ret = ARCHIVE_OK;
-
-	(void)mode;	/* UNUSED */
-
-	if ((archive_acl_types(abstract_acl)
-	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
-		/* Solaris writes POSIX.1e access and default ACLs together */
-		ret = set_acl(a, fd, name, abstract_acl, mode,
-		    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
-
-		/* Simultaneous POSIX.1e and NFSv4 is not supported */
-		return (ret);
-	}
-#if ARCHIVE_ACL_SUNOS_NFS4
-	else if ((archive_acl_types(abstract_acl) &
-	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-		ret = set_acl(a, fd, name, abstract_acl, mode,
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
-	}
-#endif
-	return (ret);
-}
-#endif	/* ARCHIVE_ACL_SUNOS */
diff --git a/c/archive_endian.h b/c/archive_endian.h
deleted file mode 100644
--- a/c/archive_endian.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*-
- * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_endian.h 201085 2009-12-28 02:17:15Z kientzle $
- *
- * Borrowed from FreeBSD's <sys/endian.h>
- */
-
-#ifndef ARCHIVE_ENDIAN_H_INCLUDED
-#define ARCHIVE_ENDIAN_H_INCLUDED
-
-/* Note:  This is a purely internal header! */
-/* Do not use this outside of libarchive internal code! */
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-/*
- * Disabling inline keyword for compilers known to choke on it:
- * - Watcom C++ in C code.  (For any version?)
- * - SGI MIPSpro
- * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
- * - IBM VisualAge 6 (XL v6)
- * - Sun WorkShop C (SunPro) before 5.9
- */
-#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
-#define	inline
-#elif defined(__IBMC__) && __IBMC__ < 700
-#define	inline
-#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
-#define inline
-#elif defined(_MSC_VER) || defined(__osf__)
-#define inline __inline
-#endif
-
-/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
-
-static inline uint16_t
-archive_be16dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	/* Store into unsigned temporaries before left shifting, to avoid
-	promotion to signed int and then left shifting into the sign bit,
-	which is undefined behaviour. */
-	unsigned int p1 = p[1];
-	unsigned int p0 = p[0];
-
-	return ((p0 << 8) | p1);
-}
-
-static inline uint32_t
-archive_be32dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	/* Store into unsigned temporaries before left shifting, to avoid
-	promotion to signed int and then left shifting into the sign bit,
-	which is undefined behaviour. */
-	unsigned int p3 = p[3];
-	unsigned int p2 = p[2];
-	unsigned int p1 = p[1];
-	unsigned int p0 = p[0];
-
-	return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3);
-}
-
-static inline uint64_t
-archive_be64dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	return (((uint64_t)archive_be32dec(p) << 32) | archive_be32dec(p + 4));
-}
-
-static inline uint16_t
-archive_le16dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	/* Store into unsigned temporaries before left shifting, to avoid
-	promotion to signed int and then left shifting into the sign bit,
-	which is undefined behaviour. */
-	unsigned int p1 = p[1];
-	unsigned int p0 = p[0];
-
-	return ((p1 << 8) | p0);
-}
-
-static inline uint32_t
-archive_le32dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	/* Store into unsigned temporaries before left shifting, to avoid
-	promotion to signed int and then left shifting into the sign bit,
-	which is undefined behaviour. */
-	unsigned int p3 = p[3];
-	unsigned int p2 = p[2];
-	unsigned int p1 = p[1];
-	unsigned int p0 = p[0];
-
-	return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0);
-}
-
-static inline uint64_t
-archive_le64dec(const void *pp)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	return (((uint64_t)archive_le32dec(p + 4) << 32) | archive_le32dec(p));
-}
-
-static inline void
-archive_be16enc(void *pp, uint16_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	p[0] = (u >> 8) & 0xff;
-	p[1] = u & 0xff;
-}
-
-static inline void
-archive_be32enc(void *pp, uint32_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	p[0] = (u >> 24) & 0xff;
-	p[1] = (u >> 16) & 0xff;
-	p[2] = (u >> 8) & 0xff;
-	p[3] = u & 0xff;
-}
-
-static inline void
-archive_be64enc(void *pp, uint64_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	archive_be32enc(p, (uint32_t)(u >> 32));
-	archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff));
-}
-
-static inline void
-archive_le16enc(void *pp, uint16_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	p[0] = u & 0xff;
-	p[1] = (u >> 8) & 0xff;
-}
-
-static inline void
-archive_le32enc(void *pp, uint32_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	p[0] = u & 0xff;
-	p[1] = (u >> 8) & 0xff;
-	p[2] = (u >> 16) & 0xff;
-	p[3] = (u >> 24) & 0xff;
-}
-
-static inline void
-archive_le64enc(void *pp, uint64_t u)
-{
-	unsigned char *p = (unsigned char *)pp;
-
-	archive_le32enc(p, (uint32_t)(u & 0xffffffff));
-	archive_le32enc(p + 4, (uint32_t)(u >> 32));
-}
-
-#endif
diff --git a/c/archive_entry.c b/c/archive_entry.c
deleted file mode 100644
--- a/c/archive_entry.c
+++ /dev/null
@@ -1,2149 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if MAJOR_IN_MKDEV
-#include <sys/mkdev.h>
-#define HAVE_MAJOR
-#elif MAJOR_IN_SYSMACROS
-#include <sys/sysmacros.h>
-#define HAVE_MAJOR
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>	/* for Linux file flags */
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h>	/* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h>	/* for Linux file flags */
-#endif
-#include <stddef.h>
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#include "archive.h"
-#include "archive_acl_private.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_entry_private.h"
-
-#if !defined(HAVE_MAJOR) && !defined(major)
-/* Replacement for major/minor/makedev. */
-#define	major(x) ((int)(0x00ff & ((x) >> 8)))
-#define	minor(x) ((int)(0xffff00ff & (x)))
-#define	makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
-#endif
-
-/* 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__) && !defined(__CYGWIN__))
-/* 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
-
-/*
- * This adjustment is needed to support the following idiom for adding
- * 1000ns to the stored time:
- * archive_entry_set_atime(archive_entry_atime(),
- *                         archive_entry_atime_nsec() + 1000)
- * The additional if() here compensates for ambiguity in the C standard,
- * which permits two possible interpretations of a % b when a is negative.
- */
-#define FIX_NS(t,ns) \
-	do {	\
-		t += ns / 1000000000; \
-		ns %= 1000000000; \
-		if (ns < 0) { --t; ns += 1000000000; } \
-	} while (0)
-
-static char *	 ae_fflagstostr(unsigned long bitset, unsigned long bitclear);
-static const wchar_t	*ae_wcstofflags(const wchar_t *stringp,
-		    unsigned long *setp, unsigned long *clrp);
-static const char	*ae_strtofflags(const char *stringp,
-		    unsigned long *setp, unsigned long *clrp);
-
-#ifndef HAVE_WCSCPY
-static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
-{
-	wchar_t *dest = s1;
-	while ((*s1 = *s2) != L'\0')
-		++s1, ++s2;
-	return dest;
-}
-#endif
-#ifndef HAVE_WCSLEN
-static size_t wcslen(const wchar_t *s)
-{
-	const wchar_t *p = s;
-	while (*p != L'\0')
-		++p;
-	return p - s;
-}
-#endif
-#ifndef HAVE_WMEMCMP
-/* Good enough for simple equality testing, but not for sorting. */
-#define wmemcmp(a,b,i)  memcmp((a), (b), (i) * sizeof(wchar_t))
-#endif
-
-/****************************************************************************
- *
- * Public Interface
- *
- ****************************************************************************/
-
-struct archive_entry *
-archive_entry_clear(struct archive_entry *entry)
-{
-	if (entry == NULL)
-		return (NULL);
-	archive_mstring_clean(&entry->ae_fflags_text);
-	archive_mstring_clean(&entry->ae_gname);
-	archive_mstring_clean(&entry->ae_hardlink);
-	archive_mstring_clean(&entry->ae_pathname);
-	archive_mstring_clean(&entry->ae_sourcepath);
-	archive_mstring_clean(&entry->ae_symlink);
-	archive_mstring_clean(&entry->ae_uname);
-	archive_entry_copy_mac_metadata(entry, NULL, 0);
-	archive_acl_clear(&entry->acl);
-	archive_entry_xattr_clear(entry);
-	archive_entry_sparse_clear(entry);
-	free(entry->stat);
-	entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
-	memset(entry, 0, sizeof(*entry));
-	return entry;
-}
-
-struct archive_entry *
-archive_entry_clone(struct archive_entry *entry)
-{
-	struct archive_entry *entry2;
-	struct ae_xattr *xp;
-	struct ae_sparse *sp;
-	size_t s;
-	const void *p;
-
-	/* Allocate new structure and copy over all of the fields. */
-	/* TODO: Should we copy the archive over?  Or require a new archive
-	 * as an argument? */
-	entry2 = archive_entry_new2(entry->archive);
-	if (entry2 == NULL)
-		return (NULL);
-	entry2->ae_stat = entry->ae_stat;
-	entry2->ae_fflags_set = entry->ae_fflags_set;
-	entry2->ae_fflags_clear = entry->ae_fflags_clear;
-
-	/* TODO: XXX If clone can have a different archive, what do we do here if
-	 * character sets are different? XXX */
-	archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
-	archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
-	archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
-	archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
-	archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
-	archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink);
-	entry2->ae_set = entry->ae_set;
-	archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
-
-	/* Copy symlink type */
-	entry2->ae_symlink_type = entry->ae_symlink_type;
-
-	/* Copy encryption status */
-	entry2->encryption = entry->encryption;
-
-	/* Copy digests */
-#define copy_digest(_e2, _e, _t) \
-	memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t))
-
-	copy_digest(entry2, entry, md5);
-	copy_digest(entry2, entry, rmd160);
-	copy_digest(entry2, entry, sha1);
-	copy_digest(entry2, entry, sha256);
-	copy_digest(entry2, entry, sha384);
-	copy_digest(entry2, entry, sha512);
-
-#undef copy_digest
-	
-	/* Copy ACL data over. */
-	archive_acl_copy(&entry2->acl, &entry->acl);
-
-	/* Copy Mac OS metadata. */
-	p = archive_entry_mac_metadata(entry, &s);
-	archive_entry_copy_mac_metadata(entry2, p, s);
-
-	/* Copy xattr data over. */
-	xp = entry->xattr_head;
-	while (xp != NULL) {
-		archive_entry_xattr_add_entry(entry2,
-		    xp->name, xp->value, xp->size);
-		xp = xp->next;
-	}
-
-	/* Copy sparse data over. */
-	sp = entry->sparse_head;
-	while (sp != NULL) {
-		archive_entry_sparse_add_entry(entry2,
-		    sp->offset, sp->length);
-		sp = sp->next;
-	}
-
-	return (entry2);
-}
-
-void
-archive_entry_free(struct archive_entry *entry)
-{
-	archive_entry_clear(entry);
-	free(entry);
-}
-
-struct archive_entry *
-archive_entry_new(void)
-{
-	return archive_entry_new2(NULL);
-}
-
-struct archive_entry *
-archive_entry_new2(struct archive *a)
-{
-	struct archive_entry *entry;
-
-	entry = (struct archive_entry *)calloc(1, sizeof(*entry));
-	if (entry == NULL)
-		return (NULL);
-	entry->archive = a;
-	entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
-	return (entry);
-}
-
-/*
- * Functions for reading fields from an archive_entry.
- */
-
-time_t
-archive_entry_atime(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_atime);
-}
-
-long
-archive_entry_atime_nsec(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_atime_nsec);
-}
-
-int
-archive_entry_atime_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_ATIME);
-}
-
-time_t
-archive_entry_birthtime(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_birthtime);
-}
-
-long
-archive_entry_birthtime_nsec(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_birthtime_nsec);
-}
-
-int
-archive_entry_birthtime_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_BIRTHTIME);
-}
-
-time_t
-archive_entry_ctime(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_ctime);
-}
-
-int
-archive_entry_ctime_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_CTIME);
-}
-
-long
-archive_entry_ctime_nsec(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_ctime_nsec);
-}
-
-dev_t
-archive_entry_dev(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_dev_is_broken_down)
-		return ae_makedev(entry->ae_stat.aest_devmajor,
-		    entry->ae_stat.aest_devminor);
-	else
-		return (entry->ae_stat.aest_dev);
-}
-
-int
-archive_entry_dev_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_DEV);
-}
-
-dev_t
-archive_entry_devmajor(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_dev_is_broken_down)
-		return (entry->ae_stat.aest_devmajor);
-	else
-		return major(entry->ae_stat.aest_dev);
-}
-
-dev_t
-archive_entry_devminor(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_dev_is_broken_down)
-		return (entry->ae_stat.aest_devminor);
-	else
-		return minor(entry->ae_stat.aest_dev);
-}
-
-__LA_MODE_T
-archive_entry_filetype(struct archive_entry *entry)
-{
-	return (AE_IFMT & entry->acl.mode);
-}
-
-void
-archive_entry_fflags(struct archive_entry *entry,
-    unsigned long *set, unsigned long *clear)
-{
-	*set = entry->ae_fflags_set;
-	*clear = entry->ae_fflags_clear;
-}
-
-/*
- * Note: if text was provided, this just returns that text.  If you
- * really need the text to be rebuilt in a canonical form, set the
- * text, ask for the bitmaps, then set the bitmaps.  (Setting the
- * bitmaps clears any stored text.)  This design is deliberate: if
- * we're editing archives, we don't want to discard flags just because
- * they aren't supported on the current system.  The bitmap<->text
- * conversions are platform-specific (see below).
- */
-const char *
-archive_entry_fflags_text(struct archive_entry *entry)
-{
-	const char *f;
-	char *p;
-
-	if (archive_mstring_get_mbs(entry->archive,
-	    &entry->ae_fflags_text, &f) == 0) {
-		if (f != NULL)
-			return (f);
-	} else if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-
-	if (entry->ae_fflags_set == 0  &&  entry->ae_fflags_clear == 0)
-		return (NULL);
-
-	p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear);
-	if (p == NULL)
-		return (NULL);
-
-	archive_mstring_copy_mbs(&entry->ae_fflags_text, p);
-	free(p);
-	if (archive_mstring_get_mbs(entry->archive,
-	    &entry->ae_fflags_text, &f) == 0)
-		return (f);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-la_int64_t
-archive_entry_gid(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_gid);
-}
-
-const char *
-archive_entry_gname(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const char *
-archive_entry_gname_utf8(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-
-const wchar_t *
-archive_entry_gname_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-_archive_entry_gname_l(struct archive_entry *entry,
-    const char **p, size_t *len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc));
-}
-
-const char *
-archive_entry_hardlink(struct archive_entry *entry)
-{
-	const char *p;
-	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_mbs(
-	    entry->archive, &entry->ae_hardlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const char *
-archive_entry_hardlink_utf8(struct archive_entry *entry)
-{
-	const char *p;
-	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_utf8(
-	    entry->archive, &entry->ae_hardlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const wchar_t *
-archive_entry_hardlink_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if ((entry->ae_set & AE_SET_HARDLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_wcs(
-	    entry->archive, &entry->ae_hardlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-_archive_entry_hardlink_l(struct archive_entry *entry,
-    const char **p, size_t *len, struct archive_string_conv *sc)
-{
-	if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
-		*p = NULL;
-		*len = 0;
-		return (0);
-	}
-	return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_hardlink, p, len, sc));
-}
-
-la_int64_t
-archive_entry_ino(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_ino);
-}
-
-int
-archive_entry_ino_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_INO);
-}
-
-la_int64_t
-archive_entry_ino64(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_ino);
-}
-
-__LA_MODE_T
-archive_entry_mode(struct archive_entry *entry)
-{
-	return (entry->acl.mode);
-}
-
-time_t
-archive_entry_mtime(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_mtime);
-}
-
-long
-archive_entry_mtime_nsec(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_mtime_nsec);
-}
-
-int
-archive_entry_mtime_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_MTIME);
-}
-
-unsigned int
-archive_entry_nlink(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_nlink);
-}
-
-/* Instead, our caller could have chosen a specific encoding
- * (archive_mstring_get_mbs, archive_mstring_get_utf8,
- * archive_mstring_get_wcs).  So we should try multiple
- * encodings.  Try mbs first because of history, even though
- * utf8 might be better for pathname portability.
- * Also omit wcs because of type mismatch (char * versus wchar *)
- */
-const char *
-archive_entry_pathname(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_mbs(
-	    entry->archive, &entry->ae_pathname, &p) == 0)
-		return (p);
-#if HAVE_EILSEQ  /*{*/
-    if (errno == EILSEQ) {
-	    if (archive_mstring_get_utf8(
-	        entry->archive, &entry->ae_pathname, &p) == 0)
-		    return (p);
-    }
-#endif  /*}*/
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const char *
-archive_entry_pathname_utf8(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_utf8(
-	    entry->archive, &entry->ae_pathname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const wchar_t *
-archive_entry_pathname_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if (archive_mstring_get_wcs(
-	    entry->archive, &entry->ae_pathname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-_archive_entry_pathname_l(struct archive_entry *entry,
-    const char **p, size_t *len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc));
-}
-
-__LA_MODE_T
-archive_entry_perm(struct archive_entry *entry)
-{
-	return (~AE_IFMT & entry->acl.mode);
-}
-
-dev_t
-archive_entry_rdev(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_rdev_is_broken_down)
-		return ae_makedev(entry->ae_stat.aest_rdevmajor,
-		    entry->ae_stat.aest_rdevminor);
-	else
-		return (entry->ae_stat.aest_rdev);
-}
-
-dev_t
-archive_entry_rdevmajor(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_rdev_is_broken_down)
-		return (entry->ae_stat.aest_rdevmajor);
-	else
-		return major(entry->ae_stat.aest_rdev);
-}
-
-dev_t
-archive_entry_rdevminor(struct archive_entry *entry)
-{
-	if (entry->ae_stat.aest_rdev_is_broken_down)
-		return (entry->ae_stat.aest_rdevminor);
-	else
-		return minor(entry->ae_stat.aest_rdev);
-}
-
-la_int64_t
-archive_entry_size(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_size);
-}
-
-int
-archive_entry_size_is_set(struct archive_entry *entry)
-{
-	return (entry->ae_set & AE_SET_SIZE);
-}
-
-const char *
-archive_entry_sourcepath(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_mbs(
-	    entry->archive, &entry->ae_sourcepath, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const wchar_t *
-archive_entry_sourcepath_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if (archive_mstring_get_wcs(
-	    entry->archive, &entry->ae_sourcepath, &p) == 0)
-		return (p);
-	return (NULL);
-}
-
-const char *
-archive_entry_symlink(struct archive_entry *entry)
-{
-	const char *p;
-	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_mbs(
-	    entry->archive, &entry->ae_symlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-archive_entry_symlink_type(struct archive_entry *entry)
-{
-	return (entry->ae_symlink_type);
-}
-
-const char *
-archive_entry_symlink_utf8(struct archive_entry *entry)
-{
-	const char *p;
-	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_utf8(
-	    entry->archive, &entry->ae_symlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const wchar_t *
-archive_entry_symlink_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if ((entry->ae_set & AE_SET_SYMLINK) == 0)
-		return (NULL);
-	if (archive_mstring_get_wcs(
-	    entry->archive, &entry->ae_symlink, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-_archive_entry_symlink_l(struct archive_entry *entry,
-    const char **p, size_t *len, struct archive_string_conv *sc)
-{
-	if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
-		*p = NULL;
-		*len = 0;
-		return (0);
-	}
-	return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_symlink, p, len, sc));
-}
-
-la_int64_t
-archive_entry_uid(struct archive_entry *entry)
-{
-	return (entry->ae_stat.aest_uid);
-}
-
-const char *
-archive_entry_uname(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const char *
-archive_entry_uname_utf8(struct archive_entry *entry)
-{
-	const char *p;
-	if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-const wchar_t *
-archive_entry_uname_w(struct archive_entry *entry)
-{
-	const wchar_t *p;
-	if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
-		return (p);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (NULL);
-}
-
-int
-_archive_entry_uname_l(struct archive_entry *entry,
-    const char **p, size_t *len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc));
-}
-
-int
-archive_entry_is_data_encrypted(struct archive_entry *entry)
-{
-	return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
-}
-
-int
-archive_entry_is_metadata_encrypted(struct archive_entry *entry)
-{
-	return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
-}
-
-int
-archive_entry_is_encrypted(struct archive_entry *entry)
-{
-	return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
-}
-
-/*
- * Functions to set archive_entry properties.
- */
-
-void
-archive_entry_set_filetype(struct archive_entry *entry, unsigned int type)
-{
-	entry->stat_valid = 0;
-	entry->acl.mode &= ~AE_IFMT;
-	entry->acl.mode |= AE_IFMT & type;
-}
-
-void
-archive_entry_set_fflags(struct archive_entry *entry,
-    unsigned long set, unsigned long clear)
-{
-	archive_mstring_clean(&entry->ae_fflags_text);
-	entry->ae_fflags_set = set;
-	entry->ae_fflags_clear = clear;
-}
-
-const char *
-archive_entry_copy_fflags_text(struct archive_entry *entry,
-    const char *flags)
-{
-	archive_mstring_copy_mbs(&entry->ae_fflags_text, flags);
-	return (ae_strtofflags(flags,
-		    &entry->ae_fflags_set, &entry->ae_fflags_clear));
-}
-
-const wchar_t *
-archive_entry_copy_fflags_text_w(struct archive_entry *entry,
-    const wchar_t *flags)
-{
-	archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);
-	return (ae_wcstofflags(flags,
-		    &entry->ae_fflags_set, &entry->ae_fflags_clear));
-}
-
-void
-archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_gid = g;
-}
-
-void
-archive_entry_set_gname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_gname, name);
-}
-
-void
-archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_utf8(&entry->ae_gname, name);
-}
-
-void
-archive_entry_copy_gname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_gname, name);
-}
-
-void
-archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
-{
-	archive_mstring_copy_wcs(&entry->ae_gname, name);
-}
-
-int
-archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
-{
-	if (archive_mstring_update_utf8(entry->archive,
-	    &entry->ae_gname, name) == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-int
-_archive_entry_copy_gname_l(struct archive_entry *entry,
-    const char *name, size_t len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
-}
-
-void
-archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
-{
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_INO;
-	entry->ae_stat.aest_ino = ino;
-}
-
-void
-archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
-{
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_INO;
-	entry->ae_stat.aest_ino = ino;
-}
-
-void
-archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
-{
-	archive_mstring_copy_mbs(&entry->ae_hardlink, target);
-	if (target != NULL)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-}
-
-void
-archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
-{
-	archive_mstring_copy_utf8(&entry->ae_hardlink, target);
-	if (target != NULL)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-}
-
-void
-archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
-{
-	archive_mstring_copy_mbs(&entry->ae_hardlink, target);
-	if (target != NULL)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-}
-
-void
-archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
-{
-	archive_mstring_copy_wcs(&entry->ae_hardlink, target);
-	if (target != NULL)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-}
-
-int
-archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target)
-{
-	if (target != NULL)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-	if (archive_mstring_update_utf8(entry->archive,
-	    &entry->ae_hardlink, target) == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-int
-_archive_entry_copy_hardlink_l(struct archive_entry *entry,
-    const char *target, size_t len, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
-	    target, len, sc);
-	if (target != NULL && r == 0)
-		entry->ae_set |= AE_SET_HARDLINK;
-	else
-		entry->ae_set &= ~AE_SET_HARDLINK;
-	return (r);
-}
-
-void
-archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
-{
-	FIX_NS(t, ns);
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_ATIME;
-	entry->ae_stat.aest_atime = t;
-	entry->ae_stat.aest_atime_nsec = ns;
-}
-
-void
-archive_entry_unset_atime(struct archive_entry *entry)
-{
-	archive_entry_set_atime(entry, 0, 0);
-	entry->ae_set &= ~AE_SET_ATIME;
-}
-
-void
-archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
-{
-	FIX_NS(t, ns);
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_BIRTHTIME;
-	entry->ae_stat.aest_birthtime = t;
-	entry->ae_stat.aest_birthtime_nsec = ns;
-}
-
-void
-archive_entry_unset_birthtime(struct archive_entry *entry)
-{
-	archive_entry_set_birthtime(entry, 0, 0);
-	entry->ae_set &= ~AE_SET_BIRTHTIME;
-}
-
-void
-archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
-{
-	FIX_NS(t, ns);
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_CTIME;
-	entry->ae_stat.aest_ctime = t;
-	entry->ae_stat.aest_ctime_nsec = ns;
-}
-
-void
-archive_entry_unset_ctime(struct archive_entry *entry)
-{
-	archive_entry_set_ctime(entry, 0, 0);
-	entry->ae_set &= ~AE_SET_CTIME;
-}
-
-void
-archive_entry_set_dev(struct archive_entry *entry, dev_t d)
-{
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_DEV;
-	entry->ae_stat.aest_dev_is_broken_down = 0;
-	entry->ae_stat.aest_dev = d;
-}
-
-void
-archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
-{
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_DEV;
-	entry->ae_stat.aest_dev_is_broken_down = 1;
-	entry->ae_stat.aest_devmajor = m;
-}
-
-void
-archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
-{
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_DEV;
-	entry->ae_stat.aest_dev_is_broken_down = 1;
-	entry->ae_stat.aest_devminor = m;
-}
-
-/* Set symlink if symlink is already set, else set hardlink. */
-void
-archive_entry_set_link(struct archive_entry *entry, const char *target)
-{
-	if (entry->ae_set & AE_SET_SYMLINK)
-		archive_mstring_copy_mbs(&entry->ae_symlink, target);
-	else
-		archive_mstring_copy_mbs(&entry->ae_hardlink, target);
-}
-
-void
-archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
-{
-	if (entry->ae_set & AE_SET_SYMLINK)
-		archive_mstring_copy_utf8(&entry->ae_symlink, target);
-	else
-		archive_mstring_copy_utf8(&entry->ae_hardlink, target);
-}
-
-/* Set symlink if symlink is already set, else set hardlink. */
-void
-archive_entry_copy_link(struct archive_entry *entry, const char *target)
-{
-	if (entry->ae_set & AE_SET_SYMLINK)
-		archive_mstring_copy_mbs(&entry->ae_symlink, target);
-	else
-		archive_mstring_copy_mbs(&entry->ae_hardlink, target);
-}
-
-/* Set symlink if symlink is already set, else set hardlink. */
-void
-archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
-{
-	if (entry->ae_set & AE_SET_SYMLINK)
-		archive_mstring_copy_wcs(&entry->ae_symlink, target);
-	else
-		archive_mstring_copy_wcs(&entry->ae_hardlink, target);
-}
-
-int
-archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
-{
-	int r;
-	if (entry->ae_set & AE_SET_SYMLINK)
-		r = archive_mstring_update_utf8(entry->archive,
-		    &entry->ae_symlink, target);
-	else
-		r = archive_mstring_update_utf8(entry->archive,
-		    &entry->ae_hardlink, target);
-	if (r == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-int
-_archive_entry_copy_link_l(struct archive_entry *entry,
-    const char *target, size_t len, struct archive_string_conv *sc)
-{
-	int r;
-
-	if (entry->ae_set & AE_SET_SYMLINK)
-		r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
-		    target, len, sc);
-	else
-		r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
-		    target, len, sc);
-	return (r);
-}
-
-void
-archive_entry_set_mode(struct archive_entry *entry, mode_t m)
-{
-	entry->stat_valid = 0;
-	entry->acl.mode = m;
-}
-
-void
-archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
-{
-	FIX_NS(t, ns);
-	entry->stat_valid = 0;
-	entry->ae_set |= AE_SET_MTIME;
-	entry->ae_stat.aest_mtime = t;
-	entry->ae_stat.aest_mtime_nsec = ns;
-}
-
-void
-archive_entry_unset_mtime(struct archive_entry *entry)
-{
-	archive_entry_set_mtime(entry, 0, 0);
-	entry->ae_set &= ~AE_SET_MTIME;
-}
-
-void
-archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_nlink = nlink;
-}
-
-void
-archive_entry_set_pathname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_pathname, name);
-}
-
-void
-archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_utf8(&entry->ae_pathname, name);
-}
-
-void
-archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_pathname, name);
-}
-
-void
-archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
-{
-	archive_mstring_copy_wcs(&entry->ae_pathname, name);
-}
-
-int
-archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
-{
-	if (archive_mstring_update_utf8(entry->archive,
-	    &entry->ae_pathname, name) == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-int
-_archive_entry_copy_pathname_l(struct archive_entry *entry,
-    const char *name, size_t len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
-	    name, len, sc));
-}
-
-void
-archive_entry_set_perm(struct archive_entry *entry, mode_t p)
-{
-	entry->stat_valid = 0;
-	entry->acl.mode &= AE_IFMT;
-	entry->acl.mode |= ~AE_IFMT & p;
-}
-
-void
-archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_rdev = m;
-	entry->ae_stat.aest_rdev_is_broken_down = 0;
-}
-
-void
-archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_rdev_is_broken_down = 1;
-	entry->ae_stat.aest_rdevmajor = m;
-}
-
-void
-archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_rdev_is_broken_down = 1;
-	entry->ae_stat.aest_rdevminor = m;
-}
-
-void
-archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_size = s;
-	entry->ae_set |= AE_SET_SIZE;
-}
-
-void
-archive_entry_unset_size(struct archive_entry *entry)
-{
-	archive_entry_set_size(entry, 0);
-	entry->ae_set &= ~AE_SET_SIZE;
-}
-
-void
-archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
-{
-	archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
-}
-
-void
-archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
-{
-	archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
-}
-
-void
-archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
-{
-	archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
-	if (linkname != NULL)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-}
-
-void
-archive_entry_set_symlink_type(struct archive_entry *entry, int type)
-{
-	entry->ae_symlink_type = type;
-}
-
-void
-archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
-{
-	archive_mstring_copy_utf8(&entry->ae_symlink, linkname);
-	if (linkname != NULL)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-}
-
-void
-archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
-{
-	archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
-	if (linkname != NULL)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-}
-
-void
-archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
-{
-	archive_mstring_copy_wcs(&entry->ae_symlink, linkname);
-	if (linkname != NULL)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-}
-
-int
-archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname)
-{
-	if (linkname != NULL)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-	if (archive_mstring_update_utf8(entry->archive,
-	    &entry->ae_symlink, linkname) == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-int
-_archive_entry_copy_symlink_l(struct archive_entry *entry,
-    const char *linkname, size_t len, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
-	    linkname, len, sc);
-	if (linkname != NULL && r == 0)
-		entry->ae_set |= AE_SET_SYMLINK;
-	else
-		entry->ae_set &= ~AE_SET_SYMLINK;
-	return (r);
-}
-
-void
-archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
-{
-	entry->stat_valid = 0;
-	entry->ae_stat.aest_uid = u;
-}
-
-void
-archive_entry_set_uname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_uname, name);
-}
-
-void
-archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_utf8(&entry->ae_uname, name);
-}
-
-void
-archive_entry_copy_uname(struct archive_entry *entry, const char *name)
-{
-	archive_mstring_copy_mbs(&entry->ae_uname, name);
-}
-
-void
-archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
-{
-	archive_mstring_copy_wcs(&entry->ae_uname, name);
-}
-
-int
-archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
-{
-	if (archive_mstring_update_utf8(entry->archive,
-	    &entry->ae_uname, name) == 0)
-		return (1);
-	if (errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (0);
-}
-
-void
-archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
-{
-	if (is_encrypted) {
-		entry->encryption |= AE_ENCRYPTION_DATA;
-	} else {
-		entry->encryption &= ~AE_ENCRYPTION_DATA;
-	}
-}
-
-void
-archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
-{
-	if (is_encrypted) {
-		entry->encryption |= AE_ENCRYPTION_METADATA;
-	} else {
-		entry->encryption &= ~AE_ENCRYPTION_METADATA;
-	}
-}
-
-int
-_archive_entry_copy_uname_l(struct archive_entry *entry,
-    const char *name, size_t len, struct archive_string_conv *sc)
-{
-	return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
-	    name, len, sc));
-}
-
-const void *
-archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
-{
-  *s = entry->mac_metadata_size;
-  return entry->mac_metadata;
-}
-
-void
-archive_entry_copy_mac_metadata(struct archive_entry *entry,
-    const void *p, size_t s)
-{
-  free(entry->mac_metadata);
-  if (p == NULL || s == 0) {
-    entry->mac_metadata = NULL;
-    entry->mac_metadata_size = 0;
-  } else {
-    entry->mac_metadata_size = s;
-    entry->mac_metadata = malloc(s);
-    if (entry->mac_metadata == NULL)
-      abort();
-    memcpy(entry->mac_metadata, p, s);
-  }
-}
-
-/* Digest handling */
-const unsigned char *
-archive_entry_digest(struct archive_entry *entry, int type)
-{
-	switch (type) {
-	case ARCHIVE_ENTRY_DIGEST_MD5:
-		return entry->digest.md5;
-	case ARCHIVE_ENTRY_DIGEST_RMD160:
-		return entry->digest.rmd160;
-	case ARCHIVE_ENTRY_DIGEST_SHA1:
-		return entry->digest.sha1;
-	case ARCHIVE_ENTRY_DIGEST_SHA256:
-		return entry->digest.sha256;
-	case ARCHIVE_ENTRY_DIGEST_SHA384:
-		return entry->digest.sha384;
-	case ARCHIVE_ENTRY_DIGEST_SHA512:
-		return entry->digest.sha512;
-	default:
-		return NULL;
-	}
-}
-
-int
-archive_entry_set_digest(struct archive_entry *entry, int type,
-    const unsigned char *digest)
-{
-#define copy_digest(_e, _t, _d)\
-	memcpy(_e->digest._t, _d, sizeof(_e->digest._t))
-
-	switch (type) {
-	case ARCHIVE_ENTRY_DIGEST_MD5:
-		copy_digest(entry, md5, digest);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_RMD160:
-		copy_digest(entry, rmd160, digest);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA1:
-		copy_digest(entry, sha1, digest);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA256:
-		copy_digest(entry, sha256, digest);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA384:
-		copy_digest(entry, sha384, digest);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA512:
-		copy_digest(entry, sha512, digest);
-		break;
-	default:
-		return ARCHIVE_WARN;
-	}
-
-	return ARCHIVE_OK;
-#undef copy_digest
-}
-
-/*
- * ACL management.  The following would, of course, be a lot simpler
- * if: 1) the last draft of POSIX.1e were a really thorough and
- * complete standard that addressed the needs of ACL archiving and 2)
- * everyone followed it faithfully.  Alas, neither is true, so the
- * following is a lot more complex than might seem necessary to the
- * uninitiated.
- */
-
-struct archive_acl *
-archive_entry_acl(struct archive_entry *entry)
-{
-	return &entry->acl;
-}
-
-void
-archive_entry_acl_clear(struct archive_entry *entry)
-{
-	archive_acl_clear(&entry->acl);
-}
-
-/*
- * Add a single ACL entry to the internal list of ACL data.
- */
-int
-archive_entry_acl_add_entry(struct archive_entry *entry,
-    int type, int permset, int tag, int id, const char *name)
-{
-	return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
-}
-
-/*
- * As above, but with a wide-character name.
- */
-int
-archive_entry_acl_add_entry_w(struct archive_entry *entry,
-    int type, int permset, int tag, int id, const wchar_t *name)
-{
-	return archive_acl_add_entry_w_len(&entry->acl,
-	    type, permset, tag, id, name, wcslen(name));
-}
-
-/*
- * Return a bitmask of ACL types in an archive entry ACL list
- */
-int
-archive_entry_acl_types(struct archive_entry *entry)
-{
-	return (archive_acl_types(&entry->acl));
-}
-
-/*
- * Return a count of entries matching "want_type".
- */
-int
-archive_entry_acl_count(struct archive_entry *entry, int want_type)
-{
-	return archive_acl_count(&entry->acl, want_type);
-}
-
-/*
- * Prepare for reading entries from the ACL data.  Returns a count
- * of entries matching "want_type", or zero if there are no
- * non-extended ACL entries of that type.
- */
-int
-archive_entry_acl_reset(struct archive_entry *entry, int want_type)
-{
-	return archive_acl_reset(&entry->acl, want_type);
-}
-
-/*
- * Return the next ACL entry in the list.  Fake entries for the
- * standard permissions and include them in the returned list.
- */
-int
-archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
-    int *permset, int *tag, int *id, const char **name)
-{
-	int r;
-	r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
-		permset, tag, id, name);
-	if (r == ARCHIVE_FATAL && errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (r);
-}
-
-/*
- * Generate a text version of the ACL. The flags parameter controls
- * the style of the generated ACL.
- */
-wchar_t *
-archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
-    int flags)
-{
-	return (archive_acl_to_text_w(&entry->acl, len, flags,
-	    entry->archive));
-}
-
-char *
-archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
-    int flags)
-{
-	return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
-}
-
-char *
-_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
-   int flags, struct archive_string_conv *sc)
-{
-	return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
-}
-
-/*
- * ACL text parser.
- */
-int
-archive_entry_acl_from_text_w(struct archive_entry *entry,
-    const wchar_t *wtext, int type)
-{
-	return (archive_acl_from_text_w(&entry->acl, wtext, type));
-}
-
-int
-archive_entry_acl_from_text(struct archive_entry *entry,
-    const char *text, int type)
-{
-	return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
-}
-
-int
-_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
-    int type, struct archive_string_conv *sc)
-{
-	return (archive_acl_from_text_l(&entry->acl, text, type, sc));
-}
-
-/* Deprecated */
-static int
-archive_entry_acl_text_compat(int *flags)
-{
-	if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
-		return (1);
-
-	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
-	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
-		*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
-
-	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
-	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
-		*flags |=  ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
-
-	*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
-
-	return (0);
-}
-
-/* Deprecated */
-const wchar_t *
-archive_entry_acl_text_w(struct archive_entry *entry, int flags)
-{
-	free(entry->acl.acl_text_w);
-	entry->acl.acl_text_w = NULL;
-	if (archive_entry_acl_text_compat(&flags) == 0)
-		entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
-		    NULL, flags, entry->archive);
-	return (entry->acl.acl_text_w);
-}
-
-/* Deprecated */
-const char *
-archive_entry_acl_text(struct archive_entry *entry, int flags)
-{
-	free(entry->acl.acl_text);
-	entry->acl.acl_text = NULL;
-	if (archive_entry_acl_text_compat(&flags) == 0)
-		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
-		    flags, NULL);
-
-	return (entry->acl.acl_text);
-}
-
-/* Deprecated */
-int
-_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
-    const char **acl_text, size_t *len, struct archive_string_conv *sc)
-{
-	free(entry->acl.acl_text);
-	entry->acl.acl_text = NULL;
-
-	if (archive_entry_acl_text_compat(&flags) == 0)
-		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
-		    (ssize_t *)len, flags, sc);
-
-	*acl_text = entry->acl.acl_text;
-
-	return (0);
-}
-
-/*
- * Following code is modified from UC Berkeley sources, and
- * is subject to the following copyright notice.
- */
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Supported file flags on FreeBSD and Mac OS:
- * sappnd,sappend		SF_APPEND
- * arch,archived		SF_ARCHIVED
- * schg,schange,simmutable	SF_IMMUTABLE
- * sunlnk,sunlink		SF_NOUNLINK	(FreeBSD only)
- * uappnd,uappend		UF_APPEND
- * compressed			UF_COMPRESSED	(Mac OS only)
- * hidden,uhidden		UF_HIDDEN
- * uchg,uchange,uimmutable	UF_IMMUTABLE
- * nodump			UF_NODUMP
- * uunlnk,uunlink		UF_NOUNLINK	(FreeBSD only)
- * offline,uoffline		UF_OFFLINE	(FreeBSD only)
- * opaque			UF_OPAQUE
- * rdonly,urdonly,readonly	UF_READONLY	(FreeBSD only)
- * reparse,ureparse		UF_REPARSE	(FreeBSD only)
- * sparse,usparse		UF_SPARSE	(FreeBSD only)
- * system,usystem		UF_SYSTEM	(FreeBSD only)
- *
- * See chflags(2) for more information
- *
- * Supported file attributes on Linux:
- * a	append only			FS_APPEND_FL		sappnd
- * A	no atime updates		FS_NOATIME_FL		atime
- * c	compress			FS_COMPR_FL		compress
- * C	no copy on write		FS_NOCOW_FL		cow
- * d	no dump				FS_NODUMP_FL		dump
- * D	synchronous directory updates	FS_DIRSYNC_FL		dirsync
- * i	immutable			FS_IMMUTABLE_FL		schg
- * j	data journalling		FS_JOURNAL_DATA_FL	journal
- * P	project hierarchy		FS_PROJINHERIT_FL	projinherit
- * s	secure deletion			FS_SECRM_FL		securedeletion
- * S	synchronous updates		FS_SYNC_FL		sync
- * t	no tail-merging			FS_NOTAIL_FL		tail
- * T	top of directory hierarchy	FS_TOPDIR_FL		topdir
- * u	undeletable			FS_UNRM_FL		undel
- *
- * See ioctl_iflags(2) for more information
- *
- * Equivalent file flags supported on FreeBSD / Mac OS and Linux:
- * SF_APPEND		FS_APPEND_FL		sappnd
- * SF_IMMUTABLE		FS_IMMUTABLE_FL		schg
- * UF_NODUMP		FS_NODUMP_FL		nodump
- */
-
-static const struct flag {
-	const char	*name;
-	const wchar_t	*wname;
-	unsigned long	 set;
-	unsigned long	 clear;
-} fileflags[] = {
-	/* Preferred (shorter) names per flag first, all prefixed by "no" */
-#ifdef SF_APPEND
-	{ "nosappnd",	L"nosappnd",		SF_APPEND,	0},
-	{ "nosappend",	L"nosappend",		SF_APPEND,	0},
-#endif
-#if defined(FS_APPEND_FL)			/* 'a' */
-	{ "nosappnd",	L"nosappnd",		FS_APPEND_FL,	0},
-	{ "nosappend",	L"nosappend",		FS_APPEND_FL,	0},
-#elif defined(EXT2_APPEND_FL)			/* 'a' */
-	{ "nosappnd",	L"nosappnd",		EXT2_APPEND_FL,	0},
-	{ "nosappend",	L"nosappend",		EXT2_APPEND_FL,	0},
-#endif
-#ifdef SF_ARCHIVED
-	{ "noarch",	L"noarch",		SF_ARCHIVED,	0},
-	{ "noarchived",	L"noarchived",       	SF_ARCHIVED,	0},
-#endif
-#ifdef SF_IMMUTABLE
-	{ "noschg",	L"noschg",		SF_IMMUTABLE,	0},
-	{ "noschange",	L"noschange",		SF_IMMUTABLE,	0},
-	{ "nosimmutable",	L"nosimmutable",	SF_IMMUTABLE,	0},
-#endif
-#if defined(FS_IMMUTABLE_FL)			/* 'i' */
-	{ "noschg",	L"noschg",		FS_IMMUTABLE_FL,	0},
-	{ "noschange",	L"noschange",		FS_IMMUTABLE_FL,	0},
-	{ "nosimmutable",	L"nosimmutable",	FS_IMMUTABLE_FL,	0},
-#elif defined(EXT2_IMMUTABLE_FL)		/* 'i' */
-	{ "noschg",	L"noschg",		EXT2_IMMUTABLE_FL,	0},
-	{ "noschange",	L"noschange",		EXT2_IMMUTABLE_FL,	0},
-	{ "nosimmutable",	L"nosimmutable",	EXT2_IMMUTABLE_FL,	0},
-#endif
-#ifdef SF_NOUNLINK
-	{ "nosunlnk",	L"nosunlnk",		SF_NOUNLINK,	0},
-	{ "nosunlink",	L"nosunlink",		SF_NOUNLINK,	0},
-#endif
-#ifdef UF_APPEND
-	{ "nouappnd",	L"nouappnd",		UF_APPEND,	0},
-	{ "nouappend",	L"nouappend",		UF_APPEND,	0},
-#endif
-#ifdef UF_IMMUTABLE
-	{ "nouchg",	L"nouchg",		UF_IMMUTABLE,	0},
-	{ "nouchange",	L"nouchange",		UF_IMMUTABLE,	0},
-	{ "nouimmutable",	L"nouimmutable",	UF_IMMUTABLE,	0},
-#endif
-#ifdef UF_NODUMP
-	{ "nodump",	L"nodump",		0,		UF_NODUMP},
-#endif
-#if defined(FS_NODUMP_FL)	/* 'd' */
-	{ "nodump",	L"nodump",		0,		FS_NODUMP_FL},
-#elif defined(EXT2_NODUMP_FL)
-	{ "nodump",	L"nodump",		0,		EXT2_NODUMP_FL},
-#endif
-#ifdef UF_OPAQUE
-	{ "noopaque",	L"noopaque",		UF_OPAQUE,	0},
-#endif
-#ifdef UF_NOUNLINK
-	{ "nouunlnk",	L"nouunlnk",		UF_NOUNLINK,	0},
-	{ "nouunlink",	L"nouunlink",		UF_NOUNLINK,	0},
-#endif
-#ifdef UF_COMPRESSED
-	/* Mac OS */
-	{ "nocompressed",	L"nocompressed",	UF_COMPRESSED,	0},
-#endif
-#ifdef UF_HIDDEN
-	{ "nohidden",	L"nohidden",		UF_HIDDEN,	0},
-	{ "nouhidden",	L"nouhidden",		UF_HIDDEN,	0},
-#endif
-#ifdef FILE_ATTRIBUTE_HIDDEN
-	{ "nohidden",	L"nohidden",	FILE_ATTRIBUTE_HIDDEN,	0},
-	{ "nouhidden",	L"nouhidden",	FILE_ATTRIBUTE_HIDDEN,	0},
-#endif
-#ifdef UF_OFFLINE
-	{ "nooffline",	L"nooffline",		UF_OFFLINE,	0},
-	{ "nouoffline",	L"nouoffline",		UF_OFFLINE,	0},
-#endif
-#ifdef UF_READONLY
-	{ "nordonly",	L"nordonly",		UF_READONLY,	0},
-	{ "nourdonly",	L"nourdonly",		UF_READONLY,	0},
-	{ "noreadonly",	L"noreadonly",		UF_READONLY,	0},
-#endif
-#ifdef FILE_ATTRIBUTE_READONLY
-	{ "nordonly",	L"nordonly",	FILE_ATTRIBUTE_READONLY,	0},
-	{ "nourdonly",	L"nourdonly",	FILE_ATTRIBUTE_READONLY,	0},
-	{ "noreadonly",	L"noreadonly",	FILE_ATTRIBUTE_READONLY,	0},
-#endif
-#ifdef UF_SPARSE
-	{ "nosparse",	L"nosparse",		UF_SPARSE,	0},
-	{ "nousparse",	L"nousparse",		UF_SPARSE,	0},
-#endif
-#ifdef UF_REPARSE
-	{ "noreparse",	L"noreparse",		UF_REPARSE,	0},
-	{ "noureparse",	L"noureparse",		UF_REPARSE,	0},
-#endif
-#ifdef UF_SYSTEM
-	{ "nosystem",	L"nosystem",		UF_SYSTEM,	0},
-	{ "nousystem",	L"nousystem",		UF_SYSTEM,	0},
-#endif
-#ifdef FILE_ATTRIBUTE_SYSTEM
-	{ "nosystem",	L"nosystem",	FILE_ATTRIBUTE_SYSTEM,	0},
-	{ "nousystem",	L"nousystem",	FILE_ATTRIBUTE_SYSTEM,	0},
-#endif
-#if defined(FS_UNRM_FL)		/* 'u' */
-	{ "noundel",	L"noundel",		FS_UNRM_FL,	0},
-#elif defined(EXT2_UNRM_FL)
-	{ "noundel",	L"noundel",		EXT2_UNRM_FL,	0},
-#endif
-
-#if defined(FS_COMPR_FL)	/* 'c' */
-	{ "nocompress",	L"nocompress",       	FS_COMPR_FL,	0},
-#elif defined(EXT2_COMPR_FL)
-	{ "nocompress",	L"nocompress",       	EXT2_COMPR_FL,	0},
-#endif
-
-#if defined(FS_NOATIME_FL)	/* 'A' */
-	{ "noatime",	L"noatime",		0,		FS_NOATIME_FL},
-#elif defined(EXT2_NOATIME_FL)
-	{ "noatime",	L"noatime",		0,		EXT2_NOATIME_FL},
-#endif
-#if defined(FS_DIRSYNC_FL)	/* 'D' */
-	{ "nodirsync",	L"nodirsync",		FS_DIRSYNC_FL,		0},
-#elif defined(EXT2_DIRSYNC_FL)
-	{ "nodirsync",	L"nodirsync",		EXT2_DIRSYNC_FL,	0},
-#endif
-#if defined(FS_JOURNAL_DATA_FL)	/* 'j' */
-	{ "nojournal-data",L"nojournal-data",	FS_JOURNAL_DATA_FL,	0},
-	{ "nojournal",	L"nojournal",		FS_JOURNAL_DATA_FL,	0},
-#elif defined(EXT3_JOURNAL_DATA_FL)
-	{ "nojournal-data",L"nojournal-data",	EXT3_JOURNAL_DATA_FL,	0},
-	{ "nojournal",	L"nojournal",		EXT3_JOURNAL_DATA_FL,	0},
-#endif
-#if defined(FS_SECRM_FL)	/* 's' */
-	{ "nosecdel",	L"nosecdel",		FS_SECRM_FL,		0},
-	{ "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL,		0},
-#elif defined(EXT2_SECRM_FL)
-	{ "nosecdel",	L"nosecdel",		EXT2_SECRM_FL,		0},
-	{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL,		0},
-#endif
-#if defined(FS_SYNC_FL)		/* 'S' */
-	{ "nosync",	L"nosync",		FS_SYNC_FL,		0},
-#elif defined(EXT2_SYNC_FL)
-	{ "nosync",	L"nosync",		EXT2_SYNC_FL,		0},
-#endif
-#if defined(FS_NOTAIL_FL)	/* 't' */
-	{ "notail",	L"notail",		0,		FS_NOTAIL_FL},
-#elif defined(EXT2_NOTAIL_FL)
-	{ "notail",	L"notail",		0,		EXT2_NOTAIL_FL},
-#endif
-#if defined(FS_TOPDIR_FL)	/* 'T' */
-	{ "notopdir",	L"notopdir",		FS_TOPDIR_FL,		0},
-#elif defined(EXT2_TOPDIR_FL)
-	{ "notopdir",	L"notopdir",		EXT2_TOPDIR_FL,		0},
-#endif
-#ifdef FS_NOCOW_FL	/* 'C' */
-	{ "nocow",	L"nocow",		0,	FS_NOCOW_FL},
-#endif
-#ifdef FS_PROJINHERIT_FL	/* 'P' */
-	{ "noprojinherit",L"noprojinherit",	FS_PROJINHERIT_FL,	0},
-#endif
-	{ NULL,		NULL,			0,		0}
-};
-
-/*
- * fflagstostr --
- *	Convert file flags to a comma-separated string.  If no flags
- *	are set, return the empty string.
- */
-static char *
-ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
-{
-	char *string, *dp;
-	const char *sp;
-	unsigned long bits;
-	const struct flag *flag;
-	size_t	length;
-
-	bits = bitset | bitclear;
-	length = 0;
-	for (flag = fileflags; flag->name != NULL; flag++)
-		if (bits & (flag->set | flag->clear)) {
-			length += strlen(flag->name) + 1;
-			bits &= ~(flag->set | flag->clear);
-		}
-
-	if (length == 0)
-		return (NULL);
-	string = (char *)malloc(length);
-	if (string == NULL)
-		return (NULL);
-
-	dp = string;
-	for (flag = fileflags; flag->name != NULL; flag++) {
-		if (bitset & flag->set || bitclear & flag->clear) {
-			sp = flag->name + 2;
-		} else if (bitset & flag->clear  ||  bitclear & flag->set) {
-			sp = flag->name;
-		} else
-			continue;
-		bitset &= ~(flag->set | flag->clear);
-		bitclear &= ~(flag->set | flag->clear);
-		if (dp > string)
-			*dp++ = ',';
-		while ((*dp++ = *sp++) != '\0')
-			;
-		dp--;
-	}
-
-	*dp = '\0';
-	return (string);
-}
-
-/*
- * strtofflags --
- *	Take string of arguments and return file flags.  This
- *	version works a little differently than strtofflags(3).
- *	In particular, it always tests every token, skipping any
- *	unrecognized tokens.  It returns a pointer to the first
- *	unrecognized token, or NULL if every token was recognized.
- *	This version is also const-correct and does not modify the
- *	provided string.
- */
-static const char *
-ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
-{
-	const char *start, *end;
-	const struct flag *flag;
-	unsigned long set, clear;
-	const char *failed;
-
-	set = clear = 0;
-	start = s;
-	failed = NULL;
-	/* Find start of first token. */
-	while (*start == '\t'  ||  *start == ' '  ||  *start == ',')
-		start++;
-	while (*start != '\0') {
-		size_t length;
-		/* Locate end of token. */
-		end = start;
-		while (*end != '\0'  &&  *end != '\t'  &&
-		    *end != ' '  &&  *end != ',')
-			end++;
-		length = end - start;
-		for (flag = fileflags; flag->name != NULL; flag++) {
-			size_t flag_length = strlen(flag->name);
-			if (length == flag_length
-			    && memcmp(start, flag->name, length) == 0) {
-				/* Matched "noXXXX", so reverse the sense. */
-				clear |= flag->set;
-				set |= flag->clear;
-				break;
-			} else if (length == flag_length - 2
-			    && memcmp(start, flag->name + 2, length) == 0) {
-				/* Matched "XXXX", so don't reverse. */
-				set |= flag->set;
-				clear |= flag->clear;
-				break;
-			}
-		}
-		/* Ignore unknown flag names. */
-		if (flag->name == NULL  &&  failed == NULL)
-			failed = start;
-
-		/* Find start of next token. */
-		start = end;
-		while (*start == '\t'  ||  *start == ' '  ||  *start == ',')
-			start++;
-
-	}
-
-	if (setp)
-		*setp = set;
-	if (clrp)
-		*clrp = clear;
-
-	/* Return location of first failure. */
-	return (failed);
-}
-
-/*
- * wcstofflags --
- *	Take string of arguments and return file flags.  This
- *	version works a little differently than strtofflags(3).
- *	In particular, it always tests every token, skipping any
- *	unrecognized tokens.  It returns a pointer to the first
- *	unrecognized token, or NULL if every token was recognized.
- *	This version is also const-correct and does not modify the
- *	provided string.
- */
-static const wchar_t *
-ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
-{
-	const wchar_t *start, *end;
-	const struct flag *flag;
-	unsigned long set, clear;
-	const wchar_t *failed;
-
-	set = clear = 0;
-	start = s;
-	failed = NULL;
-	/* Find start of first token. */
-	while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
-		start++;
-	while (*start != L'\0') {
-		size_t length;
-		/* Locate end of token. */
-		end = start;
-		while (*end != L'\0'  &&  *end != L'\t'  &&
-		    *end != L' '  &&  *end != L',')
-			end++;
-		length = end - start;
-		for (flag = fileflags; flag->wname != NULL; flag++) {
-			size_t flag_length = wcslen(flag->wname);
-			if (length == flag_length
-			    && wmemcmp(start, flag->wname, length) == 0) {
-				/* Matched "noXXXX", so reverse the sense. */
-				clear |= flag->set;
-				set |= flag->clear;
-				break;
-			} else if (length == flag_length - 2
-			    && wmemcmp(start, flag->wname + 2, length) == 0) {
-				/* Matched "XXXX", so don't reverse. */
-				set |= flag->set;
-				clear |= flag->clear;
-				break;
-			}
-		}
-		/* Ignore unknown flag names. */
-		if (flag->wname == NULL  &&  failed == NULL)
-			failed = start;
-
-		/* Find start of next token. */
-		start = end;
-		while (*start == L'\t'  ||  *start == L' '  ||  *start == L',')
-			start++;
-
-	}
-
-	if (setp)
-		*setp = set;
-	if (clrp)
-		*clrp = clear;
-
-	/* Return location of first failure. */
-	return (failed);
-}
-
-
-#ifdef TEST
-#include <stdio.h>
-int
-main(int argc, char **argv)
-{
-	struct archive_entry *entry = archive_entry_new();
-	unsigned long set, clear;
-	const wchar_t *remainder;
-
-	remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,");
-	archive_entry_fflags(entry, &set, &clear);
-
-	wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder);
-
-	wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry));
-	return (0);
-}
-#endif
diff --git a/c/archive_entry.h b/c/archive_entry.h
deleted file mode 100644
--- a/c/archive_entry.h
+++ /dev/null
@@ -1,723 +0,0 @@
-/*-
- * Copyright (c) 2003-2008 Tim Kientzle
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
- */
-
-#ifndef ARCHIVE_ENTRY_H_INCLUDED
-#define	ARCHIVE_ENTRY_H_INCLUDED
-
-/* Note: Compiler will complain if this does not match archive.h! */
-#define	ARCHIVE_VERSION_NUMBER 3007001
-
-/*
- * Note: archive_entry.h is for use outside of libarchive; the
- * configuration headers (config.h, archive_platform.h, etc.) are
- * purely internal.  Do NOT use HAVE_XXX configuration macros to
- * control the behavior of this header!  If you must conditionalize,
- * use predefined compiler and/or platform macros.
- */
-
-#include <sys/types.h>
-#include <stddef.h>  /* for wchar_t */
-#include <stdint.h>
-#include <time.h>
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
-#endif
-
-/* Get a suitable 64-bit integer type. */
-#if !defined(__LA_INT64_T_DEFINED)
-# if ARCHIVE_VERSION_NUMBER < 4000000
-#define __LA_INT64_T la_int64_t
-# endif
-#define __LA_INT64_T_DEFINED
-# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
-typedef __int64 la_int64_t;
-# else
-#include <unistd.h>
-#  if defined(_SCO_DS) || defined(__osf__)
-typedef long long la_int64_t;
-#  else
-typedef int64_t la_int64_t;
-#  endif
-# endif
-#endif
-
-/* The la_ssize_t should match the type used in 'struct stat' */
-#if !defined(__LA_SSIZE_T_DEFINED)
-/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
-# if ARCHIVE_VERSION_NUMBER < 4000000
-#define __LA_SSIZE_T la_ssize_t
-# endif
-#define __LA_SSIZE_T_DEFINED
-# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
-#  if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
-typedef ssize_t la_ssize_t;
-#  elif defined(_WIN64)
-typedef __int64 la_ssize_t;
-#  else
-typedef long la_ssize_t;
-#  endif
-# else
-# include <unistd.h>  /* ssize_t */
-typedef ssize_t la_ssize_t;
-# endif
-#endif
-
-/* Get a suitable definition for mode_t */
-#if ARCHIVE_VERSION_NUMBER >= 3999000
-/* Switch to plain 'int' for libarchive 4.0.  It's less broken than 'mode_t' */
-# define	__LA_MODE_T	int
-#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
-# define	__LA_MODE_T	unsigned short
-#else
-# define	__LA_MODE_T	mode_t
-#endif
-
-/* Large file support for Android */
-#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
-#include "android_lf.h"
-#endif
-
-/*
- * On Windows, define LIBARCHIVE_STATIC if you're building or using a
- * .lib.  The default here assumes you're building a DLL.  Only
- * libarchive source should ever define __LIBARCHIVE_BUILD.
- */
-#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
-# ifdef __LIBARCHIVE_BUILD
-#  ifdef __GNUC__
-#   define __LA_DECL	__attribute__((dllexport)) extern
-#  else
-#   define __LA_DECL	__declspec(dllexport)
-#  endif
-# else
-#  ifdef __GNUC__
-#   define __LA_DECL
-#  else
-#   define __LA_DECL	__declspec(dllimport)
-#  endif
-# endif
-#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
-#  define __LA_DECL __attribute__((visibility("default")))
-#else
-/* Static libraries on all platforms and shared libraries on non-Windows. */
-# define __LA_DECL
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
-# define __LA_DEPRECATED __attribute__((deprecated))
-#else
-# define __LA_DEPRECATED
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Description of an archive entry.
- *
- * You can think of this as "struct stat" with some text fields added in.
- *
- * TODO: Add "comment", "charset", and possibly other entries that are
- * supported by "pax interchange" format.  However, GNU, ustar, cpio,
- * and other variants don't support these features, so they're not an
- * excruciatingly high priority right now.
- *
- * TODO: "pax interchange" format allows essentially arbitrary
- * key/value attributes to be attached to any entry.  Supporting
- * such extensions may make this library useful for special
- * applications (e.g., a package manager could attach special
- * package-management attributes to each entry).
- */
-struct archive;
-struct archive_entry;
-
-/*
- * File-type constants.  These are returned from archive_entry_filetype()
- * and passed to archive_entry_set_filetype().
- *
- * These values match S_XXX defines on every platform I've checked,
- * including Windows, AIX, Linux, Solaris, and BSD.  They're
- * (re)defined here because platforms generally don't define the ones
- * they don't support.  For example, Windows doesn't define S_IFLNK or
- * S_IFBLK.  Instead of having a mass of conditional logic and system
- * checks to define any S_XXX values that aren't supported locally,
- * I've just defined a new set of such constants so that
- * libarchive-based applications can manipulate and identify archive
- * entries properly even if the hosting platform can't store them on
- * disk.
- *
- * These values are also used directly within some portable formats,
- * such as cpio.  If you find a platform that varies from these, the
- * correct solution is to leave these alone and translate from these
- * portable values to platform-native values when entries are read from
- * or written to disk.
- */
-/*
- * In libarchive 4.0, we can drop the casts here.
- * They're needed to work around Borland C's broken mode_t.
- */
-#define AE_IFMT		((__LA_MODE_T)0170000)
-#define AE_IFREG	((__LA_MODE_T)0100000)
-#define AE_IFLNK	((__LA_MODE_T)0120000)
-#define AE_IFSOCK	((__LA_MODE_T)0140000)
-#define AE_IFCHR	((__LA_MODE_T)0020000)
-#define AE_IFBLK	((__LA_MODE_T)0060000)
-#define AE_IFDIR	((__LA_MODE_T)0040000)
-#define AE_IFIFO	((__LA_MODE_T)0010000)
-
-/*
- * Symlink types
- */
-#define AE_SYMLINK_TYPE_UNDEFINED	0
-#define AE_SYMLINK_TYPE_FILE		1
-#define AE_SYMLINK_TYPE_DIRECTORY	2
-
-/*
- * Basic object manipulation
- */
-
-__LA_DECL struct archive_entry	*archive_entry_clear(struct archive_entry *);
-/* The 'clone' function does a deep copy; all of the strings are copied too. */
-__LA_DECL struct archive_entry	*archive_entry_clone(struct archive_entry *);
-__LA_DECL void			 archive_entry_free(struct archive_entry *);
-__LA_DECL struct archive_entry	*archive_entry_new(void);
-
-/*
- * This form of archive_entry_new2() will pull character-set
- * conversion information from the specified archive handle.  The
- * older archive_entry_new(void) form is equivalent to calling
- * archive_entry_new2(NULL) and will result in the use of an internal
- * default character-set conversion.
- */
-__LA_DECL struct archive_entry	*archive_entry_new2(struct archive *);
-
-/*
- * Retrieve fields from an archive_entry.
- *
- * There are a number of implicit conversions among these fields.  For
- * example, if a regular string field is set and you read the _w wide
- * character field, the entry will implicitly convert narrow-to-wide
- * using the current locale.  Similarly, dev values are automatically
- * updated when you write devmajor or devminor and vice versa.
- *
- * In addition, fields can be "set" or "unset."  Unset string fields
- * return NULL, non-string fields have _is_set() functions to test
- * whether they've been set.  You can "unset" a string field by
- * assigning NULL; non-string fields have _unset() functions to
- * unset them.
- *
- * Note: There is one ambiguity in the above; string fields will
- * also return NULL when implicit character set conversions fail.
- * This is usually what you want.
- */
-__LA_DECL time_t	 archive_entry_atime(struct archive_entry *);
-__LA_DECL long		 archive_entry_atime_nsec(struct archive_entry *);
-__LA_DECL int		 archive_entry_atime_is_set(struct archive_entry *);
-__LA_DECL time_t	 archive_entry_birthtime(struct archive_entry *);
-__LA_DECL long		 archive_entry_birthtime_nsec(struct archive_entry *);
-__LA_DECL int		 archive_entry_birthtime_is_set(struct archive_entry *);
-__LA_DECL time_t	 archive_entry_ctime(struct archive_entry *);
-__LA_DECL long		 archive_entry_ctime_nsec(struct archive_entry *);
-__LA_DECL int		 archive_entry_ctime_is_set(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_dev(struct archive_entry *);
-__LA_DECL int		 archive_entry_dev_is_set(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_devmajor(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_devminor(struct archive_entry *);
-__LA_DECL __LA_MODE_T	 archive_entry_filetype(struct archive_entry *);
-__LA_DECL void		 archive_entry_fflags(struct archive_entry *,
-			    unsigned long * /* set */,
-			    unsigned long * /* clear */);
-__LA_DECL const char	*archive_entry_fflags_text(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_gid(struct archive_entry *);
-__LA_DECL const char	*archive_entry_gname(struct archive_entry *);
-__LA_DECL const char	*archive_entry_gname_utf8(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_gname_w(struct archive_entry *);
-__LA_DECL const char	*archive_entry_hardlink(struct archive_entry *);
-__LA_DECL const char	*archive_entry_hardlink_utf8(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_hardlink_w(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_ino(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_ino64(struct archive_entry *);
-__LA_DECL int		 archive_entry_ino_is_set(struct archive_entry *);
-__LA_DECL __LA_MODE_T	 archive_entry_mode(struct archive_entry *);
-__LA_DECL time_t	 archive_entry_mtime(struct archive_entry *);
-__LA_DECL long		 archive_entry_mtime_nsec(struct archive_entry *);
-__LA_DECL int		 archive_entry_mtime_is_set(struct archive_entry *);
-__LA_DECL unsigned int	 archive_entry_nlink(struct archive_entry *);
-__LA_DECL const char	*archive_entry_pathname(struct archive_entry *);
-__LA_DECL const char	*archive_entry_pathname_utf8(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_pathname_w(struct archive_entry *);
-__LA_DECL __LA_MODE_T	 archive_entry_perm(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdev(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdevmajor(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdevminor(struct archive_entry *);
-__LA_DECL const char	*archive_entry_sourcepath(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_sourcepath_w(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_size(struct archive_entry *);
-__LA_DECL int		 archive_entry_size_is_set(struct archive_entry *);
-__LA_DECL const char	*archive_entry_strmode(struct archive_entry *);
-__LA_DECL const char	*archive_entry_symlink(struct archive_entry *);
-__LA_DECL const char	*archive_entry_symlink_utf8(struct archive_entry *);
-__LA_DECL int		 archive_entry_symlink_type(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_symlink_w(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_uid(struct archive_entry *);
-__LA_DECL const char	*archive_entry_uname(struct archive_entry *);
-__LA_DECL const char	*archive_entry_uname_utf8(struct archive_entry *);
-__LA_DECL const wchar_t	*archive_entry_uname_w(struct archive_entry *);
-__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
-__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
-__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
-
-/*
- * Set fields in an archive_entry.
- *
- * Note: Before libarchive 2.4, there were 'set' and 'copy' versions
- * of the string setters.  'copy' copied the actual string, 'set' just
- * stored the pointer.  In libarchive 2.4 and later, strings are
- * always copied.
- */
-
-__LA_DECL void	archive_entry_set_atime(struct archive_entry *, time_t, long);
-__LA_DECL void  archive_entry_unset_atime(struct archive_entry *);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
-#endif
-__LA_DECL void	archive_entry_set_birthtime(struct archive_entry *, time_t, long);
-__LA_DECL void  archive_entry_unset_birthtime(struct archive_entry *);
-__LA_DECL void	archive_entry_set_ctime(struct archive_entry *, time_t, long);
-__LA_DECL void  archive_entry_unset_ctime(struct archive_entry *);
-__LA_DECL void	archive_entry_set_dev(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_devmajor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_devminor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_filetype(struct archive_entry *, unsigned int);
-__LA_DECL void	archive_entry_set_fflags(struct archive_entry *,
-	    unsigned long /* set */, unsigned long /* clear */);
-/* Returns pointer to start of first invalid token, or NULL if none. */
-/* Note that all recognized tokens are processed, regardless. */
-__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
-	    const char *);
-__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
-	    const wchar_t *);
-__LA_DECL void	archive_entry_set_gid(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_set_gname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_gname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_gname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_gname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_hardlink(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_hardlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_hardlink(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_ino(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_set_ino64(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_set_link(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_link_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_link(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_link_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
-__LA_DECL void	archive_entry_set_mtime(struct archive_entry *, time_t, long);
-__LA_DECL void  archive_entry_unset_mtime(struct archive_entry *);
-__LA_DECL void	archive_entry_set_nlink(struct archive_entry *, unsigned int);
-__LA_DECL void	archive_entry_set_pathname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_pathname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_pathname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
-__LA_DECL void	archive_entry_set_rdev(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_rdevminor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_size(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_unset_size(struct archive_entry *);
-__LA_DECL void	archive_entry_copy_sourcepath(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
-__LA_DECL void	archive_entry_set_symlink(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_symlink_type(struct archive_entry *, int);
-__LA_DECL void	archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_symlink(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_uid(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_set_uname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_uname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_uname(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
-__LA_DECL int	archive_entry_update_uname_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
-__LA_DECL void	archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
-/*
- * Routines to bulk copy fields to/from a platform-native "struct
- * stat."  Libarchive used to just store a struct stat inside of each
- * archive_entry object, but this created issues when trying to
- * manipulate archives on systems different than the ones they were
- * created on.
- *
- * TODO: On Linux and other LFS systems, provide both stat32 and
- * stat64 versions of these functions and all of the macro glue so
- * that archive_entry_stat is magically defined to
- * archive_entry_stat32 or archive_entry_stat64 as appropriate.
- */
-__LA_DECL const struct stat	*archive_entry_stat(struct archive_entry *);
-__LA_DECL void	archive_entry_copy_stat(struct archive_entry *, const struct stat *);
-
-/*
- * Storage for Mac OS-specific AppleDouble metadata information.
- * Apple-format tar files store a separate binary blob containing
- * encoded metadata with ACL, extended attributes, etc.
- * This provides a place to store that blob.
- */
-
-__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *);
-__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
-
-/*
- * Digest routine. This is used to query the raw hex digest for the
- * given entry. The type of digest is provided as an argument.
- */
-#define ARCHIVE_ENTRY_DIGEST_MD5              0x00000001
-#define ARCHIVE_ENTRY_DIGEST_RMD160           0x00000002
-#define ARCHIVE_ENTRY_DIGEST_SHA1             0x00000003
-#define ARCHIVE_ENTRY_DIGEST_SHA256           0x00000004
-#define ARCHIVE_ENTRY_DIGEST_SHA384           0x00000005
-#define ARCHIVE_ENTRY_DIGEST_SHA512           0x00000006
-
-__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
-
-/*
- * ACL routines.  This used to simply store and return text-format ACL
- * strings, but that proved insufficient for a number of reasons:
- *   = clients need control over uname/uid and gname/gid mappings
- *   = there are many different ACL text formats
- *   = would like to be able to read/convert archives containing ACLs
- *     on platforms that lack ACL libraries
- *
- *  This last point, in particular, forces me to implement a reasonably
- *  complete set of ACL support routines.
- */
-
-/*
- * Permission bits.
- */
-#define	ARCHIVE_ENTRY_ACL_EXECUTE             0x00000001
-#define	ARCHIVE_ENTRY_ACL_WRITE               0x00000002
-#define	ARCHIVE_ENTRY_ACL_READ                0x00000004
-#define	ARCHIVE_ENTRY_ACL_READ_DATA           0x00000008
-#define	ARCHIVE_ENTRY_ACL_LIST_DIRECTORY      0x00000008
-#define	ARCHIVE_ENTRY_ACL_WRITE_DATA          0x00000010
-#define	ARCHIVE_ENTRY_ACL_ADD_FILE            0x00000010
-#define	ARCHIVE_ENTRY_ACL_APPEND_DATA         0x00000020
-#define	ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY    0x00000020
-#define	ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS    0x00000040
-#define	ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS   0x00000080
-#define	ARCHIVE_ENTRY_ACL_DELETE_CHILD        0x00000100
-#define	ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES     0x00000200
-#define	ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES    0x00000400
-#define	ARCHIVE_ENTRY_ACL_DELETE              0x00000800
-#define	ARCHIVE_ENTRY_ACL_READ_ACL            0x00001000
-#define	ARCHIVE_ENTRY_ACL_WRITE_ACL           0x00002000
-#define	ARCHIVE_ENTRY_ACL_WRITE_OWNER         0x00004000
-#define	ARCHIVE_ENTRY_ACL_SYNCHRONIZE         0x00008000
-
-#define	ARCHIVE_ENTRY_ACL_PERMS_POSIX1E			\
-	(ARCHIVE_ENTRY_ACL_EXECUTE			\
-	    | ARCHIVE_ENTRY_ACL_WRITE			\
-	    | ARCHIVE_ENTRY_ACL_READ)
-
-#define ARCHIVE_ENTRY_ACL_PERMS_NFS4			\
-	(ARCHIVE_ENTRY_ACL_EXECUTE			\
-	    | ARCHIVE_ENTRY_ACL_READ_DATA		\
-	    | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 		\
-	    | ARCHIVE_ENTRY_ACL_WRITE_DATA		\
-	    | ARCHIVE_ENTRY_ACL_ADD_FILE		\
-	    | ARCHIVE_ENTRY_ACL_APPEND_DATA		\
-	    | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY	\
-	    | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS	\
-	    | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS	\
-	    | ARCHIVE_ENTRY_ACL_DELETE_CHILD		\
-	    | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES		\
-	    | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES	\
-	    | ARCHIVE_ENTRY_ACL_DELETE			\
-	    | ARCHIVE_ENTRY_ACL_READ_ACL		\
-	    | ARCHIVE_ENTRY_ACL_WRITE_ACL		\
-	    | ARCHIVE_ENTRY_ACL_WRITE_OWNER		\
-	    | ARCHIVE_ENTRY_ACL_SYNCHRONIZE)
-
-/*
- * Inheritance values (NFS4 ACLs only); included in permset.
- */
-#define	ARCHIVE_ENTRY_ACL_ENTRY_INHERITED                   0x01000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT                0x02000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT           0x04000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT        0x08000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY                0x10000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS           0x20000000
-#define	ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS               0x40000000
-
-#define	ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4			\
-	(ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT			\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT		\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT	\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY		\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS		\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS		\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
-
-/* We need to be able to specify combinations of these. */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ACCESS	0x00000100  /* POSIX.1e only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_DEFAULT	0x00000200  /* POSIX.1e only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ALLOW	0x00000400 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_DENY	0x00000800 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_AUDIT	0x00001000 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ALARM	0x00002000 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_POSIX1E	(ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
-	    | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
-#define	ARCHIVE_ENTRY_ACL_TYPE_NFS4	(ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
-	    | ARCHIVE_ENTRY_ACL_TYPE_DENY \
-	    | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \
-	    | ARCHIVE_ENTRY_ACL_TYPE_ALARM)
-
-/* Tag values mimic POSIX.1e */
-#define	ARCHIVE_ENTRY_ACL_USER		10001	/* Specified user. */
-#define	ARCHIVE_ENTRY_ACL_USER_OBJ 	10002	/* User who owns the file. */
-#define	ARCHIVE_ENTRY_ACL_GROUP		10003	/* Specified group. */
-#define	ARCHIVE_ENTRY_ACL_GROUP_OBJ	10004	/* Group who owns the file. */
-#define	ARCHIVE_ENTRY_ACL_MASK		10005	/* Modify group access (POSIX.1e only) */
-#define	ARCHIVE_ENTRY_ACL_OTHER		10006	/* Public (POSIX.1e only) */
-#define	ARCHIVE_ENTRY_ACL_EVERYONE	10107   /* Everyone (NFS4 only) */
-
-/*
- * Set the ACL by clearing it and adding entries one at a time.
- * Unlike the POSIX.1e ACL routines, you must specify the type
- * (access/default) for each entry.  Internally, the ACL data is just
- * a soup of entries.  API calls here allow you to retrieve just the
- * entries of interest.  This design (which goes against the spirit of
- * POSIX.1e) is useful for handling archive formats that combine
- * default and access information in a single ACL list.
- */
-__LA_DECL void	 archive_entry_acl_clear(struct archive_entry *);
-__LA_DECL int	 archive_entry_acl_add_entry(struct archive_entry *,
-	    int /* type */, int /* permset */, int /* tag */,
-	    int /* qual */, const char * /* name */);
-__LA_DECL int	 archive_entry_acl_add_entry_w(struct archive_entry *,
-	    int /* type */, int /* permset */, int /* tag */,
-	    int /* qual */, const wchar_t * /* name */);
-
-/*
- * To retrieve the ACL, first "reset", then repeatedly ask for the
- * "next" entry.  The want_type parameter allows you to request only
- * certain types of entries.
- */
-__LA_DECL int	 archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
-__LA_DECL int	 archive_entry_acl_next(struct archive_entry *, int /* want_type */,
-	    int * /* type */, int * /* permset */, int * /* tag */,
-	    int * /* qual */, const char ** /* name */);
-
-/*
- * Construct a text-format ACL.  The flags argument is a bitmask that
- * can include any of the following:
- *
- * Flags only for archive entries with POSIX.1e ACL:
- * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
- * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
- *    default ACL entry.
- * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
- *    "mask" entries.
- *
- * Flags only for archive entries with NFSv4 ACL:
- * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
- *    unset permissions and flags in NFSv4 ACL permission and flag fields
- *
- * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
- * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
- *    each ACL entry.
- * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
- *    instead of newline.
- */
-#define	ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID	0x00000001
-#define	ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT	0x00000002
-#define	ARCHIVE_ENTRY_ACL_STYLE_SOLARIS		0x00000004
-#define	ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA	0x00000008
-#define	ARCHIVE_ENTRY_ACL_STYLE_COMPACT		0x00000010
-
-__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
-	    la_ssize_t * /* len */, int /* flags */);
-__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
-	    la_ssize_t * /* len */, int /* flags */);
-__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
-	    const wchar_t * /* wtext */, int /* type */);
-__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
-	    const char * /* text */, int /* type */);
-
-/* Deprecated constants */
-#define	OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID		1024
-#define	OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT	2048
-
-/* Deprecated functions */
-__LA_DECL const wchar_t	*archive_entry_acl_text_w(struct archive_entry *,
-		    int /* flags */) __LA_DEPRECATED;
-__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
-		    int /* flags */) __LA_DEPRECATED;
-
-/* Return bitmask of ACL types in an archive entry */
-__LA_DECL int	 archive_entry_acl_types(struct archive_entry *);
-
-/* Return a count of entries matching 'want_type' */
-__LA_DECL int	 archive_entry_acl_count(struct archive_entry *, int /* want_type */);
-
-/* Return an opaque ACL object. */
-/* There's not yet anything clients can actually do with this... */
-struct archive_acl;
-__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *);
-
-/*
- * extended attributes
- */
-
-__LA_DECL void	 archive_entry_xattr_clear(struct archive_entry *);
-__LA_DECL void	 archive_entry_xattr_add_entry(struct archive_entry *,
-	    const char * /* name */, const void * /* value */,
-	    size_t /* size */);
-
-/*
- * To retrieve the xattr list, first "reset", then repeatedly ask for the
- * "next" entry.
- */
-
-__LA_DECL int	archive_entry_xattr_count(struct archive_entry *);
-__LA_DECL int	archive_entry_xattr_reset(struct archive_entry *);
-__LA_DECL int	archive_entry_xattr_next(struct archive_entry *,
-	    const char ** /* name */, const void ** /* value */, size_t *);
-
-/*
- * sparse
- */
-
-__LA_DECL void	 archive_entry_sparse_clear(struct archive_entry *);
-__LA_DECL void	 archive_entry_sparse_add_entry(struct archive_entry *,
-	    la_int64_t /* offset */, la_int64_t /* length */);
-
-/*
- * To retrieve the xattr list, first "reset", then repeatedly ask for the
- * "next" entry.
- */
-
-__LA_DECL int	archive_entry_sparse_count(struct archive_entry *);
-__LA_DECL int	archive_entry_sparse_reset(struct archive_entry *);
-__LA_DECL int	archive_entry_sparse_next(struct archive_entry *,
-	    la_int64_t * /* offset */, la_int64_t * /* length */);
-
-/*
- * Utility to match up hardlinks.
- *
- * The 'struct archive_entry_linkresolver' is a cache of archive entries
- * for files with multiple links.  Here's how to use it:
- *   1. Create a lookup object with archive_entry_linkresolver_new()
- *   2. Tell it the archive format you're using.
- *   3. Hand each archive_entry to archive_entry_linkify().
- *      That function will return 0, 1, or 2 entries that should
- *      be written.
- *   4. Call archive_entry_linkify(resolver, NULL) until
- *      no more entries are returned.
- *   5. Call archive_entry_linkresolver_free(resolver) to free resources.
- *
- * The entries returned have their hardlink and size fields updated
- * appropriately.  If an entry is passed in that does not refer to
- * a file with multiple links, it is returned unchanged.  The intention
- * is that you should be able to simply filter all entries through
- * this machine.
- *
- * 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.
- *
- * Note that archive_entry_size() is reset to zero if the file
- * body should not be written to the archive.  Pay attention!
- */
-struct archive_entry_linkresolver;
-
-/*
- * There are three different strategies for marking hardlinks.
- * The descriptions below name them after the best-known
- * formats that rely on each strategy:
- *
- * "Old cpio" is the simplest, it always returns any entry unmodified.
- *    As far as I know, only cpio formats use this.  Old cpio archives
- *    store every link with the full body; the onus is on the dearchiver
- *    to detect and properly link the files as they are restored.
- * "tar" is also pretty simple; it caches a copy the first time it sees
- *    any link.  Subsequent appearances are modified to be hardlink
- *    references to the first one without any body.  Used by all tar
- *    formats, although the newest tar formats permit the "old cpio" strategy
- *    as well.  This strategy is very simple for the dearchiver,
- *    and reasonably straightforward for the archiver.
- * "new cpio" is trickier.  It stores the body only with the last
- *    occurrence.  The complication is that we might not
- *    see every link to a particular file in a single session, so
- *    there's no easy way to know when we've seen the last occurrence.
- *    The solution here is to queue one link until we see the next.
- *    At the end of the session, you can enumerate any remaining
- *    entries by calling archive_entry_linkify(NULL) and store those
- *    bodies.  If you have a file with three links l1, l2, and l3,
- *    you'll get the following behavior if you see all three links:
- *           linkify(l1) => NULL   (the resolver stores l1 internally)
- *           linkify(l2) => l1     (resolver stores l2, you write l1)
- *           linkify(l3) => l2, l3 (all links seen, you can write both).
- *    If you only see l1 and l2, you'll get this behavior:
- *           linkify(l1) => NULL
- *           linkify(l2) => l1
- *           linkify(NULL) => l2   (at end, you retrieve remaining links)
- *    As the name suggests, this strategy is used by newer cpio variants.
- *    It's noticeably more complex for the archiver, slightly more complex
- *    for the dearchiver than the tar strategy, but makes it straightforward
- *    to restore a file using any link by simply continuing to scan until
- *    you see a link that is stored with a body.  In contrast, the tar
- *    strategy requires you to rescan the archive from the beginning to
- *    correctly extract an arbitrary link.
- */
-
-__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
-__LA_DECL void archive_entry_linkresolver_set_strategy(
-	struct archive_entry_linkresolver *, int /* format_code */);
-__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
-__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
-    struct archive_entry **, struct archive_entry **);
-__LA_DECL struct archive_entry *archive_entry_partial_links(
-    struct archive_entry_linkresolver *res, unsigned int *links);
-#ifdef __cplusplus
-}
-#endif
-
-/* This is meaningless outside of this header. */
-#undef __LA_DECL
-
-#endif /* !ARCHIVE_ENTRY_H_INCLUDED */
diff --git a/c/archive_entry_copy_bhfi.c b/c/archive_entry_copy_bhfi.c
deleted file mode 100644
--- a/c/archive_entry_copy_bhfi.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive_private.h"
-#include "archive_entry.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-__inline static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		*t = (time_t)(utc.QuadPart / 10000000);	/* milli seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
-void
-archive_entry_copy_bhfi(struct archive_entry *entry,
-			BY_HANDLE_FILE_INFORMATION *bhfi)
-{
-	time_t secs;
-	long nsecs;
-
-	fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
-	archive_entry_set_atime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
-	archive_entry_set_mtime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
-	archive_entry_set_birthtime(entry, secs, nsecs);
-	archive_entry_set_ctime(entry, secs, nsecs);
-	archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
-	archive_entry_set_ino64(entry, (((int64_t)bhfi->nFileIndexHigh) << 32)
-		+ bhfi->nFileIndexLow);
-	archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
-	archive_entry_set_size(entry, (((int64_t)bhfi->nFileSizeHigh) << 32)
-		+ bhfi->nFileSizeLow);
-	/* archive_entry_set_mode(entry, st->st_mode); */
-}
-#endif
diff --git a/c/archive_entry_copy_stat.c b/c/archive_entry_copy_stat.c
deleted file mode 100644
--- a/c/archive_entry_copy_stat.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_copy_stat.c 189466 2009-03-07 00:52:02Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-
-void
-archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
-{
-#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
-	archive_entry_set_atime(entry, st->st_atime, st->st_atimespec.tv_nsec);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctimespec.tv_nsec);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtimespec.tv_nsec);
-#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-	archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
-#elif HAVE_STRUCT_STAT_ST_MTIME_NSEC
-	archive_entry_set_atime(entry, st->st_atime, st->st_atime_nsec);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_nsec);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_nsec);
-#elif HAVE_STRUCT_STAT_ST_MTIME_N
-	archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_n);
-#elif HAVE_STRUCT_STAT_ST_UMTIME
-	archive_entry_set_atime(entry, st->st_atime, st->st_uatime * 1000);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_uctime * 1000);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_umtime * 1000);
-#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
-	archive_entry_set_atime(entry, st->st_atime, st->st_atime_usec * 1000);
-	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_usec * 1000);
-	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_usec * 1000);
-#else
-	archive_entry_set_atime(entry, st->st_atime, 0);
-	archive_entry_set_ctime(entry, st->st_ctime, 0);
-	archive_entry_set_mtime(entry, st->st_mtime, 0);
-#endif
-#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
-	archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec);
-#elif HAVE_STRUCT_STAT_ST_BIRTHTIME
-	archive_entry_set_birthtime(entry, st->st_birthtime, 0);
-#else
-	archive_entry_unset_birthtime(entry);
-#endif
-	archive_entry_set_dev(entry, st->st_dev);
-	archive_entry_set_gid(entry, st->st_gid);
-	archive_entry_set_uid(entry, st->st_uid);
-	archive_entry_set_ino(entry, st->st_ino);
-	archive_entry_set_nlink(entry, st->st_nlink);
-	archive_entry_set_rdev(entry, st->st_rdev);
-	archive_entry_set_size(entry, st->st_size);
-	archive_entry_set_mode(entry, st->st_mode);
-}
diff --git a/c/archive_entry_link_resolver.c b/c/archive_entry_link_resolver.c
deleted file mode 100644
--- a/c/archive_entry_link_resolver.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_link_resolver.c 201100 2009-12-28 03:05:31Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-
-/*
- * This is mostly a pretty straightforward hash table implementation.
- * The only interesting bit is the different strategies used to
- * match up links.  These strategies match those used by various
- * archiving formats:
- *   tar - content stored with first link, remainder refer back to it.
- *       This requires us to match each subsequent link up with the
- *       first appearance.
- *   cpio - Old cpio just stored body with each link, match-ups were
- *       implicit.  This is trivial.
- *   new cpio - New cpio only stores body with last link, match-ups
- *       are implicit.  This is actually quite tricky; see the notes
- *       below.
- */
-
-/* Users pass us a format code, we translate that into a strategy here. */
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_TAR	0
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE 1
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 2
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 3
-
-/* Initial size of link cache. */
-#define	links_cache_initial_size 1024
-
-struct links_entry {
-	struct links_entry	*next;
-	struct links_entry	*previous;
-	struct archive_entry	*canonical;
-	struct archive_entry	*entry;
-	size_t			 hash;
-	unsigned int		 links; /* # links not yet seen */
-};
-
-struct archive_entry_linkresolver {
-	struct links_entry	**buckets;
-	struct links_entry	 *spare;
-	unsigned long		  number_entries;
-	size_t			  number_buckets;
-	int			  strategy;
-};
-
-#define	NEXT_ENTRY_DEFERRED	1
-#define	NEXT_ENTRY_PARTIAL	2
-#define	NEXT_ENTRY_ALL		(NEXT_ENTRY_DEFERRED | NEXT_ENTRY_PARTIAL)
-
-static struct links_entry *find_entry(struct archive_entry_linkresolver *,
-		    struct archive_entry *);
-static void grow_hash(struct archive_entry_linkresolver *);
-static struct links_entry *insert_entry(struct archive_entry_linkresolver *,
-		    struct archive_entry *);
-static struct links_entry *next_entry(struct archive_entry_linkresolver *,
-    int);
-
-struct archive_entry_linkresolver *
-archive_entry_linkresolver_new(void)
-{
-	struct archive_entry_linkresolver *res;
-
-	/* Check for positive power-of-two */
-	if (links_cache_initial_size == 0 ||
-	    (links_cache_initial_size & (links_cache_initial_size - 1)) != 0)
-		return (NULL);
-
-	res = calloc(1, sizeof(struct archive_entry_linkresolver));
-	if (res == NULL)
-		return (NULL);
-	res->number_buckets = links_cache_initial_size;
-	res->buckets = calloc(res->number_buckets, sizeof(res->buckets[0]));
-	if (res->buckets == NULL) {
-		free(res);
-		return (NULL);
-	}
-	return (res);
-}
-
-void
-archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
-    int fmt)
-{
-	int fmtbase = fmt & ARCHIVE_FORMAT_BASE_MASK;
-
-	switch (fmtbase) {
-	case ARCHIVE_FORMAT_7ZIP:
-	case ARCHIVE_FORMAT_AR:
-	case ARCHIVE_FORMAT_ZIP:
-		res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
-		break;
-	case ARCHIVE_FORMAT_CPIO:
-		switch (fmt) {
-		case ARCHIVE_FORMAT_CPIO_SVR4_NOCRC:
-		case ARCHIVE_FORMAT_CPIO_SVR4_CRC:
-			res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO;
-			break;
-		default:
-			res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
-			break;
-		}
-		break;
-	case ARCHIVE_FORMAT_MTREE:
-		res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
-		break;
-	case ARCHIVE_FORMAT_ISO9660:
-	case ARCHIVE_FORMAT_SHAR:
-	case ARCHIVE_FORMAT_TAR:
-	case ARCHIVE_FORMAT_XAR:
-		res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
-		break;
-	default:
-		res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
-		break;
-	}
-}
-
-void
-archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
-{
-	struct links_entry *le;
-
-	if (res == NULL)
-		return;
-
-	while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL)
-		archive_entry_free(le->entry);
-	free(res->buckets);
-	free(res);
-}
-
-void
-archive_entry_linkify(struct archive_entry_linkresolver *res,
-    struct archive_entry **e, struct archive_entry **f)
-{
-	struct links_entry *le;
-	struct archive_entry *t;
-
-	*f = NULL; /* Default: Don't return a second entry. */
-
-	if (*e == NULL) {
-		le = next_entry(res, NEXT_ENTRY_DEFERRED);
-		if (le != NULL) {
-			*e = le->entry;
-			le->entry = NULL;
-		}
-		return;
-	}
-
-	/* If it has only one link, then we're done. */
-	if (archive_entry_nlink(*e) == 1)
-		return;
-	/* Directories, devices never have hardlinks. */
-	if (archive_entry_filetype(*e) == AE_IFDIR
-	    || archive_entry_filetype(*e) == AE_IFBLK
-	    || archive_entry_filetype(*e) == AE_IFCHR)
-		return;
-
-	switch (res->strategy) {
-	case ARCHIVE_ENTRY_LINKIFY_LIKE_TAR:
-		le = find_entry(res, *e);
-		if (le != NULL) {
-			archive_entry_unset_size(*e);
-			archive_entry_copy_hardlink(*e,
-			    archive_entry_pathname(le->canonical));
-		} else
-			insert_entry(res, *e);
-		return;
-	case ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE:
-		le = find_entry(res, *e);
-		if (le != NULL) {
-			archive_entry_copy_hardlink(*e,
-			    archive_entry_pathname(le->canonical));
-		} else
-			insert_entry(res, *e);
-		return;
-	case ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO:
-		/* This one is trivial. */
-		return;
-	case ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO:
-		le = find_entry(res, *e);
-		if (le != NULL) {
-			/*
-			 * Put the new entry in le, return the
-			 * old entry from le.
-			 */
-			t = *e;
-			*e = le->entry;
-			le->entry = t;
-			/* Make the old entry into a hardlink. */
-			archive_entry_unset_size(*e);
-			archive_entry_copy_hardlink(*e,
-			    archive_entry_pathname(le->canonical));
-			/* If we ran out of links, return the
-			 * final entry as well. */
-			if (le->links == 0) {
-				*f = le->entry;
-				le->entry = NULL;
-			}
-		} else {
-			/*
-			 * If we haven't seen it, tuck it away
-			 * for future use.
-			 */
-			le = insert_entry(res, *e);
-			if (le == NULL)
-				/* XXX We should return an error code XXX */
-				return;
-			le->entry = *e;
-			*e = NULL;
-		}
-		return;
-	default:
-		break;
-	}
-	return;
-}
-
-static struct links_entry *
-find_entry(struct archive_entry_linkresolver *res,
-    struct archive_entry *entry)
-{
-	struct links_entry	*le;
-	size_t			 hash, bucket;
-	dev_t			 dev;
-	int64_t			 ino;
-
-	/* Free a held entry. */
-	if (res->spare != NULL) {
-		archive_entry_free(res->spare->canonical);
-		archive_entry_free(res->spare->entry);
-		free(res->spare);
-		res->spare = NULL;
-	}
-
-	dev = archive_entry_dev(entry);
-	ino = archive_entry_ino64(entry);
-	hash = (size_t)(dev ^ ino);
-
-	/* Try to locate this entry in the links cache. */
-	bucket = hash & (res->number_buckets - 1);
-	for (le = res->buckets[bucket]; le != NULL; le = le->next) {
-		if (le->hash == hash
-		    && dev == archive_entry_dev(le->canonical)
-		    && ino == archive_entry_ino64(le->canonical)) {
-			/*
-			 * Decrement link count each time and release
-			 * the entry if it hits zero.  This saves
-			 * memory and is necessary for detecting
-			 * missed links.
-			 */
-			--le->links;
-			if (le->links > 0)
-				return (le);
-			/* Remove it from this hash bucket. */
-			if (le->previous != NULL)
-				le->previous->next = le->next;
-			if (le->next != NULL)
-				le->next->previous = le->previous;
-			if (res->buckets[bucket] == le)
-				res->buckets[bucket] = le->next;
-			res->number_entries--;
-			/* Defer freeing this entry. */
-			res->spare = le;
-			return (le);
-		}
-	}
-	return (NULL);
-}
-
-static struct links_entry *
-next_entry(struct archive_entry_linkresolver *res, int mode)
-{
-	struct links_entry	*le;
-	size_t			 bucket;
-
-	/* Free a held entry. */
-	if (res->spare != NULL) {
-		archive_entry_free(res->spare->canonical);
-		archive_entry_free(res->spare->entry);
-		free(res->spare);
-		res->spare = NULL;
-	}
-
-	/* Look for next non-empty bucket in the links cache. */
-	for (bucket = 0; bucket < res->number_buckets; bucket++) {
-		for (le = res->buckets[bucket]; le != NULL; le = le->next) {
-			if (le->entry != NULL &&
-			    (mode & NEXT_ENTRY_DEFERRED) == 0)
-				continue;
-			if (le->entry == NULL &&
-			    (mode & NEXT_ENTRY_PARTIAL) == 0)
-				continue;
-			/* Remove it from this hash bucket. */
-			if (le->next != NULL)
-				le->next->previous = le->previous;
-			if (le->previous != NULL)
-				le->previous->next = le->next;
-			else
-				res->buckets[bucket] = le->next;
-			res->number_entries--;
-			/* Defer freeing this entry. */
-			res->spare = le;
-			return (le);
-		}
-	}
-	return (NULL);
-}
-
-static struct links_entry *
-insert_entry(struct archive_entry_linkresolver *res,
-    struct archive_entry *entry)
-{
-	struct links_entry *le;
-	size_t hash, bucket;
-
-	/* Add this entry to the links cache. */
-	le = calloc(1, sizeof(struct links_entry));
-	if (le == NULL)
-		return (NULL);
-	le->canonical = archive_entry_clone(entry);
-
-	/* If the links cache is getting too full, enlarge the hash table. */
-	if (res->number_entries > res->number_buckets * 2)
-		grow_hash(res);
-
-	hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry));
-	bucket = hash & (res->number_buckets - 1);
-
-	/* If we could allocate the entry, record it. */
-	if (res->buckets[bucket] != NULL)
-		res->buckets[bucket]->previous = le;
-	res->number_entries++;
-	le->next = res->buckets[bucket];
-	le->previous = NULL;
-	res->buckets[bucket] = le;
-	le->hash = hash;
-	le->links = archive_entry_nlink(entry) - 1;
-	return (le);
-}
-
-static void
-grow_hash(struct archive_entry_linkresolver *res)
-{
-	struct links_entry *le, **new_buckets;
-	size_t new_size;
-	size_t i, bucket;
-
-	/* Try to enlarge the bucket list. */
-	new_size = res->number_buckets * 2;
-	if (new_size < res->number_buckets)
-		return;
-	new_buckets = calloc(new_size, sizeof(struct links_entry *));
-
-	if (new_buckets == NULL)
-		return;
-
-	for (i = 0; i < res->number_buckets; i++) {
-		while (res->buckets[i] != NULL) {
-			/* Remove entry from old bucket. */
-			le = res->buckets[i];
-			res->buckets[i] = le->next;
-
-			/* Add entry to new bucket. */
-			bucket = le->hash & (new_size - 1);
-
-			if (new_buckets[bucket] != NULL)
-				new_buckets[bucket]->previous = le;
-			le->next = new_buckets[bucket];
-			le->previous = NULL;
-			new_buckets[bucket] = le;
-		}
-	}
-	free(res->buckets);
-	res->buckets = new_buckets;
-	res->number_buckets = new_size;
-}
-
-struct archive_entry *
-archive_entry_partial_links(struct archive_entry_linkresolver *res,
-    unsigned int *links)
-{
-	struct archive_entry	*e;
-	struct links_entry	*le;
-
-	/* Free a held entry. */
-	if (res->spare != NULL) {
-		archive_entry_free(res->spare->canonical);
-		archive_entry_free(res->spare->entry);
-		free(res->spare);
-		res->spare = NULL;
-	}
-
-	le = next_entry(res, NEXT_ENTRY_PARTIAL);
-	if (le != NULL) {
-		e = le->canonical;
-		if (links != NULL)
-			*links = le->links;
-		le->canonical = NULL;
-	} else {
-		e = NULL;
-		if (links != NULL)
-			*links = 0;
-	}
-	return (e);
-}
diff --git a/c/archive_entry_locale.h b/c/archive_entry_locale.h
deleted file mode 100644
--- a/c/archive_entry_locale.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * Copyright (c) 2011 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED
-#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-struct archive_entry;
-struct archive_string_conv;
-
-/*
- * Utility functions to set and get entry attributes by translating
- * character-set. These are designed for use in format readers and writers.
- *
- * The return code and interface of these are quite different from other
- * functions for archive_entry defined in archive_entry.h.
- * Common return code are:
- *   Return 0 if the string conversion succeeded.
- *   Return -1 if the string conversion failed.
- */
-
-#define archive_entry_gname_l	_archive_entry_gname_l
-int _archive_entry_gname_l(struct archive_entry *,
-    const char **, size_t *, struct archive_string_conv *);
-#define archive_entry_hardlink_l	_archive_entry_hardlink_l
-int _archive_entry_hardlink_l(struct archive_entry *,
-    const char **, size_t *, struct archive_string_conv *);
-#define archive_entry_pathname_l	_archive_entry_pathname_l
-int _archive_entry_pathname_l(struct archive_entry *,
-    const char **, size_t *, struct archive_string_conv *);
-#define archive_entry_symlink_l	_archive_entry_symlink_l
-int _archive_entry_symlink_l(struct archive_entry *,
-    const char **, size_t *, struct archive_string_conv *);
-#define archive_entry_uname_l	_archive_entry_uname_l
-int _archive_entry_uname_l(struct archive_entry *,
-    const char **, size_t *, struct archive_string_conv *);
-#define archive_entry_acl_text_l _archive_entry_acl_text_l
-int _archive_entry_acl_text_l(struct archive_entry *, int,
-const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
-#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
-char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
-    struct archive_string_conv *);
-#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
-int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
-    int type, struct archive_string_conv *);
-#define archive_entry_copy_gname_l	_archive_entry_copy_gname_l
-int _archive_entry_copy_gname_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-#define archive_entry_copy_hardlink_l	_archive_entry_copy_hardlink_l
-int _archive_entry_copy_hardlink_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-#define archive_entry_copy_link_l	_archive_entry_copy_link_l
-int _archive_entry_copy_link_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-#define archive_entry_copy_pathname_l	_archive_entry_copy_pathname_l
-int _archive_entry_copy_pathname_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-#define archive_entry_copy_symlink_l	_archive_entry_copy_symlink_l
-int _archive_entry_copy_symlink_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-#define archive_entry_copy_uname_l	_archive_entry_copy_uname_l
-int _archive_entry_copy_uname_l(struct archive_entry *,
-    const char *, size_t, struct archive_string_conv *);
-
-#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
diff --git a/c/archive_entry_private.h b/c/archive_entry_private.h
deleted file mode 100644
--- a/c/archive_entry_private.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $
- */
-
-#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
-#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include "archive_acl_private.h"
-#include "archive_string.h"
-
-struct ae_xattr {
-	struct ae_xattr *next;
-
-	char	*name;
-	void	*value;
-	size_t	size;
-};
-
-struct ae_sparse {
-	struct ae_sparse *next;
-
-	int64_t	 offset;
-	int64_t	 length;
-};
-
-struct ae_digest {
-	unsigned char md5[16];
-	unsigned char rmd160[20];
-	unsigned char sha1[20];
-	unsigned char sha256[32];
-	unsigned char sha384[48];
-	unsigned char sha512[64];
-};
-
-/*
- * Description of an archive entry.
- *
- * Basically, this is a "struct stat" with a few text fields added in.
- *
- * TODO: Add "comment", "charset", and possibly other entries
- * that are supported by "pax interchange" format.  However, GNU, ustar,
- * cpio, and other variants don't support these features, so they're not an
- * excruciatingly high priority right now.
- *
- * TODO: "pax interchange" format allows essentially arbitrary
- * key/value attributes to be attached to any entry.  Supporting
- * such extensions may make this library useful for special
- * applications (e.g., a package manager could attach special
- * package-management attributes to each entry).  There are tricky
- * API issues involved, so this is not going to happen until
- * there's a real demand for it.
- *
- * TODO: Design a good API for handling sparse files.
- */
-struct archive_entry {
-	struct archive *archive;
-
-	/*
-	 * Note that ae_stat.st_mode & AE_IFMT  can be  0!
-	 *
-	 * This occurs when the actual file type of the object is not
-	 * in the archive.  For example, 'tar' archives store
-	 * hardlinks without marking the type of the underlying
-	 * object.
-	 */
-
-	/*
-	 * We have a "struct aest" for holding file metadata rather than just
-	 * a "struct stat" because on some platforms the "struct stat" has
-	 * fields which are too narrow to hold the range of possible values;
-	 * we don't want to lose information if we read an archive and write
-	 * out another (e.g., in "tar -cf new.tar @old.tar").
-	 *
-	 * The "stat" pointer points to some form of platform-specific struct
-	 * stat; it is declared as a void * rather than a struct stat * as
-	 * some platforms have multiple varieties of stat structures.
-	 */
-	void *stat;
-	int  stat_valid; /* Set to 0 whenever a field in aest changes. */
-
-	struct aest {
-		int64_t		aest_atime;
-		uint32_t	aest_atime_nsec;
-		int64_t		aest_ctime;
-		uint32_t	aest_ctime_nsec;
-		int64_t		aest_mtime;
-		uint32_t	aest_mtime_nsec;
-		int64_t		aest_birthtime;
-		uint32_t	aest_birthtime_nsec;
-		int64_t		aest_gid;
-		int64_t		aest_ino;
-		uint32_t	aest_nlink;
-		uint64_t	aest_size;
-		int64_t		aest_uid;
-		/*
-		 * Because converting between device codes and
-		 * major/minor values is platform-specific and
-		 * inherently a bit risky, we only do that conversion
-		 * lazily.  That way, we will do a better job of
-		 * preserving information in those cases where no
-		 * conversion is actually required.
-		 */
-		int		aest_dev_is_broken_down;
-		dev_t		aest_dev;
-		dev_t		aest_devmajor;
-		dev_t		aest_devminor;
-		int		aest_rdev_is_broken_down;
-		dev_t		aest_rdev;
-		dev_t		aest_rdevmajor;
-		dev_t		aest_rdevminor;
-	} ae_stat;
-
-	int ae_set; /* bitmap of fields that are currently set */
-#define	AE_SET_HARDLINK	1
-#define	AE_SET_SYMLINK	2
-#define	AE_SET_ATIME	4
-#define	AE_SET_CTIME	8
-#define	AE_SET_MTIME	16
-#define	AE_SET_BIRTHTIME 32
-#define	AE_SET_SIZE	64
-#define	AE_SET_INO	128
-#define	AE_SET_DEV	256
-
-	/*
-	 * Use aes here so that we get transparent mbs<->wcs conversions.
-	 */
-	struct archive_mstring ae_fflags_text;	/* Text fflags per fflagstostr(3) */
-	unsigned long ae_fflags_set;		/* Bitmap fflags */
-	unsigned long ae_fflags_clear;
-	struct archive_mstring ae_gname;		/* Name of owning group */
-	struct archive_mstring ae_hardlink;	/* Name of target for hardlink */
-	struct archive_mstring ae_pathname;	/* Name of entry */
-	struct archive_mstring ae_symlink;		/* symlink contents */
-	struct archive_mstring ae_uname;		/* Name of owner */
-
-	/* Not used within libarchive; useful for some clients. */
-	struct archive_mstring ae_sourcepath;	/* Path this entry is sourced from. */
-
-#define AE_ENCRYPTION_NONE 0
-#define AE_ENCRYPTION_DATA 1
-#define AE_ENCRYPTION_METADATA 2
-	char encryption;
-	
-	void *mac_metadata;
-	size_t mac_metadata_size;
-
-	/* Digest support. */
-	struct ae_digest digest;
-
-	/* ACL support. */
-	struct archive_acl    acl;
-
-	/* extattr support. */
-	struct ae_xattr *xattr_head;
-	struct ae_xattr *xattr_p;
-
-	/* sparse support. */
-	struct ae_sparse *sparse_head;
-	struct ae_sparse *sparse_tail;
-	struct ae_sparse *sparse_p;
-
-	/* Miscellaneous. */
-	char		 strmode[12];
-
-	/* Symlink type support */
-	int ae_symlink_type;
-};
-
-int
-archive_entry_set_digest(struct archive_entry *entry, int type,
-    const unsigned char *digest);
-
-#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/c/archive_entry_sparse.c b/c/archive_entry_sparse.c
deleted file mode 100644
--- a/c/archive_entry_sparse.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_entry_private.h"
-
-/*
- * sparse handling
- */
-
-void
-archive_entry_sparse_clear(struct archive_entry *entry)
-{
-	struct ae_sparse *sp;
-
-	while (entry->sparse_head != NULL) {
-		sp = entry->sparse_head->next;
-		free(entry->sparse_head);
-		entry->sparse_head = sp;
-	}
-	entry->sparse_tail = NULL;
-}
-
-void
-archive_entry_sparse_add_entry(struct archive_entry *entry,
-	la_int64_t offset, la_int64_t length)
-{
-	struct ae_sparse *sp;
-
-	if (offset < 0 || length < 0)
-		/* Invalid value */
-		return;
-	if (offset > INT64_MAX - length ||
-	    offset + length > archive_entry_size(entry))
-		/* A value of "length" parameter is too large. */
-		return;
-	if ((sp = entry->sparse_tail) != NULL) {
-		if (sp->offset + sp->length > offset)
-			/* Invalid value. */
-			return;
-		if (sp->offset + sp->length == offset) {
-			if (sp->offset + sp->length + length < 0)
-				/* A value of "length" parameter is
-				 * too large. */
-				return;
-			/* Expand existing sparse block size. */
-			sp->length += length;
-			return;
-		}
-	}
-
-	if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL)
-		/* XXX Error XXX */
-		return;
-
-	sp->offset = offset;
-	sp->length = length;
-	sp->next = NULL;
-
-	if (entry->sparse_head == NULL)
-		entry->sparse_head = entry->sparse_tail = sp;
-	else {
-		/* Add a new sparse block to the tail of list. */
-		if (entry->sparse_tail != NULL)
-			entry->sparse_tail->next = sp;
-		entry->sparse_tail = sp;
-	}
-}
-
-
-/*
- * returns number of the sparse entries
- */
-int
-archive_entry_sparse_count(struct archive_entry *entry)
-{
-	struct ae_sparse *sp;
-	int count = 0;
-
-	for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
-		count++;
-
-	/*
-	 * Sanity check if this entry is exactly sparse.
-	 * If amount of sparse blocks is just one and it indicates the whole
-	 * file data, we should remove it and return zero.
-	 */
-	if (count == 1) {
-		sp = entry->sparse_head;
-		if (sp->offset == 0 &&
-		    sp->length >= archive_entry_size(entry)) {
-			count = 0;
-			archive_entry_sparse_clear(entry);
-		}
-	}
-
-	return (count);
-}
-
-int
-archive_entry_sparse_reset(struct archive_entry * entry)
-{
-	entry->sparse_p = entry->sparse_head;
-
-	return archive_entry_sparse_count(entry);
-}
-
-int
-archive_entry_sparse_next(struct archive_entry * entry,
-	la_int64_t *offset, la_int64_t *length)
-{
-	if (entry->sparse_p) {
-		*offset = entry->sparse_p->offset;
-		*length = entry->sparse_p->length;
-
-		entry->sparse_p = entry->sparse_p->next;
-
-		return (ARCHIVE_OK);
-	} else {
-		*offset = 0;
-		*length = 0;
-		return (ARCHIVE_WARN);
-	}
-}
-
-/*
- * end of sparse handling
- */
diff --git a/c/archive_entry_stat.c b/c/archive_entry_stat.c
deleted file mode 100644
--- a/c/archive_entry_stat.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_entry_private.h"
-
-const struct stat *
-archive_entry_stat(struct archive_entry *entry)
-{
-	struct stat *st;
-	if (entry->stat == NULL) {
-		entry->stat = calloc(1, sizeof(*st));
-		if (entry->stat == NULL)
-			return (NULL);
-		entry->stat_valid = 0;
-	}
-
-	/*
-	 * If none of the underlying fields have been changed, we
-	 * don't need to regenerate.  In theory, we could use a bitmap
-	 * here to flag only those items that have changed, but the
-	 * extra complexity probably isn't worth it.  It will be very
-	 * rare for anyone to change just one field then request a new
-	 * stat structure.
-	 */
-	if (entry->stat_valid)
-		return (entry->stat);
-
-	st = entry->stat;
-	/*
-	 * Use the public interfaces to extract items, so that
-	 * the appropriate conversions get invoked.
-	 */
-	st->st_atime = archive_entry_atime(entry);
-#if HAVE_STRUCT_STAT_ST_BIRTHTIME
-	st->st_birthtime = archive_entry_birthtime(entry);
-#endif
-	st->st_ctime = archive_entry_ctime(entry);
-	st->st_mtime = archive_entry_mtime(entry);
-	st->st_dev = archive_entry_dev(entry);
-	st->st_gid = (gid_t)archive_entry_gid(entry);
-	st->st_uid = (uid_t)archive_entry_uid(entry);
-	st->st_ino = (ino_t)archive_entry_ino64(entry);
-	st->st_nlink = archive_entry_nlink(entry);
-	st->st_rdev = archive_entry_rdev(entry);
-	st->st_size = (off_t)archive_entry_size(entry);
-	st->st_mode = archive_entry_mode(entry);
-
-	/*
-	 * On systems that support high-res timestamps, copy that
-	 * information into struct stat.
-	 */
-#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
-	st->st_atimespec.tv_nsec = archive_entry_atime_nsec(entry);
-	st->st_ctimespec.tv_nsec = archive_entry_ctime_nsec(entry);
-	st->st_mtimespec.tv_nsec = archive_entry_mtime_nsec(entry);
-#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-	st->st_atim.tv_nsec = archive_entry_atime_nsec(entry);
-	st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry);
-	st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry);
-#elif HAVE_STRUCT_STAT_ST_MTIME_N
-	st->st_atime_n = archive_entry_atime_nsec(entry);
-	st->st_ctime_n = archive_entry_ctime_nsec(entry);
-	st->st_mtime_n = archive_entry_mtime_nsec(entry);
-#elif HAVE_STRUCT_STAT_ST_UMTIME
-	st->st_uatime = archive_entry_atime_nsec(entry) / 1000;
-	st->st_uctime = archive_entry_ctime_nsec(entry) / 1000;
-	st->st_umtime = archive_entry_mtime_nsec(entry) / 1000;
-#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
-	st->st_atime_usec = archive_entry_atime_nsec(entry) / 1000;
-	st->st_ctime_usec = archive_entry_ctime_nsec(entry) / 1000;
-	st->st_mtime_usec = archive_entry_mtime_nsec(entry) / 1000;
-#endif
-#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
-	st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry);
-#endif
-
-	/*
-	 * TODO: On Linux, store 32 or 64 here depending on whether
-	 * the cached stat structure is a stat32 or a stat64.  This
-	 * will allow us to support both variants interchangeably.
-	 */
-	entry->stat_valid = 1;
-
-	return (st);
-}
diff --git a/c/archive_entry_strmode.c b/c/archive_entry_strmode.c
deleted file mode 100644
--- a/c/archive_entry_strmode.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.4 2008/06/15 05:14:01 kientzle Exp $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_entry_private.h"
-
-const char *
-archive_entry_strmode(struct archive_entry *entry)
-{
-	static const mode_t permbits[] =
-	    { 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 };
-	char *bp = entry->strmode;
-	mode_t mode;
-	int i;
-
-	/* Fill in a default string, then selectively override. */
-	strcpy(bp, "?rwxrwxrwx ");
-
-	mode = archive_entry_mode(entry);
-	switch (archive_entry_filetype(entry)) {
-	case AE_IFREG:  bp[0] = '-'; break;
-	case AE_IFBLK:  bp[0] = 'b'; break;
-	case AE_IFCHR:  bp[0] = 'c'; break;
-	case AE_IFDIR:  bp[0] = 'd'; break;
-	case AE_IFLNK:  bp[0] = 'l'; break;
-	case AE_IFSOCK: bp[0] = 's'; break;
-	case AE_IFIFO:  bp[0] = 'p'; break;
-	default:
-		if (archive_entry_hardlink(entry) != NULL) {
-			bp[0] = 'h';
-			break;
-		}
-	}
-
-	for (i = 0; i < 9; i++)
-		if (!(mode & permbits[i]))
-			bp[i+1] = '-';
-
-	if (mode & S_ISUID) {
-		if (mode & 0100) bp[3] = 's';
-		else bp[3] = 'S';
-	}
-	if (mode & S_ISGID) {
-		if (mode & 0010) bp[6] = 's';
-		else bp[6] = 'S';
-	}
-	if (mode & S_ISVTX) {
-		if (mode & 0001) bp[9] = 't';
-		else bp[9] = 'T';
-	}
-	if (archive_entry_acl_types(entry) != 0)
-		bp[10] = '+';
-
-	return (bp);
-}
diff --git a/c/archive_entry_xattr.c b/c/archive_entry_xattr.c
deleted file mode 100644
--- a/c/archive_entry_xattr.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_xattr.c 201096 2009-12-28 02:41:27Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>	/* for Linux file flags */
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h>	/* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h>	/* for Linux file flags */
-#endif
-#include <stddef.h>
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_entry_private.h"
-
-/*
- * extended attribute handling
- */
-
-void
-archive_entry_xattr_clear(struct archive_entry *entry)
-{
-	struct ae_xattr	*xp;
-
-	while (entry->xattr_head != NULL) {
-		xp = entry->xattr_head->next;
-		free(entry->xattr_head->name);
-		free(entry->xattr_head->value);
-		free(entry->xattr_head);
-		entry->xattr_head = xp;
-	}
-
-	entry->xattr_head = NULL;
-}
-
-void
-archive_entry_xattr_add_entry(struct archive_entry *entry,
-	const char *name, const void *value, size_t size)
-{
-	struct ae_xattr	*xp;
-
-	if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL)
-		__archive_errx(1, "Out of memory");
-
-	if ((xp->name = strdup(name)) == NULL)
-		__archive_errx(1, "Out of memory");
-
-	if ((xp->value = malloc(size)) != NULL) {
-		memcpy(xp->value, value, size);
-		xp->size = size;
-	} else
-		xp->size = 0;
-
-	xp->next = entry->xattr_head;
-	entry->xattr_head = xp;
-}
-
-
-/*
- * returns number of the extended attribute entries
- */
-int
-archive_entry_xattr_count(struct archive_entry *entry)
-{
-	struct ae_xattr *xp;
-	int count = 0;
-
-	for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
-		count++;
-
-	return count;
-}
-
-int
-archive_entry_xattr_reset(struct archive_entry * entry)
-{
-	entry->xattr_p = entry->xattr_head;
-
-	return archive_entry_xattr_count(entry);
-}
-
-int
-archive_entry_xattr_next(struct archive_entry * entry,
-	const char **name, const void **value, size_t *size)
-{
-	if (entry->xattr_p) {
-		*name = entry->xattr_p->name;
-		*value = entry->xattr_p->value;
-		*size = entry->xattr_p->size;
-
-		entry->xattr_p = entry->xattr_p->next;
-
-		return (ARCHIVE_OK);
-	} else {
-		*name = NULL;
-		*value = NULL;
-		*size = (size_t)0;
-		return (ARCHIVE_WARN);
-	}
-}
-
-/*
- * end of xattr handling
- */
diff --git a/c/archive_getdate.c b/c/archive_getdate.c
deleted file mode 100644
--- a/c/archive_getdate.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-/*
- * This code is in the public domain and has no copyright.
- *
- * This is a plain C recursive-descent translation of an old
- * public-domain YACC grammar that has been used for parsing dates in
- * very many open-source projects.
- *
- * Since the original authors were generous enough to donate their
- * work to the public domain, I feel compelled to match their
- * generosity.
- *
- * Tim Kientzle, February 2009.
- */
-
-/*
- * Header comment from original getdate.y:
- */
-
-/*
-**  Originally written by Steven M. Bellovin <smb@research.att.com> while
-**  at the University of North Carolina at Chapel Hill.  Later tweaked by
-**  a couple of people on Usenet.  Completely overhauled by Rich $alz
-**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
-**
-**  This grammar has 10 shift/reduce conflicts.
-**
-**  This code is in the public domain and has no copyright.
-*/
-
-#include "archive_platform.h"
-#ifdef __FreeBSD__
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#endif
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#define __LIBARCHIVE_BUILD 1
-#include "archive_getdate.h"
-
-/* Basic time units. */
-#define	EPOCH		1970
-#define	MINUTE		(60L)
-#define	HOUR		(60L * MINUTE)
-#define	DAY		(24L * HOUR)
-
-/* Daylight-savings mode:  on, off, or not yet known. */
-enum DSTMODE { DSTon, DSToff, DSTmaybe };
-/* Meridian:  am or pm. */
-enum { tAM, tPM };
-/* Token types returned by nexttoken() */
-enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT,
-       tUNUMBER, tZONE, tDST };
-struct token { int token; time_t value; };
-
-/*
- * Parser state.
- */
-struct gdstate {
-	struct token *tokenp; /* Pointer to next token. */
-	/* HaveXxxx counts how many of this kind of phrase we've seen;
-	 * it's a fatal error to have more than one time, zone, day,
-	 * or date phrase. */
-	int	HaveYear;
-	int	HaveMonth;
-	int	HaveDay;
-	int	HaveWeekDay; /* Day of week */
-	int	HaveTime; /* Hour/minute/second */
-	int	HaveZone; /* timezone and/or DST info */
-	int	HaveRel; /* time offset; we can have more than one */
-	/* Absolute time values. */
-	time_t	Timezone;  /* Seconds offset from GMT */
-	time_t	Day;
-	time_t	Hour;
-	time_t	Minutes;
-	time_t	Month;
-	time_t	Seconds;
-	time_t	Year;
-	/* DST selection */
-	enum DSTMODE	DSTmode;
-	/* Day of week accounting, e.g., "3rd Tuesday" */
-	time_t	DayOrdinal; /* "3" in "3rd Tuesday" */
-	time_t	DayNumber; /* "Tuesday" in "3rd Tuesday" */
-	/* Relative time values: hour/day/week offsets are measured in
-	 * seconds, month/year are counted in months. */
-	time_t	RelMonth;
-	time_t	RelSeconds;
-};
-
-/*
- * A series of functions that recognize certain common time phrases.
- * Each function returns 1 if it managed to make sense of some of the
- * tokens, zero otherwise.
- */
-
-/*
- *  hour:minute or hour:minute:second with optional AM, PM, or numeric
- *  timezone offset
- */
-static int
-timephrase(struct gdstate *gds)
-{
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == ':'
-	    && gds->tokenp[2].token == tUNUMBER
-	    && gds->tokenp[3].token == ':'
-	    && gds->tokenp[4].token == tUNUMBER) {
-		/* "12:14:18" or "22:08:07" */
-		++gds->HaveTime;
-		gds->Hour = gds->tokenp[0].value;
-		gds->Minutes = gds->tokenp[2].value;
-		gds->Seconds = gds->tokenp[4].value;
-		gds->tokenp += 5;
-	}
-	else if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == ':'
-	    && gds->tokenp[2].token == tUNUMBER) {
-		/* "12:14" or "22:08" */
-		++gds->HaveTime;
-		gds->Hour = gds->tokenp[0].value;
-		gds->Minutes = gds->tokenp[2].value;
-		gds->Seconds = 0;
-		gds->tokenp += 3;
-	}
-	else if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == tAMPM) {
-		/* "7" is a time if it's followed by "am" or "pm" */
-		++gds->HaveTime;
-		gds->Hour = gds->tokenp[0].value;
-		gds->Minutes = gds->Seconds = 0;
-		/* We'll handle the AM/PM below. */
-		gds->tokenp += 1;
-	} else {
-		/* We can't handle this. */
-		return 0;
-	}
-
-	if (gds->tokenp[0].token == tAMPM) {
-		/* "7:12pm", "12:20:13am" */
-		if (gds->Hour == 12)
-			gds->Hour = 0;
-		if (gds->tokenp[0].value == tPM)
-			gds->Hour += 12;
-		gds->tokenp += 1;
-	}
-	if (gds->tokenp[0].token == '+'
-	    && gds->tokenp[1].token == tUNUMBER) {
-		/* "7:14+0700" */
-		gds->HaveZone++;
-		gds->DSTmode = DSToff;
-		gds->Timezone = - ((gds->tokenp[1].value / 100) * HOUR
-		    + (gds->tokenp[1].value % 100) * MINUTE);
-		gds->tokenp += 2;
-	}
-	if (gds->tokenp[0].token == '-'
-	    && gds->tokenp[1].token == tUNUMBER) {
-		/* "19:14:12-0530" */
-		gds->HaveZone++;
-		gds->DSTmode = DSToff;
-		gds->Timezone = + ((gds->tokenp[1].value / 100) * HOUR
-		    + (gds->tokenp[1].value % 100) * MINUTE);
-		gds->tokenp += 2;
-	}
-	return 1;
-}
-
-/*
- * Timezone name, possibly including DST.
- */
-static int
-zonephrase(struct gdstate *gds)
-{
-	if (gds->tokenp[0].token == tZONE
-	    && gds->tokenp[1].token == tDST) {
-		gds->HaveZone++;
-		gds->Timezone = gds->tokenp[0].value;
-		gds->DSTmode = DSTon;
-		gds->tokenp += 1;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tZONE) {
-		gds->HaveZone++;
-		gds->Timezone = gds->tokenp[0].value;
-		gds->DSTmode = DSToff;
-		gds->tokenp += 1;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tDAYZONE) {
-		gds->HaveZone++;
-		gds->Timezone = gds->tokenp[0].value;
-		gds->DSTmode = DSTon;
-		gds->tokenp += 1;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Year/month/day in various combinations.
- */
-static int
-datephrase(struct gdstate *gds)
-{
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == '/'
-	    && gds->tokenp[2].token == tUNUMBER
-	    && gds->tokenp[3].token == '/'
-	    && gds->tokenp[4].token == tUNUMBER) {
-		gds->HaveYear++;
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		if (gds->tokenp[0].value >= 13) {
-			/* First number is big:  2004/01/29, 99/02/17 */
-			gds->Year = gds->tokenp[0].value;
-			gds->Month = gds->tokenp[2].value;
-			gds->Day = gds->tokenp[4].value;
-		} else if ((gds->tokenp[4].value >= 13)
-		    || (gds->tokenp[2].value >= 13)) {
-			/* Last number is big:  01/07/98 */
-			/* Middle number is big:  01/29/04 */
-			gds->Month = gds->tokenp[0].value;
-			gds->Day = gds->tokenp[2].value;
-			gds->Year = gds->tokenp[4].value;
-		} else {
-			/* No significant clues: 02/03/04 */
-			gds->Month = gds->tokenp[0].value;
-			gds->Day = gds->tokenp[2].value;
-			gds->Year = gds->tokenp[4].value;
-		}
-		gds->tokenp += 5;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == '/'
-	    && gds->tokenp[2].token == tUNUMBER) {
-		/* "1/15" */
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Month = gds->tokenp[0].value;
-		gds->Day = gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == '-'
-	    && gds->tokenp[2].token == tUNUMBER
-	    && gds->tokenp[3].token == '-'
-	    && gds->tokenp[4].token == tUNUMBER) {
-		/* ISO 8601 format.  yyyy-mm-dd.  */
-		gds->HaveYear++;
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Year = gds->tokenp[0].value;
-		gds->Month = gds->tokenp[2].value;
-		gds->Day = gds->tokenp[4].value;
-		gds->tokenp += 5;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == '-'
-	    && gds->tokenp[2].token == tMONTH
-	    && gds->tokenp[3].token == '-'
-	    && gds->tokenp[4].token == tUNUMBER) {
-		gds->HaveYear++;
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		if (gds->tokenp[0].value > 31) {
-			/* e.g. 1992-Jun-17 */
-			gds->Year = gds->tokenp[0].value;
-			gds->Month = gds->tokenp[2].value;
-			gds->Day = gds->tokenp[4].value;
-		} else {
-			/* e.g. 17-JUN-1992.  */
-			gds->Day = gds->tokenp[0].value;
-			gds->Month = gds->tokenp[2].value;
-			gds->Year = gds->tokenp[4].value;
-		}
-		gds->tokenp += 5;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tMONTH
-	    && gds->tokenp[1].token == tUNUMBER
-	    && gds->tokenp[2].token == ','
-	    && gds->tokenp[3].token == tUNUMBER) {
-		/* "June 17, 2001" */
-		gds->HaveYear++;
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Month = gds->tokenp[0].value;
-		gds->Day = gds->tokenp[1].value;
-		gds->Year = gds->tokenp[3].value;
-		gds->tokenp += 4;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tMONTH
-	    && gds->tokenp[1].token == tUNUMBER) {
-		/* "May 3" */
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Month = gds->tokenp[0].value;
-		gds->Day = gds->tokenp[1].value;
-		gds->tokenp += 2;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == tMONTH
-	    && gds->tokenp[2].token == tUNUMBER) {
-		/* "12 Sept 1997" */
-		gds->HaveYear++;
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Day = gds->tokenp[0].value;
-		gds->Month = gds->tokenp[1].value;
-		gds->Year = gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == tMONTH) {
-		/* "12 Sept" */
-		gds->HaveMonth++;
-		gds->HaveDay++;
-		gds->Day = gds->tokenp[0].value;
-		gds->Month = gds->tokenp[1].value;
-		gds->tokenp += 2;
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- * Relative time phrase: "tomorrow", "yesterday", "+1 hour", etc.
- */
-static int
-relunitphrase(struct gdstate *gds)
-{
-	if (gds->tokenp[0].token == '-'
-	    && gds->tokenp[1].token == tUNUMBER
-	    && gds->tokenp[2].token == tSEC_UNIT) {
-		/* "-3 hours" */
-		gds->HaveRel++;
-		gds->RelSeconds -= gds->tokenp[1].value * gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-	if (gds->tokenp[0].token == '+'
-	    && gds->tokenp[1].token == tUNUMBER
-	    && gds->tokenp[2].token == tSEC_UNIT) {
-		/* "+1 minute" */
-		gds->HaveRel++;
-		gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == tSEC_UNIT) {
-		/* "1 day" */
-		gds->HaveRel++;
-		gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value;
-		gds->tokenp += 2;
-		return 1;
-	}
-	if (gds->tokenp[0].token == '-'
-	    && gds->tokenp[1].token == tUNUMBER
-	    && gds->tokenp[2].token == tMONTH_UNIT) {
-		/* "-3 months" */
-		gds->HaveRel++;
-		gds->RelMonth -= gds->tokenp[1].value * gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-	if (gds->tokenp[0].token == '+'
-	    && gds->tokenp[1].token == tUNUMBER
-	    && gds->tokenp[2].token == tMONTH_UNIT) {
-		/* "+5 years" */
-		gds->HaveRel++;
-		gds->RelMonth += gds->tokenp[1].value * gds->tokenp[2].value;
-		gds->tokenp += 3;
-		return 1;
-	}
-	if (gds->tokenp[0].token == tUNUMBER
-	    && gds->tokenp[1].token == tMONTH_UNIT) {
-		/* "2 years" */
-		gds->HaveRel++;
-		gds->RelMonth += gds->tokenp[0].value * gds->tokenp[1].value;
-		gds->tokenp += 2;
-		return 1;
-	}
-	if (gds->tokenp[0].token == tSEC_UNIT) {
-		/* "now", "tomorrow" */
-		gds->HaveRel++;
-		gds->RelSeconds += gds->tokenp[0].value;
-		gds->tokenp += 1;
-		return 1;
-	}
-	if (gds->tokenp[0].token == tMONTH_UNIT) {
-		/* "month" */
-		gds->HaveRel++;
-		gds->RelMonth += gds->tokenp[0].value;
-		gds->tokenp += 1;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Day of the week specification.
- */
-static int
-dayphrase(struct gdstate *gds)
-{
-	if (gds->tokenp[0].token == tDAY) {
-		/* "tues", "wednesday," */
-		gds->HaveWeekDay++;
-		gds->DayOrdinal = 1;
-		gds->DayNumber = gds->tokenp[0].value;
-		gds->tokenp += 1;
-		if (gds->tokenp[0].token == ',')
-			gds->tokenp += 1;
-		return 1;
-	}
-	if (gds->tokenp[0].token == tUNUMBER
-		&& gds->tokenp[1].token == tDAY) {
-		/* "second tues" "3 wed" */
-		gds->HaveWeekDay++;
-		gds->DayOrdinal = gds->tokenp[0].value;
-		gds->DayNumber = gds->tokenp[1].value;
-		gds->tokenp += 2;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Try to match a phrase using one of the above functions.
- * This layer also deals with a couple of generic issues.
- */
-static int
-phrase(struct gdstate *gds)
-{
-	if (timephrase(gds))
-		return 1;
-	if (zonephrase(gds))
-		return 1;
-	if (datephrase(gds))
-		return 1;
-	if (dayphrase(gds))
-		return 1;
-	if (relunitphrase(gds)) {
-		if (gds->tokenp[0].token == tAGO) {
-			gds->RelSeconds = -gds->RelSeconds;
-			gds->RelMonth = -gds->RelMonth;
-			gds->tokenp += 1;
-		}
-		return 1;
-	}
-
-	/* Bare numbers sometimes have meaning. */
-	if (gds->tokenp[0].token == tUNUMBER) {
-		if (gds->HaveTime && !gds->HaveYear && !gds->HaveRel) {
-			gds->HaveYear++;
-			gds->Year = gds->tokenp[0].value;
-			gds->tokenp += 1;
-			return 1;
-		}
-
-		if(gds->tokenp[0].value > 10000) {
-			/* "20040301" */
-			gds->HaveYear++;
-			gds->HaveMonth++;
-			gds->HaveDay++;
-			gds->Day= (gds->tokenp[0].value)%100;
-			gds->Month= (gds->tokenp[0].value/100)%100;
-			gds->Year = gds->tokenp[0].value/10000;
-			gds->tokenp += 1;
-			return 1;
-		}
-
-		if (gds->tokenp[0].value < 24) {
-			gds->HaveTime++;
-			gds->Hour = gds->tokenp[0].value;
-			gds->Minutes = 0;
-			gds->Seconds = 0;
-			gds->tokenp += 1;
-			return 1;
-		}
-
-		if ((gds->tokenp[0].value / 100 < 24)
-		    && (gds->tokenp[0].value % 100 < 60)) {
-			/* "513" is same as "5:13" */
-			gds->Hour = gds->tokenp[0].value / 100;
-			gds->Minutes = gds->tokenp[0].value % 100;
-			gds->Seconds = 0;
-			gds->tokenp += 1;
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * A dictionary of time words.
- */
-static struct LEXICON {
-	size_t		abbrev;
-	const char	*name;
-	int		type;
-	time_t		value;
-} const TimeWords[] = {
-	/* am/pm */
-	{ 0, "am",		tAMPM,	tAM },
-	{ 0, "pm",		tAMPM,	tPM },
-
-	/* Month names. */
-	{ 3, "january",		tMONTH,  1 },
-	{ 3, "february",	tMONTH,  2 },
-	{ 3, "march",		tMONTH,  3 },
-	{ 3, "april",		tMONTH,  4 },
-	{ 3, "may",		tMONTH,  5 },
-	{ 3, "june",		tMONTH,  6 },
-	{ 3, "july",		tMONTH,  7 },
-	{ 3, "august",		tMONTH,  8 },
-	{ 3, "september",	tMONTH,  9 },
-	{ 3, "october",		tMONTH, 10 },
-	{ 3, "november",	tMONTH, 11 },
-	{ 3, "december",	tMONTH, 12 },
-
-	/* Days of the week. */
-	{ 2, "sunday",		tDAY, 0 },
-	{ 3, "monday",		tDAY, 1 },
-	{ 2, "tuesday",		tDAY, 2 },
-	{ 3, "wednesday",	tDAY, 3 },
-	{ 2, "thursday",	tDAY, 4 },
-	{ 2, "friday",		tDAY, 5 },
-	{ 2, "saturday",	tDAY, 6 },
-
-	/* Timezones: Offsets are in seconds. */
-	{ 0, "gmt",  tZONE,     0*HOUR }, /* Greenwich Mean */
-	{ 0, "ut",   tZONE,     0*HOUR }, /* Universal (Coordinated) */
-	{ 0, "utc",  tZONE,     0*HOUR },
-	{ 0, "wet",  tZONE,     0*HOUR }, /* Western European */
-	{ 0, "bst",  tDAYZONE,  0*HOUR }, /* British Summer */
-	{ 0, "wat",  tZONE,     1*HOUR }, /* West Africa */
-	{ 0, "at",   tZONE,     2*HOUR }, /* Azores */
-	/* { 0, "bst", tZONE, 3*HOUR }, */ /* Brazil Standard: Conflict */
-	/* { 0, "gst", tZONE, 3*HOUR }, */ /* Greenland Standard: Conflict*/
-	{ 0, "nft",  tZONE,     3*HOUR+30*MINUTE }, /* Newfoundland */
-	{ 0, "nst",  tZONE,     3*HOUR+30*MINUTE }, /* Newfoundland Standard */
-	{ 0, "ndt",  tDAYZONE,  3*HOUR+30*MINUTE }, /* Newfoundland Daylight */
-	{ 0, "ast",  tZONE,     4*HOUR }, /* Atlantic Standard */
-	{ 0, "adt",  tDAYZONE,  4*HOUR }, /* Atlantic Daylight */
-	{ 0, "est",  tZONE,     5*HOUR }, /* Eastern Standard */
-	{ 0, "edt",  tDAYZONE,  5*HOUR }, /* Eastern Daylight */
-	{ 0, "cst",  tZONE,     6*HOUR }, /* Central Standard */
-	{ 0, "cdt",  tDAYZONE,  6*HOUR }, /* Central Daylight */
-	{ 0, "mst",  tZONE,     7*HOUR }, /* Mountain Standard */
-	{ 0, "mdt",  tDAYZONE,  7*HOUR }, /* Mountain Daylight */
-	{ 0, "pst",  tZONE,     8*HOUR }, /* Pacific Standard */
-	{ 0, "pdt",  tDAYZONE,  8*HOUR }, /* Pacific Daylight */
-	{ 0, "yst",  tZONE,     9*HOUR }, /* Yukon Standard */
-	{ 0, "ydt",  tDAYZONE,  9*HOUR }, /* Yukon Daylight */
-	{ 0, "hst",  tZONE,     10*HOUR }, /* Hawaii Standard */
-	{ 0, "hdt",  tDAYZONE,  10*HOUR }, /* Hawaii Daylight */
-	{ 0, "cat",  tZONE,     10*HOUR }, /* Central Alaska */
-	{ 0, "ahst", tZONE,     10*HOUR }, /* Alaska-Hawaii Standard */
-	{ 0, "nt",   tZONE,     11*HOUR }, /* Nome */
-	{ 0, "idlw", tZONE,     12*HOUR }, /* Intl Date Line West */
-	{ 0, "cet",  tZONE,     -1*HOUR }, /* Central European */
-	{ 0, "met",  tZONE,     -1*HOUR }, /* Middle European */
-	{ 0, "mewt", tZONE,     -1*HOUR }, /* Middle European Winter */
-	{ 0, "mest", tDAYZONE,  -1*HOUR }, /* Middle European Summer */
-	{ 0, "swt",  tZONE,     -1*HOUR }, /* Swedish Winter */
-	{ 0, "sst",  tDAYZONE,  -1*HOUR }, /* Swedish Summer */
-	{ 0, "fwt",  tZONE,     -1*HOUR }, /* French Winter */
-	{ 0, "fst",  tDAYZONE,  -1*HOUR }, /* French Summer */
-	{ 0, "eet",  tZONE,     -2*HOUR }, /* Eastern Eur, USSR Zone 1 */
-	{ 0, "bt",   tZONE,     -3*HOUR }, /* Baghdad, USSR Zone 2 */
-	{ 0, "it",   tZONE,     -3*HOUR-30*MINUTE },/* Iran */
-	{ 0, "zp4",  tZONE,     -4*HOUR }, /* USSR Zone 3 */
-	{ 0, "zp5",  tZONE,     -5*HOUR }, /* USSR Zone 4 */
-	{ 0, "ist",  tZONE,     -5*HOUR-30*MINUTE },/* Indian Standard */
-	{ 0, "zp6",  tZONE,     -6*HOUR }, /* USSR Zone 5 */
-	/* { 0, "nst",  tZONE, -6.5*HOUR }, */ /* North Sumatra: Conflict */
-	/* { 0, "sst", tZONE, -7*HOUR }, */ /* So Sumatra, USSR 6: Conflict */
-	{ 0, "wast", tZONE,     -7*HOUR }, /* West Australian Standard */
-	{ 0, "wadt", tDAYZONE,  -7*HOUR }, /* West Australian Daylight */
-	{ 0, "jt",   tZONE,     -7*HOUR-30*MINUTE },/* Java (3pm in Cronusland!)*/
-	{ 0, "cct",  tZONE,     -8*HOUR }, /* China Coast, USSR Zone 7 */
-	{ 0, "jst",  tZONE,     -9*HOUR }, /* Japan Std, USSR Zone 8 */
-	{ 0, "cast", tZONE,     -9*HOUR-30*MINUTE },/* Ctrl Australian Std */
-	{ 0, "cadt", tDAYZONE,  -9*HOUR-30*MINUTE },/* Ctrl Australian Daylt */
-	{ 0, "east", tZONE,     -10*HOUR }, /* Eastern Australian Std */
-	{ 0, "eadt", tDAYZONE,  -10*HOUR }, /* Eastern Australian Daylt */
-	{ 0, "gst",  tZONE,     -10*HOUR }, /* Guam Std, USSR Zone 9 */
-	{ 0, "nzt",  tZONE,     -12*HOUR }, /* New Zealand */
-	{ 0, "nzst", tZONE,     -12*HOUR }, /* New Zealand Standard */
-	{ 0, "nzdt", tDAYZONE,  -12*HOUR }, /* New Zealand Daylight */
-	{ 0, "idle", tZONE,     -12*HOUR }, /* Intl Date Line East */
-
-	{ 0, "dst",  tDST,		0 },
-
-	/* Time units. */
-	{ 4, "years",		tMONTH_UNIT,	12 },
-	{ 5, "months",		tMONTH_UNIT,	1 },
-	{ 9, "fortnights",	tSEC_UNIT,	14 * DAY },
-	{ 4, "weeks",		tSEC_UNIT,	7 * DAY },
-	{ 3, "days",		tSEC_UNIT,	DAY },
-	{ 4, "hours",		tSEC_UNIT,	HOUR },
-	{ 3, "minutes",		tSEC_UNIT,	MINUTE },
-	{ 3, "seconds",		tSEC_UNIT,	1 },
-
-	/* Relative-time words. */
-	{ 0, "tomorrow",	tSEC_UNIT,	DAY },
-	{ 0, "yesterday",	tSEC_UNIT,	-DAY },
-	{ 0, "today",		tSEC_UNIT,	0 },
-	{ 0, "now",		tSEC_UNIT,	0 },
-	{ 0, "last",		tUNUMBER,	-1 },
-	{ 0, "this",		tSEC_UNIT,	0 },
-	{ 0, "next",		tUNUMBER,	2 },
-	{ 0, "first",		tUNUMBER,	1 },
-	{ 0, "1st",		tUNUMBER,	1 },
-/*	{ 0, "second",		tUNUMBER,	2 }, */
-	{ 0, "2nd",		tUNUMBER,	2 },
-	{ 0, "third",		tUNUMBER,	3 },
-	{ 0, "3rd",		tUNUMBER,	3 },
-	{ 0, "fourth",		tUNUMBER,	4 },
-	{ 0, "4th",		tUNUMBER,	4 },
-	{ 0, "fifth",		tUNUMBER,	5 },
-	{ 0, "5th",		tUNUMBER,	5 },
-	{ 0, "sixth",		tUNUMBER,	6 },
-	{ 0, "seventh",		tUNUMBER,	7 },
-	{ 0, "eighth",		tUNUMBER,	8 },
-	{ 0, "ninth",		tUNUMBER,	9 },
-	{ 0, "tenth",		tUNUMBER,	10 },
-	{ 0, "eleventh",	tUNUMBER,	11 },
-	{ 0, "twelfth",		tUNUMBER,	12 },
-	{ 0, "ago",		tAGO,		1 },
-
-	/* Military timezones. */
-	{ 0, "a",	tZONE,	1*HOUR },
-	{ 0, "b",	tZONE,	2*HOUR },
-	{ 0, "c",	tZONE,	3*HOUR },
-	{ 0, "d",	tZONE,	4*HOUR },
-	{ 0, "e",	tZONE,	5*HOUR },
-	{ 0, "f",	tZONE,	6*HOUR },
-	{ 0, "g",	tZONE,	7*HOUR },
-	{ 0, "h",	tZONE,	8*HOUR },
-	{ 0, "i",	tZONE,	9*HOUR },
-	{ 0, "k",	tZONE,	10*HOUR },
-	{ 0, "l",	tZONE,	11*HOUR },
-	{ 0, "m",	tZONE,	12*HOUR },
-	{ 0, "n",	tZONE,	-1*HOUR },
-	{ 0, "o",	tZONE,	-2*HOUR },
-	{ 0, "p",	tZONE,	-3*HOUR },
-	{ 0, "q",	tZONE,	-4*HOUR },
-	{ 0, "r",	tZONE,	-5*HOUR },
-	{ 0, "s",	tZONE,	-6*HOUR },
-	{ 0, "t",	tZONE,	-7*HOUR },
-	{ 0, "u",	tZONE,	-8*HOUR },
-	{ 0, "v",	tZONE,	-9*HOUR },
-	{ 0, "w",	tZONE,	-10*HOUR },
-	{ 0, "x",	tZONE,	-11*HOUR },
-	{ 0, "y",	tZONE,	-12*HOUR },
-	{ 0, "z",	tZONE,	0*HOUR },
-
-	/* End of table. */
-	{ 0, NULL,	0,	0 }
-};
-
-/*
- * Year is either:
- *  = A number from 0 to 99, which means a year from 1970 to 2069, or
- *  = The actual year (>=100).
- */
-static time_t
-Convert(time_t Month, time_t Day, time_t Year,
-	time_t Hours, time_t Minutes, time_t Seconds,
-	time_t Timezone, enum DSTMODE DSTmode)
-{
-	signed char DaysInMonth[12] = {
-		31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-	};
-	time_t		Julian;
-	int		i;
-	struct tm	*ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
-	struct tm	tmbuf;
-#endif
-
-	if (Year < 69)
-		Year += 2000;
-	else if (Year < 100)
-		Year += 1900;
-	DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
-	    ? 29 : 28;
-	/* Checking for 2038 bogusly assumes that time_t is 32 bits.  But
-	   I'm too lazy to try to check for time_t overflow in another way.  */
-	if (Year < EPOCH || Year >= 2038
-	    || Month < 1 || Month > 12
-	    /* Lint fluff:  "conversion from long may lose accuracy" */
-	    || Day < 1 || Day > DaysInMonth[(int)--Month]
-	    || Hours < 0 || Hours > 23
-	    || Minutes < 0 || Minutes > 59
-	    || Seconds < 0 || Seconds > 59)
-		return -1;
-
-	Julian = Day - 1;
-	for (i = 0; i < Month; i++)
-		Julian += DaysInMonth[i];
-	for (i = EPOCH; i < Year; i++)
-		Julian += 365 + (i % 4 == 0);
-	Julian *= DAY;
-	Julian += Timezone;
-	Julian += Hours * HOUR + Minutes * MINUTE + Seconds;
-#if defined(HAVE_LOCALTIME_S)
-	ltime = localtime_s(&tmbuf, &Julian) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-	ltime = localtime_r(&Julian, &tmbuf);
-#else
-	ltime = localtime(&Julian);
-#endif
-	if (DSTmode == DSTon
-	    || (DSTmode == DSTmaybe && ltime->tm_isdst))
-		Julian -= HOUR;
-	return Julian;
-}
-
-static time_t
-DSTcorrect(time_t Start, time_t Future)
-{
-	time_t		StartDay;
-	time_t		FutureDay;
-	struct tm	*ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
-	struct tm	tmbuf;
-#endif
-#if defined(HAVE_LOCALTIME_S)
-	ltime = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-	ltime = localtime_r(&Start, &tmbuf);
-#else
-	ltime = localtime(&Start);
-#endif
-	StartDay = (ltime->tm_hour + 1) % 24;
-#if defined(HAVE_LOCALTIME_S)
-	ltime = localtime_s(&tmbuf, &Future) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-	ltime = localtime_r(&Future, &tmbuf);
-#else
-	ltime = localtime(&Future);
-#endif
-	FutureDay = (ltime->tm_hour + 1) % 24;
-	return (Future - Start) + (StartDay - FutureDay) * HOUR;
-}
-
-
-static time_t
-RelativeDate(time_t Start, time_t zone, int dstmode,
-    time_t DayOrdinal, time_t DayNumber)
-{
-	struct tm	*tm;
-	time_t	t, now;
-#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
-	struct tm	tmbuf;
-#endif
-
-	t = Start - zone;
-#if defined(HAVE_GMTIME_S)
-	tm = gmtime_s(&tmbuf, &t) ? NULL : &tmbuf;
-#elif defined(HAVE_GMTIME_R)
-	tm = gmtime_r(&t, &tmbuf);
-#else
-	tm = gmtime(&t);
-#endif
-	now = Start;
-	now += DAY * ((DayNumber - tm->tm_wday + 7) % 7);
-	now += 7 * DAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
-	if (dstmode == DSTmaybe)
-		return DSTcorrect(Start, now);
-	return now - Start;
-}
-
-
-static time_t
-RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
-{
-	struct tm	*tm;
-	time_t	Month;
-	time_t	Year;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
-	struct tm	tmbuf;
-#endif
-
-	if (RelMonth == 0)
-		return 0;
-#if defined(HAVE_LOCALTIME_S)
-	tm = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-	tm = localtime_r(&Start, &tmbuf);
-#else
-	tm = localtime(&Start);
-#endif
-	Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
-	Year = Month / 12;
-	Month = Month % 12 + 1;
-	return DSTcorrect(Start,
-	    Convert(Month, (time_t)tm->tm_mday, Year,
-		(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
-		Timezone, DSTmaybe));
-}
-
-/*
- * Tokenizer.
- */
-static int
-nexttoken(const char **in, time_t *value)
-{
-	char	c;
-	char	buff[64];
-
-	for ( ; ; ) {
-		while (isspace((unsigned char)**in))
-			++*in;
-
-		/* Skip parenthesized comments. */
-		if (**in == '(') {
-			int Count = 0;
-			do {
-				c = *(*in)++;
-				if (c == '\0')
-					return c;
-				if (c == '(')
-					Count++;
-				else if (c == ')')
-					Count--;
-			} while (Count > 0);
-			continue;
-		}
-
-		/* Try the next token in the word table first. */
-		/* This allows us to match "2nd", for example. */
-		{
-			const char *src = *in;
-			const struct LEXICON *tp;
-			unsigned i = 0;
-
-			/* Force to lowercase and strip '.' characters. */
-			while (*src != '\0'
-			    && (isalnum((unsigned char)*src) || *src == '.')
-			    && i < sizeof(buff)-1) {
-				if (*src != '.') {
-					if (isupper((unsigned char)*src))
-						buff[i++] = tolower((unsigned char)*src);
-					else
-						buff[i++] = *src;
-				}
-				src++;
-			}
-			buff[i] = '\0';
-
-			/*
-			 * Find the first match.  If the word can be
-			 * abbreviated, make sure we match at least
-			 * the minimum abbreviation.
-			 */
-			for (tp = TimeWords; tp->name; tp++) {
-				size_t abbrev = tp->abbrev;
-				if (abbrev == 0)
-					abbrev = strlen(tp->name);
-				if (strlen(buff) >= abbrev
-				    && strncmp(tp->name, buff, strlen(buff))
-				    	== 0) {
-					/* Skip over token. */
-					*in = src;
-					/* Return the match. */
-					*value = tp->value;
-					return tp->type;
-				}
-			}
-		}
-
-		/*
-		 * Not in the word table, maybe it's a number.  Note:
-		 * Because '-' and '+' have other special meanings, I
-		 * don't deal with signed numbers here.
-		 */
-		if (isdigit((unsigned char)(c = **in))) {
-			for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
-				*value = 10 * *value + c - '0';
-			(*in)--;
-			return (tUNUMBER);
-		}
-
-		return *(*in)++;
-	}
-}
-
-#define	TM_YEAR_ORIGIN 1900
-
-/* Yield A - B, measured in seconds.  */
-static long
-difftm (struct tm *a, struct tm *b)
-{
-	int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
-	int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
-	int days = (
-		/* difference in day of year */
-		a->tm_yday - b->tm_yday
-		/* + intervening leap days */
-		+  ((ay >> 2) - (by >> 2))
-		-  (ay/100 - by/100)
-		+  ((ay/100 >> 2) - (by/100 >> 2))
-		/* + difference in years * 365 */
-		+  (long)(ay-by) * 365
-		);
-	return (days * DAY + (a->tm_hour - b->tm_hour) * HOUR
-	    + (a->tm_min - b->tm_min) * MINUTE
-	    + (a->tm_sec - b->tm_sec));
-}
-
-/*
- *
- * The public function.
- *
- * TODO: tokens[] array should be dynamically sized.
- */
-time_t
-__archive_get_date(time_t now, const char *p)
-{
-	struct token	tokens[256];
-	struct gdstate	_gds;
-	struct token	*lasttoken;
-	struct gdstate	*gds;
-	struct tm	local, *tm;
-	struct tm	gmt, *gmt_ptr;
-	time_t		Start;
-	time_t		tod;
-	long		tzone;
-
-	/* Clear out the parsed token array. */
-	memset(tokens, 0, sizeof(tokens));
-	/* Initialize the parser state. */
-	memset(&_gds, 0, sizeof(_gds));
-	gds = &_gds;
-
-	/* Look up the current time. */
-#if defined(HAVE_LOCALTIME_S)
-	tm = localtime_s(&local, &now) ? NULL : &local;
-#elif defined(HAVE_LOCALTIME_R)
-	tm = localtime_r(&now, &local);
-#else
-	memset(&local, 0, sizeof(local));
-	tm = localtime(&now);
-#endif
-	if (tm == NULL)
-		return -1;
-#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S)
-	local = *tm;
-#endif
-
-	/* Look up UTC if we can and use that to determine the current
-	 * timezone offset. */
-#if defined(HAVE_GMTIME_S)
-	gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
-#elif defined(HAVE_GMTIME_R)
-	gmt_ptr = gmtime_r(&now, &gmt);
-#else
-	memset(&gmt, 0, sizeof(gmt));
-	gmt_ptr = gmtime(&now);
-	if (gmt_ptr != NULL) {
-		/* Copy, in case localtime and gmtime use the same buffer. */
-		gmt = *gmt_ptr;
-	}
-#endif
-	if (gmt_ptr != NULL)
-		tzone = difftm (&gmt, &local);
-	else
-		/* This system doesn't understand timezones; fake it. */
-		tzone = 0;
-	if(local.tm_isdst)
-		tzone += HOUR;
-
-	/* Tokenize the input string. */
-	lasttoken = tokens;
-	while ((lasttoken->token = nexttoken(&p, &lasttoken->value)) != 0) {
-		++lasttoken;
-		if (lasttoken > tokens + 255)
-			return -1;
-	}
-	gds->tokenp = tokens;
-
-	/* Match phrases until we run out of input tokens. */
-	while (gds->tokenp < lasttoken) {
-		if (!phrase(gds))
-			return -1;
-	}
-
-	/* Use current local timezone if none was specified. */
-	if (!gds->HaveZone) {
-		gds->Timezone = tzone;
-		gds->DSTmode = DSTmaybe;
-	}
-
-	/* If a timezone was specified, use that for generating the default
-	 * time components instead of the local timezone. */
-	if (gds->HaveZone && gmt_ptr != NULL) {
-		now -= gds->Timezone;
-#if defined(HAVE_GMTIME_S)
-		gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
-#elif defined(HAVE_GMTIME_R)
-		gmt_ptr = gmtime_r(&now, &gmt);
-#else
-		gmt_ptr = gmtime(&now);
-#endif
-		if (gmt_ptr != NULL)
-			local = *gmt_ptr;
-		now += gds->Timezone;
-	}
-
-	if (!gds->HaveYear)
-		gds->Year = local.tm_year + 1900;
-	if (!gds->HaveMonth)
-		gds->Month = local.tm_mon + 1;
-	if (!gds->HaveDay)
-		gds->Day = local.tm_mday;
-	/* Note: No default for hour/min/sec; a specifier that just
-	 * gives date always refers to 00:00 on that date. */
-
-	/* If we saw more than one time, timezone, weekday, year, month,
-	 * or day, then give up. */
-	if (gds->HaveTime > 1 || gds->HaveZone > 1 || gds->HaveWeekDay > 1
-	    || gds->HaveYear > 1 || gds->HaveMonth > 1 || gds->HaveDay > 1)
-		return -1;
-
-	/* Compute an absolute time based on whatever absolute information
-	 * we collected. */
-	if (gds->HaveYear || gds->HaveMonth || gds->HaveDay
-	    || gds->HaveTime || gds->HaveWeekDay) {
-		Start = Convert(gds->Month, gds->Day, gds->Year,
-		    gds->Hour, gds->Minutes, gds->Seconds,
-		    gds->Timezone, gds->DSTmode);
-		if (Start < 0)
-			return -1;
-	} else {
-		Start = now;
-		if (!gds->HaveRel)
-			Start -= local.tm_hour * HOUR + local.tm_min * MINUTE
-			    + local.tm_sec;
-	}
-
-	/* Add the relative offset. */
-	Start += gds->RelSeconds;
-	Start += RelativeMonth(Start, gds->Timezone, gds->RelMonth);
-
-	/* Adjust for day-of-week offsets. */
-	if (gds->HaveWeekDay
-	    && !(gds->HaveYear || gds->HaveMonth || gds->HaveDay)) {
-		tod = RelativeDate(Start, gds->Timezone,
-		    gds->DSTmode, gds->DayOrdinal, gds->DayNumber);
-		Start += tod;
-	}
-
-	/* -1 is an error indicator, so return 0 instead of -1 if
-	 * that's the actual time. */
-	return Start == -1 ? 0 : Start;
-}
-
-
-#if	defined(TEST)
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-    time_t	d;
-    time_t	now = time(NULL);
-
-    while (*++argv != NULL) {
-	    (void)printf("Input: %s\n", *argv);
-	    d = get_date(now, *argv);
-	    if (d == -1)
-		    (void)printf("Bad format - couldn't convert.\n");
-	    else
-		    (void)printf("Output: %s\n", ctime(&d));
-    }
-    exit(0);
-    /* NOTREACHED */
-}
-#endif	/* defined(TEST) */
diff --git a/c/archive_getdate.h b/c/archive_getdate.h
deleted file mode 100644
--- a/c/archive_getdate.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * Copyright (c) 2003-2015 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_GETDATE_H_INCLUDED
-#define ARCHIVE_GETDATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include <time.h>
-
-time_t __archive_get_date(time_t now, const char *);
-
-#endif
diff --git a/c/archive_hmac.c b/c/archive_hmac.c
deleted file mode 100644
--- a/c/archive_hmac.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*-
-* Copyright (c) 2014 Michihiro NAKAJIMA
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "archive_platform.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include "archive.h"
-#include "archive_hmac_private.h"
-
-/*
- * On systems that do not support any recognized crypto libraries,
- * the archive_hmac.c file is expected to define no usable symbols.
- *
- * But some compilers and linkers choke on empty object files, so
- * define a public symbol that will always exist.  This could
- * be removed someday if this file gains another always-present
- * symbol definition.
- */
-int __libarchive_hmac_build_hack(void) {
-	return 0;
-}
-
-
-#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
-
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len);
-	return 0;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-    size_t data_len)
-{
-	CCHmacUpdate(ctx, data, data_len);
-}
-
-static void
-__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-	CCHmacFinal(ctx, out);
-	*out_len = 20;
-}
-
-static void
-__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-	memset(ctx, 0, sizeof(*ctx));
-}
-
-#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-
-#ifndef BCRYPT_HASH_REUSABLE_FLAG
-# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
-#endif
-
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-#ifdef __GNUC__
-#pragma GCC diagnostic ignored "-Wcast-qual"
-#endif
-	BCRYPT_ALG_HANDLE hAlg;
-	BCRYPT_HASH_HANDLE hHash;
-	DWORD hash_len;
-	PBYTE hash;
-	ULONG result;
-	NTSTATUS status;
-
-	ctx->hAlg = NULL;
-	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
-		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
-	if (!BCRYPT_SUCCESS(status))
-		return -1;
-	status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len,
-		sizeof(hash_len), &result, 0);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len);
-	if (hash == NULL) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		return -1;
-	}
-	status = BCryptCreateHash(hAlg, &hHash, NULL, 0,
-		(PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG);
-	if (!BCRYPT_SUCCESS(status)) {
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-		HeapFree(GetProcessHeap(), 0, hash);
-		return -1;
-	}
-
-	ctx->hAlg = hAlg;
-	ctx->hHash = hHash;
-	ctx->hash_len = hash_len;
-	ctx->hash = hash;
-
-	return 0;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-	size_t data_len)
-{
-	BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0);
-}
-
-static void
-__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-	BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0);
-	if (ctx->hash_len == *out_len)
-		memcpy(out, ctx->hash, *out_len);
-}
-
-static void
-__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-	if (ctx->hAlg != NULL) {
-		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
-		HeapFree(GetProcessHeap(), 0, ctx->hash);
-		ctx->hAlg = NULL;
-	}
-}
-
-#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H)
-
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-        const mbedtls_md_info_t *info;
-        int ret;
-
-        mbedtls_md_init(ctx);
-        info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
-        if (info == NULL) {
-                mbedtls_md_free(ctx);
-                return (-1);
-        }
-        ret = mbedtls_md_setup(ctx, info, 1);
-        if (ret != 0) {
-                mbedtls_md_free(ctx);
-                return (-1);
-        }
-	ret = mbedtls_md_hmac_starts(ctx, key, key_len);
-	if (ret != 0) {
-		mbedtls_md_free(ctx);
-		return (-1);
-	}
-	return 0;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-    size_t data_len)
-{
-	mbedtls_md_hmac_update(ctx, data, data_len);
-}
-
-static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-	(void)out_len;	/* UNUSED */
-
-	mbedtls_md_hmac_finish(ctx, out);
-}
-
-static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-	mbedtls_md_free(ctx);
-	memset(ctx, 0, sizeof(*ctx));
-}
-
-#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
-
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	hmac_sha1_set_key(ctx, key_len, key);
-	return 0;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-    size_t data_len)
-{
-	hmac_sha1_update(ctx, data_len, data);
-}
-
-static void
-__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-	hmac_sha1_digest(ctx, (unsigned)*out_len, out);
-}
-
-static void
-__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-	memset(ctx, 0, sizeof(*ctx));
-}
-
-#elif defined(HAVE_LIBCRYPTO)
-
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	EVP_MAC *mac;
-
-	char sha1[] = "SHA1";
-	OSSL_PARAM params[] = {
-		OSSL_PARAM_utf8_string("digest", sha1, sizeof(sha1) - 1),
-		OSSL_PARAM_END
-	};
-
-	mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
-	*ctx = EVP_MAC_CTX_new(mac);
-	EVP_MAC_free(mac);
-	if (*ctx == NULL)
-		return -1;
-
-	EVP_MAC_init(*ctx, key, key_len, params);
-#else
-	*ctx = HMAC_CTX_new();
-	if (*ctx == NULL)
-		return -1;
-	HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL);
-#endif
-	return 0;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-    size_t data_len)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	EVP_MAC_update(*ctx, data, data_len);
-#else
-	HMAC_Update(*ctx, data, data_len);
-#endif
-}
-
-static void
-__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	size_t len = *out_len;
-#else
-	unsigned int len = (unsigned int)*out_len;
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	EVP_MAC_final(*ctx, out, &len, *out_len);
-#else
-	HMAC_Final(*ctx, out, &len);
-#endif
-	*out_len = len;
-}
-
-static void
-__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-	EVP_MAC_CTX_free(*ctx);
-#else
-	HMAC_CTX_free(*ctx);
-#endif
-	*ctx = NULL;
-}
-
-#else
-
-/* Stub */
-static int
-__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
-{
-	(void)ctx;/* UNUSED */
-	(void)key;/* UNUSED */
-	(void)key_len;/* UNUSED */
-	return -1;
-}
-
-static void
-__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
-    size_t data_len)
-{
-	(void)ctx;/* UNUSED */
-	(void)data;/* UNUSED */
-	(void)data_len;/* UNUSED */
-}
-
-static void
-__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
-{
-	(void)ctx;/* UNUSED */
-	(void)out;/* UNUSED */
-	(void)out_len;/* UNUSED */
-}
-
-static void
-__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
-{
-	(void)ctx;/* UNUSED */
-}
-
-#endif
-
-const struct archive_hmac __archive_hmac = {
-	&__hmac_sha1_init,
-	&__hmac_sha1_update,
-	&__hmac_sha1_final,
-	&__hmac_sha1_cleanup,
-};
diff --git a/c/archive_hmac_private.h b/c/archive_hmac_private.h
deleted file mode 100644
--- a/c/archive_hmac_private.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*-
-* Copyright (c) 2014 Michihiro NAKAJIMA
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
-#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-/*
- * On systems that do not support any recognized crypto libraries,
- * the archive_hmac.c file is expected to define no usable symbols.
- *
- * But some compilers and linkers choke on empty object files, so
- * define a public symbol that will always exist.  This could
- * be removed someday if this file gains another always-present
- * symbol definition.
- */
-int __libarchive_hmac_build_hack(void);
-
-#ifdef __APPLE__
-# include <AvailabilityMacros.h>
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
-#  define ARCHIVE_HMAC_USE_Apple_CommonCrypto
-# endif
-#endif
-
-#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
-#include <CommonCrypto/CommonHMAC.h>
-
-typedef	CCHmacContext archive_hmac_sha1_ctx;
-
-#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#include <bcrypt.h>
-
-typedef struct {
-	BCRYPT_ALG_HANDLE	hAlg;
-	BCRYPT_HASH_HANDLE	hHash;
-	DWORD				hash_len;
-	PBYTE				hash;
-
-} archive_hmac_sha1_ctx;
-
-#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H)
-#include <mbedtls/md.h>
-
-typedef mbedtls_md_context_t archive_hmac_sha1_ctx;
-
-#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
-#include <nettle/hmac.h>
-
-typedef	struct hmac_sha1_ctx archive_hmac_sha1_ctx;
-
-#elif defined(HAVE_LIBCRYPTO)
-#include <openssl/opensslv.h>
-#include <openssl/hmac.h>
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-#include <openssl/params.h>
-
-typedef EVP_MAC_CTX *archive_hmac_sha1_ctx;
-
-#else
-#include "archive_openssl_hmac_private.h"
-
-typedef	HMAC_CTX* archive_hmac_sha1_ctx;
-#endif
-
-#else
-
-typedef int archive_hmac_sha1_ctx;
-
-#endif
-
-
-/* HMAC */
-#define archive_hmac_sha1_init(ctx, key, key_len)\
-	__archive_hmac.__hmac_sha1_init(ctx, key, key_len)
-#define archive_hmac_sha1_update(ctx, data, data_len)\
-	__archive_hmac.__hmac_sha1_update(ctx, data, data_len)
-#define archive_hmac_sha1_final(ctx, out, out_len)\
-  	__archive_hmac.__hmac_sha1_final(ctx, out, out_len)
-#define archive_hmac_sha1_cleanup(ctx)\
-	__archive_hmac.__hmac_sha1_cleanup(ctx)
-
-
-struct archive_hmac {
-	/* HMAC */
-	int (*__hmac_sha1_init)(archive_hmac_sha1_ctx *, const uint8_t *,
-		size_t);
-	void (*__hmac_sha1_update)(archive_hmac_sha1_ctx *, const uint8_t *,
-		size_t);
-	void (*__hmac_sha1_final)(archive_hmac_sha1_ctx *, uint8_t *, size_t *);
-	void (*__hmac_sha1_cleanup)(archive_hmac_sha1_ctx *);
-};
-
-extern const struct archive_hmac __archive_hmac;
-#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
diff --git a/c/archive_match.c b/c/archive_match.c
deleted file mode 100644
--- a/c/archive_match.c
+++ /dev/null
@@ -1,1875 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_entry.h"
-#include "archive_getdate.h"
-#include "archive_pathmatch.h"
-#include "archive_rb.h"
-#include "archive_string.h"
-
-struct match {
-	struct match		*next;
-	int			 matches;
-	struct archive_mstring	 pattern;
-};
-
-struct match_list {
-	struct match		*first;
-	struct match		**last;
-	int			 count;
-	int			 unmatched_count;
-	struct match		*unmatched_next;
-	int			 unmatched_eof;
-};
-
-struct match_file {
-	struct archive_rb_node	 node;
-	struct match_file	*next;
-	struct archive_mstring	 pathname;
-	int			 flag;
-	time_t			 mtime_sec;
-	long			 mtime_nsec;
-	time_t			 ctime_sec;
-	long			 ctime_nsec;
-};
-
-struct entry_list {
-	struct match_file	*first;
-	struct match_file	**last;
-	int			 count;
-};
-
-struct id_array {
-	size_t			 size;/* Allocated size */
-	size_t			 count;
-	int64_t			*ids;
-};
-
-#define PATTERN_IS_SET		1
-#define TIME_IS_SET		2
-#define ID_IS_SET		4
-
-struct archive_match {
-	struct archive		 archive;
-
-	/* exclusion/inclusion set flag. */
-	int			 setflag;
-
-	/* Recursively include directory content? */
-	int			 recursive_include;
-
-	/*
-	 * Matching filename patterns.
-	 */
-	struct match_list	 exclusions;
-	struct match_list	 inclusions;
-
-	/*
-	 * Matching time stamps.
-	 */
-	time_t			 now;
-	int			 newer_mtime_filter;
-	time_t			 newer_mtime_sec;
-	long			 newer_mtime_nsec;
-	int			 newer_ctime_filter;
-	time_t			 newer_ctime_sec;
-	long			 newer_ctime_nsec;
-	int			 older_mtime_filter;
-	time_t			 older_mtime_sec;
-	long			 older_mtime_nsec;
-	int			 older_ctime_filter;
-	time_t			 older_ctime_sec;
-	long			 older_ctime_nsec;
-	/*
-	 * Matching time stamps with its filename.
-	 */
-	struct archive_rb_tree	 exclusion_tree;
-	struct entry_list 	 exclusion_entry_list;
-
-	/*
-	 * Matching file owners.
-	 */
-	struct id_array 	 inclusion_uids;
-	struct id_array 	 inclusion_gids;
-	struct match_list	 inclusion_unames;
-	struct match_list	 inclusion_gnames;
-};
-
-static int	add_pattern_from_file(struct archive_match *,
-		    struct match_list *, int, const void *, int);
-static int	add_entry(struct archive_match *, int,
-		    struct archive_entry *);
-static int	add_owner_id(struct archive_match *, struct id_array *,
-		    int64_t);
-static int	add_owner_name(struct archive_match *, struct match_list *,
-		    int, const void *);
-static int	add_pattern_mbs(struct archive_match *, struct match_list *,
-		    const char *);
-static int	add_pattern_wcs(struct archive_match *, struct match_list *,
-		    const wchar_t *);
-static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
-static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
-static int	cmp_node_mbs(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static int	cmp_node_wcs(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static void	entry_list_add(struct entry_list *, struct match_file *);
-static void	entry_list_free(struct entry_list *);
-static void	entry_list_init(struct entry_list *);
-static int	error_nomem(struct archive_match *);
-static void	match_list_add(struct match_list *, struct match *);
-static void	match_list_free(struct match_list *);
-static void	match_list_init(struct match_list *);
-static int	match_list_unmatched_inclusions_next(struct archive_match *,
-		    struct match_list *, int, const void **);
-static int	match_owner_id(struct id_array *, int64_t);
-#if !defined(_WIN32) || defined(__CYGWIN__)
-static int	match_owner_name_mbs(struct archive_match *,
-		    struct match_list *, const char *);
-#else
-static int	match_owner_name_wcs(struct archive_match *,
-		    struct match_list *, const wchar_t *);
-#endif
-static int	match_path_exclusion(struct archive_match *,
-		    struct match *, int, const void *);
-static int	match_path_inclusion(struct archive_match *,
-		    struct match *, int, const void *);
-static int	owner_excluded(struct archive_match *,
-		    struct archive_entry *);
-static int	path_excluded(struct archive_match *, int, const void *);
-static int	set_timefilter(struct archive_match *, int, time_t, long,
-		    time_t, long);
-static int	set_timefilter_pathname_mbs(struct archive_match *,
-		    int, const char *);
-static int	set_timefilter_pathname_wcs(struct archive_match *,
-		    int, const wchar_t *);
-static int	set_timefilter_date(struct archive_match *, int, const char *);
-static int	set_timefilter_date_w(struct archive_match *, int,
-		    const wchar_t *);
-static int	time_excluded(struct archive_match *,
-		    struct archive_entry *);
-static int	validate_time_flag(struct archive *, int, const char *);
-
-#define get_date __archive_get_date
-
-static const struct archive_rb_tree_ops rb_ops_mbs = {
-	cmp_node_mbs, cmp_key_mbs
-};
-
-static const struct archive_rb_tree_ops rb_ops_wcs = {
-	cmp_node_wcs, cmp_key_wcs
-};
-
-/*
- * The matching logic here needs to be re-thought.  I started out to
- * try to mimic gtar's matching logic, but it's not entirely
- * consistent.  In particular 'tar -t' and 'tar -x' interpret patterns
- * on the command line as anchored, but --exclude doesn't.
- */
-
-static int
-error_nomem(struct archive_match *a)
-{
-	archive_set_error(&(a->archive), ENOMEM, "No memory");
-	a->archive.state = ARCHIVE_STATE_FATAL;
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Create an ARCHIVE_MATCH object.
- */
-struct archive *
-archive_match_new(void)
-{
-	struct archive_match *a;
-
-	a = (struct archive_match *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_MATCH_MAGIC;
-	a->archive.state = ARCHIVE_STATE_NEW;
-	a->recursive_include = 1;
-	match_list_init(&(a->inclusions));
-	match_list_init(&(a->exclusions));
-	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
-	entry_list_init(&(a->exclusion_entry_list));
-	match_list_init(&(a->inclusion_unames));
-	match_list_init(&(a->inclusion_gnames));
-	time(&a->now);
-	return (&(a->archive));
-}
-
-/*
- * Free an ARCHIVE_MATCH object.
- */
-int
-archive_match_free(struct archive *_a)
-{
-	struct archive_match *a;
-
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
-	a = (struct archive_match *)_a;
-	match_list_free(&(a->inclusions));
-	match_list_free(&(a->exclusions));
-	entry_list_free(&(a->exclusion_entry_list));
-	free(a->inclusion_uids.ids);
-	free(a->inclusion_gids.ids);
-	match_list_free(&(a->inclusion_unames));
-	match_list_free(&(a->inclusion_gnames));
-	free(a);
-	return (ARCHIVE_OK);
-}
-
-/*
- * Convenience function to perform all exclusion tests.
- *
- * Returns 1 if archive entry is excluded.
- * Returns 0 if archive entry is not excluded.
- * Returns <0 if something error happened.
- */
-int
-archive_match_excluded(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
-
-	a = (struct archive_match *)_a;
-	if (entry == NULL) {
-		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
-		return (ARCHIVE_FAILED);
-	}
-
-	r = 0;
-	if (a->setflag & PATTERN_IS_SET) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		r = path_excluded(a, 0, archive_entry_pathname_w(entry));
-#else
-		r = path_excluded(a, 1, archive_entry_pathname(entry));
-#endif
-		if (r != 0)
-			return (r);
-	}
-
-	if (a->setflag & TIME_IS_SET) {
-		r = time_excluded(a, entry);
-		if (r != 0)
-			return (r);
-	}
-
-	if (a->setflag & ID_IS_SET)
-		r = owner_excluded(a, entry);
-	return (r);
-}
-
-/*
- * Utility functions to manage exclusion/inclusion patterns
- */
-
-int
-archive_match_exclude_pattern(struct archive *_a, const char *pattern)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
-	a = (struct archive_match *)_a;
-
-	if (pattern == NULL || *pattern == '\0') {
-		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
-		return (ARCHIVE_FAILED);
-	}
-	if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
-		return (r);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
-	a = (struct archive_match *)_a;
-
-	if (pattern == NULL || *pattern == L'\0') {
-		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
-		return (ARCHIVE_FAILED);
-	}
-	if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
-		return (r);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_match_exclude_pattern_from_file(struct archive *_a,
-    const char *pathname, int nullSeparator)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
-	a = (struct archive_match *)_a;
-
-	return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
-		nullSeparator);
-}
-
-int
-archive_match_exclude_pattern_from_file_w(struct archive *_a,
-    const wchar_t *pathname, int nullSeparator)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
-	a = (struct archive_match *)_a;
-
-	return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
-		nullSeparator);
-}
-
-int
-archive_match_include_pattern(struct archive *_a, const char *pattern)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_pattern");
-	a = (struct archive_match *)_a;
-
-	if (pattern == NULL || *pattern == '\0') {
-		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
-		return (ARCHIVE_FAILED);
-	}
-	if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
-		return (r);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
-	a = (struct archive_match *)_a;
-
-	if (pattern == NULL || *pattern == L'\0') {
-		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
-		return (ARCHIVE_FAILED);
-	}
-	if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
-		return (r);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_match_include_pattern_from_file(struct archive *_a,
-    const char *pathname, int nullSeparator)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
-	a = (struct archive_match *)_a;
-
-	return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
-		nullSeparator);
-}
-
-int
-archive_match_include_pattern_from_file_w(struct archive *_a,
-    const wchar_t *pathname, int nullSeparator)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
-	a = (struct archive_match *)_a;
-
-	return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
-		nullSeparator);
-}
-
-/*
- * Test functions for pathname patterns.
- *
- * Returns 1 if archive entry is excluded.
- * Returns 0 if archive entry is not excluded.
- * Returns <0 if something error happened.
- */
-int
-archive_match_path_excluded(struct archive *_a,
-    struct archive_entry *entry)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_path_excluded");
-
-	a = (struct archive_match *)_a;
-	if (entry == NULL) {
-		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* If we don't have exclusion/inclusion pattern set at all,
-	 * the entry is always not excluded. */
-	if ((a->setflag & PATTERN_IS_SET) == 0)
-		return (0);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
-#else
-	return (path_excluded(a, 1, archive_entry_pathname(entry)));
-#endif
-}
-
-/*
- * When recursive inclusion of directory content is enabled,
- * an inclusion pattern that matches a directory will also
- * include everything beneath that directory. Enabled by default.
- *
- * For compatibility with GNU tar, exclusion patterns always
- * match if a subset of the full patch matches (i.e., they are
- * are not rooted at the beginning of the path) and thus there
- * is no corresponding non-recursive exclusion mode.
- */
-int
-archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
-	a = (struct archive_match *)_a;
-	a->recursive_include = enabled;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Utility functions to get statistic information for inclusion patterns.
- */
-int
-archive_match_path_unmatched_inclusions(struct archive *_a)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
-	a = (struct archive_match *)_a;
-
-	return (a->inclusions.unmatched_count);
-}
-
-int
-archive_match_path_unmatched_inclusions_next(struct archive *_a,
-    const char **_p)
-{
-	struct archive_match *a;
-	const void *v;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
-	a = (struct archive_match *)_a;
-
-	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
-	*_p = (const char *)v;
-	return (r);
-}
-
-int
-archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
-    const wchar_t **_p)
-{
-	struct archive_match *a;
-	const void *v;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
-	a = (struct archive_match *)_a;
-
-	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
-	*_p = (const wchar_t *)v;
-	return (r);
-}
-
-/*
- * Add inclusion/exclusion patterns.
- */
-static int
-add_pattern_mbs(struct archive_match *a, struct match_list *list,
-    const char *pattern)
-{
-	struct match *match;
-	size_t len;
-
-	match = calloc(1, sizeof(*match));
-	if (match == NULL)
-		return (error_nomem(a));
-	/* Both "foo/" and "foo" should match "foo/bar". */
-	len = strlen(pattern);
-	if (len && pattern[len - 1] == '/')
-		--len;
-	archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
-	match_list_add(list, match);
-	a->setflag |= PATTERN_IS_SET;
-	return (ARCHIVE_OK);
-}
-
-static int
-add_pattern_wcs(struct archive_match *a, struct match_list *list,
-    const wchar_t *pattern)
-{
-	struct match *match;
-	size_t len;
-
-	match = calloc(1, sizeof(*match));
-	if (match == NULL)
-		return (error_nomem(a));
-	/* Both "foo/" and "foo" should match "foo/bar". */
-	len = wcslen(pattern);
-	if (len && pattern[len - 1] == L'/')
-		--len;
-	archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
-	match_list_add(list, match);
-	a->setflag |= PATTERN_IS_SET;
-	return (ARCHIVE_OK);
-}
-
-static int
-add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
-    int mbs, const void *pathname, int nullSeparator)
-{
-	struct archive *ar;
-	struct archive_entry *ae;
-	struct archive_string as;
-	const void *buff;
-	size_t size;
-	int64_t offset;
-	int r;
-
-	ar = archive_read_new(); 
-	if (ar == NULL) {
-		archive_set_error(&(a->archive), ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	r = archive_read_support_format_raw(ar);
-	r = archive_read_support_format_empty(ar);
-	if (r != ARCHIVE_OK) {
-		archive_copy_error(&(a->archive), ar);
-		archive_read_free(ar);
-		return (r);
-	}
-	if (mbs)
-		r = archive_read_open_filename(ar, pathname, 512*20);
-	else
-		r = archive_read_open_filename_w(ar, pathname, 512*20);
-	if (r != ARCHIVE_OK) {
-		archive_copy_error(&(a->archive), ar);
-		archive_read_free(ar);
-		return (r);
-	}
-	r = archive_read_next_header(ar, &ae);
-	if (r != ARCHIVE_OK) {
-		archive_read_free(ar);
-		if (r == ARCHIVE_EOF) {
-			return (ARCHIVE_OK);
-		} else {
-			archive_copy_error(&(a->archive), ar);
-			return (r);
-		}
-	}
-
-	archive_string_init(&as);
-
-	while ((r = archive_read_data_block(ar, &buff, &size, &offset))
-	    == ARCHIVE_OK) {
-		const char *b = (const char *)buff;
-
-		while (size) {
-			const char *s = (const char *)b;
-			size_t length = 0;
-			int found_separator = 0;
-
-			while (length < size) {
-				if (nullSeparator) {
-					if (*b == '\0') {
-						found_separator = 1;
-						break;
-					}
-				} else {
-			            	if (*b == 0x0d || *b == 0x0a) {
-						found_separator = 1;
-						break;
-					}
-				}
-				b++;
-				length++;
-			}
-			if (!found_separator) {
-				archive_strncat(&as, s, length);
-				/* Read next data block. */
-				break;
-			}
-			b++;
-			size -= length + 1;
-			archive_strncat(&as, s, length);
-
-			/* If the line is not empty, add the pattern. */
-			if (archive_strlen(&as) > 0) {
-				/* Add pattern. */
-				r = add_pattern_mbs(a, mlist, as.s);
-				if (r != ARCHIVE_OK) {
-					archive_read_free(ar);
-					archive_string_free(&as);
-					return (r);
-				}
-				archive_string_empty(&as);
-			}
-		}
-	}
-
-	/* If an error occurred, report it immediately. */
-	if (r < ARCHIVE_OK) {
-		archive_copy_error(&(a->archive), ar);
-		archive_read_free(ar);
-		archive_string_free(&as);
-		return (r);
-	}
-
-	/* If the line is not empty, add the pattern. */
-	if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
-		/* Add pattern. */
-		r = add_pattern_mbs(a, mlist, as.s);
-		if (r != ARCHIVE_OK) {
-			archive_read_free(ar);
-			archive_string_free(&as);
-			return (r);
-		}
-	}
-	archive_read_free(ar);
-	archive_string_free(&as);
-	return (ARCHIVE_OK);
-}
-
-/*
- * Test if pathname is excluded by inclusion/exclusion patterns.
- */
-static int
-path_excluded(struct archive_match *a, int mbs, const void *pathname)
-{
-	struct match *match;
-	struct match *matched;
-	int r;
-
-	if (a == NULL)
-		return (0);
-
-	/* Mark off any unmatched inclusions. */
-	/* In particular, if a filename does appear in the archive and
-	 * is explicitly included and excluded, then we don't report
-	 * it as missing even though we don't extract it.
-	 */
-	matched = NULL;
-	for (match = a->inclusions.first; match != NULL;
-	    match = match->next){
-		if (match->matches == 0 &&
-		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
-			if (r < 0)
-				return (r);
-			a->inclusions.unmatched_count--;
-			match->matches++;
-			matched = match;
-		}
-	}
-
-	/* Exclusions take priority */
-	for (match = a->exclusions.first; match != NULL;
-	    match = match->next){
-		r = match_path_exclusion(a, match, mbs, pathname);
-		if (r)
-			return (r);
-	}
-
-	/* It's not excluded and we found an inclusion above, so it's
-	 * included. */
-	if (matched != NULL)
-		return (0);
-
-
-	/* We didn't find an unmatched inclusion, check the remaining ones. */
-	for (match = a->inclusions.first; match != NULL;
-	    match = match->next){
-		/* We looked at previously-unmatched inclusions already. */
-		if (match->matches > 0 &&
-		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
-			if (r < 0)
-				return (r);
-			match->matches++;
-			return (0);
-		}
-	}
-
-	/* If there were inclusions, default is to exclude. */
-	if (a->inclusions.first != NULL)
-	    return (1);
-
-	/* No explicit inclusions, default is to match. */
-	return (0);
-}
-
-/*
- * This is a little odd, but it matches the default behavior of
- * gtar.  In particular, 'a*b' will match 'foo/a1111/222b/bar'
- *
- */
-static int
-match_path_exclusion(struct archive_match *a, struct match *m,
-    int mbs, const void *pn)
-{
-	int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
-	int r;
-
-	if (mbs) {
-		const char *p;
-		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
-		if (r == 0)
-			return (archive_pathmatch(p, (const char *)pn, flag));
-	} else {
-		const wchar_t *p;
-		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
-		if (r == 0)
-			return (archive_pathmatch_w(p, (const wchar_t *)pn,
-				flag));
-	}
-	if (errno == ENOMEM)
-		return (error_nomem(a));
-	return (0);
-}
-
-/*
- * Again, mimic gtar:  inclusions are always anchored (have to match
- * the beginning of the path) even though exclusions are not anchored.
- */
-static int
-match_path_inclusion(struct archive_match *a, struct match *m,
-    int mbs, const void *pn)
-{
-	/* Recursive operation requires only a prefix match. */
-	int flag = a->recursive_include ?
-		PATHMATCH_NO_ANCHOR_END :
-		0;
-	int r;
-
-	if (mbs) {
-		const char *p;
-		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
-		if (r == 0)
-			return (archive_pathmatch(p, (const char *)pn, flag));
-	} else {
-		const wchar_t *p;
-		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
-		if (r == 0)
-			return (archive_pathmatch_w(p, (const wchar_t *)pn,
-				flag));
-	}
-	if (errno == ENOMEM)
-		return (error_nomem(a));
-	return (0);
-}
-
-static void
-match_list_init(struct match_list *list)
-{
-	list->first = NULL;
-	list->last = &(list->first);
-	list->count = 0;
-}
-
-static void
-match_list_free(struct match_list *list)
-{
-	struct match *p, *q;
-
-	for (p = list->first; p != NULL; ) {
-		q = p;
-		p = p->next;
-		archive_mstring_clean(&(q->pattern));
-		free(q);
-	}
-}
-
-static void
-match_list_add(struct match_list *list, struct match *m)
-{
-	*list->last = m;
-	list->last = &(m->next);
-	list->count++;
-	list->unmatched_count++;
-}
-
-static int
-match_list_unmatched_inclusions_next(struct archive_match *a,
-    struct match_list *list, int mbs, const void **vp)
-{
-	struct match *m;
-
-	*vp = NULL;
-	if (list->unmatched_eof) {
-		list->unmatched_eof = 0;
-		return (ARCHIVE_EOF);
-	}
-	if (list->unmatched_next == NULL) {
-		if (list->unmatched_count == 0)
-			return (ARCHIVE_EOF);
-		list->unmatched_next = list->first;
-	}
-
-	for (m = list->unmatched_next; m != NULL; m = m->next) {
-		int r;
-
-		if (m->matches)
-			continue;
-		if (mbs) {
-			const char *p;
-			r = archive_mstring_get_mbs(&(a->archive),
-				&(m->pattern), &p);
-			if (r < 0 && errno == ENOMEM)
-				return (error_nomem(a));
-			if (p == NULL)
-				p = "";
-			*vp = p;
-		} else {
-			const wchar_t *p;
-			r = archive_mstring_get_wcs(&(a->archive),
-				&(m->pattern), &p);
-			if (r < 0 && errno == ENOMEM)
-				return (error_nomem(a));
-			if (p == NULL)
-				p = L"";
-			*vp = p;
-		}
-		list->unmatched_next = m->next;
-		if (list->unmatched_next == NULL)
-			/* To return EOF next time. */
-			list->unmatched_eof = 1;
-		return (ARCHIVE_OK);
-	}
-	list->unmatched_next = NULL;
-	return (ARCHIVE_EOF);
-}
-
-/*
- * Utility functions to manage inclusion timestamps.
- */
-int
-archive_match_include_time(struct archive *_a, int flag, time_t sec,
-    long nsec)
-{
-	int r;
-
-	r = validate_time_flag(_a, flag, "archive_match_include_time");
-	if (r != ARCHIVE_OK)
-		return (r);
-	return set_timefilter((struct archive_match *)_a, flag,
-			sec, nsec, sec, nsec);
-}
-
-int
-archive_match_include_date(struct archive *_a, int flag,
-    const char *datestr)
-{
-	int r;
-
-	r = validate_time_flag(_a, flag, "archive_match_include_date");
-	if (r != ARCHIVE_OK)
-		return (r);
-	return set_timefilter_date((struct archive_match *)_a, flag, datestr);
-}
-
-int
-archive_match_include_date_w(struct archive *_a, int flag,
-    const wchar_t *datestr)
-{
-	int r;
-
-	r = validate_time_flag(_a, flag, "archive_match_include_date_w");
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
-}
-
-int
-archive_match_include_file_time(struct archive *_a, int flag,
-    const char *pathname)
-{
-	int r;
-
-	r = validate_time_flag(_a, flag, "archive_match_include_file_time");
-	if (r != ARCHIVE_OK)
-		return (r);
-	return set_timefilter_pathname_mbs((struct archive_match *)_a,
-			flag, pathname);
-}
-
-int
-archive_match_include_file_time_w(struct archive *_a, int flag,
-    const wchar_t *pathname)
-{
-	int r;
-
-	r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
-	if (r != ARCHIVE_OK)
-		return (r);
-	return set_timefilter_pathname_wcs((struct archive_match *)_a,
-			flag, pathname);
-}
-
-int
-archive_match_exclude_entry(struct archive *_a, int flag,
-    struct archive_entry *entry)
-{
-	struct archive_match *a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
-	a = (struct archive_match *)_a;
-
-	if (entry == NULL) {
-		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
-		return (ARCHIVE_FAILED);
-	}
-	r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
-	if (r != ARCHIVE_OK)
-		return (r);
-	return (add_entry(a, flag, entry));
-}
-
-/*
- * Test function for time stamps.
- *
- * Returns 1 if archive entry is excluded.
- * Returns 0 if archive entry is not excluded.
- * Returns <0 if something error happened.
- */
-int
-archive_match_time_excluded(struct archive *_a,
-    struct archive_entry *entry)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
-
-	a = (struct archive_match *)_a;
-	if (entry == NULL) {
-		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* If we don't have inclusion time set at all, the entry is always
-	 * not excluded. */
-	if ((a->setflag & TIME_IS_SET) == 0)
-		return (0);
-	return (time_excluded(a, entry));
-}
-
-static int
-validate_time_flag(struct archive *_a, int flag, const char *_fn)
-{
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, _fn);
-
-	/* Check a type of time. */
-	if (flag &
-	   ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
-		archive_set_error(_a, EINVAL, "Invalid time flag");
-		return (ARCHIVE_FAILED);
-	}
-	if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
-		archive_set_error(_a, EINVAL, "No time flag");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Check a type of comparison. */
-	if (flag &
-	   ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
-			| ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
-		archive_set_error(_a, EINVAL, "Invalid comparison flag");
-		return (ARCHIVE_FAILED);
-	}
-	if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
-	    | ARCHIVE_MATCH_EQUAL)) == 0) {
-		archive_set_error(_a, EINVAL, "No comparison flag");
-		return (ARCHIVE_FAILED);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-#define JUST_EQUAL(t) (((t) &  (ARCHIVE_MATCH_EQUAL |\
-	ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
-static int
-set_timefilter(struct archive_match *a, int timetype,
-    time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
-{
-	if (timetype & ARCHIVE_MATCH_MTIME) {
-		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
-			a->newer_mtime_filter = timetype;
-			a->newer_mtime_sec = mtime_sec;
-			a->newer_mtime_nsec = mtime_nsec;
-			a->setflag |= TIME_IS_SET;
-		}
-		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
-			a->older_mtime_filter = timetype;
-			a->older_mtime_sec = mtime_sec;
-			a->older_mtime_nsec = mtime_nsec;
-			a->setflag |= TIME_IS_SET;
-		}
-	}
-	if (timetype & ARCHIVE_MATCH_CTIME) {
-		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
-			a->newer_ctime_filter = timetype;
-			a->newer_ctime_sec = ctime_sec;
-			a->newer_ctime_nsec = ctime_nsec;
-			a->setflag |= TIME_IS_SET;
-		}
-		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
-			a->older_ctime_filter = timetype;
-			a->older_ctime_sec = ctime_sec;
-			a->older_ctime_nsec = ctime_nsec;
-			a->setflag |= TIME_IS_SET;
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
-{
-	time_t t;
-
-	if (datestr == NULL || *datestr == '\0') {
-		archive_set_error(&(a->archive), EINVAL, "date is empty");
-		return (ARCHIVE_FAILED);
-	}
-	t = get_date(a->now, datestr);
-	if (t == (time_t)-1) {
-		archive_set_error(&(a->archive), EINVAL, "invalid date string");
-		return (ARCHIVE_FAILED);
-	}
-	return set_timefilter(a, timetype, t, 0, t, 0);
-}
-
-static int
-set_timefilter_date_w(struct archive_match *a, int timetype,
-    const wchar_t *datestr)
-{
-	struct archive_string as;
-	time_t t;
-
-	if (datestr == NULL || *datestr == L'\0') {
-		archive_set_error(&(a->archive), EINVAL, "date is empty");
-		return (ARCHIVE_FAILED);
-	}
-
-	archive_string_init(&as);
-	if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
-		archive_string_free(&as);
-		if (errno == ENOMEM)
-			return (error_nomem(a));
-		archive_set_error(&(a->archive), -1,
-		    "Failed to convert WCS to MBS");
-		return (ARCHIVE_FAILED);
-	}
-	t = get_date(a->now, as.s);
-	archive_string_free(&as);
-	if (t == (time_t)-1) {
-		archive_set_error(&(a->archive), EINVAL, "invalid date string");
-		return (ARCHIVE_FAILED);
-	}
-	return set_timefilter(a, timetype, t, 0, t, 0);
-}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static int
-set_timefilter_find_data(struct archive_match *a, int timetype,
-    DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
-    DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
-{
-	ULARGE_INTEGER utc;
-	time_t ctime_sec, mtime_sec;
-	long ctime_ns, mtime_ns;
-
-	utc.HighPart = ftCreationTime_dwHighDateTime;
-	utc.LowPart = ftCreationTime_dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		ctime_sec = (time_t)(utc.QuadPart / 10000000);
-		ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		ctime_sec = 0;
-		ctime_ns = 0;
-	}
-	utc.HighPart = ftLastWriteTime_dwHighDateTime;
-	utc.LowPart = ftLastWriteTime_dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		mtime_sec = (time_t)(utc.QuadPart / 10000000);
-		mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		mtime_sec = 0;
-		mtime_ns = 0;
-	}
-	return set_timefilter(a, timetype,
-			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
-}
-
-static int
-set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
-    const char *path)
-{
-	/* NOTE: stat() on Windows cannot handle nano seconds. */
-	HANDLE h;
-	WIN32_FIND_DATAA d;
-
-	if (path == NULL || *path == '\0') {
-		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
-		return (ARCHIVE_FAILED);
-	}
-	h = FindFirstFileA(path, &d);
-	if (h == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		archive_set_error(&(a->archive), errno,
-		    "Failed to FindFirstFileA");
-		return (ARCHIVE_FAILED);
-	}
-	FindClose(h);
-	return set_timefilter_find_data(a, timetype,
-	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
-	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
-}
-
-static int
-set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
-    const wchar_t *path)
-{
-	HANDLE h;
-	WIN32_FIND_DATAW d;
-
-	if (path == NULL || *path == L'\0') {
-		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
-		return (ARCHIVE_FAILED);
-	}
-	h = FindFirstFileW(path, &d);
-	if (h == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		archive_set_error(&(a->archive), errno,
-		    "Failed to FindFirstFile");
-		return (ARCHIVE_FAILED);
-	}
-	FindClose(h);
-	return set_timefilter_find_data(a, timetype,
-	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
-	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
-}
-
-#else /* _WIN32 && !__CYGWIN__ */
-
-static int
-set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
-{
-	struct archive_entry *ae;
-	time_t ctime_sec, mtime_sec;
-	long ctime_ns, mtime_ns;
-
-	ae = archive_entry_new();
-	if (ae == NULL)
-		return (error_nomem(a));
-	archive_entry_copy_stat(ae, st);
-	ctime_sec = archive_entry_ctime(ae);
-	ctime_ns = archive_entry_ctime_nsec(ae);
-	mtime_sec = archive_entry_mtime(ae);
-	mtime_ns = archive_entry_mtime_nsec(ae);
-	archive_entry_free(ae);
-	return set_timefilter(a, timetype, mtime_sec, mtime_ns,
-			ctime_sec, ctime_ns);
-}
-
-static int
-set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
-    const char *path)
-{
-	struct stat st;
-
-	if (path == NULL || *path == '\0') {
-		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
-		return (ARCHIVE_FAILED);
-	}
-	if (la_stat(path, &st) != 0) {
-		archive_set_error(&(a->archive), errno, "Failed to stat()");
-		return (ARCHIVE_FAILED);
-	}
-	return (set_timefilter_stat(a, timetype, &st));
-}
-
-static int
-set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
-    const wchar_t *path)
-{
-	struct archive_string as;
-	int r;
-
-	if (path == NULL || *path == L'\0') {
-		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Convert WCS filename to MBS filename. */
-	archive_string_init(&as);
-	if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
-		archive_string_free(&as);
-		if (errno == ENOMEM)
-			return (error_nomem(a));
-		archive_set_error(&(a->archive), -1,
-		    "Failed to convert WCS to MBS");
-		return (ARCHIVE_FAILED);
-	}
-
-	r = set_timefilter_pathname_mbs(a, timetype, as.s);
-	archive_string_free(&as);
-
-	return (r);
-}
-#endif /* _WIN32 && !__CYGWIN__ */
-
-/*
- * Call back functions for archive_rb.
- */
-static int
-cmp_node_mbs(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
-	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
-	const char *p1, *p2;
-
-	archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
-	archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
-	if (p1 == NULL)
-		return (1);
-	if (p2 == NULL)
-		return (-1);
-	return (strcmp(p1, p2));
-}
-        
-static int
-cmp_key_mbs(const struct archive_rb_node *n, const void *key)
-{
-	struct match_file *f = (struct match_file *)(uintptr_t)n;
-	const char *p;
-
-	archive_mstring_get_mbs(NULL, &(f->pathname), &p);
-	if (p == NULL)
-		return (-1);
-	return (strcmp(p, (const char *)key));
-}
-
-static int
-cmp_node_wcs(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
-	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
-	const wchar_t *p1, *p2;
-
-	archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
-	archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
-	if (p1 == NULL)
-		return (1);
-	if (p2 == NULL)
-		return (-1);
-	return (wcscmp(p1, p2));
-}
-        
-static int
-cmp_key_wcs(const struct archive_rb_node *n, const void *key)
-{
-	struct match_file *f = (struct match_file *)(uintptr_t)n;
-	const wchar_t *p;
-
-	archive_mstring_get_wcs(NULL, &(f->pathname), &p);
-	if (p == NULL)
-		return (-1);
-	return (wcscmp(p, (const wchar_t *)key));
-}
-
-static void
-entry_list_init(struct entry_list *list)
-{
-	list->first = NULL;
-	list->last = &(list->first);
-	list->count = 0;
-}
-
-static void
-entry_list_free(struct entry_list *list)
-{
-	struct match_file *p, *q;
-
-	for (p = list->first; p != NULL; ) {
-		q = p;
-		p = p->next;
-		archive_mstring_clean(&(q->pathname));
-		free(q);
-	}
-}
-
-static void
-entry_list_add(struct entry_list *list, struct match_file *file)
-{
-	*list->last = file;
-	list->last = &(file->next);
-	list->count++;
-}
-
-static int
-add_entry(struct archive_match *a, int flag,
-    struct archive_entry *entry)
-{
-	struct match_file *f;
-	const void *pathname;
-	int r;
-
-	f = calloc(1, sizeof(*f));
-	if (f == NULL)
-		return (error_nomem(a));
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	pathname = archive_entry_pathname_w(entry);
-	if (pathname == NULL) {
-		free(f);
-		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
-		return (ARCHIVE_FAILED);
-	}
-	archive_mstring_copy_wcs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
-#else
-	(void)rb_ops_wcs;
-	pathname = archive_entry_pathname(entry);
-	if (pathname == NULL) {
-		free(f);
-		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
-		return (ARCHIVE_FAILED);
-	}
-	archive_mstring_copy_mbs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
-#endif
-	f->flag = flag;
-	f->mtime_sec = archive_entry_mtime(entry);
-	f->mtime_nsec = archive_entry_mtime_nsec(entry);
-	f->ctime_sec = archive_entry_ctime(entry);
-	f->ctime_nsec = archive_entry_ctime_nsec(entry);
-	r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
-	if (!r) {
-		struct match_file *f2;
-
-		/* Get the duplicated file. */
-		f2 = (struct match_file *)__archive_rb_tree_find_node(
-			&(a->exclusion_tree), pathname);
-
-		/*
-		 * We always overwrite comparison condition.
-		 * If you do not want to overwrite it, you should not
-		 * call archive_match_exclude_entry(). We cannot know
-		 * what behavior you really expect since overwriting
-		 * condition might be different with the flag.
-		 */
-		if (f2 != NULL) {
-			f2->flag = f->flag;
-			f2->mtime_sec = f->mtime_sec;
-			f2->mtime_nsec = f->mtime_nsec;
-			f2->ctime_sec = f->ctime_sec;
-			f2->ctime_nsec = f->ctime_nsec;
-		}
-		/* Release the duplicated file. */
-		archive_mstring_clean(&(f->pathname));
-		free(f);
-		return (ARCHIVE_OK);
-	}
-	entry_list_add(&(a->exclusion_entry_list), f);
-	a->setflag |= TIME_IS_SET;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Test if entry is excluded by its timestamp.
- */
-static int
-time_excluded(struct archive_match *a, struct archive_entry *entry)
-{
-	struct match_file *f;
-	const void *pathname;
-	time_t sec;
-	long nsec;
-
-	/*
-	 * If this file/dir is excluded by a time comparison, skip it.
-	 */
-	if (a->newer_ctime_filter) {
-		/* If ctime is not set, use mtime instead. */
-		if (archive_entry_ctime_is_set(entry))
-			sec = archive_entry_ctime(entry);
-		else
-			sec = archive_entry_mtime(entry);
-		if (sec < a->newer_ctime_sec)
-			return (1); /* Too old, skip it. */
-		if (sec == a->newer_ctime_sec) {
-			if (archive_entry_ctime_is_set(entry))
-				nsec = archive_entry_ctime_nsec(entry);
-			else
-				nsec = archive_entry_mtime_nsec(entry);
-			if (nsec < a->newer_ctime_nsec)
-				return (1); /* Too old, skip it. */
-			if (nsec == a->newer_ctime_nsec &&
-			    (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
-			      == 0)
-				return (1); /* Equal, skip it. */
-		}
-	}
-	if (a->older_ctime_filter) {
-		/* If ctime is not set, use mtime instead. */
-		if (archive_entry_ctime_is_set(entry))
-			sec = archive_entry_ctime(entry);
-		else
-			sec = archive_entry_mtime(entry);
-		if (sec > a->older_ctime_sec)
-			return (1); /* Too new, skip it. */
-		if (sec == a->older_ctime_sec) {
-			if (archive_entry_ctime_is_set(entry))
-				nsec = archive_entry_ctime_nsec(entry);
-			else
-				nsec = archive_entry_mtime_nsec(entry);
-			if (nsec > a->older_ctime_nsec)
-				return (1); /* Too new, skip it. */
-			if (nsec == a->older_ctime_nsec &&
-			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
-			      == 0)
-				return (1); /* Equal, skip it. */
-		}
-	}
-	if (a->newer_mtime_filter) {
-		sec = archive_entry_mtime(entry);
-		if (sec < a->newer_mtime_sec)
-			return (1); /* Too old, skip it. */
-		if (sec == a->newer_mtime_sec) {
-			nsec = archive_entry_mtime_nsec(entry);
-			if (nsec < a->newer_mtime_nsec)
-				return (1); /* Too old, skip it. */
-			if (nsec == a->newer_mtime_nsec &&
-			    (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
-			       == 0)
-				return (1); /* Equal, skip it. */
-		}
-	}
-	if (a->older_mtime_filter) {
-		sec = archive_entry_mtime(entry);
-		if (sec > a->older_mtime_sec)
-			return (1); /* Too new, skip it. */
-		nsec = archive_entry_mtime_nsec(entry);
-		if (sec == a->older_mtime_sec) {
-			if (nsec > a->older_mtime_nsec)
-				return (1); /* Too new, skip it. */
-			if (nsec == a->older_mtime_nsec &&
-			    (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
-			       == 0)
-				return (1); /* Equal, skip it. */
-		}
-	}
-
-	/* If there is no exclusion list, include the file. */
-	if (a->exclusion_entry_list.count == 0)
-		return (0);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	pathname = archive_entry_pathname_w(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
-#else
-	(void)rb_ops_wcs;
-	pathname = archive_entry_pathname(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
-#endif
-	if (pathname == NULL)
-		return (0);
-
-	f = (struct match_file *)__archive_rb_tree_find_node(
-		&(a->exclusion_tree), pathname);
-	/* If the file wasn't rejected, include it. */
-	if (f == NULL)
-		return (0);
-
-	if (f->flag & ARCHIVE_MATCH_CTIME) {
-		sec = archive_entry_ctime(entry);
-		if (f->ctime_sec > sec) {
-			if (f->flag & ARCHIVE_MATCH_OLDER)
-				return (1);
-		} else if (f->ctime_sec < sec) {
-			if (f->flag & ARCHIVE_MATCH_NEWER)
-				return (1);
-		} else {
-			nsec = archive_entry_ctime_nsec(entry);
-			if (f->ctime_nsec > nsec) {
-				if (f->flag & ARCHIVE_MATCH_OLDER)
-					return (1);
-			} else if (f->ctime_nsec < nsec) {
-				if (f->flag & ARCHIVE_MATCH_NEWER)
-					return (1);
-			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
-				return (1);
-		}
-	}
-	if (f->flag & ARCHIVE_MATCH_MTIME) {
-		sec = archive_entry_mtime(entry);
-		if (f->mtime_sec > sec) {
-			if (f->flag & ARCHIVE_MATCH_OLDER)
-				return (1);
-		} else if (f->mtime_sec < sec) {
-			if (f->flag & ARCHIVE_MATCH_NEWER)
-				return (1);
-		} else {
-			nsec = archive_entry_mtime_nsec(entry);
-			if (f->mtime_nsec > nsec) {
-				if (f->flag & ARCHIVE_MATCH_OLDER)
-					return (1);
-			} else if (f->mtime_nsec < nsec) {
-				if (f->flag & ARCHIVE_MATCH_NEWER)
-					return (1);
-			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
-				return (1);
-		}
-	}
-	return (0);
-}
-
-/*
- * Utility functions to manage inclusion owners
- */
-
-int
-archive_match_include_uid(struct archive *_a, la_int64_t uid)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_uid");
-	a = (struct archive_match *)_a;
-	return (add_owner_id(a, &(a->inclusion_uids), uid));
-}
-
-int
-archive_match_include_gid(struct archive *_a, la_int64_t gid)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_gid");
-	a = (struct archive_match *)_a;
-	return (add_owner_id(a, &(a->inclusion_gids), gid));
-}
-
-int
-archive_match_include_uname(struct archive *_a, const char *uname)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_uname");
-	a = (struct archive_match *)_a;
-	return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
-}
-
-int
-archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
-	a = (struct archive_match *)_a;
-	return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
-}
-
-int
-archive_match_include_gname(struct archive *_a, const char *gname)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_gname");
-	a = (struct archive_match *)_a;
-	return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
-}
-
-int
-archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
-	a = (struct archive_match *)_a;
-	return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
-}
-
-/*
- * Test function for owner(uid, gid, uname, gname).
- *
- * Returns 1 if archive entry is excluded.
- * Returns 0 if archive entry is not excluded.
- * Returns <0 if something error happened.
- */
-int
-archive_match_owner_excluded(struct archive *_a,
-    struct archive_entry *entry)
-{
-	struct archive_match *a;
-
-	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
-
-	a = (struct archive_match *)_a;
-	if (entry == NULL) {
-		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* If we don't have inclusion id set at all, the entry is always
-	 * not excluded. */
-	if ((a->setflag & ID_IS_SET) == 0)
-		return (0);
-	return (owner_excluded(a, entry));
-}
-
-static int
-add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
-{
-	unsigned i;
-
-	if (ids->count + 1 >= ids->size) {
-		void *p;
-
-		if (ids->size == 0)
-			ids->size = 8;
-		else
-			ids->size *= 2;
-		p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
-		if (p == NULL)
-			return (error_nomem(a));
-		ids->ids = (int64_t *)p;
-	}
-
-	/* Find an insert point. */
-	for (i = 0; i < ids->count; i++) {
-		if (ids->ids[i] >= id)
-			break;
-	}
-
-	/* Add owner id. */
-	if (i == ids->count)
-		ids->ids[ids->count++] = id;
-	else if (ids->ids[i] != id) {
-		memmove(&(ids->ids[i+1]), &(ids->ids[i]),
-		    (ids->count - i) * sizeof(ids->ids[0]));
-		ids->ids[i] = id;
-		ids->count++;
-	}
-	a->setflag |= ID_IS_SET;
-	return (ARCHIVE_OK);
-}
-
-static int
-match_owner_id(struct id_array *ids, int64_t id)
-{
-	unsigned b, m, t;
-
-	t = 0;
-	b = (unsigned)ids->count;
-	while (t < b) {
-		m = (t + b)>>1;
-		if (ids->ids[m] == id)
-			return (1);
-		if (ids->ids[m] < id)
-			t = m + 1;
-		else
-			b = m;
-	}
-	return (0);
-}
-
-static int
-add_owner_name(struct archive_match *a, struct match_list *list,
-    int mbs, const void *name)
-{
-	struct match *match;
-
-	match = calloc(1, sizeof(*match));
-	if (match == NULL)
-		return (error_nomem(a));
-	if (mbs)
-		archive_mstring_copy_mbs(&(match->pattern), name);
-	else
-		archive_mstring_copy_wcs(&(match->pattern), name);
-	match_list_add(list, match);
-	a->setflag |= ID_IS_SET;
-	return (ARCHIVE_OK);
-}
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-static int
-match_owner_name_mbs(struct archive_match *a, struct match_list *list,
-    const char *name)
-{
-	struct match *m;
-	const char *p;
-
-	if (name == NULL || *name == '\0')
-		return (0);
-	for (m = list->first; m; m = m->next) {
-		if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
-		    < 0 && errno == ENOMEM)
-			return (error_nomem(a));
-		if (p != NULL && strcmp(p, name) == 0) {
-			m->matches++;
-			return (1);
-		}
-	}
-	return (0);
-}
-#else
-static int
-match_owner_name_wcs(struct archive_match *a, struct match_list *list,
-    const wchar_t *name)
-{
-	struct match *m;
-	const wchar_t *p;
-
-	if (name == NULL || *name == L'\0')
-		return (0);
-	for (m = list->first; m; m = m->next) {
-		if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
-		    < 0 && errno == ENOMEM)
-			return (error_nomem(a));
-		if (p != NULL && wcscmp(p, name) == 0) {
-			m->matches++;
-			return (1);
-		}
-	}
-	return (0);
-}
-#endif
-
-/*
- * Test if entry is excluded by uid, gid, uname or gname.
- */
-static int
-owner_excluded(struct archive_match *a, struct archive_entry *entry)
-{
-	int r;
-
-	if (a->inclusion_uids.count) {
-		if (!match_owner_id(&(a->inclusion_uids),
-		    archive_entry_uid(entry)))
-			return (1);
-	}
-
-	if (a->inclusion_gids.count) {
-		if (!match_owner_id(&(a->inclusion_gids),
-		    archive_entry_gid(entry)))
-			return (1);
-	}
-
-	if (a->inclusion_unames.count) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		r = match_owner_name_wcs(a, &(a->inclusion_unames),
-			archive_entry_uname_w(entry));
-#else
-		r = match_owner_name_mbs(a, &(a->inclusion_unames),
-			archive_entry_uname(entry));
-#endif
-		if (!r)
-			return (1);
-		else if (r < 0)
-			return (r);
-	}
-
-	if (a->inclusion_gnames.count) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
-			archive_entry_gname_w(entry));
-#else
-		r = match_owner_name_mbs(a, &(a->inclusion_gnames),
-			archive_entry_gname(entry));
-#endif
-		if (!r)
-			return (1);
-		else if (r < 0)
-			return (r);
-	}
-	return (0);
-}
-
diff --git a/c/archive_openssl_evp_private.h b/c/archive_openssl_evp_private.h
deleted file mode 100644
--- a/c/archive_openssl_evp_private.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED
-#define ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include <openssl/evp.h>
-#include <openssl/opensslv.h>
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
-#include <stdlib.h> /* malloc, free */
-#include <string.h> /* memset */
-static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
-{
-	EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX));
-	return ctx;
-}
-
-static inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
-{
-	EVP_MD_CTX_cleanup(ctx);
-	memset(ctx, 0, sizeof(*ctx));
-	free(ctx);
-}
-#endif
-
-#endif
diff --git a/c/archive_openssl_hmac_private.h b/c/archive_openssl_hmac_private.h
deleted file mode 100644
--- a/c/archive_openssl_hmac_private.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED
-#define ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include <openssl/hmac.h>
-#include <openssl/opensslv.h>
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
-#include <stdlib.h> /* malloc, free */
-#include <string.h> /* memset */
-static inline HMAC_CTX *HMAC_CTX_new(void)
-{
-	HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX));
-	return ctx;
-}
-
-static inline void HMAC_CTX_free(HMAC_CTX *ctx)
-{
-	HMAC_CTX_cleanup(ctx);
-	memset(ctx, 0, sizeof(*ctx));
-	free(ctx);
-}
-#endif
-
-#endif
diff --git a/c/archive_options.c b/c/archive_options.c
deleted file mode 100644
--- a/c/archive_options.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*-
- * Copyright (c) 2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive_options_private.h"
-
-static const char *
-parse_option(const char **str,
-    const char **mod, const char **opt, const char **val);
-
-int
-_archive_set_option(struct archive *a,
-    const char *m, const char *o, const char *v,
-    int magic, const char *fn, option_handler use_option)
-{
-	const char *mp, *op, *vp;
-	int r;
-
-	archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
-
-	mp = (m != NULL && m[0] != '\0') ? m : NULL;
-	op = (o != NULL && o[0] != '\0') ? o : NULL;
-	vp = (v != NULL && v[0] != '\0') ? v : NULL;
-
-	if (op == NULL && vp == NULL)
-		return (ARCHIVE_OK);
-	if (op == NULL) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
-		return (ARCHIVE_FAILED);
-	}
-
-	r = use_option(a, mp, op, vp);
-	if (r == ARCHIVE_WARN - 1) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Unknown module name: `%s'", mp);
-		return (ARCHIVE_FAILED);
-	}
-	if (r == ARCHIVE_WARN) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Undefined option: `%s%s%s%s%s%s'",
-		    vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
-		return (ARCHIVE_FAILED);
-	}
-	return (r);
-}
-
-int
-_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v,
-    option_handler use_format_option, option_handler use_filter_option)
-{
-	int r1, r2;
-
-	if (o == NULL && v == NULL)
-		return (ARCHIVE_OK);
-	if (o == NULL)
-		return (ARCHIVE_FAILED);
-
-	r1 = use_format_option(a, m, o, v);
-	if (r1 == ARCHIVE_FATAL)
-		return (ARCHIVE_FATAL);
-
-	r2 = use_filter_option(a, m, o, v);
-	if (r2 == ARCHIVE_FATAL)
-		return (ARCHIVE_FATAL);
-
-	if (r2 == ARCHIVE_WARN - 1)
-		return r1;
-	return r1 > r2 ? r1 : r2;
-}
-
-int
-_archive_set_options(struct archive *a, const char *options,
-    int magic, const char *fn, option_handler use_option)
-{
-	int allok = 1, anyok = 0, ignore_mod_err = 0, r;
-	char *data;
-	const char *s, *mod, *opt, *val;
-
-	archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
-
-	if (options == NULL || options[0] == '\0')
-		return ARCHIVE_OK;
-
-	if ((data = strdup(options)) == NULL) {
-		archive_set_error(a,
-		    ENOMEM, "Out of memory adding file to list");
-		return (ARCHIVE_FATAL);
-	}
-	s = (const char *)data;
-
-	do {
-		mod = opt = val = NULL;
-
-		parse_option(&s, &mod, &opt, &val);
-		if (mod == NULL && opt != NULL &&
-		    strcmp("__ignore_wrong_module_name__", opt) == 0) {
-			/* Ignore module name error */
-			if (val != NULL) {
-				ignore_mod_err = 1;
-				anyok = 1;
-			}
-			continue;
-		}
-
-		r = use_option(a, mod, opt, val);
-		if (r == ARCHIVE_FATAL) {
-			free(data);
-			return (ARCHIVE_FATAL);
-		}
-		if (r == ARCHIVE_FAILED && mod != NULL) {
-			free(data);
-			return (ARCHIVE_FAILED);
-		}
-		if (r == ARCHIVE_WARN - 1) {
-			if (ignore_mod_err)
-				continue;
-			/* The module name is wrong. */
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Unknown module name: `%s'", mod);
-			free(data);
-			return (ARCHIVE_FAILED);
-		}
-		if (r == ARCHIVE_WARN) {
-			/* The option name is wrong. No-one used this. */
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Undefined option: `%s%s%s'",
-			    mod?mod:"", mod?":":"", opt);
-			free(data);
-			return (ARCHIVE_FAILED);
-		}
-		if (r == ARCHIVE_OK)
-			anyok = 1;
-		else
-			allok = 0;
-	} while (s != NULL);
-
-	free(data);
-	return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED;
-}
-
-static const char *
-parse_option(const char **s, const char **m, const char **o, const char **v)
-{
-	const char *end, *mod, *opt, *val;
-	char *p;
-
-	end = NULL;
-	mod = NULL;
-	opt = *s;
-	val = "1";
-
-	p = strchr(opt, ',');
-
-	if (p != NULL) {
-		*p = '\0';
-		end = ((const char *)p) + 1;
-	}
-
-	if (0 == strlen(opt)) {
-		*s = end;
-		*m = NULL;
-		*o = NULL;
-		*v = NULL;
-		return end;
-	}
-
-	p = strchr(opt, ':');
-	if (p != NULL) {
-		*p = '\0';
-		mod = opt;
-		opt = ++p;
-	}
-
-	p = strchr(opt, '=');
-	if (p != NULL) {
-		*p = '\0';
-		val = ++p;
-	} else if (opt[0] == '!') {
-		++opt;
-		val = NULL;
-	}
-
-	*s = end;
-	*m = mod;
-	*o = opt;
-	*v = val;
-
-	return end;
-}
-
diff --git a/c/archive_options_private.h b/c/archive_options_private.h
deleted file mode 100644
--- a/c/archive_options_private.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED
-#define ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive_private.h"
-
-typedef int (*option_handler)(struct archive *a,
-    const char *mod, const char *opt, const char *val);
-
-int
-_archive_set_option(struct archive *a,
-    const char *mod, const char *opt, const char *val,
-    int magic, const char *fn, option_handler use_option);
-
-int
-_archive_set_options(struct archive *a, const char *options,
-    int magic, const char *fn, option_handler use_option);
-
-int
-_archive_set_either_option(struct archive *a,
-    const char *m, const char *o, const char *v,
-    option_handler use_format_option, option_handler use_filter_option);
-
-#endif
diff --git a/c/archive_pack_dev.c b/c/archive_pack_dev.c
deleted file mode 100644
--- a/c/archive_pack_dev.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*	$NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $	*/
-
-/*-
- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Originally from NetBSD's mknod(8) source. */
-
-#include "archive_platform.h"
-
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-#if !defined(lint)
-__RCSID("$NetBSD$");
-#endif /* not lint */
-
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if MAJOR_IN_MKDEV
-#include <sys/mkdev.h>
-#define HAVE_MAJOR
-#elif MAJOR_IN_SYSMACROS
-#include <sys/sysmacros.h>
-#define HAVE_MAJOR
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive_pack_dev.h"
-
-static	pack_t	pack_netbsd;
-static	pack_t	pack_freebsd;
-static	pack_t	pack_8_8;
-static	pack_t	pack_12_20;
-static	pack_t	pack_14_18;
-static	pack_t	pack_8_24;
-static	pack_t	pack_bsdos;
-static	int	__LA_LIBC_CC compare_format(const void *, const void *);
-
-static const char iMajorError[] = "invalid major number";
-static const char iMinorError[] = "invalid minor number";
-static const char tooManyFields[] = "too many fields for format";
-
-/* This is blatantly stolen from libarchive/archive_entry.c,
- * in an attempt to get this to play nice on MinGW... */
-#if !defined(HAVE_MAJOR) && !defined(major)
-/* Replacement for major/minor/makedev. */
-#define major(x) ((int)(0x00ff & ((x) >> 8)))
-#define minor(x) ((int)(0xffff00ff & (x)))
-#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
-#endif
-
-/* Play games to come up with a suitable makedev() definition. */
-#ifdef __QNXNTO__
-/* QNX.  <sigh> */
-#include <sys/netmgr.h>
-#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
-#elif defined makedev
-/* There's a "makedev" macro. */
-#define apd_makedev(maj, min) makedev((maj), (min))
-#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
-/* Windows. <sigh> */
-#define apd_makedev(maj, min) mkdev((maj), (min))
-#else
-/* There's a "makedev" function. */
-#define apd_makedev(maj, min) makedev((maj), (min))
-#endif
-
-/* exported */
-dev_t
-pack_native(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = apd_makedev(numbers[0], numbers[1]);
-		if ((unsigned long)major(dev) != numbers[0])
-			*error = iMajorError;
-		else if ((unsigned long)minor(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-static dev_t
-pack_netbsd(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_netbsd(numbers[0], numbers[1]);
-		if ((unsigned long)major_netbsd(dev) != numbers[0])
-			*error = iMajorError;
-		else if ((unsigned long)minor_netbsd(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_freebsd(x)	((int32_t)(((x) & 0x0000ff00) >> 8))
-#define	minor_freebsd(x)	((int32_t)(((x) & 0xffff00ff) >> 0))
-#define	makedev_freebsd(x,y)	((dev_t)((((x) << 8) & 0x0000ff00) | \
-					 (((y) << 0) & 0xffff00ff)))
-
-static dev_t
-pack_freebsd(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_freebsd(numbers[0], numbers[1]);
-		if ((unsigned long)major_freebsd(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_freebsd(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_8_8(x)		((int32_t)(((x) & 0x0000ff00) >> 8))
-#define	minor_8_8(x)		((int32_t)(((x) & 0x000000ff) >> 0))
-#define	makedev_8_8(x,y)	((dev_t)((((x) << 8) & 0x0000ff00) | \
-					 (((y) << 0) & 0x000000ff)))
-
-static dev_t
-pack_8_8(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_8_8(numbers[0], numbers[1]);
-		if ((unsigned long)major_8_8(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_8_8(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_12_20(x)		((int32_t)(((x) & 0xfff00000) >> 20))
-#define	minor_12_20(x)		((int32_t)(((x) & 0x000fffff) >>  0))
-#define	makedev_12_20(x,y)	((dev_t)((((x) << 20) & 0xfff00000) | \
-					 (((y) <<  0) & 0x000fffff)))
-
-static dev_t
-pack_12_20(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_12_20(numbers[0], numbers[1]);
-		if ((unsigned long)major_12_20(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_12_20(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_14_18(x)		((int32_t)(((x) & 0xfffc0000) >> 18))
-#define	minor_14_18(x)		((int32_t)(((x) & 0x0003ffff) >>  0))
-#define	makedev_14_18(x,y)	((dev_t)((((x) << 18) & 0xfffc0000) | \
-					 (((y) <<  0) & 0x0003ffff)))
-
-static dev_t
-pack_14_18(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_14_18(numbers[0], numbers[1]);
-		if ((unsigned long)major_14_18(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_14_18(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_8_24(x)		((int32_t)(((x) & 0xff000000) >> 24))
-#define	minor_8_24(x)		((int32_t)(((x) & 0x00ffffff) >>  0))
-#define	makedev_8_24(x,y)	((dev_t)((((x) << 24) & 0xff000000) | \
-					 (((y) <<  0) & 0x00ffffff)))
-
-static dev_t
-pack_8_24(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_8_24(numbers[0], numbers[1]);
-		if ((unsigned long)major_8_24(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_8_24(dev) != numbers[1])
-			*error = iMinorError;
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-#define	major_12_12_8(x)	((int32_t)(((x) & 0xfff00000) >> 20))
-#define	unit_12_12_8(x)		((int32_t)(((x) & 0x000fff00) >>  8))
-#define	subunit_12_12_8(x)	((int32_t)(((x) & 0x000000ff) >>  0))
-#define	makedev_12_12_8(x,y,z)	((dev_t)((((x) << 20) & 0xfff00000) | \
-					 (((y) <<  8) & 0x000fff00) | \
-					 (((z) <<  0) & 0x000000ff)))
-
-static dev_t
-pack_bsdos(int n, unsigned long numbers[], const char **error)
-{
-	dev_t dev = 0;
-
-	if (n == 2) {
-		dev = makedev_12_20(numbers[0], numbers[1]);
-		if ((unsigned long)major_12_20(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)minor_12_20(dev) != numbers[1])
-			*error = iMinorError;
-	} else if (n == 3) {
-		dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
-		if ((unsigned long)major_12_12_8(dev) != numbers[0])
-			*error = iMajorError;
-		if ((unsigned long)unit_12_12_8(dev) != numbers[1])
-			*error = "invalid unit number";
-		if ((unsigned long)subunit_12_12_8(dev) != numbers[2])
-			*error = "invalid subunit number";
-	} else
-		*error = tooManyFields;
-	return (dev);
-}
-
-
-		/* list of formats and pack functions */
-		/* this list must be sorted lexically */
-static const struct format {
-	const char	*name;
-	pack_t		*pack;
-} formats[] = {
-	{"386bsd",  pack_8_8},
-	{"4bsd",    pack_8_8},
-	{"bsdos",   pack_bsdos},
-	{"freebsd", pack_freebsd},
-	{"hpux",    pack_8_24},
-	{"isc",     pack_8_8},
-	{"linux",   pack_8_8},
-	{"native",  pack_native},
-	{"netbsd",  pack_netbsd},
-	{"osf1",    pack_12_20},
-	{"sco",     pack_8_8},
-	{"solaris", pack_14_18},
-	{"sunos",   pack_8_8},
-	{"svr3",    pack_8_8},
-	{"svr4",    pack_14_18},
-	{"ultrix",  pack_8_8},
-};
-
-static int
-__LA_LIBC_CC
-compare_format(const void *key, const void *element)
-{
-	const char		*name;
-	const struct format	*format;
-
-	name = key;
-	format = element;
-
-	return (strcmp(name, format->name));
-}
-
-
-pack_t *
-pack_find(const char *name)
-{
-	struct format	*format;
-
-	format = bsearch(name, formats,
-	    sizeof(formats)/sizeof(formats[0]),
-	    sizeof(formats[0]), compare_format);
-	if (format == 0)
-		return (NULL);
-	return (format->pack);
-}
diff --git a/c/archive_pack_dev.h b/c/archive_pack_dev.h
deleted file mode 100644
--- a/c/archive_pack_dev.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*	$NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $	*/
-
-/*-
- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Originally from NetBSD's mknod(8) source. */
-
-#ifndef	ARCHIVE_PACK_DEV_H
-#define	ARCHIVE_PACK_DEV_H
-
-typedef	dev_t pack_t(int, unsigned long [], const char **);
-
-pack_t	*pack_find(const char *);
-pack_t	 pack_native;
-
-#define	major_netbsd(x)		((int32_t)((((x) & 0x000fff00) >>  8)))
-#define	minor_netbsd(x)		((int32_t)((((x) & 0xfff00000) >> 12) | \
-					   (((x) & 0x000000ff) >>  0)))
-#define	makedev_netbsd(x,y)	((dev_t)((((x) <<  8) & 0x000fff00) | \
-					 (((y) << 12) & 0xfff00000) | \
-					 (((y) <<  0) & 0x000000ff)))
-
-#endif	/* ARCHIVE_PACK_DEV_H */
diff --git a/c/archive_pathmatch.c b/c/archive_pathmatch.c
deleted file mode 100644
--- a/c/archive_pathmatch.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#include "archive_pathmatch.h"
-
-/*
- * Check whether a character 'c' is matched by a list specification [...]:
- *    * Leading '!' or '^' negates the class.
- *    * <char>-<char> is a range of characters
- *    * \<char> removes any special meaning for <char>
- *
- * Some interesting boundary cases:
- *   a-d-e is one range (a-d) followed by two single characters - and e.
- *   \a-\d is same as a-d
- *   a\-d is three single characters: a, d, -
- *   Trailing - is not special (so [a-] is two characters a and -).
- *   Initial - is not special ([a-] is same as [-a] is same as [\\-a])
- *   This function never sees a trailing \.
- *   [] always fails
- *   [!] always succeeds
- */
-static int
-pm_list(const char *start, const char *end, const char c, int flags)
-{
-	const char *p = start;
-	char rangeStart = '\0', nextRangeStart;
-	int match = 1, nomatch = 0;
-
-	/* This will be used soon... */
-	(void)flags; /* UNUSED */
-
-	/* If this is a negated class, return success for nomatch. */
-	if ((*p == '!' || *p == '^') && p < end) {
-		match = 0;
-		nomatch = 1;
-		++p;
-	}
-
-	while (p < end) {
-		nextRangeStart = '\0';
-		switch (*p) {
-		case '-':
-			/* Trailing or initial '-' is not special. */
-			if ((rangeStart == '\0') || (p == end - 1)) {
-				if (*p == c)
-					return (match);
-			} else {
-				char rangeEnd = *++p;
-				if (rangeEnd == '\\')
-					rangeEnd = *++p;
-				if ((rangeStart <= c) && (c <= rangeEnd))
-					return (match);
-			}
-			break;
-		case '\\':
-			++p;
-			/* Fall through */
-		default:
-			if (*p == c)
-				return (match);
-			nextRangeStart = *p; /* Possible start of range. */
-		}
-		rangeStart = nextRangeStart;
-		++p;
-	}
-	return (nomatch);
-}
-
-static int
-pm_list_w(const wchar_t *start, const wchar_t *end, const wchar_t c, int flags)
-{
-	const wchar_t *p = start;
-	wchar_t rangeStart = L'\0', nextRangeStart;
-	int match = 1, nomatch = 0;
-
-	/* This will be used soon... */
-	(void)flags; /* UNUSED */
-
-	/* If this is a negated class, return success for nomatch. */
-	if ((*p == L'!' || *p == L'^') && p < end) {
-		match = 0;
-		nomatch = 1;
-		++p;
-	}
-
-	while (p < end) {
-		nextRangeStart = L'\0';
-		switch (*p) {
-		case L'-':
-			/* Trailing or initial '-' is not special. */
-			if ((rangeStart == L'\0') || (p == end - 1)) {
-				if (*p == c)
-					return (match);
-			} else {
-				wchar_t rangeEnd = *++p;
-				if (rangeEnd == L'\\')
-					rangeEnd = *++p;
-				if ((rangeStart <= c) && (c <= rangeEnd))
-					return (match);
-			}
-			break;
-		case L'\\':
-			++p;
-			/* Fall through */
-		default:
-			if (*p == c)
-				return (match);
-			nextRangeStart = *p; /* Possible start of range. */
-		}
-		rangeStart = nextRangeStart;
-		++p;
-	}
-	return (nomatch);
-}
-
-/*
- * If s is pointing to "./", ".//", "./././" or the like, skip it.
- */
-static const char *
-pm_slashskip(const char *s) {
-	while ((*s == '/')
-	    || (s[0] == '.' && s[1] == '/')
-	    || (s[0] == '.' && s[1] == '\0'))
-		++s;
-	return (s);
-}
-
-static const wchar_t *
-pm_slashskip_w(const wchar_t *s) {
-	while ((*s == L'/')
-	    || (s[0] == L'.' && s[1] == L'/')
-	    || (s[0] == L'.' && s[1] == L'\0'))
-		++s;
-	return (s);
-}
-
-static int
-pm(const char *p, const char *s, int flags)
-{
-	const char *end;
-
-	/*
-	 * Ignore leading './', './/', '././', etc.
-	 */
-	if (s[0] == '.' && s[1] == '/')
-		s = pm_slashskip(s + 1);
-	if (p[0] == '.' && p[1] == '/')
-		p = pm_slashskip(p + 1);
-
-	for (;;) {
-		switch (*p) {
-		case '\0':
-			if (s[0] == '/') {
-				if (flags & PATHMATCH_NO_ANCHOR_END)
-					return (1);
-				/* "dir" == "dir/" == "dir/." */
-				s = pm_slashskip(s);
-			}
-			return (*s == '\0');
-		case '?':
-			/* ? always succeeds, unless we hit end of 's' */
-			if (*s == '\0')
-				return (0);
-			break;
-		case '*':
-			/* "*" == "**" == "***" ... */
-			while (*p == '*')
-				++p;
-			/* Trailing '*' always succeeds. */
-			if (*p == '\0')
-				return (1);
-			while (*s) {
-				if (archive_pathmatch(p, s, flags))
-					return (1);
-				++s;
-			}
-			return (0);
-		case '[':
-			/*
-			 * Find the end of the [...] character class,
-			 * ignoring \] that might occur within the class.
-			 */
-			end = p + 1;
-			while (*end != '\0' && *end != ']') {
-				if (*end == '\\' && end[1] != '\0')
-					++end;
-				++end;
-			}
-			if (*end == ']') {
-				/* We found [...], try to match it. */
-				if (!pm_list(p + 1, end, *s, flags))
-					return (0);
-				p = end; /* Jump to trailing ']' char. */
-				break;
-			} else
-				/* No final ']', so just match '['. */
-				if (*p != *s)
-					return (0);
-			break;
-		case '\\':
-			/* Trailing '\\' matches itself. */
-			if (p[1] == '\0') {
-				if (*s != '\\')
-					return (0);
-			} else {
-				++p;
-				if (*p != *s)
-					return (0);
-			}
-			break;
-		case '/':
-			if (*s != '/' && *s != '\0')
-				return (0);
-			/* Note: pattern "/\./" won't match "/";
-			 * pm_slashskip() correctly stops at backslash. */
-			p = pm_slashskip(p);
-			s = pm_slashskip(s);
-			if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
-				return (1);
-			--p; /* Counteract the increment below. */
-			--s;
-			break;
-		case '$':
-			/* '$' is special only at end of pattern and only
-			 * if PATHMATCH_NO_ANCHOR_END is specified. */
-			if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
-				/* "dir" == "dir/" == "dir/." */
-				return (*pm_slashskip(s) == '\0');
-			}
-			/* Otherwise, '$' is not special. */
-			/* FALL THROUGH */
-		default:
-			if (*p != *s)
-				return (0);
-			break;
-		}
-		++p;
-		++s;
-	}
-}
-
-static int
-pm_w(const wchar_t *p, const wchar_t *s, int flags)
-{
-	const wchar_t *end;
-
-	/*
-	 * Ignore leading './', './/', '././', etc.
-	 */
-	if (s[0] == L'.' && s[1] == L'/')
-		s = pm_slashskip_w(s + 1);
-	if (p[0] == L'.' && p[1] == L'/')
-		p = pm_slashskip_w(p + 1);
-
-	for (;;) {
-		switch (*p) {
-		case L'\0':
-			if (s[0] == L'/') {
-				if (flags & PATHMATCH_NO_ANCHOR_END)
-					return (1);
-				/* "dir" == "dir/" == "dir/." */
-				s = pm_slashskip_w(s);
-			}
-			return (*s == L'\0');
-		case L'?':
-			/* ? always succeeds, unless we hit end of 's' */
-			if (*s == L'\0')
-				return (0);
-			break;
-		case L'*':
-			/* "*" == "**" == "***" ... */
-			while (*p == L'*')
-				++p;
-			/* Trailing '*' always succeeds. */
-			if (*p == L'\0')
-				return (1);
-			while (*s) {
-				if (archive_pathmatch_w(p, s, flags))
-					return (1);
-				++s;
-			}
-			return (0);
-		case L'[':
-			/*
-			 * Find the end of the [...] character class,
-			 * ignoring \] that might occur within the class.
-			 */
-			end = p + 1;
-			while (*end != L'\0' && *end != L']') {
-				if (*end == L'\\' && end[1] != L'\0')
-					++end;
-				++end;
-			}
-			if (*end == L']') {
-				/* We found [...], try to match it. */
-				if (!pm_list_w(p + 1, end, *s, flags))
-					return (0);
-				p = end; /* Jump to trailing ']' char. */
-				break;
-			} else
-				/* No final ']', so just match '['. */
-				if (*p != *s)
-					return (0);
-			break;
-		case L'\\':
-			/* Trailing '\\' matches itself. */
-			if (p[1] == L'\0') {
-				if (*s != L'\\')
-					return (0);
-			} else {
-				++p;
-				if (*p != *s)
-					return (0);
-			}
-			break;
-		case L'/':
-			if (*s != L'/' && *s != L'\0')
-				return (0);
-			/* Note: pattern "/\./" won't match "/";
-			 * pm_slashskip() correctly stops at backslash. */
-			p = pm_slashskip_w(p);
-			s = pm_slashskip_w(s);
-			if (*p == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END))
-				return (1);
-			--p; /* Counteract the increment below. */
-			--s;
-			break;
-		case L'$':
-			/* '$' is special only at end of pattern and only
-			 * if PATHMATCH_NO_ANCHOR_END is specified. */
-			if (p[1] == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
-				/* "dir" == "dir/" == "dir/." */
-				return (*pm_slashskip_w(s) == L'\0');
-			}
-			/* Otherwise, '$' is not special. */
-			/* FALL THROUGH */
-		default:
-			if (*p != *s)
-				return (0);
-			break;
-		}
-		++p;
-		++s;
-	}
-}
-
-/* Main entry point. */
-int
-__archive_pathmatch(const char *p, const char *s, int flags)
-{
-	/* Empty pattern only matches the empty string. */
-	if (p == NULL || *p == '\0')
-		return (s == NULL || *s == '\0');
-	else if (s == NULL)
-		return (0);
-
-	/* Leading '^' anchors the start of the pattern. */
-	if (*p == '^') {
-		++p;
-		flags &= ~PATHMATCH_NO_ANCHOR_START;
-	}
-
-	if (*p == '/' && *s != '/')
-		return (0);
-
-	/* Certain patterns anchor implicitly. */
-	if (*p == '*' || *p == '/') {
-		while (*p == '/')
-			++p;
-		while (*s == '/')
-			++s;
-		return (pm(p, s, flags));
-	}
-
-	/* If start is unanchored, try to match start of each path element. */
-	if (flags & PATHMATCH_NO_ANCHOR_START) {
-		for ( ; s != NULL; s = strchr(s, '/')) {
-			if (*s == '/')
-				s++;
-			if (pm(p, s, flags))
-				return (1);
-		}
-		return (0);
-	}
-
-	/* Default: Match from beginning. */
-	return (pm(p, s, flags));
-}
-
-int
-__archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
-{
-	/* Empty pattern only matches the empty string. */
-	if (p == NULL || *p == L'\0')
-		return (s == NULL || *s == L'\0');
-	else if (s == NULL)
-		return (0);
-
-	/* Leading '^' anchors the start of the pattern. */
-	if (*p == L'^') {
-		++p;
-		flags &= ~PATHMATCH_NO_ANCHOR_START;
-	}
-
-	if (*p == L'/' && *s != L'/')
-		return (0);
-
-	/* Certain patterns anchor implicitly. */
-	if (*p == L'*' || *p == L'/') {
-		while (*p == L'/')
-			++p;
-		while (*s == L'/')
-			++s;
-		return (pm_w(p, s, flags));
-	}
-
-	/* If start is unanchored, try to match start of each path element. */
-	if (flags & PATHMATCH_NO_ANCHOR_START) {
-		for ( ; s != NULL; s = wcschr(s, L'/')) {
-			if (*s == L'/')
-				s++;
-			if (pm_w(p, s, flags))
-				return (1);
-		}
-		return (0);
-	}
-
-	/* Default: Match from beginning. */
-	return (pm_w(p, s, flags));
-}
diff --git a/c/archive_pathmatch.h b/c/archive_pathmatch.h
deleted file mode 100644
--- a/c/archive_pathmatch.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_PATHMATCH_H
-#define ARCHIVE_PATHMATCH_H
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-/* Don't anchor at beginning unless the pattern starts with "^" */
-#define PATHMATCH_NO_ANCHOR_START	1
-/* Don't anchor at end unless the pattern ends with "$" */
-#define PATHMATCH_NO_ANCHOR_END 	2
-
-/* Note that "^" and "$" are not special unless you set the corresponding
- * flag above. */
-
-int __archive_pathmatch(const char *p, const char *s, int flags);
-int __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags);
-
-#define archive_pathmatch(p, s, f)	__archive_pathmatch(p, s, f)
-#define archive_pathmatch_w(p, s, f)	__archive_pathmatch_w(p, s, f)
-
-#endif
diff --git a/c/archive_platform.h b/c/archive_platform.h
deleted file mode 100644
--- a/c/archive_platform.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_platform.h 201090 2009-12-28 02:22:04Z kientzle $
- */
-
-/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
-
-/*
- * This header is the first thing included in any of the libarchive
- * source files.  As far as possible, platform-specific issues should
- * be dealt with here and not within individual source files.  I'm
- * actively trying to minimize #if blocks within the main source,
- * since they obfuscate the code.
- */
-
-#ifndef ARCHIVE_PLATFORM_H_INCLUDED
-#define	ARCHIVE_PLATFORM_H_INCLUDED
-
-/* archive.h and archive_entry.h require this. */
-#define	__LIBARCHIVE_BUILD 1
-
-#if defined(PLATFORM_CONFIG_H)
-/* Use hand-built config.h in environments that need it. */
-#include PLATFORM_CONFIG_H
-#elif defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in archive_platform.h.
-#endif
-
-/* On macOS check for some symbols based on the deployment target version.  */
-#if defined(__APPLE__)
-# undef HAVE_FUTIMENS
-# undef HAVE_UTIMENSAT
-# include <AvailabilityMacros.h>
-# if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
-#  define HAVE_FUTIMENS 1
-#  define HAVE_UTIMENSAT 1
-# endif
-#endif
-
-/* It should be possible to get rid of this by extending the feature-test
- * macros to cover Windows API functions, probably along with non-trivial
- * refactoring of code to find structures that sit more cleanly on top of
- * either Windows or Posix APIs. */
-#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
-#include "archive_windows.h"
-/* The C library on Windows specifies a calling convention for callback
- * functions and exports; when we interact with them (capture pointers,
- * call and pass function pointers) we need to match their calling
- * convention.
- * This only matters when libarchive is built with /Gr, /Gz or /Gv
- * (which change the default calling convention.) */
-#define __LA_LIBC_CC __cdecl
-#else
-#define la_stat(path,stref)		stat(path,stref)
-#define __LA_LIBC_CC
-#endif
-
-/*
- * The config files define a lot of feature macros.  The following
- * uses those macros to select/define replacements and include key
- * headers as required.
- */
-
-/* Get a real definition for __FBSDID or __RCSID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define them so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define	__FBSDID(a)     struct _undefined_hack
-#endif
-#ifndef __RCSID
-#define	__RCSID(a)     struct _undefined_hack
-#endif
-
-/* Try to get standard C99-style integer type definitions. */
-#if HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#if HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-/* Borland warns about its own constants!  */
-#if defined(__BORLANDC__)
-# if HAVE_DECL_UINT64_MAX
-#  undef	UINT64_MAX
-#  undef	HAVE_DECL_UINT64_MAX
-# endif
-# if HAVE_DECL_UINT64_MIN
-#  undef	UINT64_MIN
-#  undef	HAVE_DECL_UINT64_MIN
-# endif
-# if HAVE_DECL_INT64_MAX
-#  undef	INT64_MAX
-#  undef	HAVE_DECL_INT64_MAX
-# endif
-# if HAVE_DECL_INT64_MIN
-#  undef	INT64_MIN
-#  undef	HAVE_DECL_INT64_MIN
-# endif
-#endif
-
-/* Some platforms lack the standard *_MAX definitions. */
-#if !HAVE_DECL_SIZE_MAX
-#define	SIZE_MAX (~(size_t)0)
-#endif
-#if !HAVE_DECL_SSIZE_MAX
-#define	SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1))
-#endif
-#if !HAVE_DECL_UINT32_MAX
-#define	UINT32_MAX (~(uint32_t)0)
-#endif
-#if !HAVE_DECL_INT32_MAX
-#define	INT32_MAX ((int32_t)(UINT32_MAX >> 1))
-#endif
-#if !HAVE_DECL_INT32_MIN
-#define	INT32_MIN ((int32_t)(~INT32_MAX))
-#endif
-#if !HAVE_DECL_UINT64_MAX
-#define	UINT64_MAX (~(uint64_t)0)
-#endif
-#if !HAVE_DECL_INT64_MAX
-#define	INT64_MAX ((int64_t)(UINT64_MAX >> 1))
-#endif
-#if !HAVE_DECL_INT64_MIN
-#define	INT64_MIN ((int64_t)(~INT64_MAX))
-#endif
-#if !HAVE_DECL_UINTMAX_MAX
-#define	UINTMAX_MAX (~(uintmax_t)0)
-#endif
-#if !HAVE_DECL_INTMAX_MAX
-#define	INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1))
-#endif
-#if !HAVE_DECL_INTMAX_MIN
-#define	INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
-#endif
-
-/* Some platforms lack the standard PRIxN/PRIdN definitions. */
-#if !HAVE_INTTYPES_H || !defined(PRIx32) || !defined(PRId32)
-#ifndef PRIx32
-#if SIZEOF_INT == 4
-#define PRIx32 "x"
-#elif SIZEOF_LONG == 4
-#define PRIx32 "lx"
-#else
-#error No suitable 32-bit unsigned integer type found for this platform
-#endif
-#endif // PRIx32
-#ifndef PRId32
-#if SIZEOF_INT == 4
-#define PRId32 "d"
-#elif SIZEOF_LONG == 4
-#define PRId32 "ld"
-#else
-#error No suitable 32-bit signed integer type found for this platform
-#endif
-#endif // PRId32
-#endif // !HAVE_INTTYPES_H || !defined(PRIx32) || !defined(PRId32)
-
-/*
- * If we can't restore metadata using a file descriptor, then
- * for compatibility's sake, close files before trying to restore metadata.
- */
-#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN)
-#define	CAN_RESTORE_METADATA_FD
-#endif
-
-/*
- * glibc 2.24 deprecates readdir_r
- * bionic c deprecates readdir_r too
- */
-#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__))
-#define	USE_READDIR_R	1
-#else
-#undef	USE_READDIR_R
-#endif
-
-/* Set up defaults for internal error codes. */
-#ifndef ARCHIVE_ERRNO_FILE_FORMAT
-#if HAVE_EFTYPE
-#define	ARCHIVE_ERRNO_FILE_FORMAT EFTYPE
-#else
-#if HAVE_EILSEQ
-#define	ARCHIVE_ERRNO_FILE_FORMAT EILSEQ
-#else
-#define	ARCHIVE_ERRNO_FILE_FORMAT EINVAL
-#endif
-#endif
-#endif
-
-#ifndef ARCHIVE_ERRNO_PROGRAMMER
-#define	ARCHIVE_ERRNO_PROGRAMMER EINVAL
-#endif
-
-#ifndef ARCHIVE_ERRNO_MISC
-#define	ARCHIVE_ERRNO_MISC (-1)
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ >= 7)
-#define	__LA_FALLTHROUGH	__attribute__((fallthrough))
-#else
-#define	__LA_FALLTHROUGH
-#endif
-
-#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
diff --git a/c/archive_platform_acl.h b/c/archive_platform_acl.h
deleted file mode 100644
--- a/c/archive_platform_acl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
-
-#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
-#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST_COMMON
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-/*
- * Determine what ACL types are supported
- */
-#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
-#define ARCHIVE_ACL_POSIX1E     1
-#endif
-
-#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
-    ARCHIVE_ACL_DARWIN  || ARCHIVE_ACL_LIBRICHACL
-#define ARCHIVE_ACL_NFS4        1
-#endif
-
-#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
-#define ARCHIVE_ACL_SUPPORT     1
-#endif
-
-#endif	/* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
diff --git a/c/archive_platform_xattr.h b/c/archive_platform_xattr.h
deleted file mode 100644
--- a/c/archive_platform_xattr.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * Copyright (c) 2017 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
-
-#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED
-#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST_COMMON
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-/*
- * Determine if we support extended attributes
- */
-#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \
-    ARCHIVE_XATTR_AIX
-#define ARCHIVE_XATTR_SUPPORT     1
-#endif
-
-#endif	/* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
diff --git a/c/archive_ppmd7.c b/c/archive_ppmd7.c
deleted file mode 100644
--- a/c/archive_ppmd7.c
+++ /dev/null
@@ -1,1168 +0,0 @@
-/* Ppmd7.c -- PPMdH codec
-2010-03-12 : Igor Pavlov : Public domain
-This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
-
-#include "archive_platform.h"
-
-#include <stdlib.h>
-
-#include "archive_ppmd7_private.h"
-
-#ifdef PPMD_32BIT
-  #define Ppmd7_GetPtr(p, ptr) (ptr)
-  #define Ppmd7_GetContext(p, ptr) (ptr)
-  #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
-#else
-  #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
-  #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
-  #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
-#endif
-
-#define Ppmd7_GetBinSumm(p) \
-    &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
-    p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
-    (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
-    2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
-    ((p->RunLength >> 26) & 0x20)]
-
-#define kTopValue (1 << 24)
-#define MAX_FREQ 124
-#define UNIT_SIZE 12
-
-#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
-#define U2I(nu) (p->Units2Indx[(nu) - 1])
-#define I2U(indx) (p->Indx2Units[indx])
-
-#ifdef PPMD_32BIT
-  #define REF(ptr) (ptr)
-#else
-  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
-#endif
-
-#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
-
-#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
-#define STATS(ctx) Ppmd7_GetStats(p, ctx)
-#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
-#define SUFFIX(ctx) CTX((ctx)->Suffix)
-
-static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
-static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
-
-typedef CPpmd7_Context * CTX_PTR;
-
-struct CPpmd7_Node_;
-
-typedef
-  #ifdef PPMD_32BIT
-    struct CPpmd7_Node_ *
-  #else
-    UInt32
-  #endif
-  CPpmd7_Node_Ref;
-
-typedef struct CPpmd7_Node_
-{
-  UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
-  UInt16 NU;
-  CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
-  CPpmd7_Node_Ref Prev;
-} CPpmd7_Node;
-
-#ifdef PPMD_32BIT
-  #define NODE(ptr) (ptr)
-#else
-  #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
-#endif
-
-static void Ppmd7_Update1(CPpmd7 *p);
-static void Ppmd7_Update1_0(CPpmd7 *p);
-static void Ppmd7_Update2(CPpmd7 *p);
-static void Ppmd7_UpdateBin(CPpmd7 *p);
-static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked,
-                                    UInt32 *scale);
-
-/* ----------- Base ----------- */
-
-static void Ppmd7_Construct(CPpmd7 *p)
-{
-  unsigned i, k, m;
-
-  p->Base = 0;
-
-  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
-  {
-    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
-    do { p->Units2Indx[k++] = (Byte)i; } while(--step);
-    p->Indx2Units[i] = (Byte)k;
-  }
-
-  p->NS2BSIndx[0] = (0 << 1);
-  p->NS2BSIndx[1] = (1 << 1);
-  memset(p->NS2BSIndx + 2, (2 << 1), 9);
-  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
-
-  for (i = 0; i < 3; i++)
-    p->NS2Indx[i] = (Byte)i;
-  for (m = i, k = 1; i < 256; i++)
-  {
-    p->NS2Indx[i] = (Byte)m;
-    if (--k == 0)
-      k = (++m) - 2;
-  }
-
-  memset(p->HB2Flag, 0, 0x40);
-  memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
-}
-
-static void Ppmd7_Free(CPpmd7 *p)
-{
-  free(p->Base);
-  p->Size = 0;
-  p->Base = 0;
-}
-
-static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
-{
-  if (p->Base == 0 || p->Size != size)
-  {
-    /* RestartModel() below assumes that p->Size >= UNIT_SIZE
-       (see the calculation of m->MinContext). */
-    if (size < UNIT_SIZE) {
-      return False;
-    }
-    Ppmd7_Free(p);
-    p->AlignOffset =
-      #ifdef PPMD_32BIT
-        (4 - size) & 3;
-      #else
-        4 - (size & 3);
-      #endif
-    if ((p->Base = (Byte *)malloc(p->AlignOffset + size
-        #ifndef PPMD_32BIT
-        + UNIT_SIZE
-        #endif
-        )) == 0)
-      return False;
-    p->Size = size;
-  }
-  return True;
-}
-
-static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
-{
-  *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
-  p->FreeList[indx] = REF(node);
-}
-
-static void *RemoveNode(CPpmd7 *p, unsigned indx)
-{
-  CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
-  p->FreeList[indx] = *node;
-  return node;
-}
-
-static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
-{
-  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
-  ptr = (Byte *)ptr + U2B(I2U(newIndx));
-  if (I2U(i = U2I(nu)) != nu)
-  {
-    unsigned k = I2U(--i);
-    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
-  }
-  InsertNode(p, ptr, i);
-}
-
-static void GlueFreeBlocks(CPpmd7 *p)
-{
-  #ifdef PPMD_32BIT
-  CPpmd7_Node headItem;
-  CPpmd7_Node_Ref head = &headItem;
-  #else
-  CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
-  #endif
-  
-  CPpmd7_Node_Ref n = head;
-  unsigned i;
-
-  p->GlueCount = 255;
-
-  /* create doubly-linked list of free blocks */
-  for (i = 0; i < PPMD_NUM_INDEXES; i++)
-  {
-    UInt16 nu = I2U(i);
-    CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
-    p->FreeList[i] = 0;
-    while (next != 0)
-    {
-      CPpmd7_Node *node = NODE(next);
-      node->Next = n;
-      n = NODE(n)->Prev = next;
-      next = *(const CPpmd7_Node_Ref *)node;
-      node->Stamp = 0;
-      node->NU = (UInt16)nu;
-    }
-  }
-  NODE(head)->Stamp = 1;
-  NODE(head)->Next = n;
-  NODE(n)->Prev = head;
-  if (p->LoUnit != p->HiUnit)
-    ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
-  
-  /* Glue free blocks */
-  while (n != head)
-  {
-    CPpmd7_Node *node = NODE(n);
-    UInt32 nu = (UInt32)node->NU;
-    for (;;)
-    {
-      CPpmd7_Node *node2 = NODE(n) + nu;
-      nu += node2->NU;
-      if (node2->Stamp != 0 || nu >= 0x10000)
-        break;
-      NODE(node2->Prev)->Next = node2->Next;
-      NODE(node2->Next)->Prev = node2->Prev;
-      node->NU = (UInt16)nu;
-    }
-    n = node->Next;
-  }
-  
-  /* Fill lists of free blocks */
-  for (n = NODE(head)->Next; n != head;)
-  {
-    CPpmd7_Node *node = NODE(n);
-    unsigned nu;
-    CPpmd7_Node_Ref next = node->Next;
-    for (nu = node->NU; nu > 128; nu -= 128, node += 128)
-      InsertNode(p, node, PPMD_NUM_INDEXES - 1);
-    if (I2U(i = U2I(nu)) != nu)
-    {
-      unsigned k = I2U(--i);
-      InsertNode(p, node + k, nu - k - 1);
-    }
-    InsertNode(p, node, i);
-    n = next;
-  }
-}
-
-static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
-{
-  unsigned i;
-  void *retVal;
-  if (p->GlueCount == 0)
-  {
-    GlueFreeBlocks(p);
-    if (p->FreeList[indx] != 0)
-      return RemoveNode(p, indx);
-  }
-  i = indx;
-  do
-  {
-    if (++i == PPMD_NUM_INDEXES)
-    {
-      UInt32 numBytes = U2B(I2U(indx));
-      p->GlueCount--;
-      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
-    }
-  }
-  while (p->FreeList[i] == 0);
-  retVal = RemoveNode(p, i);
-  SplitBlock(p, retVal, i, indx);
-  return retVal;
-}
-
-static void *AllocUnits(CPpmd7 *p, unsigned indx)
-{
-  UInt32 numBytes;
-  if (p->FreeList[indx] != 0)
-    return RemoveNode(p, indx);
-  numBytes = U2B(I2U(indx));
-  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
-  {
-    void *retVal = p->LoUnit;
-    p->LoUnit += numBytes;
-    return retVal;
-  }
-  return AllocUnitsRare(p, indx);
-}
-
-#define MyMem12Cpy(dest, src, num) \
-  { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
-    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
-
-static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
-{
-  unsigned i0 = U2I(oldNU);
-  unsigned i1 = U2I(newNU);
-  if (i0 == i1)
-    return oldPtr;
-  if (p->FreeList[i1] != 0)
-  {
-    void *ptr = RemoveNode(p, i1);
-    MyMem12Cpy(ptr, oldPtr, newNU);
-    InsertNode(p, oldPtr, i0);
-    return ptr;
-  }
-  SplitBlock(p, oldPtr, i0, i1);
-  return oldPtr;
-}
-
-#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
-
-static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
-{
-  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
-  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
-}
-
-static void RestartModel(CPpmd7 *p)
-{
-  unsigned i, k, m;
-
-  memset(p->FreeList, 0, sizeof(p->FreeList));
-  p->Text = p->Base + p->AlignOffset;
-  p->HiUnit = p->Text + p->Size;
-  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
-  p->GlueCount = 0;
-
-  p->OrderFall = p->MaxOrder;
-  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
-  p->PrevSuccess = 0;
-
-  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
-  p->MinContext->Suffix = 0;
-  p->MinContext->NumStats = 256;
-  p->MinContext->SummFreq = 256 + 1;
-  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
-  p->LoUnit += U2B(256 / 2);
-  p->MinContext->Stats = REF(p->FoundState);
-  for (i = 0; i < 256; i++)
-  {
-    CPpmd_State *s = &p->FoundState[i];
-    s->Symbol = (Byte)i;
-    s->Freq = 1;
-    SetSuccessor(s, 0);
-  }
-
-  for (i = 0; i < 128; i++)
-    for (k = 0; k < 8; k++)
-    {
-      UInt16 *dest = p->BinSumm[i] + k;
-      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
-      for (m = 0; m < 64; m += 8)
-        dest[m] = val;
-    }
-  
-  for (i = 0; i < 25; i++)
-    for (k = 0; k < 16; k++)
-    {
-      CPpmd_See *s = &p->See[i][k];
-      s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
-      s->Count = 4;
-    }
-}
-
-static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
-{
-  p->MaxOrder = maxOrder;
-  RestartModel(p);
-  p->DummySee.Shift = PPMD_PERIOD_BITS;
-  p->DummySee.Summ = 0; /* unused */
-  p->DummySee.Count = 64; /* unused */
-}
-
-static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
-{
-  CPpmd_State upState;
-  CTX_PTR c = p->MinContext;
-  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
-  CPpmd_State *ps[PPMD7_MAX_ORDER];
-  unsigned numPs = 0;
-  
-  if (!skip)
-    ps[numPs++] = p->FoundState;
-  
-  while (c->Suffix)
-  {
-    CPpmd_Void_Ref successor;
-    CPpmd_State *s;
-    c = SUFFIX(c);
-    if (c->NumStats != 1)
-    {
-      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
-    }
-    else
-      s = ONE_STATE(c);
-    successor = SUCCESSOR(s);
-    if (successor != upBranch)
-    {
-      c = CTX(successor);
-      if (numPs == 0)
-        return c;
-      break;
-    }
-    ps[numPs++] = s;
-  }
-  
-  upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
-  SetSuccessor(&upState, upBranch + 1);
-  
-  if (c->NumStats == 1)
-    upState.Freq = ONE_STATE(c)->Freq;
-  else
-  {
-    UInt32 cf, s0;
-    CPpmd_State *s;
-    for (s = STATS(c); s->Symbol != upState.Symbol; s++);
-    cf = s->Freq - 1;
-    s0 = c->SummFreq - c->NumStats - cf;
-    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
-  }
-
-  while (numPs != 0)
-  {
-    /* Create Child */
-    CTX_PTR c1; /* = AllocContext(p); */
-    if (p->HiUnit != p->LoUnit)
-      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
-    else if (p->FreeList[0] != 0)
-      c1 = (CTX_PTR)RemoveNode(p, 0);
-    else
-    {
-      c1 = (CTX_PTR)AllocUnitsRare(p, 0);
-      if (!c1)
-        return NULL;
-    }
-    c1->NumStats = 1;
-    *ONE_STATE(c1) = upState;
-    c1->Suffix = REF(c);
-    SetSuccessor(ps[--numPs], REF(c1));
-    c = c1;
-  }
-  
-  return c;
-}
-
-static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
-{
-  CPpmd_State tmp = *t1;
-  *t1 = *t2;
-  *t2 = tmp;
-}
-
-static void UpdateModel(CPpmd7 *p)
-{
-  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
-  CTX_PTR c;
-  unsigned s0, ns;
-  
-  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
-  {
-    c = SUFFIX(p->MinContext);
-    
-    if (c->NumStats == 1)
-    {
-      CPpmd_State *s = ONE_STATE(c);
-      if (s->Freq < 32)
-        s->Freq++;
-    }
-    else
-    {
-      CPpmd_State *s = STATS(c);
-      if (s->Symbol != p->FoundState->Symbol)
-      {
-        do { s++; } while (s->Symbol != p->FoundState->Symbol);
-        if (s[0].Freq >= s[-1].Freq)
-        {
-          SwapStates(&s[0], &s[-1]);
-          s--;
-        }
-      }
-      if (s->Freq < MAX_FREQ - 9)
-      {
-        s->Freq += 2;
-        c->SummFreq += 2;
-      }
-    }
-  }
-
-  if (p->OrderFall == 0)
-  {
-    p->MinContext = p->MaxContext = CreateSuccessors(p, True);
-    if (p->MinContext == 0)
-    {
-      RestartModel(p);
-      return;
-    }
-    SetSuccessor(p->FoundState, REF(p->MinContext));
-    return;
-  }
-  
-  *p->Text++ = p->FoundState->Symbol;
-  successor = REF(p->Text);
-  if (p->Text >= p->UnitsStart)
-  {
-    RestartModel(p);
-    return;
-  }
-  
-  if (fSuccessor)
-  {
-    if (fSuccessor <= successor)
-    {
-      CTX_PTR cs = CreateSuccessors(p, False);
-      if (cs == NULL)
-      {
-        RestartModel(p);
-        return;
-      }
-      fSuccessor = REF(cs);
-    }
-    if (--p->OrderFall == 0)
-    {
-      successor = fSuccessor;
-      p->Text -= (p->MaxContext != p->MinContext);
-    }
-  }
-  else
-  {
-    SetSuccessor(p->FoundState, successor);
-    fSuccessor = REF(p->MinContext);
-  }
-  
-  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
-  
-  for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
-  {
-    unsigned ns1;
-    UInt32 cf, sf;
-    if ((ns1 = c->NumStats) != 1)
-    {
-      if ((ns1 & 1) == 0)
-      {
-        /* Expand for one UNIT */
-        unsigned oldNU = ns1 >> 1;
-        unsigned i = U2I(oldNU);
-        if (i != U2I(oldNU + 1))
-        {
-          void *ptr = AllocUnits(p, i + 1);
-          void *oldPtr;
-          if (!ptr)
-          {
-            RestartModel(p);
-            return;
-          }
-          oldPtr = STATS(c);
-          MyMem12Cpy(ptr, oldPtr, oldNU);
-          InsertNode(p, oldPtr, i);
-          c->Stats = STATS_REF(ptr);
-        }
-      }
-      c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
-    }
-    else
-    {
-      CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
-      if (!s)
-      {
-        RestartModel(p);
-        return;
-      }
-      *s = *ONE_STATE(c);
-      c->Stats = REF(s);
-      if (s->Freq < MAX_FREQ / 4 - 1)
-        s->Freq <<= 1;
-      else
-        s->Freq = MAX_FREQ - 4;
-      c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
-    }
-    cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
-    sf = (UInt32)s0 + c->SummFreq;
-    if (cf < 6 * sf)
-    {
-      cf = 1 + (cf > sf) + (cf >= 4 * sf);
-      c->SummFreq += 3;
-    }
-    else
-    {
-      cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
-      c->SummFreq = (UInt16)(c->SummFreq + cf);
-    }
-    {
-      CPpmd_State *s = STATS(c) + ns1;
-      SetSuccessor(s, successor);
-      s->Symbol = p->FoundState->Symbol;
-      s->Freq = (Byte)cf;
-      c->NumStats = (UInt16)(ns1 + 1);
-    }
-  }
-  p->MaxContext = p->MinContext = CTX(fSuccessor);
-}
-  
-static void Rescale(CPpmd7 *p)
-{
-  unsigned i, adder, sumFreq, escFreq;
-  CPpmd_State *stats = STATS(p->MinContext);
-  CPpmd_State *s = p->FoundState;
-  {
-    CPpmd_State tmp = *s;
-    for (; s != stats; s--)
-      s[0] = s[-1];
-    *s = tmp;
-  }
-  escFreq = p->MinContext->SummFreq - s->Freq;
-  s->Freq += 4;
-  adder = (p->OrderFall != 0);
-  s->Freq = (Byte)((s->Freq + adder) >> 1);
-  sumFreq = s->Freq;
-  
-  i = p->MinContext->NumStats - 1;
-  do
-  {
-    escFreq -= (++s)->Freq;
-    s->Freq = (Byte)((s->Freq + adder) >> 1);
-    sumFreq += s->Freq;
-    if (s[0].Freq > s[-1].Freq)
-    {
-      CPpmd_State *s1 = s;
-      CPpmd_State tmp = *s1;
-      do
-        s1[0] = s1[-1];
-      while (--s1 != stats && tmp.Freq > s1[-1].Freq);
-      *s1 = tmp;
-    }
-  }
-  while (--i);
-  
-  if (s->Freq == 0)
-  {
-    unsigned numStats = p->MinContext->NumStats;
-    unsigned n0, n1;
-    do { i++; } while ((--s)->Freq == 0);
-    escFreq += i;
-    p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
-    if (p->MinContext->NumStats == 1)
-    {
-      CPpmd_State tmp = *stats;
-      do
-      {
-        tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
-        escFreq >>= 1;
-      }
-      while (escFreq > 1);
-      InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
-      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
-      return;
-    }
-    n0 = (numStats + 1) >> 1;
-    n1 = (p->MinContext->NumStats + 1) >> 1;
-    if (n0 != n1)
-      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
-  }
-  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
-  p->FoundState = STATS(p->MinContext);
-}
-
-static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
-{
-  CPpmd_See *see;
-  unsigned nonMasked = p->MinContext->NumStats - numMasked;
-  if (p->MinContext->NumStats != 256)
-  {
-    see = p->See[p->NS2Indx[nonMasked - 1]] +
-        (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
-        2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
-        4 * (numMasked > nonMasked) +
-        p->HiBitsFlag;
-    {
-      unsigned r = (see->Summ >> see->Shift);
-      see->Summ = (UInt16)(see->Summ - r);
-      *escFreq = r + (r == 0);
-    }
-  }
-  else
-  {
-    see = &p->DummySee;
-    *escFreq = 1;
-  }
-  return see;
-}
-
-static void NextContext(CPpmd7 *p)
-{
-  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
-  if (p->OrderFall == 0 && (Byte *)c > p->Text)
-    p->MinContext = p->MaxContext = c;
-  else
-    UpdateModel(p);
-}
-
-static void Ppmd7_Update1(CPpmd7 *p)
-{
-  CPpmd_State *s = p->FoundState;
-  s->Freq += 4;
-  p->MinContext->SummFreq += 4;
-  if (s[0].Freq > s[-1].Freq)
-  {
-    SwapStates(&s[0], &s[-1]);
-    p->FoundState = --s;
-    if (s->Freq > MAX_FREQ)
-      Rescale(p);
-  }
-  NextContext(p);
-}
-
-static void Ppmd7_Update1_0(CPpmd7 *p)
-{
-  p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
-  p->RunLength += p->PrevSuccess;
-  p->MinContext->SummFreq += 4;
-  if ((p->FoundState->Freq += 4) > MAX_FREQ)
-    Rescale(p);
-  NextContext(p);
-}
-
-static void Ppmd7_UpdateBin(CPpmd7 *p)
-{
-  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
-  p->PrevSuccess = 1;
-  p->RunLength++;
-  NextContext(p);
-}
-
-static void Ppmd7_Update2(CPpmd7 *p)
-{
-  p->MinContext->SummFreq += 4;
-  if ((p->FoundState->Freq += 4) > MAX_FREQ)
-    Rescale(p);
-  p->RunLength = p->InitRL;
-  UpdateModel(p);
-}
-
-/* ---------- Decode ---------- */
-
-static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p)
-{
-  unsigned i;
-  p->Low = p->Bottom = 0;
-  p->Range = 0xFFFFFFFF;
-  for (i = 0; i < 4; i++)
-    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
-  return (p->Code < 0xFFFFFFFF);
-}
-
-static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
-{
-  if (p->Stream->Read((void *)p->Stream) != 0)
-    return False;
-  return Ppmd_RangeDec_Init(p);
-}
-
-static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p)
-{
-  if (!Ppmd_RangeDec_Init(p))
-    return False;
-  p->Bottom = 0x8000;
-  return True;
-}
-
-static UInt32 Range_GetThreshold(void *pp, UInt32 total)
-{
-  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
-  return (p->Code - p->Low) / (p->Range /= total);
-}
-
-static void Range_Normalize(CPpmd7z_RangeDec *p)
-{
-  while (1)
-  {
-    if((p->Low ^ (p->Low + p->Range)) >= kTopValue)
-    {
-      if(p->Range >= p->Bottom)
-        break;
-      else
-        p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1);
-    }
-    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
-    p->Range <<= 8;
-    p->Low <<= 8;
-  }
-}
-
-static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size)
-{
-  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
-  p->Code -= start * p->Range;
-  p->Range *= size;
-  Range_Normalize(p);
-}
-
-static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size)
-{
-  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
-  p->Low += start * p->Range;
-  p->Range *= size;
-  Range_Normalize(p);
-}
-
-static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0)
-{
-  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
-  UInt32 newBound = (p->Range >> 14) * size0;
-  UInt32 symbol;
-  if (p->Code < newBound)
-  {
-    symbol = 0;
-    p->Range = newBound;
-  }
-  else
-  {
-    symbol = 1;
-    p->Code -= newBound;
-    p->Range -= newBound;
-  }
-  Range_Normalize(p);
-  return symbol;
-}
-
-static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0)
-{
-  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
-  UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE);
-  if(value < size0)
-  {
-    bit = 0;
-    p->p.Decode(p, 0, size0);
-  }
-  else
-  {
-    bit = 1;
-    p->p.Decode(p, size0, PPMD_BIN_SCALE - size0);
-  }
-  return bit;
-}
-
-static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
-{
-  p->p.GetThreshold = Range_GetThreshold;
-  p->p.Decode = Range_Decode_7z;
-  p->p.DecodeBit = Range_DecodeBit_7z;
-}
-
-static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
-{
-  p->p.GetThreshold = Range_GetThreshold;
-  p->p.Decode = Range_Decode_RAR;
-  p->p.DecodeBit = Range_DecodeBit_RAR;
-}
-
-#define MASK(sym) ((signed char *)charMask)[sym]
-
-static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
-{
-  size_t charMask[256 / sizeof(size_t)];
-  if (p->MinContext->NumStats != 1)
-  {
-    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
-    unsigned i;
-    UInt32 count, hiCnt;
-    if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
-    {
-      Byte symbol;
-      rc->Decode(rc, 0, s->Freq);
-      p->FoundState = s;
-      symbol = s->Symbol;
-      Ppmd7_Update1_0(p);
-      return symbol;
-    }
-    p->PrevSuccess = 0;
-    i = p->MinContext->NumStats - 1;
-    do
-    {
-      if ((hiCnt += (++s)->Freq) > count)
-      {
-        Byte symbol;
-        rc->Decode(rc, hiCnt - s->Freq, s->Freq);
-        p->FoundState = s;
-        symbol = s->Symbol;
-        Ppmd7_Update1(p);
-        return symbol;
-      }
-    }
-    while (--i);
-    if (count >= p->MinContext->SummFreq)
-      return -2;
-    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
-    rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
-    PPMD_SetAllBitsIn256Bytes(charMask);
-    MASK(s->Symbol) = 0;
-    i = p->MinContext->NumStats - 1;
-    do { MASK((--s)->Symbol) = 0; } while (--i);
-  }
-  else
-  {
-    UInt16 *prob = Ppmd7_GetBinSumm(p);
-    if (rc->DecodeBit(rc, *prob) == 0)
-    {
-      Byte symbol;
-      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
-      symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
-      Ppmd7_UpdateBin(p);
-      return symbol;
-    }
-    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
-    p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
-    PPMD_SetAllBitsIn256Bytes(charMask);
-    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
-    p->PrevSuccess = 0;
-  }
-  for (;;)
-  {
-    CPpmd_State *ps[256], *s;
-    UInt32 freqSum, count, hiCnt;
-    CPpmd_See *see;
-    unsigned i, num, numMasked = p->MinContext->NumStats;
-    do
-    {
-      p->OrderFall++;
-      if (!p->MinContext->Suffix)
-        return -1;
-      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
-    }
-    while (p->MinContext->NumStats == numMasked);
-    hiCnt = 0;
-    s = Ppmd7_GetStats(p, p->MinContext);
-    i = 0;
-    num = p->MinContext->NumStats - numMasked;
-    do
-    {
-      int k = (int)(MASK(s->Symbol));
-      hiCnt += (s->Freq & k);
-      ps[i] = s++;
-      i -= k;
-    }
-    while (i != num);
-
-    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
-    freqSum += hiCnt;
-    count = rc->GetThreshold(rc, freqSum);
-
-    if (count < hiCnt)
-    {
-      Byte symbol;
-      CPpmd_State **pps = ps;
-      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
-      s = *pps;
-      rc->Decode(rc, hiCnt - s->Freq, s->Freq);
-      Ppmd_See_Update(see);
-      p->FoundState = s;
-      symbol = s->Symbol;
-      Ppmd7_Update2(p);
-      return symbol;
-    }
-    if (count >= freqSum)
-      return -2;
-    rc->Decode(rc, hiCnt, freqSum - hiCnt);
-    see->Summ = (UInt16)(see->Summ + freqSum);
-    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
-  }
-}
-
-/* ---------- Encode ---------- Ppmd7Enc.c */
-
-#define kTopValue (1 << 24)
-
-static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
-{
-  p->Low = 0;
-  p->Range = 0xFFFFFFFF;
-  p->Cache = 0;
-  p->CacheSize = 1;
-}
-
-static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
-{
-  if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
-  {
-    Byte temp = p->Cache;
-    do
-    {
-      p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
-      temp = 0xFF;
-    }
-    while(--p->CacheSize != 0);
-    p->Cache = (Byte)((UInt32)p->Low >> 24);
-  }
-  p->CacheSize++;
-  p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
-}
-
-static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
-{
-  p->Low += (UInt64)start * (UInt64)(p->Range /= total);
-  p->Range *= size;
-  while (p->Range < kTopValue)
-  {
-    p->Range <<= 8;
-    RangeEnc_ShiftLow(p);
-  }
-}
-
-static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
-{
-  p->Range = (p->Range >> 14) * size0;
-  while (p->Range < kTopValue)
-  {
-    p->Range <<= 8;
-    RangeEnc_ShiftLow(p);
-  }
-}
-
-static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
-{
-  UInt32 newBound = (p->Range >> 14) * size0;
-  p->Low += newBound;
-  p->Range -= newBound;
-  while (p->Range < kTopValue)
-  {
-    p->Range <<= 8;
-    RangeEnc_ShiftLow(p);
-  }
-}
-
-static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
-{
-  unsigned i;
-  for (i = 0; i < 5; i++)
-    RangeEnc_ShiftLow(p);
-}
-
-
-#define MASK(sym) ((signed char *)charMask)[sym]
-
-static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
-{
-  size_t charMask[256 / sizeof(size_t)];
-  if (p->MinContext->NumStats != 1)
-  {
-    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
-    UInt32 sum;
-    unsigned i;
-    if (s->Symbol == symbol)
-    {
-      RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
-      p->FoundState = s;
-      Ppmd7_Update1_0(p);
-      return;
-    }
-    p->PrevSuccess = 0;
-    sum = s->Freq;
-    i = p->MinContext->NumStats - 1;
-    do
-    {
-      if ((++s)->Symbol == symbol)
-      {
-        RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
-        p->FoundState = s;
-        Ppmd7_Update1(p);
-        return;
-      }
-      sum += s->Freq;
-    }
-    while (--i);
-    
-    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
-    PPMD_SetAllBitsIn256Bytes(charMask);
-    MASK(s->Symbol) = 0;
-    i = p->MinContext->NumStats - 1;
-    do { MASK((--s)->Symbol) = 0; } while (--i);
-    RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
-  }
-  else
-  {
-    UInt16 *prob = Ppmd7_GetBinSumm(p);
-    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
-    if (s->Symbol == symbol)
-    {
-      RangeEnc_EncodeBit_0(rc, *prob);
-      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
-      p->FoundState = s;
-      Ppmd7_UpdateBin(p);
-      return;
-    }
-    else
-    {
-      RangeEnc_EncodeBit_1(rc, *prob);
-      *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
-      p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
-      PPMD_SetAllBitsIn256Bytes(charMask);
-      MASK(s->Symbol) = 0;
-      p->PrevSuccess = 0;
-    }
-  }
-  for (;;)
-  {
-    UInt32 escFreq;
-    CPpmd_See *see;
-    CPpmd_State *s;
-    UInt32 sum;
-    unsigned i, numMasked = p->MinContext->NumStats;
-    do
-    {
-      p->OrderFall++;
-      if (!p->MinContext->Suffix)
-        return; /* EndMarker (symbol = -1) */
-      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
-    }
-    while (p->MinContext->NumStats == numMasked);
-    
-    see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
-    s = Ppmd7_GetStats(p, p->MinContext);
-    sum = 0;
-    i = p->MinContext->NumStats;
-    do
-    {
-      int cur = s->Symbol;
-      if (cur == symbol)
-      {
-        UInt32 low = sum;
-        CPpmd_State *s1 = s;
-        do
-        {
-          sum += (s->Freq & (int)(MASK(s->Symbol)));
-          s++;
-        }
-        while (--i);
-        RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
-        Ppmd_See_Update(see);
-        p->FoundState = s1;
-        Ppmd7_Update2(p);
-        return;
-      }
-      sum += (s->Freq & (int)(MASK(cur)));
-      MASK(cur) = 0;
-      s++;
-    }
-    while (--i);
-    
-    RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
-    see->Summ = (UInt16)(see->Summ + sum + escFreq);
-  }
-}
-
-const IPpmd7 __archive_ppmd7_functions =
-{
-  &Ppmd7_Construct,
-  &Ppmd7_Alloc,
-  &Ppmd7_Free,
-  &Ppmd7_Init,
-  &Ppmd7z_RangeDec_CreateVTable,
-  &PpmdRAR_RangeDec_CreateVTable,
-  &Ppmd7z_RangeDec_Init,
-  &PpmdRAR_RangeDec_Init,
-  &Ppmd7_DecodeSymbol,
-  &Ppmd7z_RangeEnc_Init,
-  &Ppmd7z_RangeEnc_FlushData,
-  &Ppmd7_EncodeSymbol
-};
diff --git a/c/archive_ppmd7_private.h b/c/archive_ppmd7_private.h
deleted file mode 100644
--- a/c/archive_ppmd7_private.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Ppmd7.h -- PPMdH compression codec
-2010-03-12 : Igor Pavlov : Public domain
-This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
-
-/* This code supports virtual RangeDecoder and includes the implementation
-of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
-If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
-
-#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
-#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include "archive_ppmd_private.h"
-
-#define PPMD7_MIN_ORDER 2
-#define PPMD7_MAX_ORDER 64
-
-#define PPMD7_MIN_MEM_SIZE (1 << 11)
-#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3)
-
-struct CPpmd7_Context_;
-
-typedef
-  #ifdef PPMD_32BIT
-    struct CPpmd7_Context_ *
-  #else
-    UInt32
-  #endif
-  CPpmd7_Context_Ref;
-
-typedef struct CPpmd7_Context_
-{
-  UInt16 NumStats;
-  UInt16 SummFreq;
-  CPpmd_State_Ref Stats;
-  CPpmd7_Context_Ref Suffix;
-} CPpmd7_Context;
-
-#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
-
-typedef struct
-{
-  CPpmd7_Context *MinContext, *MaxContext;
-  CPpmd_State *FoundState;
-  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
-  Int32 RunLength, InitRL; /* must be 32-bit at least */
-
-  UInt32 Size;
-  UInt32 GlueCount;
-  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
-  UInt32 AlignOffset;
-
-  Byte Indx2Units[PPMD_NUM_INDEXES];
-  Byte Units2Indx[128];
-  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
-  Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
-  CPpmd_See DummySee, See[25][16];
-  UInt16 BinSumm[128][64];
-} CPpmd7;
-
-/* ---------- Decode ---------- */
-
-typedef struct
-{
-  UInt32 (*GetThreshold)(void *p, UInt32 total);
-  void (*Decode)(void *p, UInt32 start, UInt32 size);
-  UInt32 (*DecodeBit)(void *p, UInt32 size0);
-} IPpmd7_RangeDec;
-
-typedef struct
-{
-  IPpmd7_RangeDec p;
-  UInt32 Range;
-  UInt32 Code;
-  UInt32 Low;
-  UInt32 Bottom;
-  IByteIn *Stream;
-} CPpmd7z_RangeDec;
-
-/* ---------- Encode ---------- */
-
-typedef struct
-{
-  UInt64 Low;
-  UInt32 Range;
-  Byte Cache;
-  UInt64 CacheSize;
-  IByteOut *Stream;
-} CPpmd7z_RangeEnc;
-
-typedef struct
-{
-  /* Base Functions */
-  void (*Ppmd7_Construct)(CPpmd7 *p);
-  Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size);
-  void (*Ppmd7_Free)(CPpmd7 *p);
-  void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
-  #define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
-
-  /* Decode Functions */
-  void (*Ppmd7z_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
-  void (*PpmdRAR_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
-  Bool (*Ppmd7z_RangeDec_Init)(CPpmd7z_RangeDec *p);
-  Bool (*PpmdRAR_RangeDec_Init)(CPpmd7z_RangeDec *p);
-  #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
-  int (*Ppmd7_DecodeSymbol)(CPpmd7 *p, IPpmd7_RangeDec *rc);
-
-  /* Encode Functions */
-  void (*Ppmd7z_RangeEnc_Init)(CPpmd7z_RangeEnc *p);
-  void (*Ppmd7z_RangeEnc_FlushData)(CPpmd7z_RangeEnc *p);
-
-  void (*Ppmd7_EncodeSymbol)(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
-} IPpmd7;
-
-extern const IPpmd7 __archive_ppmd7_functions;
-#endif
diff --git a/c/archive_ppmd8.c b/c/archive_ppmd8.c
deleted file mode 100644
--- a/c/archive_ppmd8.c
+++ /dev/null
@@ -1,1287 +0,0 @@
-/* Ppmd8.c -- PPMdI codec
-2016-05-21 : Igor Pavlov : Public domain
-This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
-
-#include "archive_platform.h"
-
-#include <string.h>
-
-#include "archive_ppmd8_private.h"
-
-const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
-static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
-
-#define MAX_FREQ 124
-#define UNIT_SIZE 12
-
-#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
-#define U2I(nu) (p->Units2Indx[(nu) - 1])
-#define I2U(indx) (p->Indx2Units[indx])
-
-#ifdef PPMD_32BIT
-  #define REF(ptr) (ptr)
-#else
-  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
-#endif
-
-#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
-
-#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))
-#define STATS(ctx) Ppmd8_GetStats(p, ctx)
-#define ONE_STATE(ctx) Ppmd8Context_OneState(ctx)
-#define SUFFIX(ctx) CTX((ctx)->Suffix)
-
-#define kTop (1 << 24)
-#define kBot (1 << 15)
-
-typedef CPpmd8_Context * CTX_PTR;
-
-struct CPpmd8_Node_;
-
-typedef
-  #ifdef PPMD_32BIT
-    struct CPpmd8_Node_ *
-  #else
-    UInt32
-  #endif
-  CPpmd8_Node_Ref;
-
-typedef struct CPpmd8_Node_
-{
-  UInt32 Stamp;
-  CPpmd8_Node_Ref Next;
-  UInt32 NU;
-} CPpmd8_Node;
-
-#ifdef PPMD_32BIT
-  #define NODE(ptr) (ptr)
-#else
-  #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs)))
-#endif
-
-#define EMPTY_NODE 0xFFFFFFFF
-
-void Ppmd8_Construct(CPpmd8 *p)
-{
-  unsigned i, k, m;
-
-  p->Base = 0;
-
-  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
-  {
-    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
-    do { p->Units2Indx[k++] = (Byte)i; } while (--step);
-    p->Indx2Units[i] = (Byte)k;
-  }
-
-  p->NS2BSIndx[0] = (0 << 1);
-  p->NS2BSIndx[1] = (1 << 1);
-  memset(p->NS2BSIndx + 2, (2 << 1), 9);
-  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
-
-  for (i = 0; i < 5; i++)
-    p->NS2Indx[i] = (Byte)i;
-  for (m = i, k = 1; i < 260; i++)
-  {
-    p->NS2Indx[i] = (Byte)m;
-    if (--k == 0)
-      k = (++m) - 4;
-  }
-}
-
-void Ppmd8_Free(CPpmd8 *p)
-{
-  free(p->Base);
-  p->Size = 0;
-  p->Base = 0;
-}
-
-Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size)
-{
-  if (p->Base == 0 || p->Size != size)
-  {
-    Ppmd8_Free(p);
-    p->AlignOffset =
-      #ifdef PPMD_32BIT
-        (4 - size) & 3;
-      #else
-        4 - (size & 3);
-      #endif
-    if ((p->Base = (Byte *)malloc(p->AlignOffset + size)) == 0)
-      return False;
-    p->Size = size;
-  }
-  return True;
-}
-
-static void InsertNode(CPpmd8 *p, void *node, unsigned indx)
-{
-  ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;
-  ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx];
-  ((CPpmd8_Node *)node)->NU = I2U(indx);
-  p->FreeList[indx] = REF(node);
-  p->Stamps[indx]++;
-}
-
-static void *RemoveNode(CPpmd8 *p, unsigned indx)
-{
-  CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);
-  p->FreeList[indx] = node->Next;
-  p->Stamps[indx]--;
-  return node;
-}
-
-static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
-{
-  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
-  ptr = (Byte *)ptr + U2B(I2U(newIndx));
-  if (I2U(i = U2I(nu)) != nu)
-  {
-    unsigned k = I2U(--i);
-    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
-  }
-  InsertNode(p, ptr, i);
-}
-
-static void GlueFreeBlocks(CPpmd8 *p)
-{
-  CPpmd8_Node_Ref head = 0;
-  CPpmd8_Node_Ref *prev = &head;
-  unsigned i;
-
-  p->GlueCount = 1 << 13;
-  memset(p->Stamps, 0, sizeof(p->Stamps));
-  
-  /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end.
-     All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */
-  if (p->LoUnit != p->HiUnit)
-    ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
-
-  /* Glue free blocks */
-  for (i = 0; i < PPMD_NUM_INDEXES; i++)
-  {
-    CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];
-    p->FreeList[i] = 0;
-    while (next != 0)
-    {
-      CPpmd8_Node *node = NODE(next);
-      if (node->NU != 0)
-      {
-        CPpmd8_Node *node2;
-        *prev = next;
-        prev = &(node->Next);
-        while ((node2 = node + node->NU)->Stamp == EMPTY_NODE)
-        {
-          node->NU += node2->NU;
-          node2->NU = 0;
-        }
-      }
-      next = node->Next;
-    }
-  }
-  *prev = 0;
-  
-  /* Fill lists of free blocks */
-  while (head != 0)
-  {
-    CPpmd8_Node *node = NODE(head);
-    unsigned nu;
-    head = node->Next;
-    nu = node->NU;
-    if (nu == 0)
-      continue;
-    for (; nu > 128; nu -= 128, node += 128)
-      InsertNode(p, node, PPMD_NUM_INDEXES - 1);
-    if (I2U(i = U2I(nu)) != nu)
-    {
-      unsigned k = I2U(--i);
-      InsertNode(p, node + k, nu - k - 1);
-    }
-    InsertNode(p, node, i);
-  }
-}
-
-static void *AllocUnitsRare(CPpmd8 *p, unsigned indx)
-{
-  unsigned i;
-  void *retVal;
-  if (p->GlueCount == 0)
-  {
-    GlueFreeBlocks(p);
-    if (p->FreeList[indx] != 0)
-      return RemoveNode(p, indx);
-  }
-  i = indx;
-  do
-  {
-    if (++i == PPMD_NUM_INDEXES)
-    {
-      UInt32 numBytes = U2B(I2U(indx));
-      p->GlueCount--;
-      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
-    }
-  }
-  while (p->FreeList[i] == 0);
-  retVal = RemoveNode(p, i);
-  SplitBlock(p, retVal, i, indx);
-  return retVal;
-}
-
-static void *AllocUnits(CPpmd8 *p, unsigned indx)
-{
-  UInt32 numBytes;
-  if (p->FreeList[indx] != 0)
-    return RemoveNode(p, indx);
-  numBytes = U2B(I2U(indx));
-  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
-  {
-    void *retVal = p->LoUnit;
-    p->LoUnit += numBytes;
-    return retVal;
-  }
-  return AllocUnitsRare(p, indx);
-}
-
-#define MyMem12Cpy(dest, src, num) \
-  { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
-    do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
-
-static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
-{
-  unsigned i0 = U2I(oldNU);
-  unsigned i1 = U2I(newNU);
-  if (i0 == i1)
-    return oldPtr;
-  if (p->FreeList[i1] != 0)
-  {
-    void *ptr = RemoveNode(p, i1);
-    MyMem12Cpy(ptr, oldPtr, newNU);
-    InsertNode(p, oldPtr, i0);
-    return ptr;
-  }
-  SplitBlock(p, oldPtr, i0, i1);
-  return oldPtr;
-}
-
-static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)
-{
-  InsertNode(p, ptr, U2I(nu));
-}
-
-static void SpecialFreeUnit(CPpmd8 *p, void *ptr)
-{
-  if ((Byte *)ptr != p->UnitsStart)
-    InsertNode(p, ptr, 0);
-  else
-  {
-    #ifdef PPMD8_FREEZE_SUPPORT
-    *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */
-    #endif
-    p->UnitsStart += UNIT_SIZE;
-  }
-}
-
-static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)
-{
-  unsigned indx = U2I(nu);
-  void *ptr;
-  if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx])
-    return oldPtr;
-  ptr = RemoveNode(p, indx);
-  MyMem12Cpy(ptr, oldPtr, nu);
-  if ((Byte*)oldPtr != p->UnitsStart)
-    InsertNode(p, oldPtr, indx);
-  else
-    p->UnitsStart += U2B(I2U(indx));
-  return ptr;
-}
-
-static void ExpandTextArea(CPpmd8 *p)
-{
-  UInt32 count[PPMD_NUM_INDEXES];
-  unsigned i;
-  memset(count, 0, sizeof(count));
-  if (p->LoUnit != p->HiUnit)
-    ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
-  
-  {
-    CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart;
-    for (; node->Stamp == EMPTY_NODE; node += node->NU)
-    {
-      node->Stamp = 0;
-      count[U2I(node->NU)]++;
-    }
-    p->UnitsStart = (Byte *)node;
-  }
-  
-  for (i = 0; i < PPMD_NUM_INDEXES; i++)
-  {
-    CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i];
-    while (count[i] != 0)
-    {
-      CPpmd8_Node *node = NODE(*next);
-      while (node->Stamp == 0)
-      {
-        *next = node->Next;
-        node = NODE(*next);
-        p->Stamps[i]--;
-        if (--count[i] == 0)
-          break;
-      }
-      next = &node->Next;
-    }
-  }
-}
-
-#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
-
-static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
-{
-  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
-  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
-}
-
-#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
-
-static void RestartModel(CPpmd8 *p)
-{
-  unsigned i, k, m, r;
-
-  memset(p->FreeList, 0, sizeof(p->FreeList));
-  memset(p->Stamps, 0, sizeof(p->Stamps));
-  RESET_TEXT(0);
-  p->HiUnit = p->Text + p->Size;
-  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
-  p->GlueCount = 0;
-
-  p->OrderFall = p->MaxOrder;
-  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
-  p->PrevSuccess = 0;
-
-  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
-  p->MinContext->Suffix = 0;
-  p->MinContext->NumStats = 255;
-  p->MinContext->Flags = 0;
-  p->MinContext->SummFreq = 256 + 1;
-  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
-  p->LoUnit += U2B(256 / 2);
-  p->MinContext->Stats = REF(p->FoundState);
-  for (i = 0; i < 256; i++)
-  {
-    CPpmd_State *s = &p->FoundState[i];
-    s->Symbol = (Byte)i;
-    s->Freq = 1;
-    SetSuccessor(s, 0);
-  }
-
-  for (i = m = 0; m < 25; m++)
-  {
-    while (p->NS2Indx[i] == m)
-      i++;
-    for (k = 0; k < 8; k++)
-    {
-      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));
-      UInt16 *dest = p->BinSumm[m] + k;
-      for (r = 0; r < 64; r += 8)
-        dest[r] = val;
-    }
-  }
-
-  for (i = m = 0; m < 24; m++)
-  {
-    while (p->NS2Indx[i + 3] == m + 3)
-      i++;
-    for (k = 0; k < 32; k++)
-    {
-      CPpmd_See *s = &p->See[m][k];
-      s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4));
-      s->Count = 7;
-    }
-  }
-}
-
-void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)
-{
-  p->MaxOrder = maxOrder;
-  p->RestoreMethod = restoreMethod;
-  RestartModel(p);
-  p->DummySee.Shift = PPMD_PERIOD_BITS;
-  p->DummySee.Summ = 0; /* unused */
-  p->DummySee.Count = 64; /* unused */
-}
-
-static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)
-{
-  unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
-  CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
-  ctx->Stats = REF(s);
-  #ifdef PPMD8_FREEZE_SUPPORT
-  /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */
-  scale |= (ctx->SummFreq >= ((UInt32)1 << 15));
-  #endif
-  flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
-  escFreq = ctx->SummFreq - s->Freq;
-  sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));
-  do
-  {
-    escFreq -= (++s)->Freq;
-    sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale));
-    flags |= 0x08 * (s->Symbol >= 0x40);
-  }
-  while (--i);
-  ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));
-  ctx->Flags = (Byte)flags;
-}
-
-static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
-{
-  CPpmd_State tmp = *t1;
-  *t1 = *t2;
-  *t2 = tmp;
-}
-
-static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order)
-{
-  int i;
-  unsigned tmp;
-  CPpmd_State *s;
-  
-  if (!ctx->NumStats)
-  {
-    s = ONE_STATE(ctx);
-    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart)
-    {
-      if (order < p->MaxOrder)
-        SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
-      else
-        SetSuccessor(s, 0);
-      if (SUCCESSOR(s) || order <= 9) /* O_BOUND */
-        return REF(ctx);
-    }
-    SpecialFreeUnit(p, ctx);
-    return 0;
-  }
-
-  ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1));
-
-  for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--)
-    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart)
-    {
-      CPpmd_State *s2 = STATS(ctx) + (i--);
-      SetSuccessor(s, 0);
-      SwapStates(s, s2);
-    }
-    else if (order < p->MaxOrder)
-      SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
-    else
-      SetSuccessor(s, 0);
-    
-  if (i != ctx->NumStats && order)
-  {
-    ctx->NumStats = (Byte)i;
-    s = STATS(ctx);
-    if (i < 0)
-    {
-      FreeUnits(p, s, tmp);
-      SpecialFreeUnit(p, ctx);
-      return 0;
-    }
-    if (i == 0)
-    {
-      ctx->Flags = (Byte)((ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
-      *ONE_STATE(ctx) = *s;
-      FreeUnits(p, s, tmp);
-      /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */
-      ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3);
-    }
-    else
-      Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i);
-  }
-  return REF(ctx);
-}
-
-#ifdef PPMD8_FREEZE_SUPPORT
-static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order)
-{
-  CPpmd_State *s;
-  if (!ctx->NumStats)
-  {
-    s = ONE_STATE(ctx);
-    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
-      SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
-    else
-      SetSuccessor(s, 0);
-    /* Suffix context can be removed already, since different (high-order)
-       Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */
-    if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))
-    {
-      FreeUnits(p, ctx, 1);
-      return 0;
-    }
-    else
-      return REF(ctx);
-  }
-
-  for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--)
-    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
-      SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
-    else
-      SetSuccessor(s, 0);
-  
-  return REF(ctx);
-}
-#endif
-
-static UInt32 GetUsedMemory(const CPpmd8 *p)
-{
-  UInt32 v = 0;
-  unsigned i;
-  for (i = 0; i < PPMD_NUM_INDEXES; i++)
-    v += p->Stamps[i] * I2U(i);
-  return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v);
-}
-
-#ifdef PPMD8_FREEZE_SUPPORT
-  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor)
-#else
-  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)
-#endif
-
-static void RestoreModel(CPpmd8 *p, CTX_PTR c1
-    #ifdef PPMD8_FREEZE_SUPPORT
-    , CTX_PTR fSuccessor
-    #endif
-    )
-{
-  CTX_PTR c;
-  CPpmd_State *s;
-  RESET_TEXT(0);
-  for (c = p->MaxContext; c != c1; c = SUFFIX(c))
-    if (--(c->NumStats) == 0)
-    {
-      s = STATS(c);
-      c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
-      *ONE_STATE(c) = *s;
-      SpecialFreeUnit(p, s);
-      ONE_STATE(c)->Freq = (Byte)(((unsigned)ONE_STATE(c)->Freq + 11) >> 3);
-    }
-    else
-      Refresh(p, c, (c->NumStats+3) >> 1, 0);
- 
-  for (; c != p->MinContext; c = SUFFIX(c))
-    if (!c->NumStats)
-      ONE_STATE(c)->Freq = (Byte)(ONE_STATE(c)->Freq - (ONE_STATE(c)->Freq >> 1));
-    else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats)
-      Refresh(p, c, (c->NumStats + 2) >> 1, 1);
-
-  #ifdef PPMD8_FREEZE_SUPPORT
-  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
-  {
-    p->MaxContext = fSuccessor;
-    p->GlueCount += !(p->Stamps[1] & 1);
-  }
-  else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)
-  {
-    while (p->MaxContext->Suffix)
-      p->MaxContext = SUFFIX(p->MaxContext);
-    RemoveBinContexts(p, p->MaxContext, 0);
-    p->RestoreMethod++;
-    p->GlueCount = 0;
-    p->OrderFall = p->MaxOrder;
-  }
-  else
-  #endif
-  if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1))
-    RestartModel(p);
-  else
-  {
-    while (p->MaxContext->Suffix)
-      p->MaxContext = SUFFIX(p->MaxContext);
-    do
-    {
-      CutOff(p, p->MaxContext, 0);
-      ExpandTextArea(p);
-    }
-    while (GetUsedMemory(p) > 3 * (p->Size >> 2));
-    p->GlueCount = 0;
-    p->OrderFall = p->MaxOrder;
-  }
-}
-
-static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c)
-{
-  CPpmd_State upState;
-  Byte flags;
-  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
-  /* fixed over Shkarin's code. Maybe it could work without + 1 too. */
-  CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
-  unsigned numPs = 0;
-  
-  if (!skip)
-    ps[numPs++] = p->FoundState;
-  
-  while (c->Suffix)
-  {
-    CPpmd_Void_Ref successor;
-    CPpmd_State *s;
-    c = SUFFIX(c);
-    if (s1)
-    {
-      s = s1;
-      s1 = NULL;
-    }
-    else if (c->NumStats != 0)
-    {
-      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
-      if (s->Freq < MAX_FREQ - 9)
-      {
-        s->Freq++;
-        c->SummFreq++;
-      }
-    }
-    else
-    {
-      s = ONE_STATE(c);
-      s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24)));
-    }
-    successor = SUCCESSOR(s);
-    if (successor != upBranch)
-    {
-      c = CTX(successor);
-      if (numPs == 0)
-        return c;
-      break;
-    }
-    ps[numPs++] = s;
-  }
-  
-  upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch);
-  SetSuccessor(&upState, upBranch + 1);
-  flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40));
-
-  if (c->NumStats == 0)
-    upState.Freq = ONE_STATE(c)->Freq;
-  else
-  {
-    UInt32 cf, s0;
-    CPpmd_State *s;
-    for (s = STATS(c); s->Symbol != upState.Symbol; s++);
-    cf = s->Freq - 1;
-    s0 = c->SummFreq - c->NumStats - cf;
-    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
-  }
-
-  do
-  {
-    /* Create Child */
-    CTX_PTR c1; /* = AllocContext(p); */
-    if (p->HiUnit != p->LoUnit)
-      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
-    else if (p->FreeList[0] != 0)
-      c1 = (CTX_PTR)RemoveNode(p, 0);
-    else
-    {
-      c1 = (CTX_PTR)AllocUnitsRare(p, 0);
-      if (!c1)
-        return NULL;
-    }
-    c1->NumStats = 0;
-    c1->Flags = flags;
-    *ONE_STATE(c1) = upState;
-    c1->Suffix = REF(c);
-    SetSuccessor(ps[--numPs], REF(c1));
-    c = c1;
-  }
-  while (numPs != 0);
-  
-  return c;
-}
-
-static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
-{
-  CPpmd_State *s = NULL;
-  CTX_PTR c1 = c;
-  CPpmd_Void_Ref upBranch = REF(p->Text);
-  
-  #ifdef PPMD8_FREEZE_SUPPORT
-  /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */
-  CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
-  unsigned numPs = 0;
-  ps[numPs++] = p->FoundState;
-  #endif
-
-  SetSuccessor(p->FoundState, upBranch);
-  p->OrderFall++;
-
-  for (;;)
-  {
-    if (s1)
-    {
-      c = SUFFIX(c);
-      s = s1;
-      s1 = NULL;
-    }
-    else
-    {
-      if (!c->Suffix)
-      {
-        #ifdef PPMD8_FREEZE_SUPPORT
-        if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
-        {
-          do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
-          RESET_TEXT(1);
-          p->OrderFall = 1;
-        }
-        #endif
-        return c;
-      }
-      c = SUFFIX(c);
-      if (c->NumStats)
-      {
-        if ((s = STATS(c))->Symbol != p->FoundState->Symbol)
-          do { s++; } while (s->Symbol != p->FoundState->Symbol);
-        if (s->Freq < MAX_FREQ - 9)
-        {
-          s->Freq += 2;
-          c->SummFreq += 2;
-        }
-      }
-      else
-      {
-        s = ONE_STATE(c);
-        s->Freq = (Byte)(s->Freq + (s->Freq < 32));
-      }
-    }
-    if (SUCCESSOR(s))
-      break;
-    #ifdef PPMD8_FREEZE_SUPPORT
-    ps[numPs++] = s;
-    #endif
-    SetSuccessor(s, upBranch);
-    p->OrderFall++;
-  }
-  
-  #ifdef PPMD8_FREEZE_SUPPORT
-  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
-  {
-    c = CTX(SUCCESSOR(s));
-    do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
-    RESET_TEXT(1);
-    p->OrderFall = 1;
-    return c;
-  }
-  else
-  #endif
-  if (SUCCESSOR(s) <= upBranch)
-  {
-    CTX_PTR successor;
-    CPpmd_State *s2 = p->FoundState;
-    p->FoundState = s;
-
-    successor = CreateSuccessors(p, False, NULL, c);
-    if (successor == NULL)
-      SetSuccessor(s, 0);
-    else
-      SetSuccessor(s, REF(successor));
-    p->FoundState = s2;
-  }
-  
-  if (p->OrderFall == 1 && c1 == p->MaxContext)
-  {
-    SetSuccessor(p->FoundState, SUCCESSOR(s));
-    p->Text--;
-  }
-  if (SUCCESSOR(s) == 0)
-    return NULL;
-  return CTX(SUCCESSOR(s));
-}
-
-static void UpdateModel(CPpmd8 *p)
-{
-  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
-  CTX_PTR c;
-  unsigned s0, ns, fFreq = p->FoundState->Freq;
-  Byte flag, fSymbol = p->FoundState->Symbol;
-  CPpmd_State *s = NULL;
-  
-  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
-  {
-    c = SUFFIX(p->MinContext);
-    
-    if (c->NumStats == 0)
-    {
-      s = ONE_STATE(c);
-      if (s->Freq < 32)
-        s->Freq++;
-    }
-    else
-    {
-      s = STATS(c);
-      if (s->Symbol != p->FoundState->Symbol)
-      {
-        do { s++; } while (s->Symbol != p->FoundState->Symbol);
-        if (s[0].Freq >= s[-1].Freq)
-        {
-          SwapStates(&s[0], &s[-1]);
-          s--;
-        }
-      }
-      if (s->Freq < MAX_FREQ - 9)
-      {
-        s->Freq += 2;
-        c->SummFreq += 2;
-      }
-    }
-  }
-  
-  c = p->MaxContext;
-  if (p->OrderFall == 0 && fSuccessor)
-  {
-    CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext);
-    if (cs == 0)
-    {
-      SetSuccessor(p->FoundState, 0);
-      RESTORE_MODEL(c, CTX(fSuccessor));
-    }
-    else
-    {
-      SetSuccessor(p->FoundState, REF(cs));
-      p->MaxContext = cs;
-    }
-    return;
-  }
-  
-  *p->Text++ = p->FoundState->Symbol;
-  successor = REF(p->Text);
-  if (p->Text >= p->UnitsStart)
-  {
-    RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */
-    return;
-  }
-  
-  if (!fSuccessor)
-  {
-    CTX_PTR cs = ReduceOrder(p, s, p->MinContext);
-    if (cs == NULL)
-    {
-      RESTORE_MODEL(c, 0);
-      return;
-    }
-    fSuccessor = REF(cs);
-  }
-  else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart)
-  {
-    CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext);
-    if (cs == NULL)
-    {
-      RESTORE_MODEL(c, 0);
-      return;
-    }
-    fSuccessor = REF(cs);
-  }
-  
-  if (--p->OrderFall == 0)
-  {
-    successor = fSuccessor;
-    p->Text -= (p->MaxContext != p->MinContext);
-  }
-  #ifdef PPMD8_FREEZE_SUPPORT
-  else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
-  {
-    successor = fSuccessor;
-    RESET_TEXT(0);
-    p->OrderFall = 0;
-  }
-  #endif
-  
-  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq;
-  flag = (Byte)(0x08 * (fSymbol >= 0x40));
-  
-  for (; c != p->MinContext; c = SUFFIX(c))
-  {
-    unsigned ns1;
-    UInt32 cf, sf;
-    if ((ns1 = c->NumStats) != 0)
-    {
-      if ((ns1 & 1) != 0)
-      {
-        /* Expand for one UNIT */
-        unsigned oldNU = (ns1 + 1) >> 1;
-        unsigned i = U2I(oldNU);
-        if (i != U2I(oldNU + 1))
-        {
-          void *ptr = AllocUnits(p, i + 1);
-          void *oldPtr;
-          if (!ptr)
-          {
-            RESTORE_MODEL(c, CTX(fSuccessor));
-            return;
-          }
-          oldPtr = STATS(c);
-          MyMem12Cpy(ptr, oldPtr, oldNU);
-          InsertNode(p, oldPtr, i);
-          c->Stats = STATS_REF(ptr);
-        }
-      }
-      c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns));
-    }
-    else
-    {
-      CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0);
-      if (!s2)
-      {
-        RESTORE_MODEL(c, CTX(fSuccessor));
-        return;
-      }
-      *s2 = *ONE_STATE(c);
-      c->Stats = REF(s2);
-      if (s2->Freq < MAX_FREQ / 4 - 1)
-        s2->Freq <<= 1;
-      else
-        s2->Freq = MAX_FREQ - 4;
-      c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2));
-    }
-    cf = 2 * fFreq * (c->SummFreq + 6);
-    sf = (UInt32)s0 + c->SummFreq;
-    if (cf < 6 * sf)
-    {
-      cf = 1 + (cf > sf) + (cf >= 4 * sf);
-      c->SummFreq += 4;
-    }
-    else
-    {
-      cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);
-      c->SummFreq = (UInt16)(c->SummFreq + cf);
-    }
-    {
-      CPpmd_State *s2 = STATS(c) + ns1 + 1;
-      SetSuccessor(s2, successor);
-      s2->Symbol = fSymbol;
-      s2->Freq = (Byte)cf;
-      c->Flags |= flag;
-      c->NumStats = (Byte)(ns1 + 1);
-    }
-  }
-  p->MaxContext = p->MinContext = CTX(fSuccessor);
-}
-  
-static void Rescale(CPpmd8 *p)
-{
-  unsigned i, adder, sumFreq, escFreq;
-  CPpmd_State *stats = STATS(p->MinContext);
-  CPpmd_State *s = p->FoundState;
-  {
-    CPpmd_State tmp = *s;
-    for (; s != stats; s--)
-      s[0] = s[-1];
-    *s = tmp;
-  }
-  escFreq = p->MinContext->SummFreq - s->Freq;
-  s->Freq += 4;
-  adder = (p->OrderFall != 0
-      #ifdef PPMD8_FREEZE_SUPPORT
-      || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE
-      #endif
-      );
-  s->Freq = (Byte)((s->Freq + adder) >> 1);
-  sumFreq = s->Freq;
-  
-  i = p->MinContext->NumStats;
-  do
-  {
-    escFreq -= (++s)->Freq;
-    s->Freq = (Byte)((s->Freq + adder) >> 1);
-    sumFreq += s->Freq;
-    if (s[0].Freq > s[-1].Freq)
-    {
-      CPpmd_State *s1 = s;
-      CPpmd_State tmp = *s1;
-      do
-        s1[0] = s1[-1];
-      while (--s1 != stats && tmp.Freq > s1[-1].Freq);
-      *s1 = tmp;
-    }
-  }
-  while (--i);
-  
-  if (s->Freq == 0)
-  {
-    unsigned numStats = p->MinContext->NumStats;
-    unsigned n0, n1;
-    do { i++; } while ((--s)->Freq == 0);
-    escFreq += i;
-    p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i);
-    if (p->MinContext->NumStats == 0)
-    {
-      CPpmd_State tmp = *stats;
-      tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq);
-      if (tmp.Freq > MAX_FREQ / 3)
-        tmp.Freq = MAX_FREQ / 3;
-      InsertNode(p, stats, U2I((numStats + 2) >> 1));
-      p->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40));
-      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
-      return;
-    }
-    n0 = (numStats + 2) >> 1;
-    n1 = (p->MinContext->NumStats + 2) >> 1;
-    if (n0 != n1)
-      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
-    p->MinContext->Flags &= ~0x08;
-    p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40);
-    i = p->MinContext->NumStats;
-    do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i);
-  }
-  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
-  p->MinContext->Flags |= 0x4;
-  p->FoundState = STATS(p->MinContext);
-}
-
-CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
-{
-  CPpmd_See *see;
-  if (p->MinContext->NumStats != 0xFF)
-  {
-    see = p->See[(unsigned)p->NS2Indx[(unsigned)p->MinContext->NumStats + 2] - 3] +
-        (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +
-        2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats <
-        ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +
-        p->MinContext->Flags;
-    {
-      unsigned r = (see->Summ >> see->Shift);
-      see->Summ = (UInt16)(see->Summ - r);
-      *escFreq = r + (r == 0);
-    }
-  }
-  else
-  {
-    see = &p->DummySee;
-    *escFreq = 1;
-  }
-  return see;
-}
-
-static void NextContext(CPpmd8 *p)
-{
-  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
-  if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart)
-    p->MinContext = p->MaxContext = c;
-  else
-  {
-    UpdateModel(p);
-    p->MinContext = p->MaxContext;
-  }
-}
-
-void Ppmd8_Update1(CPpmd8 *p)
-{
-  CPpmd_State *s = p->FoundState;
-  s->Freq += 4;
-  p->MinContext->SummFreq += 4;
-  if (s[0].Freq > s[-1].Freq)
-  {
-    SwapStates(&s[0], &s[-1]);
-    p->FoundState = --s;
-    if (s->Freq > MAX_FREQ)
-      Rescale(p);
-  }
-  NextContext(p);
-}
-
-void Ppmd8_Update1_0(CPpmd8 *p)
-{
-  p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);
-  p->RunLength += p->PrevSuccess;
-  p->MinContext->SummFreq += 4;
-  if ((p->FoundState->Freq += 4) > MAX_FREQ)
-    Rescale(p);
-  NextContext(p);
-}
-
-void Ppmd8_UpdateBin(CPpmd8 *p)
-{
-  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));
-  p->PrevSuccess = 1;
-  p->RunLength++;
-  NextContext(p);
-}
-
-void Ppmd8_Update2(CPpmd8 *p)
-{
-  p->MinContext->SummFreq += 4;
-  if ((p->FoundState->Freq += 4) > MAX_FREQ)
-    Rescale(p);
-  p->RunLength = p->InitRL;
-  UpdateModel(p);
-  p->MinContext = p->MaxContext;
-}
-
-/* Ppmd8Dec.c -- PPMdI Decoder
-2010-04-16 : Igor Pavlov : Public domain
-This code is based on:
-  PPMd var.I (2002): Dmitry Shkarin : Public domain
-  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
-
-Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
-{
-  unsigned i;
-  p->Low = 0;
-  p->Range = 0xFFFFFFFF;
-  p->Code = 0;
-  for (i = 0; i < 4; i++)
-    p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
-  return (p->Code < 0xFFFFFFFF);
-}
-
-static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
-{
-  return p->Code / (p->Range /= total);
-}
-
-static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
-{
-  start *= p->Range;
-  p->Low += start;
-  p->Code -= start;
-  p->Range *= size;
-
-  while ((p->Low ^ (p->Low + p->Range)) < kTop ||
-      (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
-  {
-    p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
-    p->Range <<= 8;
-    p->Low <<= 8;
-  }
-}
-
-#define MASK(sym) ((signed char *)charMask)[sym]
-
-int Ppmd8_DecodeSymbol(CPpmd8 *p)
-{
-  size_t charMask[256 / sizeof(size_t)];
-  if (p->MinContext->NumStats != 0)
-  {
-    CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
-    unsigned i;
-    UInt32 count, hiCnt;
-    if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
-    {
-      Byte symbol;
-      RangeDec_Decode(p, 0, s->Freq);
-      p->FoundState = s;
-      symbol = s->Symbol;
-      Ppmd8_Update1_0(p);
-      return symbol;
-    }
-    p->PrevSuccess = 0;
-    i = p->MinContext->NumStats;
-    do
-    {
-      if ((hiCnt += (++s)->Freq) > count)
-      {
-        Byte symbol;
-        RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
-        p->FoundState = s;
-        symbol = s->Symbol;
-        Ppmd8_Update1(p);
-        return symbol;
-      }
-    }
-    while (--i);
-    if (count >= p->MinContext->SummFreq)
-      return -2;
-    RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
-    PPMD_SetAllBitsIn256Bytes(charMask);
-    MASK(s->Symbol) = 0;
-    i = p->MinContext->NumStats;
-    do { MASK((--s)->Symbol) = 0; } while (--i);
-  }
-  else
-  {
-    UInt16 *prob = Ppmd8_GetBinSumm(p);
-    if (((p->Code / (p->Range >>= 14)) < *prob))
-    {
-      Byte symbol;
-      RangeDec_Decode(p, 0, *prob);
-      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
-      symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
-      Ppmd8_UpdateBin(p);
-      return symbol;
-    }
-    RangeDec_Decode(p, *prob, (1 << 14) - *prob);
-    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
-    p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
-    PPMD_SetAllBitsIn256Bytes(charMask);
-    MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
-    p->PrevSuccess = 0;
-  }
-  for (;;)
-  {
-    CPpmd_State *ps[256], *s;
-    UInt32 freqSum, count, hiCnt;
-    CPpmd_See *see;
-    unsigned i, num, numMasked = p->MinContext->NumStats;
-    do
-    {
-      p->OrderFall++;
-      if (!p->MinContext->Suffix)
-        return -1;
-      p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
-    }
-    while (p->MinContext->NumStats == numMasked);
-    hiCnt = 0;
-    s = Ppmd8_GetStats(p, p->MinContext);
-    i = 0;
-    num = p->MinContext->NumStats - numMasked;
-    do
-    {
-      int k = (int)(MASK(s->Symbol));
-      hiCnt += (s->Freq & k);
-      ps[i] = s++;
-      i -= k;
-    }
-    while (i != num);
-    
-    see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
-    freqSum += hiCnt;
-    count = RangeDec_GetThreshold(p, freqSum);
-    
-    if (count < hiCnt)
-    {
-      Byte symbol;
-      CPpmd_State **pps = ps;
-      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
-      s = *pps;
-      RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
-      Ppmd_See_Update(see);
-      p->FoundState = s;
-      symbol = s->Symbol;
-      Ppmd8_Update2(p);
-      return symbol;
-    }
-    if (count >= freqSum)
-      return -2;
-    RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
-    see->Summ = (UInt16)(see->Summ + freqSum);
-    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
-  }
-}
-
-/* H->I changes:
-  NS2Indx
-  GlewCount, and Glue method
-  BinSum
-  See / EscFreq
-  CreateSuccessors updates more suffix contexts
-  UpdateModel consts.
-  PrevSuccess Update
-*/
-
-const IPpmd8 __archive_ppmd8_functions =
-{
-  &Ppmd8_Construct,
-  &Ppmd8_Alloc,
-  &Ppmd8_Free,
-  &Ppmd8_Init,
-  &Ppmd8_RangeDec_Init,
-  &Ppmd8_DecodeSymbol,
-};
diff --git a/c/archive_ppmd8_private.h b/c/archive_ppmd8_private.h
deleted file mode 100644
--- a/c/archive_ppmd8_private.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Ppmd8.h -- PPMdI codec
-2011-01-27 : Igor Pavlov : Public domain
-This code is based on:
-  PPMd var.I (2002): Dmitry Shkarin : Public domain
-  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
-
-#ifndef ARCHIVE_PPMD8_PRIVATE_H_INCLUDED
-#define ARCHIVE_PPMD8_PRIVATE_H_INCLUDED
-
-#include "archive_ppmd_private.h"
-
-#define PPMD8_MIN_ORDER 2
-#define PPMD8_MAX_ORDER 16
-
-struct CPpmd8_Context_;
-
-typedef
-  #ifdef PPMD_32BIT
-    struct CPpmd8_Context_ *
-  #else
-    UInt32
-  #endif
-  CPpmd8_Context_Ref;
-
-#pragma pack(push, 1)
-
-typedef struct CPpmd8_Context_
-{
-  Byte NumStats;
-  Byte Flags;
-  UInt16 SummFreq;
-  CPpmd_State_Ref Stats;
-  CPpmd8_Context_Ref Suffix;
-} CPpmd8_Context;
-
-#pragma pack(pop)
-
-#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
-
-/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed
-   code is not compatible with original code for some files compressed
-   in FREEZE mode. So we disable FREEZE mode support. */
-
-enum
-{
-  PPMD8_RESTORE_METHOD_RESTART,
-  PPMD8_RESTORE_METHOD_CUT_OFF
-  #ifdef PPMD8_FREEZE_SUPPORT
-  , PPMD8_RESTORE_METHOD_FREEZE
-  #endif
-};
-
-typedef struct
-{
-  CPpmd8_Context *MinContext, *MaxContext;
-  CPpmd_State *FoundState;
-  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;
-  Int32 RunLength, InitRL; /* must be 32-bit at least */
-
-  UInt32 Size;
-  UInt32 GlueCount;
-  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
-  UInt32 AlignOffset;
-  unsigned RestoreMethod;
-
-  /* Range Coder */
-  UInt32 Range;
-  UInt32 Code;
-  UInt32 Low;
-  union
-  {
-    IByteIn *In;
-    IByteOut *Out;
-  } Stream;
-
-  Byte Indx2Units[PPMD_NUM_INDEXES];
-  Byte Units2Indx[128];
-  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
-  UInt32 Stamps[PPMD_NUM_INDEXES];
-
-  Byte NS2BSIndx[256], NS2Indx[260];
-  CPpmd_See DummySee, See[24][32];
-  UInt16 BinSumm[25][64];
-} CPpmd8;
-
-void Ppmd8_Construct(CPpmd8 *p);
-Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size);
-void Ppmd8_Free(CPpmd8 *p);
-void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
-#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
-
-
-/* ---------- Internal Functions ---------- */
-
-extern const Byte PPMD8_kExpEscape[16];
-
-#ifdef PPMD_32BIT
-  #define Ppmd8_GetPtr(p, ptr) (ptr)
-  #define Ppmd8_GetContext(p, ptr) (ptr)
-  #define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)
-#else
-  #define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
-  #define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))
-  #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
-#endif
-
-void Ppmd8_Update1(CPpmd8 *p);
-void Ppmd8_Update1_0(CPpmd8 *p);
-void Ppmd8_Update2(CPpmd8 *p);
-void Ppmd8_UpdateBin(CPpmd8 *p);
-
-#define Ppmd8_GetBinSumm(p) \
-    &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
-    p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
-    p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
-
-CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
-
-
-/* ---------- Decode ---------- */
-
-Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
-#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
-int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
-
-/* ---------- Encode ---------- */
-
-#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
-void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
-void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
-
-typedef struct
-{
-  /* Base Functions */
-  void (*Ppmd8_Construct)(CPpmd8 *p);
-  Bool (*Ppmd8_Alloc)(CPpmd8 *p, UInt32 size);
-  void (*Ppmd8_Free)(CPpmd8 *p);
-  void (*Ppmd8_Init)(CPpmd8 *p, unsigned max_order, unsigned restore_method);
-  #define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
-
-  /* Decode Functions */
-  int (*Ppmd8_RangeDec_Init)(CPpmd8 *p);
-  int (*Ppmd8_DecodeSymbol)(CPpmd8 *p);
-} IPpmd8;
-
-extern const IPpmd8 __archive_ppmd8_functions;
-
-#endif
diff --git a/c/archive_ppmd_private.h b/c/archive_ppmd_private.h
deleted file mode 100644
--- a/c/archive_ppmd_private.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Ppmd.h -- PPMD codec common code
-2010-03-12 : Igor Pavlov : Public domain
-This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
-
-#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED
-#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include <stddef.h>
-
-#include "archive_read_private.h"
-
-/*** Begin defined in Types.h ***/
-
-#if !defined(ZCONF_H)
-typedef unsigned char Byte;
-#endif
-typedef short Int16;
-typedef unsigned short UInt16;
-
-#ifdef _LZMA_UINT32_IS_ULONG
-typedef long Int32;
-typedef unsigned long UInt32;
-#else
-typedef int Int32;
-typedef unsigned int UInt32;
-#endif
-
-#ifdef _SZ_NO_INT_64
-
-/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
-   NOTES: Some code will work incorrectly in that case! */
-
-typedef long Int64;
-typedef unsigned long UInt64;
-
-#else
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
-#define UINT64_CONST(n) n
-#else
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
-#define UINT64_CONST(n) n ## ULL
-#endif
-
-#endif
-
-typedef int Bool;
-#define True 1
-#define False 0
-
-/* The following interfaces use first parameter as pointer to structure */
-
-typedef struct
-{
-  struct archive_read *a;
-  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
-} IByteIn;
-
-typedef struct
-{
-  struct archive_write *a;
-  void (*Write)(void *p, Byte b);
-} IByteOut;
-
-/*** End defined in Types.h ***/
-/*** Begin defined in CpuArch.h ***/
-
-#if defined(_M_IX86) || defined(__i386__)
-#define MY_CPU_X86
-#endif
-
-#if defined(MY_CPU_X86) || defined(_M_ARM)
-#define MY_CPU_32BIT
-#endif
-
-#ifdef MY_CPU_32BIT
-#define PPMD_32BIT
-#endif
-
-/*** End defined in CpuArch.h ***/
-
-#define PPMD_INT_BITS 7
-#define PPMD_PERIOD_BITS 7
-#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
-
-#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
-#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
-#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
-#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
-
-#define PPMD_N1 4
-#define PPMD_N2 4
-#define PPMD_N3 4
-#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
-#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
-
-/* SEE-contexts for PPM-contexts with masked symbols */
-typedef struct
-{
-  UInt16 Summ; /* Freq */
-  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */
-  Byte Count;  /* Count to next change of Shift */
-} CPpmd_See;
-
-#define Ppmd_See_Update(p)  if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
-    { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
-
-typedef struct
-{
-  Byte Symbol;
-  Byte Freq;
-  UInt16 SuccessorLow;
-  UInt16 SuccessorHigh;
-} CPpmd_State;
-
-typedef
-  #ifdef PPMD_32BIT
-    CPpmd_State *
-  #else
-    UInt32
-  #endif
-  CPpmd_State_Ref;
-
-typedef
-  #ifdef PPMD_32BIT
-    void *
-  #else
-    UInt32
-  #endif
-  CPpmd_Void_Ref;
-
-typedef
-  #ifdef PPMD_32BIT
-    Byte *
-  #else
-    UInt32
-  #endif
-  CPpmd_Byte_Ref;
-
-#define PPMD_SetAllBitsIn256Bytes(p) \
-  { unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
-  p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
-
-#endif
diff --git a/c/archive_private.h b/c/archive_private.h
deleted file mode 100644
--- a/c/archive_private.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_private.h 201098 2009-12-28 02:58:14Z kientzle $
- */
-
-#ifndef ARCHIVE_PRIVATE_H_INCLUDED
-#define ARCHIVE_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#if HAVE_ICONV_H
-#include <iconv.h>
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-			  (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
-#define	__LA_DEAD	__attribute__((__noreturn__))
-#else
-#define	__LA_DEAD
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ > 2 || \
-			  (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
-#define	__LA_UNUSED	__attribute__((__unused__))
-#else
-#define	__LA_UNUSED
-#endif
-
-#define	ARCHIVE_WRITE_MAGIC	(0xb0c5c0deU)
-#define	ARCHIVE_READ_MAGIC	(0xdeb0c5U)
-#define	ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
-#define	ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U)
-#define	ARCHIVE_MATCH_MAGIC	(0xcad11c9U)
-
-#define	ARCHIVE_STATE_NEW	1U
-#define	ARCHIVE_STATE_HEADER	2U
-#define	ARCHIVE_STATE_DATA	4U
-#define	ARCHIVE_STATE_EOF	0x10U
-#define	ARCHIVE_STATE_CLOSED	0x20U
-#define	ARCHIVE_STATE_FATAL	0x8000U
-#define	ARCHIVE_STATE_ANY	(0xFFFFU & ~ARCHIVE_STATE_FATAL)
-
-struct archive_vtable {
-	int	(*archive_close)(struct archive *);
-	int	(*archive_free)(struct archive *);
-	int	(*archive_write_header)(struct archive *,
-	    struct archive_entry *);
-	int	(*archive_write_finish_entry)(struct archive *);
-	ssize_t	(*archive_write_data)(struct archive *,
-	    const void *, size_t);
-	ssize_t	(*archive_write_data_block)(struct archive *,
-	    const void *, size_t, int64_t);
-
-	int	(*archive_read_next_header)(struct archive *,
-	    struct archive_entry **);
-	int	(*archive_read_next_header2)(struct archive *,
-	    struct archive_entry *);
-	int	(*archive_read_data_block)(struct archive *,
-	    const void **, size_t *, int64_t *);
-
-	int	(*archive_filter_count)(struct archive *);
-	int64_t (*archive_filter_bytes)(struct archive *, int);
-	int	(*archive_filter_code)(struct archive *, int);
-	const char * (*archive_filter_name)(struct archive *, int);
-};
-
-struct archive_string_conv;
-
-struct archive {
-	/*
-	 * The magic/state values are used to sanity-check the
-	 * client's usage.  If an API function is called at a
-	 * ridiculous time, or the client passes us an invalid
-	 * pointer, these values allow me to catch that.
-	 */
-	unsigned int	magic;
-	unsigned int	state;
-
-	/*
-	 * Some public API functions depend on the "real" type of the
-	 * archive object.
-	 */
-	const struct archive_vtable *vtable;
-
-	int		  archive_format;
-	const char	 *archive_format_name;
-
-	/* Number of file entries processed. */
-	int		  file_count;
-
-	int		  archive_error_number;
-	const char	 *error;
-	struct archive_string	error_string;
-
-	char *current_code;
-	unsigned current_codepage; /* Current ACP(ANSI CodePage). */
-	unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
-	struct archive_string_conv *sconv;
-
-	/*
-	 * Used by archive_read_data() to track blocks and copy
-	 * data to client buffers, filling gaps with zero bytes.
-	 */
-	const char	 *read_data_block;
-	int64_t		  read_data_offset;
-	int64_t		  read_data_output_offset;
-	size_t		  read_data_remaining;
-
-	/*
-	 * Used by formats/filters to determine the amount of data
-	 * requested from a call to archive_read_data(). This is only
-	 * useful when the format/filter has seek support.
-	 */
-	char		  read_data_is_posix_read;
-	size_t		  read_data_requested;
-};
-
-/* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */
-int	__archive_check_magic(struct archive *, unsigned int magic,
-	    unsigned int state, const char *func);
-#define	archive_check_magic(a, expected_magic, allowed_states, function_name) \
-	do { \
-		int magic_test = __archive_check_magic((a), (expected_magic), \
-			(allowed_states), (function_name)); \
-		if (magic_test == ARCHIVE_FATAL) \
-			return ARCHIVE_FATAL; \
-	} while (0)
-
-void	__archive_errx(int retvalue, const char *msg) __LA_DEAD;
-
-void	__archive_ensure_cloexec_flag(int fd);
-int	__archive_mktemp(const char *tmpdir);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-int	__archive_mkstemp(wchar_t *template);
-#else
-int	__archive_mkstemp(char *template);
-#endif
-
-int	__archive_clean(struct archive *);
-
-void __archive_reset_read_data(struct archive *);
-
-#define	err_combine(a,b)	((a) < (b) ? (a) : (b))
-
-#if defined(__BORLANDC__) || (defined(_MSC_VER) &&  _MSC_VER <= 1300)
-# define	ARCHIVE_LITERAL_LL(x)	x##i64
-# define	ARCHIVE_LITERAL_ULL(x)	x##ui64
-#else
-# define	ARCHIVE_LITERAL_LL(x)	x##ll
-# define	ARCHIVE_LITERAL_ULL(x)	x##ull
-#endif
-
-#endif
diff --git a/c/archive_random.c b/c/archive_random.c
deleted file mode 100644
--- a/c/archive_random.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
-
-#ifdef HAVE_FCNTL
-#include <fcntl.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-
-static void la_arc4random_buf(void *, size_t);
-
-#endif /* HAVE_ARC4RANDOM_BUF */
-
-#include "archive.h"
-#include "archive_random_private.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-/* don't use bcrypt when XP needs to be supported */
-#include <bcrypt.h>
-
-/* Common in other bcrypt implementations, but missing from VS2008. */
-#ifndef BCRYPT_SUCCESS
-#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
-#endif
-
-#elif defined(HAVE_WINCRYPT_H)
-#include <wincrypt.h>
-#endif
-#endif
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-/*
- * Random number generator function.
- * This simply calls arc4random_buf function if the platform provides it.
- */
-
-int
-archive_random(void *buf, size_t nbytes)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	NTSTATUS status;
-	BCRYPT_ALG_HANDLE hAlg;
-
-	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
-	if (!BCRYPT_SUCCESS(status))
-		return ARCHIVE_FAILED;
-	status = BCryptGenRandom(hAlg, buf, nbytes, 0);
-	BCryptCloseAlgorithmProvider(hAlg, 0);
-	if (!BCRYPT_SUCCESS(status))
-		return ARCHIVE_FAILED;
-
-	return ARCHIVE_OK;
-# else
-	HCRYPTPROV hProv;
-	BOOL success;
-
-	success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
-	    CRYPT_VERIFYCONTEXT);
-	if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
-		success = CryptAcquireContext(&hProv, NULL, NULL,
-		    PROV_RSA_FULL, CRYPT_NEWKEYSET);
-	}
-	if (success) {
-		success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf);
-		CryptReleaseContext(hProv, 0);
-		if (success)
-			return ARCHIVE_OK;
-	}
-	/* TODO: Does this case really happen? */
-	return ARCHIVE_FAILED;
-# endif
-#elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
-	la_arc4random_buf(buf, nbytes);
-	return ARCHIVE_OK;
-#else
-	arc4random_buf(buf, nbytes);
-	return ARCHIVE_OK;
-#endif
-}
-
-#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
-
-/*	$OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $	*/
-/*
- * Copyright (c) 1996, David Mazieres <dm@uun.org>
- * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Arc4 random number generator for OpenBSD.
- *
- * This code is derived from section 17.1 of Applied Cryptography,
- * second edition, which describes a stream cipher allegedly
- * compatible with RSA Labs "RC4" cipher (the actual description of
- * which is a trade secret).  The same algorithm is used as a stream
- * cipher called "arcfour" in Tatu Ylonen's ssh package.
- *
- * RC4 is a registered trademark of RSA Laboratories.
- */
-
-#ifdef __GNUC__
-#define inline __inline
-#else				/* !__GNUC__ */
-#define inline
-#endif				/* !__GNUC__ */
-
-struct arc4_stream {
-	uint8_t i;
-	uint8_t j;
-	uint8_t s[256];
-};
-
-#define	RANDOMDEV	"/dev/urandom"
-#define	KEYSIZE		128
-#ifdef HAVE_PTHREAD_H
-static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
-#define	_ARC4_LOCK()	pthread_mutex_lock(&arc4random_mtx);
-#define	_ARC4_UNLOCK()  pthread_mutex_unlock(&arc4random_mtx);
-#else
-#define	_ARC4_LOCK()
-#define	_ARC4_UNLOCK()
-#endif
-
-static int rs_initialized;
-static struct arc4_stream rs;
-static pid_t arc4_stir_pid;
-static int arc4_count;
-
-static inline uint8_t arc4_getbyte(void);
-static void arc4_stir(void);
-
-static inline void
-arc4_init(void)
-{
-	int     n;
-
-	for (n = 0; n < 256; n++)
-		rs.s[n] = n;
-	rs.i = 0;
-	rs.j = 0;
-}
-
-static inline void
-arc4_addrandom(uint8_t *dat, int datlen)
-{
-	int     n;
-	uint8_t si;
-
-	rs.i--;
-	for (n = 0; n < 256; n++) {
-		rs.i = (rs.i + 1);
-		si = rs.s[rs.i];
-		rs.j = (rs.j + si + dat[n % datlen]);
-		rs.s[rs.i] = rs.s[rs.j];
-		rs.s[rs.j] = si;
-	}
-	rs.j = rs.i;
-}
-
-static void
-arc4_stir(void)
-{
-	int done, fd, i;
-	struct {
-		struct timeval	tv;
-		pid_t		pid;
-		uint8_t		rnd[KEYSIZE];
-	} rdat;
-
-	if (!rs_initialized) {
-		arc4_init();
-		rs_initialized = 1;
-	}
-	done = 0;
-	fd = open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
-	if (fd >= 0) {
-		if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
-			done = 1;
-		(void)close(fd);
-	}
-	if (!done) {
-		(void)gettimeofday(&rdat.tv, NULL);
-		rdat.pid = getpid();
-		/* We'll just take whatever was on the stack too... */
-	}
-
-	arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
-
-	/*
-	 * Discard early keystream, as per recommendations in:
-	 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
-	 * As per the Network Operations Division, cryptographic requirements
-	 * published on wikileaks on March 2017.
-	 */
-
-	for (i = 0; i < 3072; i++)
-		(void)arc4_getbyte();
-	arc4_count = 1600000;
-}
-
-static void
-arc4_stir_if_needed(void)
-{
-	pid_t pid = getpid();
-
-	if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
-		arc4_stir_pid = pid;
-		arc4_stir();
-	}
-}
-
-static inline uint8_t
-arc4_getbyte(void)
-{
-	uint8_t si, sj;
-
-	rs.i = (rs.i + 1);
-	si = rs.s[rs.i];
-	rs.j = (rs.j + si);
-	sj = rs.s[rs.j];
-	rs.s[rs.i] = sj;
-	rs.s[rs.j] = si;
-	return (rs.s[(si + sj) & 0xff]);
-}
-
-static void
-la_arc4random_buf(void *_buf, size_t n)
-{
-	uint8_t *buf = (uint8_t *)_buf;
-	_ARC4_LOCK();
-	arc4_stir_if_needed();
-	while (n--) {
-		if (--arc4_count <= 0)
-			arc4_stir();
-		buf[n] = arc4_getbyte();
-	}
-	_ARC4_UNLOCK();
-}
-
-#endif /* !HAVE_ARC4RANDOM_BUF */
diff --git a/c/archive_random_private.h b/c/archive_random_private.h
deleted file mode 100644
--- a/c/archive_random_private.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
-#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-/* Random number generator. */
-int archive_random(void *buf, size_t nbytes);
-
-#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
diff --git a/c/archive_rb.c b/c/archive_rb.c
deleted file mode 100644
--- a/c/archive_rb.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matt Thomas <matt@3am-software.com>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Based on: NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp
- */
-
-#include "archive_platform.h"
-
-#include <stddef.h>
-
-#include "archive_rb.h"
-
-/* Keep in sync with archive_rb.h */
-#define	RB_DIR_LEFT		0
-#define	RB_DIR_RIGHT		1
-#define	RB_DIR_OTHER		1
-#define	rb_left			rb_nodes[RB_DIR_LEFT]
-#define	rb_right		rb_nodes[RB_DIR_RIGHT]
-
-#define	RB_FLAG_POSITION	0x2
-#define	RB_FLAG_RED		0x1
-#define	RB_FLAG_MASK		(RB_FLAG_POSITION|RB_FLAG_RED)
-#define	RB_FATHER(rb) \
-    ((struct archive_rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
-#define	RB_SET_FATHER(rb, father) \
-    ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
-
-#define	RB_SENTINEL_P(rb)	((rb) == NULL)
-#define	RB_LEFT_SENTINEL_P(rb)	RB_SENTINEL_P((rb)->rb_left)
-#define	RB_RIGHT_SENTINEL_P(rb)	RB_SENTINEL_P((rb)->rb_right)
-#define	RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
-#define	RB_CHILDLESS_P(rb) \
-    (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
-#define	RB_TWOCHILDREN_P(rb) \
-    (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
-
-#define	RB_POSITION(rb)	\
-    (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
-#define	RB_RIGHT_P(rb)		(RB_POSITION(rb) == RB_DIR_RIGHT)
-#define	RB_LEFT_P(rb)		(RB_POSITION(rb) == RB_DIR_LEFT)
-#define	RB_RED_P(rb) 		(!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
-#define	RB_BLACK_P(rb) 		(RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
-#define	RB_MARK_RED(rb) 	((void)((rb)->rb_info |= RB_FLAG_RED))
-#define	RB_MARK_BLACK(rb) 	((void)((rb)->rb_info &= ~RB_FLAG_RED))
-#define	RB_INVERT_COLOR(rb) 	((void)((rb)->rb_info ^= RB_FLAG_RED))
-#define	RB_ROOT_P(rbt, rb)	((rbt)->rbt_root == (rb))
-#define	RB_SET_POSITION(rb, position) \
-    ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
-    ((rb)->rb_info &= ~RB_FLAG_POSITION)))
-#define	RB_ZERO_PROPERTIES(rb)	((void)((rb)->rb_info &= ~RB_FLAG_MASK))
-#define	RB_COPY_PROPERTIES(dst, src) \
-    ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
-#define RB_SWAP_PROPERTIES(a, b) do { \
-    uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
-    (a)->rb_info ^= xorinfo; \
-    (b)->rb_info ^= xorinfo; \
-  } while (/*CONSTCOND*/ 0)
-
-static void __archive_rb_tree_insert_rebalance(struct archive_rb_tree *,
-    struct archive_rb_node *);
-static void __archive_rb_tree_removal_rebalance(struct archive_rb_tree *,
-    struct archive_rb_node *, unsigned int);
-
-#define	RB_SENTINEL_NODE	NULL
-
-#define T	1
-#define	F	0
-
-void
-__archive_rb_tree_init(struct archive_rb_tree *rbt,
-    const struct archive_rb_tree_ops *ops)
-{
-	rbt->rbt_ops = ops;
-	*((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
-}
-
-struct archive_rb_node *
-__archive_rb_tree_find_node(struct archive_rb_tree *rbt, const void *key)
-{
-	archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-	struct archive_rb_node *parent = rbt->rbt_root;
-
-	while (!RB_SENTINEL_P(parent)) {
-		const signed int diff = (*compare_key)(parent, key);
-		if (diff == 0)
-			return parent;
-		parent = parent->rb_nodes[diff > 0];
-	}
-
-	return NULL;
-}
- 
-struct archive_rb_node *
-__archive_rb_tree_find_node_geq(struct archive_rb_tree *rbt, const void *key)
-{
-	archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-	struct archive_rb_node *parent = rbt->rbt_root;
-	struct archive_rb_node *last = NULL;
-
-	while (!RB_SENTINEL_P(parent)) {
-		const signed int diff = (*compare_key)(parent, key);
-		if (diff == 0)
-			return parent;
-		if (diff < 0)
-			last = parent;
-		parent = parent->rb_nodes[diff > 0];
-	}
-
-	return last;
-}
- 
-struct archive_rb_node *
-__archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key)
-{
-	archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
-	struct archive_rb_node *parent = rbt->rbt_root;
-	struct archive_rb_node *last = NULL;
-
-	while (!RB_SENTINEL_P(parent)) {
-		const signed int diff = (*compare_key)(parent, key);
-		if (diff == 0)
-			return parent;
-		if (diff > 0)
-			last = parent;
-		parent = parent->rb_nodes[diff > 0];
-	}
-
-	return last;
-}
-
-int
-__archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self)
-{
-	archive_rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
-	struct archive_rb_node *parent, *tmp;
-	unsigned int position;
-	int rebalance;
-
-	tmp = rbt->rbt_root;
-	/*
-	 * This is a hack.  Because rbt->rbt_root is just a
-	 * struct archive_rb_node *, just like rb_node->rb_nodes[RB_DIR_LEFT],
-	 * we can use this fact to avoid a lot of tests for root and know
-	 * that even at root, updating
-	 * RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
-	 * update rbt->rbt_root.
-	 */
-	parent = (struct archive_rb_node *)(void *)&rbt->rbt_root;
-	position = RB_DIR_LEFT;
-
-	/*
-	 * Find out where to place this new leaf.
-	 */
-	while (!RB_SENTINEL_P(tmp)) {
-		const signed int diff = (*compare_nodes)(tmp, self);
-		if (diff == 0) {
-			/*
-			 * Node already exists; don't insert.
-			 */
-			return F;
-		}
-		parent = tmp;
-		position = (diff > 0);
-		tmp = parent->rb_nodes[position];
-	}
-
-	/*
-	 * Initialize the node and insert as a leaf into the tree.
-	 */
-	RB_SET_FATHER(self, parent);
-	RB_SET_POSITION(self, position);
-	if (parent == (struct archive_rb_node *)(void *)&rbt->rbt_root) {
-		RB_MARK_BLACK(self);		/* root is always black */
-		rebalance = F;
-	} else {
-		/*
-		 * All new nodes are colored red.  We only need to rebalance
-		 * if our parent is also red.
-		 */
-		RB_MARK_RED(self);
-		rebalance = RB_RED_P(parent);
-	}
-	self->rb_left = parent->rb_nodes[position];
-	self->rb_right = parent->rb_nodes[position];
-	parent->rb_nodes[position] = self;
-
-	/*
-	 * Rebalance tree after insertion
-	 */
-	if (rebalance)
-		__archive_rb_tree_insert_rebalance(rbt, self);
-
-	return T;
-}
-
-/*
- * Swap the location and colors of 'self' and its child @ which.  The child
- * can not be a sentinel node.  This is our rotation function.  However,
- * since it preserves coloring, it great simplifies both insertion and
- * removal since rotation almost always involves the exchanging of colors
- * as a separate step.
- */
-/*ARGSUSED*/
-static void
-__archive_rb_tree_reparent_nodes(
-    struct archive_rb_node *old_father, const unsigned int which)
-{
-	const unsigned int other = which ^ RB_DIR_OTHER;
-	struct archive_rb_node * const grandpa = RB_FATHER(old_father);
-	struct archive_rb_node * const old_child = old_father->rb_nodes[which];
-	struct archive_rb_node * const new_father = old_child;
-	struct archive_rb_node * const new_child = old_father;
-
-	if (new_father == NULL)
-		return;
-	/*
-	 * Exchange descendant linkages.
-	 */
-	grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
-	new_child->rb_nodes[which] = old_child->rb_nodes[other];
-	new_father->rb_nodes[other] = new_child;
-
-	/*
-	 * Update ancestor linkages
-	 */
-	RB_SET_FATHER(new_father, grandpa);
-	RB_SET_FATHER(new_child, new_father);
-
-	/*
-	 * Exchange properties between new_father and new_child.  The only
-	 * change is that new_child's position is now on the other side.
-	 */
-	RB_SWAP_PROPERTIES(new_father, new_child);
-	RB_SET_POSITION(new_child, other);
-
-	/*
-	 * Make sure to reparent the new child to ourself.
-	 */
-	if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
-		RB_SET_FATHER(new_child->rb_nodes[which], new_child);
-		RB_SET_POSITION(new_child->rb_nodes[which], which);
-	}
-
-}
-
-static void
-__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self)
-{
-	struct archive_rb_node * father = RB_FATHER(self);
-	struct archive_rb_node * grandpa;
-	struct archive_rb_node * uncle;
-	unsigned int which;
-	unsigned int other;
-
-	for (;;) {
-		/*
-		 * We are red and our parent is red, therefore we must have a
-		 * grandfather and he must be black.
-		 */
-		grandpa = RB_FATHER(father);
-		which = (father == grandpa->rb_right);
-		other = which ^ RB_DIR_OTHER;
-		uncle = grandpa->rb_nodes[other];
-
-		if (RB_BLACK_P(uncle))
-			break;
-
-		/*
-		 * Case 1: our uncle is red
-		 *   Simply invert the colors of our parent and
-		 *   uncle and make our grandparent red.  And
-		 *   then solve the problem up at his level.
-		 */
-		RB_MARK_BLACK(uncle);
-		RB_MARK_BLACK(father);
-		if (RB_ROOT_P(rbt, grandpa)) {
-			/*
-			 * If our grandpa is root, don't bother
-			 * setting him to red, just return.
-			 */
-			return;
-		}
-		RB_MARK_RED(grandpa);
-		self = grandpa;
-		father = RB_FATHER(self);
-		if (RB_BLACK_P(father)) {
-			/*
-			 * If our great-grandpa is black, we're done.
-			 */
-			return;
-		}
-	}
-
-	/*
-	 * Case 2&3: our uncle is black.
-	 */
-	if (self == father->rb_nodes[other]) {
-		/*
-		 * Case 2: we are on the same side as our uncle
-		 *   Swap ourselves with our parent so this case
-		 *   becomes case 3.  Basically our parent becomes our
-		 *   child.
-		 */
-		__archive_rb_tree_reparent_nodes(father, other);
-	}
-	/*
-	 * Case 3: we are opposite a child of a black uncle.
-	 *   Swap our parent and grandparent.  Since our grandfather
-	 *   is black, our father will become black and our new sibling
-	 *   (former grandparent) will become red.
-	 */
-	__archive_rb_tree_reparent_nodes(grandpa, which);
-
-	/*
-	 * Final step: Set the root to black.
-	 */
-	RB_MARK_BLACK(rbt->rbt_root);
-}
-
-static void
-__archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self, int rebalance)
-{
-	const unsigned int which = RB_POSITION(self);
-	struct archive_rb_node *father = RB_FATHER(self);
-
-	/*
-	 * Since we are childless, we know that self->rb_left is pointing
-	 * to the sentinel node.
-	 */
-	father->rb_nodes[which] = self->rb_left;
-
-	/*
-	 * Rebalance if requested.
-	 */
-	if (rebalance)
-		__archive_rb_tree_removal_rebalance(rbt, father, which);
-}
-
-/*
- * When deleting an interior node
- */
-static void
-__archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self, struct archive_rb_node *standin)
-{
-	const unsigned int standin_which = RB_POSITION(standin);
-	unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
-	struct archive_rb_node *standin_son;
-	struct archive_rb_node *standin_father = RB_FATHER(standin);
-	int rebalance = RB_BLACK_P(standin);
-
-	if (standin_father == self) {
-		/*
-		 * As a child of self, any children would be opposite of
-		 * our parent.
-		 */
-		standin_son = standin->rb_nodes[standin_which];
-	} else {
-		/*
-		 * Since we aren't a child of self, any children would be
-		 * on the same side as our parent.
-		 */
-		standin_son = standin->rb_nodes[standin_other];
-	}
-
-	if (RB_RED_P(standin_son)) {
-		/*
-		 * We know we have a red child so if we flip it to black
-		 * we don't have to rebalance.
-		 */
-		RB_MARK_BLACK(standin_son);
-		rebalance = F;
-
-		if (standin_father != self) {
-			/*
-			 * Change the son's parentage to point to his grandpa.
-			 */
-			RB_SET_FATHER(standin_son, standin_father);
-			RB_SET_POSITION(standin_son, standin_which);
-		}
-	}
-
-	if (standin_father == self) {
-		/*
-		 * If we are about to delete the standin's father, then when
-		 * we call rebalance, we need to use ourselves as our father.
-		 * Otherwise remember our original father.  Also, since we are
-		 * our standin's father we only need to reparent the standin's
-		 * brother.
-		 *
-		 * |    R      -->     S    |
-		 * |  Q   S    -->   Q   T  |
-		 * |        t  -->          |
-		 *
-		 * Have our son/standin adopt his brother as his new son.
-		 */
-		standin_father = standin;
-	} else {
-		/*
-		 * |    R          -->    S       .  |
-		 * |   / \  |   T  -->   / \  |  /   |
-		 * |  ..... | S    -->  ..... | T    |
-		 *
-		 * Sever standin's connection to his father.
-		 */
-		standin_father->rb_nodes[standin_which] = standin_son;
-		/*
-		 * Adopt the far son.
-		 */
-		standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
-		RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
-		/*
-		 * Use standin_other because we need to preserve standin_which
-		 * for the removal_rebalance.
-		 */
-		standin_other = standin_which;
-	}
-
-	/*
-	 * Move the only remaining son to our standin.  If our standin is our
-	 * son, this will be the only son needed to be moved.
-	 */
-	standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
-	RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
-
-	/*
-	 * Now copy the result of self to standin and then replace
-	 * self with standin in the tree.
-	 */
-	RB_COPY_PROPERTIES(standin, self);
-	RB_SET_FATHER(standin, RB_FATHER(self));
-	RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
-
-	if (rebalance)
-		__archive_rb_tree_removal_rebalance(rbt, standin_father, standin_which);
-}
-
-/*
- * We could do this by doing
- *	__archive_rb_tree_node_swap(rbt, self, which);
- *	__archive_rb_tree_prune_node(rbt, self, F);
- *
- * But it's more efficient to just evaluate and recolor the child.
- */
-static void
-__archive_rb_tree_prune_blackred_branch(
-    struct archive_rb_node *self, unsigned int which)
-{
-	struct archive_rb_node *father = RB_FATHER(self);
-	struct archive_rb_node *son = self->rb_nodes[which];
-
-	/*
-	 * Remove ourselves from the tree and give our former child our
-	 * properties (position, color, root).
-	 */
-	RB_COPY_PROPERTIES(son, self);
-	father->rb_nodes[RB_POSITION(son)] = son;
-	RB_SET_FATHER(son, father);
-}
-/*
- *
- */
-void
-__archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self)
-{
-	struct archive_rb_node *standin;
-	unsigned int which;
-
-	/*
-	 * In the following diagrams, we (the node to be removed) are S.  Red
-	 * nodes are lowercase.  T could be either red or black.
-	 *
-	 * Remember the major axiom of the red-black tree: the number of
-	 * black nodes from the root to each leaf is constant across all
-	 * leaves, only the number of red nodes varies.
-	 *
-	 * Thus removing a red leaf doesn't require any other changes to a
-	 * red-black tree.  So if we must remove a node, attempt to rearrange
-	 * the tree so we can remove a red node.
-	 *
-	 * The simplest case is a childless red node or a childless root node:
-	 *
-	 * |    T  -->    T  |    or    |  R  -->  *  |
-	 * |  s    -->  *    |
-	 */
-	if (RB_CHILDLESS_P(self)) {
-		const int rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
-		__archive_rb_tree_prune_node(rbt, self, rebalance);
-		return;
-	}
-	if (!RB_TWOCHILDREN_P(self)) {
-		/*
-		 * The next simplest case is the node we are deleting is
-		 * black and has one red child.
-		 *
-		 * |      T  -->      T  -->      T  |
-		 * |    S    -->  R      -->  R      |
-		 * |  r      -->    s    -->    *    |
-		 */
-		which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
-		__archive_rb_tree_prune_blackred_branch(self, which);
-		return;
-	}
-
-	/*
-	 * We invert these because we prefer to remove from the inside of
-	 * the tree.
-	 */
-	which = RB_POSITION(self) ^ RB_DIR_OTHER;
-
-	/*
-	 * Let's find the node closes to us opposite of our parent
-	 * Now swap it with ourself, "prune" it, and rebalance, if needed.
-	 */
-	standin = __archive_rb_tree_iterate(rbt, self, which);
-	__archive_rb_tree_swap_prune_and_rebalance(rbt, self, standin);
-}
-
-static void
-__archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
-    struct archive_rb_node *parent, unsigned int which)
-{
-
-	while (RB_BLACK_P(parent->rb_nodes[which])) {
-		unsigned int other = which ^ RB_DIR_OTHER;
-		struct archive_rb_node *brother = parent->rb_nodes[other];
-
-		if (brother == NULL)
-			return;/* The tree may be broken. */
-		/*
-		 * For cases 1, 2a, and 2b, our brother's children must
-		 * be black and our father must be black
-		 */
-		if (RB_BLACK_P(parent)
-		    && RB_BLACK_P(brother->rb_left)
-		    && RB_BLACK_P(brother->rb_right)) {
-			if (RB_RED_P(brother)) {
-				/*
-				 * Case 1: Our brother is red, swap its
-				 * position (and colors) with our parent. 
-				 * This should now be case 2b (unless C or E
-				 * has a red child which is case 3; thus no
-				 * explicit branch to case 2b).
-				 *
-				 *    B         ->        D
-				 *  A     d     ->    b     E
-				 *      C   E   ->  A   C
-				 */
-				__archive_rb_tree_reparent_nodes(parent, other);
-				brother = parent->rb_nodes[other];
-				if (brother == NULL)
-					return;/* The tree may be broken. */
-			} else {
-				/*
-				 * Both our parent and brother are black.
-				 * Change our brother to red, advance up rank
-				 * and go through the loop again.
-				 *
-				 *    B         ->   *B
-				 * *A     D     ->  A     d
-				 *      C   E   ->      C   E
-				 */
-				RB_MARK_RED(brother);
-				if (RB_ROOT_P(rbt, parent))
-					return;	/* root == parent == black */
-				which = RB_POSITION(parent);
-				parent = RB_FATHER(parent);
-				continue;
-			}
-		}
-		/*
-		 * Avoid an else here so that case 2a above can hit either
-		 * case 2b, 3, or 4.
-		 */
-		if (RB_RED_P(parent)
-		    && RB_BLACK_P(brother)
-		    && RB_BLACK_P(brother->rb_left)
-		    && RB_BLACK_P(brother->rb_right)) {
-			/*
-			 * We are black, our father is red, our brother and
-			 * both nephews are black.  Simply invert/exchange the
-			 * colors of our father and brother (to black and red
-			 * respectively).
-			 *
-			 *	|    f        -->    F        |
-			 *	|  *     B    -->  *     b    |
-			 *	|      N   N  -->      N   N  |
-			 */
-			RB_MARK_BLACK(parent);
-			RB_MARK_RED(brother);
-			break;		/* We're done! */
-		} else {
-			/*
-			 * Our brother must be black and have at least one
-			 * red child (it may have two).
-			 */
-			if (RB_BLACK_P(brother->rb_nodes[other])) {
-				/*
-				 * Case 3: our brother is black, our near
-				 * nephew is red, and our far nephew is black.
-				 * Swap our brother with our near nephew.  
-				 * This result in a tree that matches case 4.
-				 * (Our father could be red or black).
-				 *
-				 *	|    F      -->    F      |
-				 *	|  x     B  -->  x   B    |
-				 *	|      n    -->        n  |
-				 */
-				__archive_rb_tree_reparent_nodes(brother, which);
-				brother = parent->rb_nodes[other];
-			}
-			/*
-			 * Case 4: our brother is black and our far nephew
-			 * is red.  Swap our father and brother locations and
-			 * change our far nephew to black.  (these can be
-			 * done in either order so we change the color first).
-			 * The result is a valid red-black tree and is a
-			 * terminal case.  (again we don't care about the
-			 * father's color)
-			 *
-			 * If the father is red, we will get a red-black-black
-			 * tree:
-			 *	|  f      ->  f      -->    b    |
-			 *	|    B    ->    B    -->  F   N  |
-			 *	|      n  ->      N  -->         |
-			 *
-			 * If the father is black, we will get an all black
-			 * tree:
-			 *	|  F      ->  F      -->    B    |
-			 *	|    B    ->    B    -->  F   N  |
-			 *	|      n  ->      N  -->         |
-			 *
-			 * If we had two red nephews, then after the swap,
-			 * our former father would have a red grandson. 
-			 */
-			if (brother->rb_nodes[other] == NULL)
-				return;/* The tree may be broken. */
-			RB_MARK_BLACK(brother->rb_nodes[other]);
-			__archive_rb_tree_reparent_nodes(parent, other);
-			break;		/* We're done! */
-		}
-	}
-}
-
-struct archive_rb_node *
-__archive_rb_tree_iterate(struct archive_rb_tree *rbt,
-    struct archive_rb_node *self, const unsigned int direction)
-{
-	const unsigned int other = direction ^ RB_DIR_OTHER;
-
-	if (self == NULL) {
-		self = rbt->rbt_root;
-		if (RB_SENTINEL_P(self))
-			return NULL;
-		while (!RB_SENTINEL_P(self->rb_nodes[direction]))
-			self = self->rb_nodes[direction];
-		return self;
-	}
-	/*
-	 * We can't go any further in this direction.  We proceed up in the
-	 * opposite direction until our parent is in direction we want to go.
-	 */
-	if (RB_SENTINEL_P(self->rb_nodes[direction])) {
-		while (!RB_ROOT_P(rbt, self)) {
-			if (other == (unsigned int)RB_POSITION(self))
-				return RB_FATHER(self);
-			self = RB_FATHER(self);
-		}
-		return NULL;
-	}
-
-	/*
-	 * Advance down one in current direction and go down as far as possible
-	 * in the opposite direction.
-	 */
-	self = self->rb_nodes[direction];
-	while (!RB_SENTINEL_P(self->rb_nodes[other]))
-		self = self->rb_nodes[other];
-	return self;
-}
diff --git a/c/archive_rb.h b/c/archive_rb.h
deleted file mode 100644
--- a/c/archive_rb.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matt Thomas <matt@3am-software.com>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Based on NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp
- */
-
-#ifndef ARCHIVE_RB_H_INCLUDED
-#define	ARCHIVE_RB_H_INCLUDED
-
-struct archive_rb_node {
-	struct archive_rb_node *rb_nodes[2];
-	/*
-	 * rb_info contains the two flags and the parent back pointer.
-	 * We put the two flags in the low two bits since we know that
-	 * rb_node will have an alignment of 4 or 8 bytes.
-	 */
-	uintptr_t rb_info;
-};
-
-#define	ARCHIVE_RB_DIR_LEFT		0
-#define	ARCHIVE_RB_DIR_RIGHT		1
-
-#define ARCHIVE_RB_TREE_MIN(T) \
-    __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_LEFT)
-#define ARCHIVE_RB_TREE_MAX(T) \
-    __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_RIGHT)
-#define ARCHIVE_RB_TREE_NEXT(T, N) \
-    __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT)
-#define ARCHIVE_RB_TREE_PREV(T, N) \
-    __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT)
-#define ARCHIVE_RB_TREE_FOREACH(N, T) \
-    for ((N) = ARCHIVE_RB_TREE_MIN(T); (N); \
-	(N) = ARCHIVE_RB_TREE_NEXT((T), (N)))
-#define ARCHIVE_RB_TREE_FOREACH_REVERSE(N, T) \
-    for ((N) = ARCHIVE_RB_TREE_MAX(T); (N); \
-	(N) = ARCHIVE_RB_TREE_PREV((T), (N)))
-#define ARCHIVE_RB_TREE_FOREACH_SAFE(N, T, S) \
-    for ((N) = ARCHIVE_RB_TREE_MIN(T); \
-	(N) && ((S) = ARCHIVE_RB_TREE_NEXT((T), (N)), 1); \
-	(N) = (S))
-#define ARCHIVE_RB_TREE_FOREACH_REVERSE_SAFE(N, T, S) \
-    for ((N) = ARCHIVE_RB_TREE_MAX(T); \
-        (N) && ((S) = ARCHIVE_RB_TREE_PREV((T), (N)), 1); \
-        (N) = (S))
-
-/*
- * archive_rbto_compare_nodes_fn:
- *	return a positive value if the first node < the second node.
- *	return a negative value if the first node > the second node.
- *	return 0 if they are considered same.
- *
- * archive_rbto_compare_key_fn:
- *	return a positive value if the node < the key.
- *	return a negative value if the node > the key.
- *	return 0 if they are considered same.
- */
-
-typedef signed int (*const archive_rbto_compare_nodes_fn)(const struct archive_rb_node *,
-    const struct archive_rb_node *);
-typedef signed int (*const archive_rbto_compare_key_fn)(const struct archive_rb_node *,
-    const void *);
-
-struct archive_rb_tree_ops {
-	archive_rbto_compare_nodes_fn rbto_compare_nodes;
-	archive_rbto_compare_key_fn rbto_compare_key;
-};
-
-struct archive_rb_tree {
-	struct archive_rb_node *rbt_root;
-	const struct archive_rb_tree_ops *rbt_ops;
-};
-
-void	__archive_rb_tree_init(struct archive_rb_tree *,
-    const struct archive_rb_tree_ops *);
-int	__archive_rb_tree_insert_node(struct archive_rb_tree *,
-    struct archive_rb_node *);
-struct archive_rb_node	*
-	__archive_rb_tree_find_node(struct archive_rb_tree *, const void *);
-struct archive_rb_node	*
-	__archive_rb_tree_find_node_geq(struct archive_rb_tree *, const void *);
-struct archive_rb_node	*
-	__archive_rb_tree_find_node_leq(struct archive_rb_tree *, const void *);
-void	__archive_rb_tree_remove_node(struct archive_rb_tree *, struct archive_rb_node *);
-struct archive_rb_node *
-	__archive_rb_tree_iterate(struct archive_rb_tree *,
-	struct archive_rb_node *, const unsigned int);
-
-#endif	/* ARCHIVE_RB_H_*/
diff --git a/c/archive_read.c b/c/archive_read.c
deleted file mode 100644
--- a/c/archive_read.c
+++ /dev/null
@@ -1,1756 +0,0 @@
-/*-
- * Copyright (c) 2003-2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This file contains the "essential" portions of the read API, that
- * is, stuff that will probably always be used by any client that
- * actually needs to read an archive.  Optional pieces have been, as
- * far as possible, separated out into separate files to avoid
- * needlessly bloating statically-linked clients.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:23Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#define minimum(a, b) (a < b ? a : b)
-
-static int	choose_filters(struct archive_read *);
-static int	choose_format(struct archive_read *);
-static int	close_filters(struct archive_read *);
-static int64_t	_archive_filter_bytes(struct archive *, int);
-static int	_archive_filter_code(struct archive *, int);
-static const char *_archive_filter_name(struct archive *, int);
-static int  _archive_filter_count(struct archive *);
-static int	_archive_read_close(struct archive *);
-static int	_archive_read_data_block(struct archive *,
-		    const void **, size_t *, int64_t *);
-static int	_archive_read_free(struct archive *);
-static int	_archive_read_next_header(struct archive *,
-		    struct archive_entry **);
-static int	_archive_read_next_header2(struct archive *,
-		    struct archive_entry *);
-static int64_t  advance_file_pointer(struct archive_read_filter *, int64_t);
-
-static const struct archive_vtable
-archive_read_vtable = {
-	.archive_filter_bytes = _archive_filter_bytes,
-	.archive_filter_code = _archive_filter_code,
-	.archive_filter_name = _archive_filter_name,
-	.archive_filter_count = _archive_filter_count,
-	.archive_read_data_block = _archive_read_data_block,
-	.archive_read_next_header = _archive_read_next_header,
-	.archive_read_next_header2 = _archive_read_next_header2,
-	.archive_free = _archive_read_free,
-	.archive_close = _archive_read_close,
-};
-
-/*
- * Allocate, initialize and return a struct archive object.
- */
-struct archive *
-archive_read_new(void)
-{
-	struct archive_read *a;
-
-	a = (struct archive_read *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_READ_MAGIC;
-
-	a->archive.state = ARCHIVE_STATE_NEW;
-	a->entry = archive_entry_new2(&a->archive);
-	a->archive.vtable = &archive_read_vtable;
-
-	a->passphrases.last = &a->passphrases.first;
-
-	return (&a->archive);
-}
-
-/*
- * Record the do-not-extract-to file. This belongs in archive_read_extract.c.
- */
-void
-archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
-    la_int64_t i)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-		ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file"))
-		return;
-	a->skip_file_set = 1;
-	a->skip_file_dev = d;
-	a->skip_file_ino = i;
-}
-
-/*
- * Open the archive
- */
-int
-archive_read_open(struct archive *a, void *client_data,
-    archive_open_callback *client_opener, archive_read_callback *client_reader,
-    archive_close_callback *client_closer)
-{
-	/* Old archive_read_open() is just a thin shell around
-	 * archive_read_open1. */
-	archive_read_set_open_callback(a, client_opener);
-	archive_read_set_read_callback(a, client_reader);
-	archive_read_set_close_callback(a, client_closer);
-	archive_read_set_callback_data(a, client_data);
-	return archive_read_open1(a);
-}
-
-
-int
-archive_read_open2(struct archive *a, void *client_data,
-    archive_open_callback *client_opener,
-    archive_read_callback *client_reader,
-    archive_skip_callback *client_skipper,
-    archive_close_callback *client_closer)
-{
-	/* Old archive_read_open2() is just a thin shell around
-	 * archive_read_open1. */
-	archive_read_set_callback_data(a, client_data);
-	archive_read_set_open_callback(a, client_opener);
-	archive_read_set_read_callback(a, client_reader);
-	archive_read_set_skip_callback(a, client_skipper);
-	archive_read_set_close_callback(a, client_closer);
-	return archive_read_open1(a);
-}
-
-static ssize_t
-client_read_proxy(struct archive_read_filter *self, const void **buff)
-{
-	ssize_t r;
-	r = (self->archive->client.reader)(&self->archive->archive,
-	    self->data, buff);
-	return (r);
-}
-
-static int64_t
-client_skip_proxy(struct archive_read_filter *self, int64_t request)
-{
-	if (request < 0)
-		__archive_errx(1, "Negative skip requested.");
-	if (request == 0)
-		return 0;
-
-	if (self->archive->client.skipper != NULL) {
-		/* Seek requests over 1GiB are broken down into
-		 * multiple seeks.  This avoids overflows when the
-		 * requests get passed through 32-bit arguments. */
-		int64_t skip_limit = (int64_t)1 << 30;
-		int64_t total = 0;
-		for (;;) {
-			int64_t get, ask = request;
-			if (ask > skip_limit)
-				ask = skip_limit;
-			get = (self->archive->client.skipper)
-				(&self->archive->archive, self->data, ask);
-			total += get;
-			if (get == 0 || get == request)
-				return (total);
-			if (get > request)
-				return ARCHIVE_FATAL;
-			request -= get;
-		}
-	} else if (self->archive->client.seeker != NULL
-		&& request > 64 * 1024) {
-		/* If the client provided a seeker but not a skipper,
-		 * we can use the seeker to skip forward.
-		 *
-		 * Note: This isn't always a good idea.  The client
-		 * skipper is allowed to skip by less than requested
-		 * if it needs to maintain block alignment.  The
-		 * seeker is not allowed to play such games, so using
-		 * the seeker here may be a performance loss compared
-		 * to just reading and discarding.  That's why we
-		 * only do this for skips of over 64k.
-		 */
-		int64_t before = self->position;
-		int64_t after = (self->archive->client.seeker)
-		    (&self->archive->archive, self->data, request, SEEK_CUR);
-		if (after != before + request)
-			return ARCHIVE_FATAL;
-		return after - before;
-	}
-	return 0;
-}
-
-static int64_t
-client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
-{
-	/* DO NOT use the skipper here!  If we transparently handled
-	 * forward seek here by using the skipper, that will break
-	 * other libarchive code that assumes a successful forward
-	 * seek means it can also seek backwards.
-	 */
-	if (self->archive->client.seeker == NULL) {
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Current client reader does not support seeking a device");
-		return (ARCHIVE_FAILED);
-	}
-	return (self->archive->client.seeker)(&self->archive->archive,
-	    self->data, offset, whence);
-}
-
-static int
-read_client_close_proxy(struct archive_read *a)
-{
-	int r = ARCHIVE_OK, r2;
-	unsigned int i;
-
-	if (a->client.closer == NULL)
-		return (r);
-	for (i = 0; i < a->client.nodes; i++)
-	{
-		r2 = (a->client.closer)
-			((struct archive *)a, a->client.dataset[i].data);
-		if (r > r2)
-			r = r2;
-	}
-	return (r);
-}
-
-static int
-client_close_proxy(struct archive_read_filter *self)
-{
-	return read_client_close_proxy(self->archive);
-}
-
-static int
-client_open_proxy(struct archive_read_filter *self)
-{
-  int r = ARCHIVE_OK;
-	if (self->archive->client.opener != NULL)
-		r = (self->archive->client.opener)(
-		    (struct archive *)self->archive, self->data);
-	return (r);
-}
-
-static int
-client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
-{
-  int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
-	void *data2 = NULL;
-
-	/* Don't do anything if already in the specified data node */
-	if (self->archive->client.cursor == iindex)
-		return (ARCHIVE_OK);
-
-	self->archive->client.cursor = iindex;
-	data2 = self->archive->client.dataset[self->archive->client.cursor].data;
-	if (self->archive->client.switcher != NULL)
-	{
-		r1 = r2 = (self->archive->client.switcher)
-			((struct archive *)self->archive, self->data, data2);
-		self->data = data2;
-	}
-	else
-	{
-		/* Attempt to call close and open instead */
-		if (self->archive->client.closer != NULL)
-			r1 = (self->archive->client.closer)
-				((struct archive *)self->archive, self->data);
-		self->data = data2;
-		r2 = client_open_proxy(self);
-	}
-	return (r1 < r2) ? r1 : r2;
-}
-
-int
-archive_read_set_open_callback(struct archive *_a,
-    archive_open_callback *client_opener)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_open_callback");
-	a->client.opener = client_opener;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_read_callback(struct archive *_a,
-    archive_read_callback *client_reader)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_read_callback");
-	a->client.reader = client_reader;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_skip_callback(struct archive *_a,
-    archive_skip_callback *client_skipper)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_skip_callback");
-	a->client.skipper = client_skipper;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_seek_callback(struct archive *_a,
-    archive_seek_callback *client_seeker)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_seek_callback");
-	a->client.seeker = client_seeker;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_close_callback(struct archive *_a,
-    archive_close_callback *client_closer)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_close_callback");
-	a->client.closer = client_closer;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_switch_callback(struct archive *_a,
-    archive_switch_callback *client_switcher)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_switch_callback");
-	a->client.switcher = client_switcher;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_set_callback_data(struct archive *_a, void *client_data)
-{
-	return archive_read_set_callback_data2(_a, client_data, 0);
-}
-
-int
-archive_read_set_callback_data2(struct archive *_a, void *client_data,
-    unsigned int iindex)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_set_callback_data2");
-
-	if (a->client.nodes == 0)
-	{
-		a->client.dataset = (struct archive_read_data_node *)
-		    calloc(1, sizeof(*a->client.dataset));
-		if (a->client.dataset == NULL)
-		{
-			archive_set_error(&a->archive, ENOMEM,
-				"No memory.");
-			return ARCHIVE_FATAL;
-		}
-		a->client.nodes = 1;
-	}
-
-	if (iindex > a->client.nodes - 1)
-	{
-		archive_set_error(&a->archive, EINVAL,
-			"Invalid index specified.");
-		return ARCHIVE_FATAL;
-	}
-	a->client.dataset[iindex].data = client_data;
-	a->client.dataset[iindex].begin_position = -1;
-	a->client.dataset[iindex].total_size = -1;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_add_callback_data(struct archive *_a, void *client_data,
-    unsigned int iindex)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	void *p;
-	unsigned int i;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_add_callback_data");
-	if (iindex > a->client.nodes) {
-		archive_set_error(&a->archive, EINVAL,
-			"Invalid index specified.");
-		return ARCHIVE_FATAL;
-	}
-	p = realloc(a->client.dataset, sizeof(*a->client.dataset)
-		* (++(a->client.nodes)));
-	if (p == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-			"No memory.");
-		return ARCHIVE_FATAL;
-	}
-	a->client.dataset = (struct archive_read_data_node *)p;
-	for (i = a->client.nodes - 1; i > iindex; i--) {
-		a->client.dataset[i].data = a->client.dataset[i-1].data;
-		a->client.dataset[i].begin_position = -1;
-		a->client.dataset[i].total_size = -1;
-	}
-	a->client.dataset[iindex].data = client_data;
-	a->client.dataset[iindex].begin_position = -1;
-	a->client.dataset[iindex].total_size = -1;
-	return ARCHIVE_OK;
-}
-
-int
-archive_read_append_callback_data(struct archive *_a, void *client_data)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	return archive_read_add_callback_data(_a, client_data, a->client.nodes);
-}
-
-int
-archive_read_prepend_callback_data(struct archive *_a, void *client_data)
-{
-	return archive_read_add_callback_data(_a, client_data, 0);
-}
-
-static const struct archive_read_filter_vtable
-none_reader_vtable = {
-	.read = client_read_proxy,
-	.close = client_close_proxy,
-};
-
-int
-archive_read_open1(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_filter *filter, *tmp;
-	int slot, e = ARCHIVE_OK;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_open");
-	archive_clear_error(&a->archive);
-
-	if (a->client.reader == NULL) {
-		archive_set_error(&a->archive, EINVAL,
-		    "No reader function provided to archive_read_open");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Open data source. */
-	if (a->client.opener != NULL) {
-		e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
-		if (e != 0) {
-			/* If the open failed, call the closer to clean up. */
-			read_client_close_proxy(a);
-			return (e);
-		}
-	}
-
-	filter = calloc(1, sizeof(*filter));
-	if (filter == NULL)
-		return (ARCHIVE_FATAL);
-	filter->bidder = NULL;
-	filter->upstream = NULL;
-	filter->archive = a;
-	filter->data = a->client.dataset[0].data;
-	filter->vtable = &none_reader_vtable;
-	filter->name = "none";
-	filter->code = ARCHIVE_FILTER_NONE;
-	filter->can_skip = 1;
-	filter->can_seek = 1;
-
-	a->client.dataset[0].begin_position = 0;
-	if (!a->filter || !a->bypass_filter_bidding)
-	{
-		a->filter = filter;
-		/* Build out the input pipeline. */
-		e = choose_filters(a);
-		if (e < ARCHIVE_WARN) {
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	}
-	else
-	{
-		/* Need to add "NONE" type filter at the end of the filter chain */
-		tmp = a->filter;
-		while (tmp->upstream)
-			tmp = tmp->upstream;
-		tmp->upstream = filter;
-	}
-
-	if (!a->format)
-	{
-		slot = choose_format(a);
-		if (slot < 0) {
-			close_filters(a);
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-		a->format = &(a->formats[slot]);
-	}
-
-	a->archive.state = ARCHIVE_STATE_HEADER;
-
-	/* Ensure libarchive starts from the first node in a multivolume set */
-	client_switch_proxy(a->filter, 0);
-	return (e);
-}
-
-/*
- * Allow each registered stream transform to bid on whether
- * it wants to handle this stream.  Repeat until we've finished
- * building the pipeline.
- */
-
-/* We won't build a filter pipeline with more stages than this. */
-#define MAX_NUMBER_FILTERS 25
-
-static int
-choose_filters(struct archive_read *a)
-{
-	int number_bidders, i, bid, best_bid, number_filters;
-	struct archive_read_filter_bidder *bidder, *best_bidder;
-	struct archive_read_filter *filter;
-	ssize_t avail;
-	int r;
-
-	for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
-		number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-		best_bid = 0;
-		best_bidder = NULL;
-
-		bidder = a->bidders;
-		for (i = 0; i < number_bidders; i++, bidder++) {
-			if (bidder->vtable == NULL)
-				continue;
-			bid = (bidder->vtable->bid)(bidder, a->filter);
-			if (bid > best_bid) {
-				best_bid = bid;
-				best_bidder = bidder;
-			}
-		}
-
-		/* If no bidder, we're done. */
-		if (best_bidder == NULL) {
-			/* Verify the filter by asking it for some data. */
-			__archive_read_filter_ahead(a->filter, 1, &avail);
-			if (avail < 0) {
-				__archive_read_free_filters(a);
-				return (ARCHIVE_FATAL);
-			}
-			return (ARCHIVE_OK);
-		}
-
-		filter
-		    = (struct archive_read_filter *)calloc(1, sizeof(*filter));
-		if (filter == NULL)
-			return (ARCHIVE_FATAL);
-		filter->bidder = best_bidder;
-		filter->archive = a;
-		filter->upstream = a->filter;
-		a->filter = filter;
-		r = (best_bidder->vtable->init)(a->filter);
-		if (r != ARCHIVE_OK) {
-			__archive_read_free_filters(a);
-			return (ARCHIVE_FATAL);
-		}
-	}
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Input requires too many filters for decoding");
-	return (ARCHIVE_FATAL);
-}
-
-int
-__archive_read_header(struct archive_read *a, struct archive_entry *entry)
-{
-	if (!a->filter->vtable->read_header)
-		return (ARCHIVE_OK);
-	return a->filter->vtable->read_header(a->filter, entry);
-}
-
-/*
- * Read header of next entry.
- */
-static int
-_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int r1 = ARCHIVE_OK, r2;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_next_header");
-
-	archive_entry_clear(entry);
-	archive_clear_error(&a->archive);
-
-	/*
-	 * If client didn't consume entire data, skip any remainder
-	 * (This is especially important for GNU incremental directories.)
-	 */
-	if (a->archive.state == ARCHIVE_STATE_DATA) {
-		r1 = archive_read_data_skip(&a->archive);
-		if (r1 == ARCHIVE_EOF)
-			archive_set_error(&a->archive, EIO,
-			    "Premature end-of-file.");
-		if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) {
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	/* Record start-of-header offset in uncompressed stream. */
-	a->header_position = a->filter->position;
-
-	++_a->file_count;
-	r2 = (a->format->read_header)(a, entry);
-
-	/*
-	 * EOF and FATAL are persistent at this layer.  By
-	 * modifying the state, we guarantee that future calls to
-	 * read a header or read data will fail.
-	 */
-	switch (r2) {
-	case ARCHIVE_EOF:
-		a->archive.state = ARCHIVE_STATE_EOF;
-		--_a->file_count;/* Revert a file counter. */
-		break;
-	case ARCHIVE_OK:
-		a->archive.state = ARCHIVE_STATE_DATA;
-		break;
-	case ARCHIVE_WARN:
-		a->archive.state = ARCHIVE_STATE_DATA;
-		break;
-	case ARCHIVE_RETRY:
-		break;
-	case ARCHIVE_FATAL:
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		break;
-	}
-
-	__archive_reset_read_data(&a->archive);
-
-	a->data_start_node = a->client.cursor;
-	/* EOF always wins; otherwise return the worst error. */
-	return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
-}
-
-static int
-_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
-{
-	int ret;
-	struct archive_read *a = (struct archive_read *)_a;
-	*entryp = NULL;
-	ret = _archive_read_next_header2(_a, a->entry);
-	*entryp = a->entry;
-	return ret;
-}
-
-/*
- * Allow each registered format to bid on whether it wants to handle
- * the next entry.  Return index of winning bidder.
- */
-static int
-choose_format(struct archive_read *a)
-{
-	int slots;
-	int i;
-	int bid, best_bid;
-	int best_bid_slot;
-
-	slots = sizeof(a->formats) / sizeof(a->formats[0]);
-	best_bid = -1;
-	best_bid_slot = -1;
-
-	/* Set up a->format for convenience of bidders. */
-	a->format = &(a->formats[0]);
-	for (i = 0; i < slots; i++, a->format++) {
-		if (a->format->bid) {
-			bid = (a->format->bid)(a, best_bid);
-			if (bid == ARCHIVE_FATAL)
-				return (ARCHIVE_FATAL);
-			if (a->filter->position != 0)
-				__archive_read_seek(a, 0, SEEK_SET);
-			if ((bid > best_bid) || (best_bid_slot < 0)) {
-				best_bid = bid;
-				best_bid_slot = i;
-			}
-		}
-	}
-
-	/*
-	 * There were no bidders; this is a serious programmer error
-	 * and demands a quick and definitive abort.
-	 */
-	if (best_bid_slot < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "No formats registered");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * There were bidders, but no non-zero bids; this means we
-	 * can't support this stream.
-	 */
-	if (best_bid < 1) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unrecognized archive format");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (best_bid_slot);
-}
-
-/*
- * Return the file offset (within the uncompressed data stream) where
- * the last header started.
- */
-la_int64_t
-archive_read_header_position(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_header_position");
-	return (a->header_position);
-}
-
-/*
- * Returns 1 if the archive contains at least one encrypted entry.
- * If the archive format not support encryption at all
- * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
- * If for any other reason (e.g. not enough data read so far)
- * we cannot say whether there are encrypted entries, then
- * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
- * In general, this function will return values below zero when the
- * reader is uncertain or totally incapable of encryption support.
- * When this function returns 0 you can be sure that the reader
- * supports encryption detection but no encrypted entries have
- * been found yet.
- *
- * NOTE: If the metadata/header of an archive is also encrypted, you
- * cannot rely on the number of encrypted entries. That is why this
- * function does not return the number of encrypted entries but#
- * just shows that there are some.
- */
-int
-archive_read_has_encrypted_entries(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int format_supports_encryption = archive_read_format_capabilities(_a)
-			& (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
-
-	if (!_a || !format_supports_encryption) {
-		/* Format in general doesn't support encryption */
-		return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
-	}
-
-	/* A reader potentially has read enough data now. */
-	if (a->format && a->format->has_encrypted_entries) {
-		return (a->format->has_encrypted_entries)(a);
-	}
-
-	/* For any other reason we cannot say how many entries are there. */
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-}
-
-/*
- * Returns a bitmask of capabilities that are supported by the archive format reader.
- * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
- */
-int
-archive_read_format_capabilities(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	if (a && a->format && a->format->format_capabilties) {
-		return (a->format->format_capabilties)(a);
-	}
-	return ARCHIVE_READ_FORMAT_CAPS_NONE;
-}
-
-/*
- * Read data from an archive entry, using a read(2)-style interface.
- * This is a convenience routine that just calls
- * archive_read_data_block and copies the results into the client
- * buffer, filling any gaps with zero bytes.  Clients using this
- * API can be completely ignorant of sparse-file issues; sparse files
- * will simply be padded with nulls.
- *
- * DO NOT intermingle calls to this function and archive_read_data_block
- * to read a single entry body.
- */
-la_ssize_t
-archive_read_data(struct archive *_a, void *buff, size_t s)
-{
-	struct archive *a = (struct archive *)_a;
-	char	*dest;
-	const void *read_buf;
-	size_t	 bytes_read;
-	size_t	 len;
-	int	 r;
-
-	bytes_read = 0;
-	dest = (char *)buff;
-
-	while (s > 0) {
-		if (a->read_data_offset == a->read_data_output_offset &&
-		    a->read_data_remaining == 0) {
-			read_buf = a->read_data_block;
-			a->read_data_is_posix_read = 1;
-			a->read_data_requested = s;
-			r = archive_read_data_block(a, &read_buf,
-			    &a->read_data_remaining, &a->read_data_offset);
-			a->read_data_block = read_buf;
-			if (r == ARCHIVE_EOF)
-				return (bytes_read);
-			/*
-			 * Error codes are all negative, so the status
-			 * return here cannot be confused with a valid
-			 * byte count.  (ARCHIVE_OK is zero.)
-			 */
-			if (r < ARCHIVE_OK)
-				return (r);
-		}
-
-		if (a->read_data_offset < a->read_data_output_offset) {
-			archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Encountered out-of-order sparse blocks");
-			return (ARCHIVE_RETRY);
-		}
-
-		/* Compute the amount of zero padding needed. */
-		if (a->read_data_output_offset + (int64_t)s <
-		    a->read_data_offset) {
-			len = s;
-		} else if (a->read_data_output_offset <
-		    a->read_data_offset) {
-			len = (size_t)(a->read_data_offset -
-			    a->read_data_output_offset);
-		} else
-			len = 0;
-
-		/* Add zeroes. */
-		memset(dest, 0, len);
-		s -= len;
-		a->read_data_output_offset += len;
-		dest += len;
-		bytes_read += len;
-
-		/* Copy data if there is any space left. */
-		if (s > 0) {
-			len = a->read_data_remaining;
-			if (len > s)
-				len = s;
-			if (len) {
-				memcpy(dest, a->read_data_block, len);
-				s -= len;
-				a->read_data_block += len;
-				a->read_data_remaining -= len;
-				a->read_data_output_offset += len;
-				a->read_data_offset += len;
-				dest += len;
-				bytes_read += len;
-			}
-		}
-	}
-	a->read_data_is_posix_read = 0;
-	a->read_data_requested = 0;
-	return (bytes_read);
-}
-
-/*
- * Reset the read_data_* variables, used for starting a new entry.
- */
-void __archive_reset_read_data(struct archive * a)
-{
-	a->read_data_output_offset = 0;
-	a->read_data_remaining = 0;
-	a->read_data_is_posix_read = 0;
-	a->read_data_requested = 0;
-
-   /* extra resets, from rar.c */
-   a->read_data_block = NULL;
-   a->read_data_offset = 0;
-}
-
-/*
- * Skip over all remaining data in this entry.
- */
-int
-archive_read_data_skip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int r;
-	const void *buff;
-	size_t size;
-	int64_t offset;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_data_skip");
-
-	if (a->format->read_data_skip != NULL)
-		r = (a->format->read_data_skip)(a);
-	else {
-		while ((r = archive_read_data_block(&a->archive,
-			    &buff, &size, &offset))
-		    == ARCHIVE_OK)
-			;
-	}
-
-	if (r == ARCHIVE_EOF)
-		r = ARCHIVE_OK;
-
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	return (r);
-}
-
-la_int64_t
-archive_seek_data(struct archive *_a, int64_t offset, int whence)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_seek_data_block");
-
-	if (a->format->seek_data == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Internal error: "
-		    "No format_seek_data_block function registered");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (a->format->seek_data)(a, offset, whence);
-}
-
-/*
- * Read the next block of entry data from the archive.
- * This is a zero-copy interface; the client receives a pointer,
- * size, and file offset of the next available block of data.
- *
- * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if
- * the end of entry is encountered.
- */
-static int
-_archive_read_data_block(struct archive *_a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_data_block");
-
-	if (a->format->read_data == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Internal error: "
-		    "No format->read_data function registered");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (a->format->read_data)(a, buff, size, offset);
-}
-
-static int
-close_filters(struct archive_read *a)
-{
-	struct archive_read_filter *f = a->filter;
-	int r = ARCHIVE_OK;
-	/* Close each filter in the pipeline. */
-	while (f != NULL) {
-		struct archive_read_filter *t = f->upstream;
-		if (!f->closed && f->vtable != NULL) {
-			int r1 = (f->vtable->close)(f);
-			f->closed = 1;
-			if (r1 < r)
-				r = r1;
-		}
-		free(f->buffer);
-		f->buffer = NULL;
-		f = t;
-	}
-	return r;
-}
-
-void
-__archive_read_free_filters(struct archive_read *a)
-{
-	/* Make sure filters are closed and their buffers are freed */
-	close_filters(a);
-
-	while (a->filter != NULL) {
-		struct archive_read_filter *t = a->filter->upstream;
-		free(a->filter);
-		a->filter = t;
-	}
-}
-
-/*
- * return the count of # of filters in use
- */
-static int
-_archive_filter_count(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_filter *p = a->filter;
-	int count = 0;
-	while(p) {
-		count++;
-		p = p->upstream;
-	}
-	return count;
-}
-
-/*
- * Close the file and all I/O.
- */
-static int
-_archive_read_close(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
-
-	archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
-	if (a->archive.state == ARCHIVE_STATE_CLOSED)
-		return (ARCHIVE_OK);
-	archive_clear_error(&a->archive);
-	a->archive.state = ARCHIVE_STATE_CLOSED;
-
-	/* TODO: Clean up the formatters. */
-
-	/* Release the filter objects. */
-	r1 = close_filters(a);
-	if (r1 < r)
-		r = r1;
-
-	return (r);
-}
-
-/*
- * Release memory and other resources.
- */
-static int
-_archive_read_free(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_passphrase *p;
-	int i, n;
-	int slots;
-	int r = ARCHIVE_OK;
-
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
-	if (a->archive.state != ARCHIVE_STATE_CLOSED
-	    && a->archive.state != ARCHIVE_STATE_FATAL)
-		r = archive_read_close(&a->archive);
-
-	/* Call cleanup functions registered by optional components. */
-	if (a->cleanup_archive_extract != NULL)
-		r = (a->cleanup_archive_extract)(a);
-
-	/* Cleanup format-specific data. */
-	slots = sizeof(a->formats) / sizeof(a->formats[0]);
-	for (i = 0; i < slots; i++) {
-		a->format = &(a->formats[i]);
-		if (a->formats[i].cleanup)
-			(a->formats[i].cleanup)(a);
-	}
-
-	/* Free the filters */
-	__archive_read_free_filters(a);
-
-	/* Release the bidder objects. */
-	n = sizeof(a->bidders)/sizeof(a->bidders[0]);
-	for (i = 0; i < n; i++) {
-		if (a->bidders[i].vtable == NULL ||
-		    a->bidders[i].vtable->free == NULL)
-			continue;
-		(a->bidders[i].vtable->free)(&a->bidders[i]);
-	}
-
-	/* Release passphrase list. */
-	p = a->passphrases.first;
-	while (p != NULL) {
-		struct archive_read_passphrase *np = p->next;
-
-		/* A passphrase should be cleaned. */
-		memset(p->passphrase, 0, strlen(p->passphrase));
-		free(p->passphrase);
-		free(p);
-		p = np;
-	}
-
-	archive_string_free(&a->archive.error_string);
-	archive_entry_free(a->entry);
-	a->archive.magic = 0;
-	__archive_clean(&a->archive);
-	free(a->client.dataset);
-	free(a);
-	return (r);
-}
-
-static struct archive_read_filter *
-get_filter(struct archive *_a, int n)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_filter *f = a->filter;
-	/* We use n == -1 for 'the last filter', which is always the
-	 * client proxy. */
-	if (n == -1 && f != NULL) {
-		struct archive_read_filter *last = f;
-		f = f->upstream;
-		while (f != NULL) {
-			last = f;
-			f = f->upstream;
-		}
-		return (last);
-	}
-	if (n < 0)
-		return NULL;
-	while (n > 0 && f != NULL) {
-		f = f->upstream;
-		--n;
-	}
-	return (f);
-}
-
-static int
-_archive_filter_code(struct archive *_a, int n)
-{
-	struct archive_read_filter *f = get_filter(_a, n);
-	return f == NULL ? -1 : f->code;
-}
-
-static const char *
-_archive_filter_name(struct archive *_a, int n)
-{
-	struct archive_read_filter *f = get_filter(_a, n);
-	return f != NULL ? f->name : NULL;
-}
-
-static int64_t
-_archive_filter_bytes(struct archive *_a, int n)
-{
-	struct archive_read_filter *f = get_filter(_a, n);
-	return f == NULL ? -1 : f->position;
-}
-
-/*
- * Used internally by read format handlers to register their bid and
- * initialization functions.
- */
-int
-__archive_read_register_format(struct archive_read *a,
-    void *format_data,
-    const char *name,
-    int (*bid)(struct archive_read *, int),
-    int (*options)(struct archive_read *, const char *, const char *),
-    int (*read_header)(struct archive_read *, struct archive_entry *),
-    int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
-    int (*read_data_skip)(struct archive_read *),
-    int64_t (*seek_data)(struct archive_read *, int64_t, int),
-    int (*cleanup)(struct archive_read *),
-    int (*format_capabilities)(struct archive_read *),
-    int (*has_encrypted_entries)(struct archive_read *))
-{
-	int i, number_slots;
-
-	archive_check_magic(&a->archive,
-	    ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "__archive_read_register_format");
-
-	number_slots = sizeof(a->formats) / sizeof(a->formats[0]);
-
-	for (i = 0; i < number_slots; i++) {
-		if (a->formats[i].bid == bid)
-			return (ARCHIVE_WARN); /* We've already installed */
-		if (a->formats[i].bid == NULL) {
-			a->formats[i].bid = bid;
-			a->formats[i].options = options;
-			a->formats[i].read_header = read_header;
-			a->formats[i].read_data = read_data;
-			a->formats[i].read_data_skip = read_data_skip;
-			a->formats[i].seek_data = seek_data;
-			a->formats[i].cleanup = cleanup;
-			a->formats[i].data = format_data;
-			a->formats[i].name = name;
-			a->formats[i].format_capabilties = format_capabilities;
-			a->formats[i].has_encrypted_entries = has_encrypted_entries;
-			return (ARCHIVE_OK);
-		}
-	}
-
-	archive_set_error(&a->archive, ENOMEM,
-	    "Not enough slots for format registration");
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Used internally by decompression routines to register their bid and
- * initialization functions.
- */
-int
-__archive_read_register_bidder(struct archive_read *a,
-	void *bidder_data,
-	const char *name,
-	const struct archive_read_filter_bidder_vtable *vtable)
-{
-	struct archive_read_filter_bidder *bidder;
-	int i, number_slots;
-
-	archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "__archive_read_register_bidder");
-
-	number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-	for (i = 0; i < number_slots; i++) {
-		if (a->bidders[i].vtable != NULL)
-			continue;
-		memset(a->bidders + i, 0, sizeof(a->bidders[0]));
-		bidder = (a->bidders + i);
-		bidder->data = bidder_data;
-		bidder->name = name;
-		bidder->vtable = vtable;
-		if (bidder->vtable->bid == NULL || bidder->vtable->init == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-					"Internal error: "
-					"no bid/init for filter bidder");
-			return (ARCHIVE_FATAL);
-		}
-
-		return (ARCHIVE_OK);
-	}
-
-	archive_set_error(&a->archive, ENOMEM,
-	    "Not enough slots for filter registration");
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * The next section implements the peek/consume internal I/O
- * system used by archive readers.  This system allows simple
- * read-ahead for consumers while preserving zero-copy operation
- * most of the time.
- *
- * The two key operations:
- *  * The read-ahead function returns a pointer to a block of data
- *    that satisfies a minimum request.
- *  * The consume function advances the file pointer.
- *
- * In the ideal case, filters generate blocks of data
- * and __archive_read_ahead() just returns pointers directly into
- * those blocks.  Then __archive_read_consume() just bumps those
- * pointers.  Only if your request would span blocks does the I/O
- * layer use a copy buffer to provide you with a contiguous block of
- * data.
- *
- * A couple of useful idioms:
- *  * "I just want some data."  Ask for 1 byte and pay attention to
- *    the "number of bytes available" from __archive_read_ahead().
- *    Consume whatever you actually use.
- *  * "I want to output a large block of data."  As above, ask for 1 byte,
- *    emit all that's available (up to whatever limit you have), consume
- *    it all, then repeat until you're done.  This effectively means that
- *    you're passing along the blocks that came from your provider.
- *  * "I want to peek ahead by a large amount."  Ask for 4k or so, then
- *    double and repeat until you get an error or have enough.  Note
- *    that the I/O layer will likely end up expanding its copy buffer
- *    to fit your request, so use this technique cautiously.  This
- *    technique is used, for example, by some of the format tasting
- *    code that has uncertain look-ahead needs.
- */
-
-/*
- * Looks ahead in the input stream:
- *  * If 'avail' pointer is provided, that returns number of bytes available
- *    in the current buffer, which may be much larger than requested.
- *  * If end-of-file, *avail gets set to zero.
- *  * If error, *avail gets error code.
- *  * If request can be met, returns pointer to data.
- *  * If minimum request cannot be met, returns NULL.
- *
- * Note: If you just want "some data", ask for 1 byte and pay attention
- * to *avail, which will have the actual amount available.  If you
- * know exactly how many bytes you need, just ask for that and treat
- * a NULL return as an error.
- *
- * Important:  This does NOT move the file pointer.  See
- * __archive_read_consume() below.
- */
-const void *
-__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
-{
-	return (__archive_read_filter_ahead(a->filter, min, avail));
-}
-
-const void *
-__archive_read_filter_ahead(struct archive_read_filter *filter,
-    size_t min, ssize_t *avail)
-{
-	ssize_t bytes_read;
-	size_t tocopy;
-
-	if (filter->fatal) {
-		if (avail)
-			*avail = ARCHIVE_FATAL;
-		return (NULL);
-	}
-
-	/*
-	 * Keep pulling more data until we can satisfy the request.
-	 */
-	for (;;) {
-
-		/*
-		 * If we can satisfy from the copy buffer (and the
-		 * copy buffer isn't empty), we're done.  In particular,
-		 * note that min == 0 is a perfectly well-defined
-		 * request.
-		 */
-		if (filter->avail >= min && filter->avail > 0) {
-			if (avail != NULL)
-				*avail = filter->avail;
-			return (filter->next);
-		}
-
-		/*
-		 * We can satisfy directly from client buffer if everything
-		 * currently in the copy buffer is still in the client buffer.
-		 */
-		if (filter->client_total >= filter->client_avail + filter->avail
-		    && filter->client_avail + filter->avail >= min) {
-			/* "Roll back" to client buffer. */
-			filter->client_avail += filter->avail;
-			filter->client_next -= filter->avail;
-			/* Copy buffer is now empty. */
-			filter->avail = 0;
-			filter->next = filter->buffer;
-			/* Return data from client buffer. */
-			if (avail != NULL)
-				*avail = filter->client_avail;
-			return (filter->client_next);
-		}
-
-		/* Move data forward in copy buffer if necessary. */
-		if (filter->next > filter->buffer &&
-		    filter->next + min > filter->buffer + filter->buffer_size) {
-			if (filter->avail > 0)
-				memmove(filter->buffer, filter->next,
-				    filter->avail);
-			filter->next = filter->buffer;
-		}
-
-		/* If we've used up the client data, get more. */
-		if (filter->client_avail <= 0) {
-			if (filter->end_of_file) {
-				if (avail != NULL)
-					*avail = 0;
-				return (NULL);
-			}
-			bytes_read = (filter->vtable->read)(filter,
-			    &filter->client_buff);
-			if (bytes_read < 0) {		/* Read error. */
-				filter->client_total = filter->client_avail = 0;
-				filter->client_next =
-				    filter->client_buff = NULL;
-				filter->fatal = 1;
-				if (avail != NULL)
-					*avail = ARCHIVE_FATAL;
-				return (NULL);
-			}
-			if (bytes_read == 0) {
-				/* Check for another client object first */
-				if (filter->archive->client.cursor !=
-				      filter->archive->client.nodes - 1) {
-					if (client_switch_proxy(filter,
-					    filter->archive->client.cursor + 1)
-					    == ARCHIVE_OK)
-						continue;
-				}
-				/* Premature end-of-file. */
-				filter->client_total = filter->client_avail = 0;
-				filter->client_next =
-				    filter->client_buff = NULL;
-				filter->end_of_file = 1;
-				/* Return whatever we do have. */
-				if (avail != NULL)
-					*avail = filter->avail;
-				return (NULL);
-			}
-			filter->client_total = bytes_read;
-			filter->client_avail = filter->client_total;
-			filter->client_next = filter->client_buff;
-		} else {
-			/*
-			 * We can't satisfy the request from the copy
-			 * buffer or the existing client data, so we
-			 * need to copy more client data over to the
-			 * copy buffer.
-			 */
-
-			/* Ensure the buffer is big enough. */
-			if (min > filter->buffer_size) {
-				size_t s, t;
-				char *p;
-
-				/* Double the buffer; watch for overflow. */
-				s = t = filter->buffer_size;
-				if (s == 0)
-					s = min;
-				while (s < min) {
-					t *= 2;
-					if (t <= s) { /* Integer overflow! */
-						archive_set_error(
-						    &filter->archive->archive,
-						    ENOMEM,
-						    "Unable to allocate copy"
-						    " buffer");
-						filter->fatal = 1;
-						if (avail != NULL)
-							*avail = ARCHIVE_FATAL;
-						return (NULL);
-					}
-					s = t;
-				}
-				/* Now s >= min, so allocate a new buffer. */
-				p = (char *)malloc(s);
-				if (p == NULL) {
-					archive_set_error(
-						&filter->archive->archive,
-						ENOMEM,
-					    "Unable to allocate copy buffer");
-					filter->fatal = 1;
-					if (avail != NULL)
-						*avail = ARCHIVE_FATAL;
-					return (NULL);
-				}
-				/* Move data into newly-enlarged buffer. */
-				if (filter->avail > 0)
-					memmove(p, filter->next, filter->avail);
-				free(filter->buffer);
-				filter->next = filter->buffer = p;
-				filter->buffer_size = s;
-			}
-
-			/* We can add client data to copy buffer. */
-			/* First estimate: copy to fill rest of buffer. */
-			tocopy = (filter->buffer + filter->buffer_size)
-			    - (filter->next + filter->avail);
-			/* Don't waste time buffering more than we need to. */
-			if (tocopy + filter->avail > min)
-				tocopy = min - filter->avail;
-			/* Don't copy more than is available. */
-			if (tocopy > filter->client_avail)
-				tocopy = filter->client_avail;
-
-			memcpy(filter->next + filter->avail,
-			    filter->client_next, tocopy);
-			/* Remove this data from client buffer. */
-			filter->client_next += tocopy;
-			filter->client_avail -= tocopy;
-			/* add it to copy buffer. */
-			filter->avail += tocopy;
-		}
-	}
-}
-
-/*
- * Move the file pointer forward.
- */
-int64_t
-__archive_read_consume(struct archive_read *a, int64_t request)
-{
-	return (__archive_read_filter_consume(a->filter, request));
-}
-
-int64_t
-__archive_read_filter_consume(struct archive_read_filter * filter,
-    int64_t request)
-{
-	int64_t skipped;
-
-	if (request < 0)
-		return ARCHIVE_FATAL;
-	if (request == 0)
-		return 0;
-
-	skipped = advance_file_pointer(filter, request);
-	if (skipped == request)
-		return (skipped);
-	/* We hit EOF before we satisfied the skip request. */
-	if (skipped < 0)  /* Map error code to 0 for error message below. */
-		skipped = 0;
-	archive_set_error(&filter->archive->archive,
-	    ARCHIVE_ERRNO_MISC,
-	    "Truncated input file (needed %jd bytes, only %jd available)",
-	    (intmax_t)request, (intmax_t)skipped);
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Advance the file pointer by the amount requested.
- * Returns the amount actually advanced, which may be less than the
- * request if EOF is encountered first.
- * Returns a negative value if there's an I/O error.
- */
-static int64_t
-advance_file_pointer(struct archive_read_filter *filter, int64_t request)
-{
-	int64_t bytes_skipped, total_bytes_skipped = 0;
-	ssize_t bytes_read;
-	size_t min;
-
-	if (filter->fatal)
-		return (-1);
-
-	/* Use up the copy buffer first. */
-	if (filter->avail > 0) {
-		min = (size_t)minimum(request, (int64_t)filter->avail);
-		filter->next += min;
-		filter->avail -= min;
-		request -= min;
-		filter->position += min;
-		total_bytes_skipped += min;
-	}
-
-	/* Then use up the client buffer. */
-	if (filter->client_avail > 0) {
-		min = (size_t)minimum(request, (int64_t)filter->client_avail);
-		filter->client_next += min;
-		filter->client_avail -= min;
-		request -= min;
-		filter->position += min;
-		total_bytes_skipped += min;
-	}
-	if (request == 0)
-		return (total_bytes_skipped);
-
-	/* If there's an optimized skip function, use it. */
-	if (filter->can_skip != 0) {
-		bytes_skipped = client_skip_proxy(filter, request);
-		if (bytes_skipped < 0) {	/* error */
-			filter->fatal = 1;
-			return (bytes_skipped);
-		}
-		filter->position += bytes_skipped;
-		total_bytes_skipped += bytes_skipped;
-		request -= bytes_skipped;
-		if (request == 0)
-			return (total_bytes_skipped);
-	}
-
-	/* Use ordinary reads as necessary to complete the request. */
-	for (;;) {
-		bytes_read = (filter->vtable->read)(filter, &filter->client_buff);
-		if (bytes_read < 0) {
-			filter->client_buff = NULL;
-			filter->fatal = 1;
-			return (bytes_read);
-		}
-
-		if (bytes_read == 0) {
-			if (filter->archive->client.cursor !=
-			      filter->archive->client.nodes - 1) {
-				if (client_switch_proxy(filter,
-				    filter->archive->client.cursor + 1)
-				    == ARCHIVE_OK)
-					continue;
-			}
-			filter->client_buff = NULL;
-			filter->end_of_file = 1;
-			return (total_bytes_skipped);
-		}
-
-		if (bytes_read >= request) {
-			filter->client_next =
-			    ((const char *)filter->client_buff) + request;
-			filter->client_avail = (size_t)(bytes_read - request);
-			filter->client_total = bytes_read;
-			total_bytes_skipped += request;
-			filter->position += request;
-			return (total_bytes_skipped);
-		}
-
-		filter->position += bytes_read;
-		total_bytes_skipped += bytes_read;
-		request -= bytes_read;
-	}
-}
-
-/**
- * Returns ARCHIVE_FAILED if seeking isn't supported.
- */
-int64_t
-__archive_read_seek(struct archive_read *a, int64_t offset, int whence)
-{
-	return __archive_read_filter_seek(a->filter, offset, whence);
-}
-
-int64_t
-__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
-    int whence)
-{
-	struct archive_read_client *client;
-	int64_t r;
-	unsigned int cursor;
-
-	if (filter->closed || filter->fatal)
-		return (ARCHIVE_FATAL);
-	if (filter->can_seek == 0)
-		return (ARCHIVE_FAILED);
-
-	client = &(filter->archive->client);
-	switch (whence) {
-	case SEEK_CUR:
-		/* Adjust the offset and use SEEK_SET instead */
-		offset += filter->position;
-		__LA_FALLTHROUGH;
-	case SEEK_SET:
-		cursor = 0;
-		while (1)
-		{
-			if (client->dataset[cursor].begin_position < 0 ||
-			    client->dataset[cursor].total_size < 0 ||
-			    client->dataset[cursor].begin_position +
-			      client->dataset[cursor].total_size - 1 > offset ||
-			    cursor + 1 >= client->nodes)
-				break;
-			r = client->dataset[cursor].begin_position +
-				client->dataset[cursor].total_size;
-			client->dataset[++cursor].begin_position = r;
-		}
-		while (1) {
-			r = client_switch_proxy(filter, cursor);
-			if (r != ARCHIVE_OK)
-				return r;
-			if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
-				return r;
-			client->dataset[cursor].total_size = r;
-			if (client->dataset[cursor].begin_position +
-			    client->dataset[cursor].total_size - 1 > offset ||
-			    cursor + 1 >= client->nodes)
-				break;
-			r = client->dataset[cursor].begin_position +
-				client->dataset[cursor].total_size;
-			client->dataset[++cursor].begin_position = r;
-		}
-		offset -= client->dataset[cursor].begin_position;
-		if (offset < 0
-		    || offset > client->dataset[cursor].total_size)
-			return ARCHIVE_FATAL;
-		if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
-			return r;
-		break;
-
-	case SEEK_END:
-		cursor = 0;
-		while (1) {
-			if (client->dataset[cursor].begin_position < 0 ||
-			    client->dataset[cursor].total_size < 0 ||
-			    cursor + 1 >= client->nodes)
-				break;
-			r = client->dataset[cursor].begin_position +
-				client->dataset[cursor].total_size;
-			client->dataset[++cursor].begin_position = r;
-		}
-		while (1) {
-			r = client_switch_proxy(filter, cursor);
-			if (r != ARCHIVE_OK)
-				return r;
-			if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
-				return r;
-			client->dataset[cursor].total_size = r;
-			r = client->dataset[cursor].begin_position +
-				client->dataset[cursor].total_size;
-			if (cursor + 1 >= client->nodes)
-				break;
-			client->dataset[++cursor].begin_position = r;
-		}
-		while (1) {
-			if (r + offset >=
-			    client->dataset[cursor].begin_position)
-				break;
-			offset += client->dataset[cursor].total_size;
-			if (cursor == 0)
-				break;
-			cursor--;
-			r = client->dataset[cursor].begin_position +
-				client->dataset[cursor].total_size;
-		}
-		offset = (r + offset) - client->dataset[cursor].begin_position;
-		if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
-			return r;
-		r = client_seek_proxy(filter, offset, SEEK_SET);
-		if (r < ARCHIVE_OK)
-			return r;
-		break;
-
-	default:
-		return (ARCHIVE_FATAL);
-	}
-	r += client->dataset[cursor].begin_position;
-
-	if (r >= 0) {
-		/*
-		 * Ouch.  Clearing the buffer like this hurts, especially
-		 * at bid time.  A lot of our efficiency at bid time comes
-		 * from having bidders reuse the data we've already read.
-		 *
-		 * TODO: If the seek request is in data we already
-		 * have, then don't call the seek callback.
-		 *
-		 * TODO: Zip seeks to end-of-file at bid time.  If
-		 * other formats also start doing this, we may need to
-		 * find a way for clients to fudge the seek offset to
-		 * a block boundary.
-		 *
-		 * Hmmm... If whence was SEEK_END, we know the file
-		 * size is (r - offset).  Can we use that to simplify
-		 * the TODO items above?
-		 */
-		filter->avail = filter->client_avail = 0;
-		filter->next = filter->buffer;
-		filter->position = r;
-		filter->end_of_file = 0;
-	}
-	return r;
-}
diff --git a/c/archive_read_add_passphrase.c b/c/archive_read_add_passphrase.c
deleted file mode 100644
--- a/c/archive_read_add_passphrase.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "archive_read_private.h"
-
-static void
-add_passphrase_to_tail(struct archive_read *a,
-    struct archive_read_passphrase *p)
-{
-	*a->passphrases.last = p;
-	a->passphrases.last = &p->next;
-	p->next = NULL;
-}
-
-static struct archive_read_passphrase *
-remove_passphrases_from_head(struct archive_read *a)
-{
-	struct archive_read_passphrase *p;
-
-	p = a->passphrases.first;
-	if (p != NULL)
-		a->passphrases.first = p->next;
-	return (p);
-}
-
-static void
-insert_passphrase_to_head(struct archive_read *a,
-    struct archive_read_passphrase *p)
-{
-	p->next = a->passphrases.first;
-	a->passphrases.first = p;
-	if (&a->passphrases.first == a->passphrases.last) {
-		a->passphrases.last = &p->next;
-		p->next = NULL;
-	}
-}
-
-static struct archive_read_passphrase *
-new_read_passphrase(struct archive_read *a, const char *passphrase)
-{
-	struct archive_read_passphrase *p;
-
-	p = malloc(sizeof(*p));
-	if (p == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (NULL);
-	}
-	p->passphrase = strdup(passphrase);
-	if (p->passphrase == NULL) {
-		free(p);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (NULL);
-	}
-	return (p);
-}
-
-int
-archive_read_add_passphrase(struct archive *_a, const char *passphrase)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_passphrase *p;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-		"archive_read_add_passphrase");
-
-	if (passphrase == NULL || passphrase[0] == '\0') {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Empty passphrase is unacceptable");
-		return (ARCHIVE_FAILED);
-	}
-
-	p = new_read_passphrase(a, passphrase);
-	if (p == NULL)
-		return (ARCHIVE_FATAL);
-	add_passphrase_to_tail(a, p);
-
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_set_passphrase_callback(struct archive *_a, void *client_data,
-    archive_passphrase_callback *cb)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-		"archive_read_set_passphrase_callback");
-
-	a->passphrases.callback = cb;
-	a->passphrases.client_data = client_data;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Call this in advance when you start to get a passphrase for decryption
- * for a entry.
- */
-void
-__archive_read_reset_passphrase(struct archive_read *a)
-{
-
-	a->passphrases.candidate = -1;
-}
-
-/*
- * Get a passphrase for decryption.
- */
-const char *
-__archive_read_next_passphrase(struct archive_read *a)
-{
-	struct archive_read_passphrase *p;
-	const char *passphrase;
-
-	if (a->passphrases.candidate < 0) {
-		/* Count out how many passphrases we have. */
-		int cnt = 0;
-
-		for (p = a->passphrases.first; p != NULL; p = p->next)
-			cnt++;
-		a->passphrases.candidate = cnt;
-		p = a->passphrases.first;
-	} else if (a->passphrases.candidate > 1) {
-		/* Rotate a passphrase list. */
-		a->passphrases.candidate--;
-		p = remove_passphrases_from_head(a);
-		add_passphrase_to_tail(a, p);
-		/* Pick a new passphrase candidate up. */
-		p = a->passphrases.first;
-	} else if (a->passphrases.candidate == 1) {
-		/* This case is that all candidates failed to decrypt. */
-		a->passphrases.candidate = 0;
-		if (a->passphrases.first->next != NULL) {
-			/* Rotate a passphrase list. */
-			p = remove_passphrases_from_head(a);
-			add_passphrase_to_tail(a, p);
-		}
-		p = NULL;
-	} else  /* There is no passphrase candidate. */
-		p = NULL;
-
-	if (p != NULL)
-		passphrase = p->passphrase;
-	else if (a->passphrases.callback != NULL) {
-		/* Get a passphrase through a call-back function
-		 * since we tried all passphrases out or we don't
-		 * have it. */
-		passphrase = a->passphrases.callback(&a->archive,
-		    a->passphrases.client_data);
-		if (passphrase != NULL) {
-			p = new_read_passphrase(a, passphrase);
-			if (p == NULL)
-				return (NULL);
-			insert_passphrase_to_head(a, p);
-			a->passphrases.candidate = 1;
-		}
-	} else
-		passphrase = NULL;
-
-	return (passphrase);
-}
diff --git a/c/archive_read_append_filter.c b/c/archive_read_append_filter.c
deleted file mode 100644
--- a/c/archive_read_append_filter.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*-
- * Copyright (c) 2003-2012 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-int
-archive_read_append_filter(struct archive *_a, int code)
-{
-  int r1, r2, number_bidders, i;
-  char str[20];
-  struct archive_read_filter_bidder *bidder;
-  struct archive_read_filter *filter;
-  struct archive_read *a = (struct archive_read *)_a;
-
-  r2 = (ARCHIVE_OK);
-  switch (code)
-  {
-    case ARCHIVE_FILTER_NONE:
-      /* No filter to add, so do nothing.
-       * NOTE: An initial "NONE" type filter is always set at the end of the
-       * filter chain.
-       */
-      r1 = (ARCHIVE_OK);
-      break;
-    case ARCHIVE_FILTER_GZIP:
-      strcpy(str, "gzip");
-      r1 = archive_read_support_filter_gzip(_a);
-      break;
-    case ARCHIVE_FILTER_BZIP2:
-      strcpy(str, "bzip2");
-      r1 = archive_read_support_filter_bzip2(_a);
-      break;
-    case ARCHIVE_FILTER_COMPRESS:
-      strcpy(str, "compress (.Z)");
-      r1 = archive_read_support_filter_compress(_a);
-      break;
-    case ARCHIVE_FILTER_PROGRAM:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Cannot append program filter using archive_read_append_filter");
-      return (ARCHIVE_FATAL);
-    case ARCHIVE_FILTER_LZMA:
-      strcpy(str, "lzma");
-      r1 = archive_read_support_filter_lzma(_a);
-      break;
-    case ARCHIVE_FILTER_XZ:
-      strcpy(str, "xz");
-      r1 = archive_read_support_filter_xz(_a);
-      break;
-    case ARCHIVE_FILTER_UU:
-      strcpy(str, "uu");
-      r1 = archive_read_support_filter_uu(_a);
-      break;
-    case ARCHIVE_FILTER_RPM:
-      strcpy(str, "rpm");
-      r1 = archive_read_support_filter_rpm(_a);
-      break;
-    case ARCHIVE_FILTER_LZ4:
-      strcpy(str, "lz4");
-      r1 = archive_read_support_filter_lz4(_a);
-      break;
-    case ARCHIVE_FILTER_ZSTD:
-      strcpy(str, "zstd");
-      r1 = archive_read_support_filter_zstd(_a);
-      break;
-    case ARCHIVE_FILTER_LZIP:
-      strcpy(str, "lzip");
-      r1 = archive_read_support_filter_lzip(_a);
-      break;
-    case ARCHIVE_FILTER_LRZIP:
-      strcpy(str, "lrzip");
-      r1 = archive_read_support_filter_lrzip(_a);
-      break;
-    default:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Invalid filter code specified");
-      return (ARCHIVE_FATAL);
-  }
-
-  if (code != ARCHIVE_FILTER_NONE)
-  {
-    number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-    bidder = a->bidders;
-    for (i = 0; i < number_bidders; i++, bidder++)
-    {
-      if (!bidder->name || !strcmp(bidder->name, str))
-        break;
-    }
-    if (!bidder->name || strcmp(bidder->name, str))
-    {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Internal error: Unable to append filter");
-      return (ARCHIVE_FATAL);
-    }
-
-    filter
-        = (struct archive_read_filter *)calloc(1, sizeof(*filter));
-    if (filter == NULL)
-    {
-      archive_set_error(&a->archive, ENOMEM, "Out of memory");
-      return (ARCHIVE_FATAL);
-    }
-    filter->bidder = bidder;
-    filter->archive = a;
-    filter->upstream = a->filter;
-    a->filter = filter;
-    r2 = (bidder->vtable->init)(a->filter);
-    if (r2 != ARCHIVE_OK) {
-      __archive_read_free_filters(a);
-      return (ARCHIVE_FATAL);
-    }
-  }
-
-  a->bypass_filter_bidding = 1;
-  return (r1 < r2) ? r1 : r2;
-}
-
-int
-archive_read_append_filter_program(struct archive *_a, const char *cmd)
-{
-  return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
-}
-
-int
-archive_read_append_filter_program_signature(struct archive *_a,
-  const char *cmd, const void *signature, size_t signature_len)
-{
-  int r, number_bidders, i;
-  struct archive_read_filter_bidder *bidder;
-  struct archive_read_filter *filter;
-  struct archive_read *a = (struct archive_read *)_a;
-
-  if (archive_read_support_filter_program_signature(_a, cmd, signature,
-    signature_len) != (ARCHIVE_OK))
-    return (ARCHIVE_FATAL);
-
-  number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
-
-  bidder = a->bidders;
-  for (i = 0; i < number_bidders; i++, bidder++)
-  {
-    /* Program bidder name set to filter name after initialization */
-    if (bidder->data && !bidder->name)
-      break;
-  }
-  if (!bidder->data)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-        "Internal error: Unable to append program filter");
-    return (ARCHIVE_FATAL);
-  }
-
-  filter
-      = (struct archive_read_filter *)calloc(1, sizeof(*filter));
-  if (filter == NULL)
-  {
-    archive_set_error(&a->archive, ENOMEM, "Out of memory");
-    return (ARCHIVE_FATAL);
-  }
-  filter->bidder = bidder;
-  filter->archive = a;
-  filter->upstream = a->filter;
-  a->filter = filter;
-  r = (bidder->vtable->init)(a->filter);
-  if (r != ARCHIVE_OK) {
-    __archive_read_free_filters(a);
-    return (ARCHIVE_FATAL);
-  }
-  bidder->name = a->filter->name;
-
-  a->bypass_filter_bidding = 1;
-  return r;
-}
diff --git a/c/archive_read_data_into_fd.c b/c/archive_read_data_into_fd.c
deleted file mode 100644
--- a/c/archive_read_data_into_fd.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.16 2008/05/23 05:01:29 cperciva Exp $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-/* Maximum amount of data to write at one time. */
-#define	MAX_WRITE	(1024 * 1024)
-
-/*
- * This implementation minimizes copying of data and is sparse-file aware.
- */
-static int
-pad_to(struct archive *a, int fd, int can_lseek,
-    size_t nulls_size, const char *nulls,
-    int64_t target_offset, int64_t actual_offset)
-{
-	size_t to_write;
-	ssize_t bytes_written;
-
-	if (can_lseek) {
-		actual_offset = lseek(fd,
-		    target_offset - actual_offset, SEEK_CUR);
-		if (actual_offset != target_offset) {
-			archive_set_error(a, errno, "Seek error");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_OK);
-	}
-	while (target_offset > actual_offset) {
-		to_write = nulls_size;
-		if (target_offset < actual_offset + (int64_t)nulls_size)
-			to_write = (size_t)(target_offset - actual_offset);
-		bytes_written = write(fd, nulls, to_write);
-		if (bytes_written < 0) {
-			archive_set_error(a, errno, "Write error");
-			return (ARCHIVE_FATAL);
-		}
-		actual_offset += bytes_written;
-	}
-	return (ARCHIVE_OK);
-}
-
-
-int
-archive_read_data_into_fd(struct archive *a, int fd)
-{
-	struct stat st;
-	int r, r2;
-	const void *buff;
-	size_t size, bytes_to_write;
-	ssize_t bytes_written;
-	int64_t target_offset;
-	int64_t actual_offset = 0;
-	int can_lseek;
-	char *nulls = NULL;
-	size_t nulls_size = 16384;
-
-	archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_data_into_fd");
-
-	can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
-	if (!can_lseek) {
-		nulls = calloc(1, nulls_size);
-		if (!nulls) {
-			r = ARCHIVE_FATAL;
-			goto cleanup;
-		}
-	}
-
-	while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) ==
-	    ARCHIVE_OK) {
-		const char *p = buff;
-		if (target_offset > actual_offset) {
-			r = pad_to(a, fd, can_lseek, nulls_size, nulls,
-			    target_offset, actual_offset);
-			if (r != ARCHIVE_OK)
-				break;
-			actual_offset = target_offset;
-		}
-		while (size > 0) {
-			bytes_to_write = size;
-			if (bytes_to_write > MAX_WRITE)
-				bytes_to_write = MAX_WRITE;
-			bytes_written = write(fd, p, bytes_to_write);
-			if (bytes_written < 0) {
-				archive_set_error(a, errno, "Write error");
-				r = ARCHIVE_FATAL;
-				goto cleanup;
-			}
-			actual_offset += bytes_written;
-			p += bytes_written;
-			size -= bytes_written;
-		}
-	}
-
-	if (r == ARCHIVE_EOF && target_offset > actual_offset) {
-		r2 = pad_to(a, fd, can_lseek, nulls_size, nulls,
-		    target_offset, actual_offset);
-		if (r2 != ARCHIVE_OK)
-			r = r2;
-	}
-
-cleanup:
-	free(nulls);
-	if (r != ARCHIVE_EOF)
-		return (r);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_disk_entry_from_file.c b/c/archive_read_disk_entry_from_file.c
deleted file mode 100644
--- a/c/archive_read_disk_entry_from_file.c
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD");
-
-/* This is the tree-walking code for POSIX systems. */
-#if !defined(_WIN32) || defined(__CYGWIN__)
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_EXTATTR_H
-#include <sys/extattr.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if defined(HAVE_SYS_XATTR_H)
-#include <sys/xattr.h>
-#elif defined(HAVE_ATTR_XATTR_H)
-#include <attr/xattr.h>
-#endif
-#ifdef HAVE_SYS_EA_H
-#include <sys/ea.h>
-#endif
-#ifdef HAVE_COPYFILE_H
-#include <copyfile.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_LINUX_TYPES_H
-#include <linux/types.h>
-#endif
-#ifdef HAVE_LINUX_FIEMAP_H
-#include <linux/fiemap.h>
-#endif
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h>      /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h>     /* Linux file flags, broken on Cygwin */
-#endif
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-static int setup_mac_metadata(struct archive_read_disk *,
-    struct archive_entry *, int *fd);
-#ifdef ARCHIVE_XATTR_FREEBSD
-static int setup_xattrs_namespace(struct archive_read_disk *,
-    struct archive_entry *, int *, int);
-#endif
-static int setup_xattrs(struct archive_read_disk *,
-    struct archive_entry *, int *fd);
-static int setup_sparse(struct archive_read_disk *,
-    struct archive_entry *, int *fd);
-#if defined(HAVE_LINUX_FIEMAP_H)
-static int setup_sparse_fiemap(struct archive_read_disk *,
-    struct archive_entry *, int *fd);
-#endif
-
-#if !ARCHIVE_ACL_SUPPORT
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	(void)a;      /* UNUSED */
-	(void)entry;  /* UNUSED */
-	(void)fd;     /* UNUSED */
-	return (ARCHIVE_OK);
-}
-#endif
-
-/*
- * Enter working directory and return working pathname of archive_entry.
- * If a pointer to an integer is provided and its value is below zero
- * open a file descriptor on this pathname.
- */
-const char *
-archive_read_disk_entry_setup_path(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	const char *path;
-
-	path = archive_entry_sourcepath(entry);
-
-	if (path == NULL || (a->tree != NULL &&
-	    a->tree_enter_working_dir(a->tree) != 0))
-		path = archive_entry_pathname(entry);
-	if (path == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		   "Couldn't determine path");
-	} else if (fd != NULL && *fd < 0 && a->tree != NULL &&
-	    (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) {
-		*fd = a->open_on_current_dir(a->tree, path,
-		    O_RDONLY | O_NONBLOCK);
-	}
-	return (path);
-}
-
-int
-archive_read_disk_entry_from_file(struct archive *_a,
-    struct archive_entry *entry,
-    int fd,
-    const struct stat *st)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	const char *path, *name;
-	struct stat s;
-	int initial_fd = fd;
-	int r, r1;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
-		"archive_read_disk_entry_from_file");
-
-	archive_clear_error(_a);
-	path = archive_entry_sourcepath(entry);
-	if (path == NULL)
-		path = archive_entry_pathname(entry);
-
-	if (a->tree == NULL) {
-		if (st == NULL) {
-#if HAVE_FSTAT
-			if (fd >= 0) {
-				if (fstat(fd, &s) != 0) {
-					archive_set_error(&a->archive, errno,
-					    "Can't fstat");
-					return (ARCHIVE_FAILED);
-				}
-			} else
-#endif
-#if HAVE_LSTAT
-			if (!a->follow_symlinks) {
-				if (lstat(path, &s) != 0) {
-					archive_set_error(&a->archive, errno,
-					    "Can't lstat %s", path);
-					return (ARCHIVE_FAILED);
-				}
-			} else
-#endif
-			if (la_stat(path, &s) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Can't stat %s", path);
-				return (ARCHIVE_FAILED);
-			}
-			st = &s;
-		}
-		archive_entry_copy_stat(entry, st);
-	}
-
-	/* Lookup uname/gname */
-	name = archive_read_disk_uname(_a, archive_entry_uid(entry));
-	if (name != NULL)
-		archive_entry_copy_uname(entry, name);
-	name = archive_read_disk_gname(_a, archive_entry_gid(entry));
-	if (name != NULL)
-		archive_entry_copy_gname(entry, name);
-
-#ifdef HAVE_STRUCT_STAT_ST_FLAGS
-	/* On FreeBSD, we get flags for free with the stat. */
-	/* TODO: Does this belong in copy_stat()? */
-	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
-		archive_entry_set_fflags(entry, st->st_flags, 0);
-#endif
-
-#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
-    (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
-	/* Linux requires an extra ioctl to pull the flags.  Although
-	 * this is an extra step, it has a nice side-effect: We get an
-	 * open file descriptor which we can use in the subsequent lookups. */
-	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
-	    (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
-		if (fd < 0) {
-			if (a->tree != NULL)
-				fd = a->open_on_current_dir(a->tree, path,
-					O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-			else
-				fd = open(path, O_RDONLY | O_NONBLOCK |
-						O_CLOEXEC);
-			__archive_ensure_cloexec_flag(fd);
-		}
-		if (fd >= 0) {
-			int stflags;
-			r = ioctl(fd,
-#if defined(FS_IOC_GETFLAGS)
-			    FS_IOC_GETFLAGS,
-#else
-			    EXT2_IOC_GETFLAGS,
-#endif
-			    &stflags);
-			if (r == 0 && stflags != 0)
-				archive_entry_set_fflags(entry, stflags, 0);
-		}
-	}
-#endif
-
-#if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
-	if (S_ISLNK(st->st_mode)) {
-		size_t linkbuffer_len = st->st_size;
-		char *linkbuffer;
-		int lnklen;
-
-		linkbuffer = malloc(linkbuffer_len + 1);
-		if (linkbuffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Couldn't read link data");
-			return (ARCHIVE_FAILED);
-		}
-		if (a->tree != NULL) {
-#ifdef HAVE_READLINKAT
-			lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
-			    path, linkbuffer, linkbuffer_len);
-#else
-			if (a->tree_enter_working_dir(a->tree) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Couldn't read link data");
-				free(linkbuffer);
-				return (ARCHIVE_FAILED);
-			}
-			lnklen = readlink(path, linkbuffer, linkbuffer_len);
-#endif /* HAVE_READLINKAT */
-		} else
-			lnklen = readlink(path, linkbuffer, linkbuffer_len);
-		if (lnklen < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't read link data");
-			free(linkbuffer);
-			return (ARCHIVE_FAILED);
-		}
-		linkbuffer[lnklen] = '\0';
-		archive_entry_set_symlink(entry, linkbuffer);
-		free(linkbuffer);
-	}
-#endif /* HAVE_READLINK || HAVE_READLINKAT */
-
-	r = 0;
-	if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
-		r = archive_read_disk_entry_setup_acls(a, entry, &fd);
-	if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
-		r1 = setup_xattrs(a, entry, &fd);
-		if (r1 < r)
-			r = r1;
-	}
-	if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
-		r1 = setup_mac_metadata(a, entry, &fd);
-		if (r1 < r)
-			r = r1;
-	}
-	if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
-		r1 = setup_sparse(a, entry, &fd);
-		if (r1 < r)
-			r = r1;
-	}
-
-	/* If we opened the file earlier in this function, close it. */
-	if (initial_fd != fd)
-		close(fd);
-	return (r);
-}
-
-#if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
-/*
- * The Mac OS "copyfile()" API copies the extended metadata for a
- * file into a separate file in AppleDouble format (see RFC 1740).
- *
- * Mac OS tar and cpio implementations store this extended
- * metadata as a separate entry just before the regular entry
- * with a "._" prefix added to the filename.
- *
- * Note that this is currently done unconditionally; the tar program has
- * an option to discard this information before the archive is written.
- *
- * TODO: If there's a failure, report it and return ARCHIVE_WARN.
- */
-static int
-setup_mac_metadata(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	int tempfd = -1;
-	int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
-	struct stat copyfile_stat;
-	int ret = ARCHIVE_OK;
-	void *buff = NULL;
-	int have_attrs;
-	const char *name, *tempdir;
-	struct archive_string tempfile;
-
-	(void)fd; /* UNUSED */
-
-	name = archive_read_disk_entry_setup_path(a, entry, NULL);
-	if (name == NULL)
-		return (ARCHIVE_WARN);
-
-	/* Short-circuit if there's nothing to do. */
-	have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
-	if (have_attrs == -1) {
-		archive_set_error(&a->archive, errno,
-			"Could not check extended attributes");
-		return (ARCHIVE_WARN);
-	}
-	if (have_attrs == 0)
-		return (ARCHIVE_OK);
-
-	tempdir = NULL;
-	if (issetugid() == 0)
-		tempdir = getenv("TMPDIR");
-	if (tempdir == NULL)
-		tempdir = _PATH_TMP;
-	archive_string_init(&tempfile);
-	archive_strcpy(&tempfile, tempdir);
-	archive_strcat(&tempfile, "tar.md.XXXXXX");
-	tempfd = mkstemp(tempfile.s);
-	if (tempfd < 0) {
-		archive_set_error(&a->archive, errno,
-		    "Could not open extended attribute file");
-		ret = ARCHIVE_WARN;
-		goto cleanup;
-	}
-	__archive_ensure_cloexec_flag(tempfd);
-
-	/* XXX I wish copyfile() could pack directly to a memory
-	 * buffer; that would avoid the temp file here.  For that
-	 * matter, it would be nice if fcopyfile() actually worked,
-	 * that would reduce the many open/close races here. */
-	if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
-		archive_set_error(&a->archive, errno,
-		    "Could not pack extended attributes");
-		ret = ARCHIVE_WARN;
-		goto cleanup;
-	}
-	if (fstat(tempfd, &copyfile_stat)) {
-		archive_set_error(&a->archive, errno,
-		    "Could not check size of extended attributes");
-		ret = ARCHIVE_WARN;
-		goto cleanup;
-	}
-	buff = malloc(copyfile_stat.st_size);
-	if (buff == NULL) {
-		archive_set_error(&a->archive, errno,
-		    "Could not allocate memory for extended attributes");
-		ret = ARCHIVE_WARN;
-		goto cleanup;
-	}
-	if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
-		archive_set_error(&a->archive, errno,
-		    "Could not read extended attributes into memory");
-		ret = ARCHIVE_WARN;
-		goto cleanup;
-	}
-	archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
-
-cleanup:
-	if (tempfd >= 0) {
-		close(tempfd);
-		unlink(tempfile.s);
-	}
-	archive_string_free(&tempfile);
-	free(buff);
-	return (ret);
-}
-
-#else
-
-/*
- * Stub implementation for non-Mac systems.
- */
-static int
-setup_mac_metadata(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	(void)a; /* UNUSED */
-	(void)entry; /* UNUSED */
-	(void)fd; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-#endif
-
-#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
-
-/*
- * Linux, Darwin and AIX extended attribute support.
- *
- * TODO:  By using a stack-allocated buffer for the first
- * call to getxattr(), we might be able to avoid the second
- * call entirely.  We only need the second call if the
- * stack-allocated buffer is too small.  But a modest buffer
- * of 1024 bytes or so will often be big enough.  Same applies
- * to listxattr().
- */
-
-
-static int
-setup_xattr(struct archive_read_disk *a,
-    struct archive_entry *entry, const char *name, int fd, const char *accpath)
-{
-	ssize_t size;
-	void *value = NULL;
-
-
-	if (fd >= 0) {
-#if ARCHIVE_XATTR_LINUX
-		size = fgetxattr(fd, name, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		size = fgetxattr(fd, name, NULL, 0, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		size = fgetea(fd, name, NULL, 0);
-#endif
-	} else if (!a->follow_symlinks) {
-#if ARCHIVE_XATTR_LINUX
-		size = lgetxattr(accpath, name, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		size = getxattr(accpath, name, NULL, 0, 0, XATTR_NOFOLLOW);
-#elif ARCHIVE_XATTR_AIX
-		size = lgetea(accpath, name, NULL, 0);
-#endif
-	} else {
-#if ARCHIVE_XATTR_LINUX
-		size = getxattr(accpath, name, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		size = getxattr(accpath, name, NULL, 0, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		size = getea(accpath, name, NULL, 0);
-#endif
-	}
-
-	if (size == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Couldn't query extended attribute");
-		return (ARCHIVE_WARN);
-	}
-
-	if (size > 0 && (value = malloc(size)) == NULL) {
-		archive_set_error(&a->archive, errno, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-
-	if (fd >= 0) {
-#if ARCHIVE_XATTR_LINUX
-		size = fgetxattr(fd, name, value, size);
-#elif ARCHIVE_XATTR_DARWIN
-		size = fgetxattr(fd, name, value, size, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		size = fgetea(fd, name, value, size);
-#endif
-	} else if (!a->follow_symlinks) {
-#if ARCHIVE_XATTR_LINUX
-		size = lgetxattr(accpath, name, value, size);
-#elif ARCHIVE_XATTR_DARWIN
-		size = getxattr(accpath, name, value, size, 0, XATTR_NOFOLLOW);
-#elif ARCHIVE_XATTR_AIX
-		size = lgetea(accpath, name, value, size);
-#endif
-	} else {
-#if ARCHIVE_XATTR_LINUX
-		size = getxattr(accpath, name, value, size);
-#elif ARCHIVE_XATTR_DARWIN
-		size = getxattr(accpath, name, value, size, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		size = getea(accpath, name, value, size);
-#endif
-	}
-
-	if (size == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Couldn't read extended attribute");
-		return (ARCHIVE_WARN);
-	}
-
-	archive_entry_xattr_add_entry(entry, name, value, size);
-
-	free(value);
-	return (ARCHIVE_OK);
-}
-
-static int
-setup_xattrs(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	char *list, *p;
-	const char *path;
-	ssize_t list_size;
-
-	path = NULL;
-
-	if (*fd < 0) {
-		path = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (path == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	if (*fd >= 0) {
-#if ARCHIVE_XATTR_LINUX
-		list_size = flistxattr(*fd, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = flistxattr(*fd, NULL, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		list_size = flistea(*fd, NULL, 0);
-#endif
-	} else if (!a->follow_symlinks) {
-#if ARCHIVE_XATTR_LINUX
-		list_size = llistxattr(path, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = listxattr(path, NULL, 0, XATTR_NOFOLLOW);
-#elif ARCHIVE_XATTR_AIX
-		list_size = llistea(path, NULL, 0);
-#endif
-	} else {
-#if ARCHIVE_XATTR_LINUX
-		list_size = listxattr(path, NULL, 0);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = listxattr(path, NULL, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-		list_size = listea(path, NULL, 0);
-#endif
-	}
-
-	if (list_size == -1) {
-		if (errno == ENOTSUP || errno == ENOSYS)
-			return (ARCHIVE_OK);
-		archive_set_error(&a->archive, errno,
-			"Couldn't list extended attributes");
-		return (ARCHIVE_WARN);
-	}
-
-	if (list_size == 0)
-		return (ARCHIVE_OK);
-
-	if ((list = malloc(list_size)) == NULL) {
-		archive_set_error(&a->archive, errno, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (*fd >= 0) {
-#if ARCHIVE_XATTR_LINUX
-		list_size = flistxattr(*fd, list, list_size);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = flistxattr(*fd, list, list_size, 0);
-#elif ARCHIVE_XATTR_AIX
-		list_size = flistea(*fd, list, list_size);
-#endif
-	} else if (!a->follow_symlinks) {
-#if ARCHIVE_XATTR_LINUX
-		list_size = llistxattr(path, list, list_size);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = listxattr(path, list, list_size, XATTR_NOFOLLOW);
-#elif ARCHIVE_XATTR_AIX
-		list_size = llistea(path, list, list_size);
-#endif
-	} else {
-#if ARCHIVE_XATTR_LINUX
-		list_size = listxattr(path, list, list_size);
-#elif ARCHIVE_XATTR_DARWIN
-		list_size = listxattr(path, list, list_size, 0);
-#elif ARCHIVE_XATTR_AIX
-		list_size = listea(path, list, list_size);
-#endif
-	}
-
-	if (list_size == -1) {
-		archive_set_error(&a->archive, errno,
-			"Couldn't retrieve extended attributes");
-		free(list);
-		return (ARCHIVE_WARN);
-	}
-
-	for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
-#if ARCHIVE_XATTR_LINUX
-		/* Linux: skip POSIX.1e ACL extended attributes */
-		if (strncmp(p, "system.", 7) == 0 &&
-		   (strcmp(p + 7, "posix_acl_access") == 0 ||
-		    strcmp(p + 7, "posix_acl_default") == 0))
-			continue;
-		if (strncmp(p, "trusted.SGI_", 12) == 0 &&
-		   (strcmp(p + 12, "ACL_DEFAULT") == 0 ||
-		    strcmp(p + 12, "ACL_FILE") == 0))
-			continue;
-
-		/* Linux: xfsroot namespace is obsolete and unsupported */
-		if (strncmp(p, "xfsroot.", 8) == 0)
-			continue;
-#endif
-		setup_xattr(a, entry, p, *fd, path);
-	}
-
-	free(list);
-	return (ARCHIVE_OK);
-}
-
-#elif ARCHIVE_XATTR_FREEBSD
-
-/*
- * FreeBSD extattr interface.
- */
-
-/* TODO: Implement this.  Follow the Linux model above, but
- * with FreeBSD-specific system calls, of course.  Be careful
- * to not include the system extattrs that hold ACLs; we handle
- * those separately.
- */
-static int
-setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
-    int namespace, const char *name, const char *fullname, int fd,
-    const char *path);
-
-static int
-setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
-    int namespace, const char *name, const char *fullname, int fd,
-    const char *accpath)
-{
-	ssize_t size;
-	void *value = NULL;
-
-	if (fd >= 0)
-		size = extattr_get_fd(fd, namespace, name, NULL, 0);
-	else if (!a->follow_symlinks)
-		size = extattr_get_link(accpath, namespace, name, NULL, 0);
-	else
-		size = extattr_get_file(accpath, namespace, name, NULL, 0);
-
-	if (size == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Couldn't query extended attribute");
-		return (ARCHIVE_WARN);
-	}
-
-	if (size > 0 && (value = malloc(size)) == NULL) {
-		archive_set_error(&a->archive, errno, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (fd >= 0)
-		size = extattr_get_fd(fd, namespace, name, value, size);
-	else if (!a->follow_symlinks)
-		size = extattr_get_link(accpath, namespace, name, value, size);
-	else
-		size = extattr_get_file(accpath, namespace, name, value, size);
-
-	if (size == -1) {
-		free(value);
-		archive_set_error(&a->archive, errno,
-		    "Couldn't read extended attribute");
-		return (ARCHIVE_WARN);
-	}
-
-	archive_entry_xattr_add_entry(entry, fullname, value, size);
-
-	free(value);
-	return (ARCHIVE_OK);
-}
-
-static int
-setup_xattrs_namespace(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd, int namespace)
-{
-	char buff[512];
-	char *list, *p;
-	ssize_t list_size;
-	const char *path;
-
-	path = NULL;
-
-	if (*fd < 0) {
-		path = archive_read_disk_entry_setup_path(a, entry, fd);
-		if (path == NULL)
-			return (ARCHIVE_WARN);
-	}
-
-	if (*fd >= 0)
-		list_size = extattr_list_fd(*fd, namespace, NULL, 0);
-	else if (!a->follow_symlinks)
-		list_size = extattr_list_link(path, namespace, NULL, 0);
-	else
-		list_size = extattr_list_file(path, namespace, NULL, 0);
-
-	if (list_size == -1 && errno == EOPNOTSUPP)
-		return (ARCHIVE_OK);
-	if (list_size == -1 && errno == EPERM)
-		return (ARCHIVE_OK);
-	if (list_size == -1) {
-		archive_set_error(&a->archive, errno,
-			"Couldn't list extended attributes");
-		return (ARCHIVE_WARN);
-	}
-
-	if (list_size == 0)
-		return (ARCHIVE_OK);
-
-	if ((list = malloc(list_size)) == NULL) {
-		archive_set_error(&a->archive, errno, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (*fd >= 0)
-		list_size = extattr_list_fd(*fd, namespace, list, list_size);
-	else if (!a->follow_symlinks)
-		list_size = extattr_list_link(path, namespace, list, list_size);
-	else
-		list_size = extattr_list_file(path, namespace, list, list_size);
-
-	if (list_size == -1) {
-		archive_set_error(&a->archive, errno,
-			"Couldn't retrieve extended attributes");
-		free(list);
-		return (ARCHIVE_WARN);
-	}
-
-	p = list;
-	while ((p - list) < list_size) {
-		size_t len = 255 & (int)*p;
-		char *name;
-
-		if (namespace == EXTATTR_NAMESPACE_SYSTEM) {
-			if (!strcmp(p + 1, "nfs4.acl") ||
-			    !strcmp(p + 1, "posix1e.acl_access") ||
-			    !strcmp(p + 1, "posix1e.acl_default")) {
-				p += 1 + len;
-				continue;
-			}
-			strcpy(buff, "system.");
-		} else {
-			strcpy(buff, "user.");
-		}
-		name = buff + strlen(buff);
-		memcpy(name, p + 1, len);
-		name[len] = '\0';
-		setup_xattr(a, entry, namespace, name, buff, *fd, path);
-		p += 1 + len;
-	}
-
-	free(list);
-	return (ARCHIVE_OK);
-}
-
-static int
-setup_xattrs(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	int namespaces[2];
-	int i, res;
-
-	namespaces[0] = EXTATTR_NAMESPACE_USER;
-	namespaces[1] = EXTATTR_NAMESPACE_SYSTEM;
-
-	for (i = 0; i < 2; i++) {
-		res = setup_xattrs_namespace(a, entry, fd,
-		    namespaces[i]);
-		switch (res) {
-			case (ARCHIVE_OK):
-			case (ARCHIVE_WARN):
-				break;
-			default:
-				return (res);
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-#else
-
-/*
- * Generic (stub) extended attribute support.
- */
-static int
-setup_xattrs(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	(void)a;     /* UNUSED */
-	(void)entry; /* UNUSED */
-	(void)fd;    /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-#endif
-
-#if defined(HAVE_LINUX_FIEMAP_H)
-
-/*
- * Linux FIEMAP sparse interface.
- *
- * The FIEMAP ioctl returns an "extent" for each physical allocation
- * on disk.  We need to process those to generate a more compact list
- * of logical file blocks.  We also need to be very careful to use
- * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
- * does not report allocations for newly-written data that hasn't
- * been synced to disk.
- *
- * It's important to return a minimal sparse file list because we want
- * to not trigger sparse file extensions if we don't have to, since
- * not all readers support them.
- */
-
-static int
-setup_sparse_fiemap(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	char buff[4096];
-	struct fiemap *fm;
-	struct fiemap_extent *fe;
-	int64_t size;
-	int count, do_fiemap, iters;
-	int exit_sts = ARCHIVE_OK;
-	const char *path;
-
-	if (archive_entry_filetype(entry) != AE_IFREG
-	    || archive_entry_size(entry) <= 0
-	    || archive_entry_hardlink(entry) != NULL)
-		return (ARCHIVE_OK);
-
-	if (*fd < 0) {
-		path = archive_read_disk_entry_setup_path(a, entry, NULL);
-		if (path == NULL)
-			return (ARCHIVE_FAILED);
-
-		if (a->tree != NULL)
-			*fd = a->open_on_current_dir(a->tree, path,
-				O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-		else
-			*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-		if (*fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't open `%s'", path);
-			return (ARCHIVE_FAILED);
-		}
-		__archive_ensure_cloexec_flag(*fd);
-	}
-
-	/* Initialize buffer to avoid the error valgrind complains about. */
-	memset(buff, 0, sizeof(buff));
-	count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
-	fm = (struct fiemap *)buff;
-	fm->fm_start = 0;
-	fm->fm_length = ~0ULL;;
-	fm->fm_flags = FIEMAP_FLAG_SYNC;
-	fm->fm_extent_count = count;
-	do_fiemap = 1;
-	size = archive_entry_size(entry);
-	for (iters = 0; ; ++iters) {
-		int i, r;
-
-		r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
-		if (r < 0) {
-			/* When something error happens, it is better we
-			 * should return ARCHIVE_OK because an earlier
-			 * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
-			goto exit_setup_sparse_fiemap;
-		}
-		if (fm->fm_mapped_extents == 0) {
-			if (iters == 0) {
-				/* Fully sparse file; insert a zero-length "data" entry */
-				archive_entry_sparse_add_entry(entry, 0, 0);
-			}
-			break;
-		}
-		fe = fm->fm_extents;
-		for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
-			if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
-				/* The fe_length of the last block does not
-				 * adjust itself to its size files. */
-				int64_t length = fe->fe_length;
-				if (fe->fe_logical + length > (uint64_t)size)
-					length -= fe->fe_logical + length - size;
-				if (fe->fe_logical == 0 && length == size) {
-					/* This is not sparse. */
-					do_fiemap = 0;
-					break;
-				}
-				if (length > 0)
-					archive_entry_sparse_add_entry(entry,
-					    fe->fe_logical, length);
-			}
-			if (fe->fe_flags & FIEMAP_EXTENT_LAST)
-				do_fiemap = 0;
-		}
-		if (do_fiemap) {
-			fe = fm->fm_extents + fm->fm_mapped_extents -1;
-			fm->fm_start = fe->fe_logical + fe->fe_length;
-		} else
-			break;
-	}
-exit_setup_sparse_fiemap:
-	return (exit_sts);
-}
-
-#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
-static int
-setup_sparse(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	return setup_sparse_fiemap(a, entry, fd);
-}
-#endif
-#endif	/* defined(HAVE_LINUX_FIEMAP_H) */
-
-#if defined(SEEK_HOLE) && defined(SEEK_DATA)
-
-/*
- * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
- */
-
-static int
-setup_sparse(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	int64_t size;
-	off_t initial_off;
-	off_t off_s, off_e;
-	int exit_sts = ARCHIVE_OK;
-	int check_fully_sparse = 0;
-	const char *path;
-
-	if (archive_entry_filetype(entry) != AE_IFREG
-	    || archive_entry_size(entry) <= 0
-	    || archive_entry_hardlink(entry) != NULL)
-		return (ARCHIVE_OK);
-
-	/* Does filesystem support the reporting of hole ? */
-	if (*fd < 0)
-		path = archive_read_disk_entry_setup_path(a, entry, fd);
-	else
-		path = NULL;
-
-	if (*fd >= 0) {
-#ifdef _PC_MIN_HOLE_SIZE
-		if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
-			return (ARCHIVE_OK);
-#endif
-		initial_off = lseek(*fd, 0, SEEK_CUR);
-		if (initial_off != 0)
-			lseek(*fd, 0, SEEK_SET);
-	} else {
-		if (path == NULL)
-			return (ARCHIVE_FAILED);
-#ifdef _PC_MIN_HOLE_SIZE
-		if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
-			return (ARCHIVE_OK);
-#endif
-		*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-		if (*fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't open `%s'", path);
-			return (ARCHIVE_FAILED);
-		}
-		__archive_ensure_cloexec_flag(*fd);
-		initial_off = 0;
-	}
-
-#ifndef _PC_MIN_HOLE_SIZE
-	/* Check if the underlying filesystem supports seek hole */
-	off_s = lseek(*fd, 0, SEEK_HOLE);
-	if (off_s < 0)
-#if defined(HAVE_LINUX_FIEMAP_H)
-		return setup_sparse_fiemap(a, entry, fd);
-#else
-		goto exit_setup_sparse;
-#endif
-	else if (off_s > 0)
-		lseek(*fd, 0, SEEK_SET);
-#endif
-
-	off_s = 0;
-	size = archive_entry_size(entry);
-	while (off_s < size) {
-		off_s = lseek(*fd, off_s, SEEK_DATA);
-		if (off_s == (off_t)-1) {
-			if (errno == ENXIO) {
-				/* no more hole */
-				if (archive_entry_sparse_count(entry) == 0) {
-					/* Potentially a fully-sparse file. */
-					check_fully_sparse = 1;
-				}
-				break;
-			}
-			archive_set_error(&a->archive, errno,
-			    "lseek(SEEK_HOLE) failed");
-			exit_sts = ARCHIVE_FAILED;
-			goto exit_setup_sparse;
-		}
-		off_e = lseek(*fd, off_s, SEEK_HOLE);
-		if (off_e == (off_t)-1) {
-			if (errno == ENXIO) {
-				off_e = lseek(*fd, 0, SEEK_END);
-				if (off_e != (off_t)-1)
-					break;/* no more data */
-			}
-			archive_set_error(&a->archive, errno,
-			    "lseek(SEEK_DATA) failed");
-			exit_sts = ARCHIVE_FAILED;
-			goto exit_setup_sparse;
-		}
-		if (off_s == 0 && off_e == size)
-			break;/* This is not sparse. */
-		archive_entry_sparse_add_entry(entry, off_s,
-			off_e - off_s);
-		off_s = off_e;
-	}
-
-	if (check_fully_sparse) {
-		if (lseek(*fd, 0, SEEK_HOLE) == 0 &&
-			lseek(*fd, 0, SEEK_END) == size) {
-			/* Fully sparse file; insert a zero-length "data" entry */
-			archive_entry_sparse_add_entry(entry, 0, 0);
-		}
-	}
-exit_setup_sparse:
-	lseek(*fd, initial_off, SEEK_SET);
-	return (exit_sts);
-}
-
-#elif !defined(HAVE_LINUX_FIEMAP_H)
-
-/*
- * Generic (stub) sparse support.
- */
-static int
-setup_sparse(struct archive_read_disk *a,
-    struct archive_entry *entry, int *fd)
-{
-	(void)a;     /* UNUSED */
-	(void)entry; /* UNUSED */
-	(void)fd;    /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-#endif
-
-#endif /* !defined(_WIN32) || defined(__CYGWIN__) */
-
diff --git a/c/archive_read_disk_posix.c b/c/archive_read_disk_posix.c
deleted file mode 100644
--- a/c/archive_read_disk_posix.c
+++ /dev/null
@@ -1,2760 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This is the tree-walking code for POSIX systems. */
-#if !defined(_WIN32) || defined(__CYGWIN__)
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_STATFS_H
-#include <sys/statfs.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_LINUX_MAGIC_H
-#include <linux/magic.h>
-#endif
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>
-#elif HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h>      /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h>     /* Linux file flags, broken on Cygwin */
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-
-#ifndef HAVE_FCHDIR
-#error fchdir function required.
-#endif
-#ifndef O_BINARY
-#define O_BINARY	0
-#endif
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-#if defined(__hpux) && !defined(HAVE_DIRFD)
-#define dirfd(x) ((x)->__dd_fd)
-#define HAVE_DIRFD
-#endif
-
-/*-
- * This is a new directory-walking system that addresses a number
- * of problems I've had with fts(3).  In particular, it has no
- * pathname-length limits (other than the size of 'int'), handles
- * deep logical traversals, uses considerably less memory, and has
- * an opaque interface (easier to modify in the future).
- *
- * Internally, it keeps a single list of "tree_entry" items that
- * represent filesystem objects that require further attention.
- * Non-directories are not kept in memory: they are pulled from
- * readdir(), returned to the client, then freed as soon as possible.
- * Any directory entry to be traversed gets pushed onto the stack.
- *
- * There is surprisingly little information that needs to be kept for
- * each item on the stack.  Just the name, depth (represented here as the
- * string length of the parent directory's pathname), and some markers
- * indicating how to get back to the parent (via chdir("..") for a
- * regular dir or via fchdir(2) for a symlink).
- */
-/*
- * TODO:
- *    1) Loop checking.
- *    3) Arbitrary logical traversals by closing/reopening intermediate fds.
- */
-
-struct restore_time {
-	const char		*name;
-	time_t			 mtime;
-	long			 mtime_nsec;
-	time_t			 atime;
-	long			 atime_nsec;
-	mode_t			 filetype;
-	int			 noatime;
-};
-
-struct tree_entry {
-	int			 depth;
-	struct tree_entry	*next;
-	struct tree_entry	*parent;
-	struct archive_string	 name;
-	size_t			 dirname_length;
-	int64_t			 dev;
-	int64_t			 ino;
-	int			 flags;
-	int			 filesystem_id;
-	/* How to return back to the parent of a symlink. */
-	int			 symlink_parent_fd;
-	/* How to restore time of a directory. */
-	struct restore_time	 restore_time;
-};
-
-struct filesystem {
-	int64_t		dev;
-	int		synthetic;
-	int		remote;
-	int		noatime;
-#if defined(USE_READDIR_R)
-	size_t		name_max;
-#endif
-	long		incr_xfer_size;
-	long		max_xfer_size;
-	long		min_xfer_size;
-	long		xfer_align;
-
-	/*
-	 * Buffer used for reading file contents.
-	 */
-	/* Exactly allocated memory pointer. */
-	unsigned char	*allocation_ptr;
-	/* Pointer adjusted to the filesystem alignment . */
-	unsigned char	*buff;
-	size_t		 buff_size;
-};
-
-/* Definitions for tree_entry.flags bitmap. */
-#define	isDir		1  /* This entry is a regular directory. */
-#define	isDirLink	2  /* This entry is a symbolic link to a directory. */
-#define	needsFirstVisit	4  /* This is an initial entry. */
-#define	needsDescent	8  /* This entry needs to be previsited. */
-#define	needsOpen	16 /* This is a directory that needs to be opened. */
-#define	needsAscent	32 /* This entry needs to be postvisited. */
-
-/*
- * Local data for this package.
- */
-struct tree {
-	struct tree_entry	*stack;
-	struct tree_entry	*current;
-	DIR			*d;
-#define	INVALID_DIR_HANDLE NULL
-	struct dirent		*de;
-#if defined(USE_READDIR_R)
-	struct dirent		*dirent;
-	size_t			 dirent_allocated;
-#endif
-	int			 flags;
-	int			 visit_type;
-	/* Error code from last failed operation. */
-	int			 tree_errno;
-
-	/* Dynamically-sized buffer for holding path */
-	struct archive_string	 path;
-
-	/* Last path element */
-	const char		*basename;
-	/* Leading dir length */
-	size_t			 dirname_length;
-
-	int			 depth;
-	int			 openCount;
-	int			 maxOpenCount;
-	int			 initial_dir_fd;
-	int			 working_dir_fd;
-
-	struct stat		 lst;
-	struct stat		 st;
-	int			 descend;
-	int			 nlink;
-	/* How to restore time of a file. */
-	struct restore_time	 restore_time;
-
-	struct entry_sparse {
-		int64_t		 length;
-		int64_t		 offset;
-	}			*sparse_list, *current_sparse;
-	int			 sparse_count;
-	int			 sparse_list_size;
-
-	char			 initial_symlink_mode;
-	char			 symlink_mode;
-	struct filesystem	*current_filesystem;
-	struct filesystem	*filesystem_table;
-	int			 initial_filesystem_id;
-	int			 current_filesystem_id;
-	int			 max_filesystem_id;
-	int			 allocated_filesystem;
-
-	int			 entry_fd;
-	int			 entry_eof;
-	int64_t			 entry_remaining_bytes;
-	int64_t			 entry_total;
-	unsigned char		*entry_buff;
-	size_t			 entry_buff_size;
-};
-
-/* Definitions for tree.flags bitmap. */
-#define	hasStat		16 /* The st entry is valid. */
-#define	hasLstat	32 /* The lst entry is valid. */
-#define	onWorkingDir	64 /* We are on the working dir where we are
-			    * reading directory entry at this time. */
-#define	needsRestoreTimes 128
-#define	onInitialDir	256 /* We are on the initial dir. */
-
-static int
-tree_dir_next_posix(struct tree *t);
-
-#ifdef HAVE_DIRENT_D_NAMLEN
-/* BSD extension; avoids need for a strlen() call. */
-#define	D_NAMELEN(dp)	(dp)->d_namlen
-#else
-#define	D_NAMELEN(dp)	(strlen((dp)->d_name))
-#endif
-
-/* Initiate/terminate a tree traversal. */
-static struct tree *tree_open(const char *, int, int);
-static struct tree *tree_reopen(struct tree *, const char *, int);
-static void tree_close(struct tree *);
-static void tree_free(struct tree *);
-static void tree_push(struct tree *, const char *, int, int64_t, int64_t,
-		struct restore_time *);
-static int tree_enter_initial_dir(struct tree *);
-static int tree_enter_working_dir(struct tree *);
-static int tree_current_dir_fd(struct tree *);
-
-/*
- * tree_next() returns Zero if there is no next entry, non-zero if
- * there is.  Note that directories are visited three times.
- * Directories are always visited first as part of enumerating their
- * parent; that is a "regular" visit.  If tree_descend() is invoked at
- * that time, the directory is added to a work list and will
- * subsequently be visited two more times: once just after descending
- * into the directory ("postdescent") and again just after ascending
- * back to the parent ("postascent").
- *
- * TREE_ERROR_DIR is returned if the descent failed (because the
- * directory couldn't be opened, for instance).  This is returned
- * instead of TREE_POSTDESCENT/TREE_POSTASCENT.  TREE_ERROR_DIR is not a
- * fatal error, but it does imply that the relevant subtree won't be
- * visited.  TREE_ERROR_FATAL is returned for an error that left the
- * traversal completely hosed.  Right now, this is only returned for
- * chdir() failures during ascent.
- */
-#define	TREE_REGULAR		1
-#define	TREE_POSTDESCENT	2
-#define	TREE_POSTASCENT		3
-#define	TREE_ERROR_DIR		-1
-#define	TREE_ERROR_FATAL	-2
-
-static int tree_next(struct tree *);
-
-/*
- * Return information about the current entry.
- */
-
-/*
- * The current full pathname, length of the full pathname, and a name
- * that can be used to access the file.  Because tree does use chdir
- * extensively, the access path is almost never the same as the full
- * current path.
- *
- * TODO: On platforms that support it, use openat()-style operations
- * to eliminate the chdir() operations entirely while still supporting
- * arbitrarily deep traversals.  This makes access_path troublesome to
- * support, of course, which means we'll need a rich enough interface
- * that clients can function without it.  (In particular, we'll need
- * tree_current_open() that returns an open file descriptor.)
- *
- */
-static const char *tree_current_path(struct tree *);
-static const char *tree_current_access_path(struct tree *);
-
-/*
- * Request the lstat() or stat() data for the current path.  Since the
- * tree package needs to do some of this anyway, and caches the
- * results, you should take advantage of it here if you need it rather
- * than make a redundant stat() or lstat() call of your own.
- */
-static const struct stat *tree_current_stat(struct tree *);
-static const struct stat *tree_current_lstat(struct tree *);
-static int	tree_current_is_symblic_link_target(struct tree *);
-
-/* The following functions use tricks to avoid a certain number of
- * stat()/lstat() calls. */
-/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
-static int tree_current_is_physical_dir(struct tree *);
-/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
-static int tree_current_is_dir(struct tree *);
-static int update_current_filesystem(struct archive_read_disk *a,
-		    int64_t dev);
-static int setup_current_filesystem(struct archive_read_disk *);
-static int tree_target_is_same_as_parent(struct tree *, const struct stat *);
-
-static int	_archive_read_disk_open(struct archive *, const char *);
-static int	_archive_read_free(struct archive *);
-static int	_archive_read_close(struct archive *);
-static int	_archive_read_data_block(struct archive *,
-		    const void **, size_t *, int64_t *);
-static int	_archive_read_next_header(struct archive *,
-		    struct archive_entry **);
-static int	_archive_read_next_header2(struct archive *,
-		    struct archive_entry *);
-static const char *trivial_lookup_gname(void *, int64_t gid);
-static const char *trivial_lookup_uname(void *, int64_t uid);
-static int	setup_sparse(struct archive_read_disk *, struct archive_entry *);
-static int	close_and_restore_time(int fd, struct tree *,
-		    struct restore_time *);
-static int	open_on_current_dir(struct tree *, const char *, int);
-static int	tree_dup(int);
-
-
-static const struct archive_vtable
-archive_read_disk_vtable = {
-	.archive_free = _archive_read_free,
-	.archive_close = _archive_read_close,
-	.archive_read_data_block = _archive_read_data_block,
-	.archive_read_next_header = _archive_read_next_header,
-	.archive_read_next_header2 = _archive_read_next_header2,
-};
-
-const char *
-archive_read_disk_gname(struct archive *_a, la_int64_t gid)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-		ARCHIVE_STATE_ANY, "archive_read_disk_gname"))
-		return (NULL);
-	if (a->lookup_gname == NULL)
-		return (NULL);
-	return ((*a->lookup_gname)(a->lookup_gname_data, gid));
-}
-
-const char *
-archive_read_disk_uname(struct archive *_a, la_int64_t uid)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-		ARCHIVE_STATE_ANY, "archive_read_disk_uname"))
-		return (NULL);
-	if (a->lookup_uname == NULL)
-		return (NULL);
-	return ((*a->lookup_uname)(a->lookup_uname_data, uid));
-}
-
-int
-archive_read_disk_set_gname_lookup(struct archive *_a,
-    void *private_data,
-    const char * (*lookup_gname)(void *private, la_int64_t gid),
-    void (*cleanup_gname)(void *private))
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup");
-
-	if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
-		(a->cleanup_gname)(a->lookup_gname_data);
-
-	a->lookup_gname = lookup_gname;
-	a->cleanup_gname = cleanup_gname;
-	a->lookup_gname_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_uname_lookup(struct archive *_a,
-    void *private_data,
-    const char * (*lookup_uname)(void *private, la_int64_t uid),
-    void (*cleanup_uname)(void *private))
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup");
-
-	if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
-		(a->cleanup_uname)(a->lookup_uname_data);
-
-	a->lookup_uname = lookup_uname;
-	a->cleanup_uname = cleanup_uname;
-	a->lookup_uname_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Create a new archive_read_disk object and initialize it with global state.
- */
-struct archive *
-archive_read_disk_new(void)
-{
-	struct archive_read_disk *a;
-
-	a = (struct archive_read_disk *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
-	a->archive.state = ARCHIVE_STATE_NEW;
-	a->archive.vtable = &archive_read_disk_vtable;
-	a->entry = archive_entry_new2(&a->archive);
-	a->lookup_uname = trivial_lookup_uname;
-	a->lookup_gname = trivial_lookup_gname;
-	a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
-	a->open_on_current_dir = open_on_current_dir;
-	a->tree_current_dir_fd = tree_current_dir_fd;
-	a->tree_enter_working_dir = tree_enter_working_dir;
-	return (&a->archive);
-}
-
-static int
-_archive_read_free(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	int r;
-
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
-
-	if (a->archive.state != ARCHIVE_STATE_CLOSED)
-		r = _archive_read_close(&a->archive);
-	else
-		r = ARCHIVE_OK;
-
-	tree_free(a->tree);
-	if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
-		(a->cleanup_gname)(a->lookup_gname_data);
-	if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
-		(a->cleanup_uname)(a->lookup_uname_data);
-	archive_string_free(&a->archive.error_string);
-	archive_entry_free(a->entry);
-	a->archive.magic = 0;
-	__archive_clean(&a->archive);
-	free(a);
-	return (r);
-}
-
-static int
-_archive_read_close(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
-
-	if (a->archive.state != ARCHIVE_STATE_FATAL)
-		a->archive.state = ARCHIVE_STATE_CLOSED;
-
-	tree_close(a->tree);
-
-	return (ARCHIVE_OK);
-}
-
-static void
-setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
-    int follow_symlinks)
-{
-	a->symlink_mode = symlink_mode;
-	a->follow_symlinks = follow_symlinks;
-	if (a->tree != NULL) {
-		a->tree->initial_symlink_mode = a->symlink_mode;
-		a->tree->symlink_mode = a->symlink_mode;
-	}
-}
-
-int
-archive_read_disk_set_symlink_logical(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical");
-	setup_symlink_mode(a, 'L', 1);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_symlink_physical(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical");
-	setup_symlink_mode(a, 'P', 0);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_symlink_hybrid(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid");
-	setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_atime_restored(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
-#ifdef HAVE_UTIMES
-	a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
-	if (a->tree != NULL)
-		a->tree->flags |= needsRestoreTimes;
-	return (ARCHIVE_OK);
-#else
-	/* Display warning and unset flag */
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Cannot restore access time on this system");
-	a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
-	return (ARCHIVE_WARN);
-#endif
-}
-
-int
-archive_read_disk_set_behavior(struct archive *_a, int flags)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	int r = ARCHIVE_OK;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
-
-	a->flags = flags;
-
-	if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
-		r = archive_read_disk_set_atime_restored(_a);
-	else {
-		if (a->tree != NULL)
-			a->tree->flags &= ~needsRestoreTimes;
-	}
-	return (r);
-}
-
-/*
- * Trivial implementations of gname/uname lookup functions.
- * These are normally overridden by the client, but these stub
- * versions ensure that we always have something that works.
- */
-static const char *
-trivial_lookup_gname(void *private_data, int64_t gid)
-{
-	(void)private_data; /* UNUSED */
-	(void)gid; /* UNUSED */
-	return (NULL);
-}
-
-static const char *
-trivial_lookup_uname(void *private_data, int64_t uid)
-{
-	(void)private_data; /* UNUSED */
-	(void)uid; /* UNUSED */
-	return (NULL);
-}
-
-/*
- * Allocate memory for the reading buffer adjusted to the filesystem
- * alignment.
- */
-static int
-setup_suitable_read_buffer(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	struct filesystem *cf = t->current_filesystem;
-	size_t asize;
-	size_t s;
-
-	if (cf->allocation_ptr == NULL) {
-		/* If we couldn't get a filesystem alignment,
-		 * we use 4096 as default value but we won't use
-		 * O_DIRECT to open() and openat() operations. */
-		long xfer_align = (cf->xfer_align == -1)?4096:cf->xfer_align;
-
-		if (cf->max_xfer_size != -1)
-			asize = cf->max_xfer_size + xfer_align;
-		else {
-			long incr = cf->incr_xfer_size;
-			/* Some platform does not set a proper value to
-			 * incr_xfer_size.*/
-			if (incr < 0)
-				incr = cf->min_xfer_size;
-			if (cf->min_xfer_size < 0) {
-				incr = xfer_align;
-				asize = xfer_align;
-			} else
-				asize = cf->min_xfer_size;
-
-			/* Increase a buffer size up to 64K bytes in
-			 * a proper increment size. */
-			while (asize < 1024*64)
-				asize += incr;
-			/* Take a margin to adjust to the filesystem
-			 * alignment. */
-			asize += xfer_align;
-		}
-		cf->allocation_ptr = malloc(asize);
-		if (cf->allocation_ptr == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Couldn't allocate memory");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-
-		/*
-		 * Calculate proper address for the filesystem.
-		 */
-		s = (uintptr_t)cf->allocation_ptr;
-		s %= xfer_align;
-		if (s > 0)
-			s = xfer_align - s;
-
-		/*
-		 * Set a read buffer pointer in the proper alignment of
-		 * the current filesystem.
-		 */
-		cf->buff = cf->allocation_ptr + s;
-		cf->buff_size = asize - xfer_align;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-_archive_read_data_block(struct archive *_a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-	int r;
-	ssize_t bytes;
-	int64_t sparse_bytes;
-	size_t buffbytes;
-	int empty_sparse_region = 0;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_data_block");
-
-	if (t->entry_eof || t->entry_remaining_bytes <= 0) {
-		r = ARCHIVE_EOF;
-		goto abort_read_data;
-	}
-
-	/*
-	 * Open the current file.
-	 */
-	if (t->entry_fd < 0) {
-		int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
-
-		/*
-		 * Eliminate or reduce cache effects if we can.
-		 *
-		 * Carefully consider this to be enabled.
-		 */
-#if defined(O_DIRECT) && 0/* Disabled for now */
-		if (t->current_filesystem->xfer_align != -1 &&
-		    t->nlink == 1)
-			flags |= O_DIRECT;
-#endif
-#if defined(O_NOATIME)
-		/*
-		 * Linux has O_NOATIME flag; use it if we need.
-		 */
-		if ((t->flags & needsRestoreTimes) != 0 &&
-		    t->restore_time.noatime == 0)
-			flags |= O_NOATIME;
-#endif
-		t->entry_fd = open_on_current_dir(t,
-		    tree_current_access_path(t), flags);
-		__archive_ensure_cloexec_flag(t->entry_fd);
-#if defined(O_NOATIME)
-		/*
-		 * When we did open the file with O_NOATIME flag,
-		 * if successful, set 1 to t->restore_time.noatime
-		 * not to restore an atime of the file later.
-		 * if failed by EPERM, retry it without O_NOATIME flag.
-		 */
-		if (flags & O_NOATIME) {
-			if (t->entry_fd >= 0)
-				t->restore_time.noatime = 1;
-			else if (errno == EPERM)
-				flags &= ~O_NOATIME;
-		}
-#endif
-		if (t->entry_fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't open %s", tree_current_path(t));
-			r = ARCHIVE_FAILED;
-			tree_enter_initial_dir(t);
-			goto abort_read_data;
-		}
-		tree_enter_initial_dir(t);
-	}
-
-	/*
-	 * Allocate read buffer if not allocated.
-	 */
-	if (t->current_filesystem->allocation_ptr == NULL) {
-		r = setup_suitable_read_buffer(a);
-		if (r != ARCHIVE_OK) {
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			goto abort_read_data;
-		}
-	}
-	t->entry_buff = t->current_filesystem->buff;
-	t->entry_buff_size = t->current_filesystem->buff_size;
-
-	buffbytes = t->entry_buff_size;
-	if ((int64_t)buffbytes > t->current_sparse->length)
-		buffbytes = t->current_sparse->length;
-
-	if (t->current_sparse->length == 0)
-		empty_sparse_region = 1;
-
-	/*
-	 * Skip hole.
-	 * TODO: Should we consider t->current_filesystem->xfer_align?
-	 */
-	if (t->current_sparse->offset > t->entry_total) {
-		if (lseek(t->entry_fd,
-		    (off_t)t->current_sparse->offset, SEEK_SET) < 0) {
-			archive_set_error(&a->archive, errno, "Seek error");
-			r = ARCHIVE_FATAL;
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			goto abort_read_data;
-		}
-		sparse_bytes = t->current_sparse->offset - t->entry_total;
-		t->entry_remaining_bytes -= sparse_bytes;
-		t->entry_total += sparse_bytes;
-	}
-
-	/*
-	 * Read file contents.
-	 */
-	if (buffbytes > 0) {
-		bytes = read(t->entry_fd, t->entry_buff, buffbytes);
-		if (bytes < 0) {
-			archive_set_error(&a->archive, errno, "Read error");
-			r = ARCHIVE_FATAL;
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			goto abort_read_data;
-		}
-	} else
-		bytes = 0;
-	/*
-	 * Return an EOF unless we've read a leading empty sparse region, which
-	 * is used to represent fully-sparse files.
-	*/
-	if (bytes == 0 && !empty_sparse_region) {
-		/* Get EOF */
-		t->entry_eof = 1;
-		r = ARCHIVE_EOF;
-		goto abort_read_data;
-	}
-	*buff = t->entry_buff;
-	*size = bytes;
-	*offset = t->entry_total;
-	t->entry_total += bytes;
-	t->entry_remaining_bytes -= bytes;
-	if (t->entry_remaining_bytes == 0) {
-		/* Close the current file descriptor */
-		close_and_restore_time(t->entry_fd, t, &t->restore_time);
-		t->entry_fd = -1;
-		t->entry_eof = 1;
-	}
-	t->current_sparse->offset += bytes;
-	t->current_sparse->length -= bytes;
-	if (t->current_sparse->length == 0 && !t->entry_eof)
-		t->current_sparse++;
-	return (ARCHIVE_OK);
-
-abort_read_data:
-	*buff = NULL;
-	*size = 0;
-	*offset = t->entry_total;
-	if (t->entry_fd >= 0) {
-		/* Close the current file descriptor */
-		close_and_restore_time(t->entry_fd, t, &t->restore_time);
-		t->entry_fd = -1;
-	}
-	return (r);
-}
-
-static int
-next_entry(struct archive_read_disk *a, struct tree *t,
-    struct archive_entry *entry)
-{
-	const struct stat *st; /* info to use for this entry */
-	const struct stat *lst;/* lstat() information */
-	const char *name;
-	int delayed, delayed_errno, descend, r;
-	struct archive_string delayed_str;
-
-	delayed = ARCHIVE_OK;
-	delayed_errno = 0;
-	archive_string_init(&delayed_str);
-
-	st = NULL;
-	lst = NULL;
-	t->descend = 0;
-	do {
-		switch (tree_next(t)) {
-		case TREE_ERROR_FATAL:
-			archive_set_error(&a->archive, t->tree_errno,
-			    "%s: Unable to continue traversing directory tree",
-			    tree_current_path(t));
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			tree_enter_initial_dir(t);
-			return (ARCHIVE_FATAL);
-		case TREE_ERROR_DIR:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: Couldn't visit directory",
-			    tree_current_path(t));
-			tree_enter_initial_dir(t);
-			return (ARCHIVE_FAILED);
-		case 0:
-			tree_enter_initial_dir(t);
-			return (ARCHIVE_EOF);
-		case TREE_POSTDESCENT:
-		case TREE_POSTASCENT:
-			break;
-		case TREE_REGULAR:
-			lst = tree_current_lstat(t);
-			if (lst == NULL) {
-			    if (errno == ENOENT && t->depth > 0) {
-				delayed = ARCHIVE_WARN;
-				delayed_errno = errno;
-				if (delayed_str.length == 0) {
-					archive_string_sprintf(&delayed_str,
-					    "%s", tree_current_path(t));
-				} else {
-					archive_string_sprintf(&delayed_str,
-					    " %s", tree_current_path(t));
-				}
-			    } else {
-				archive_set_error(&a->archive, errno,
-				    "%s: Cannot stat",
-				    tree_current_path(t));
-				tree_enter_initial_dir(t);
-				return (ARCHIVE_FAILED);
-			    }
-			}
-			break;
-		}
-	} while (lst == NULL);
-
-#ifdef __APPLE__
-	if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
-		/* If we're using copyfile(), ignore "._XXX" files. */
-		const char *bname = strrchr(tree_current_path(t), '/');
-		if (bname == NULL)
-			bname = tree_current_path(t);
-		else
-			++bname;
-		if (bname[0] == '.' && bname[1] == '_')
-			return (ARCHIVE_RETRY);
-	}
-#endif
-
-	archive_entry_copy_pathname(entry, tree_current_path(t));
-	/*
-	 * Perform path matching.
-	 */
-	if (a->matching) {
-		r = archive_match_path_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/*
-	 * Distinguish 'L'/'P'/'H' symlink following.
-	 */
-	switch(t->symlink_mode) {
-	case 'H':
-		/* 'H': After the first item, rest like 'P'. */
-		t->symlink_mode = 'P';
-		/* 'H': First item (from command line) like 'L'. */
-		/* FALLTHROUGH */
-	case 'L':
-		/* 'L': Do descend through a symlink to dir. */
-		descend = tree_current_is_dir(t);
-		/* 'L': Follow symlinks to files. */
-		a->symlink_mode = 'L';
-		a->follow_symlinks = 1;
-		/* 'L': Archive symlinks as targets, if we can. */
-		st = tree_current_stat(t);
-		if (st != NULL && !tree_target_is_same_as_parent(t, st))
-			break;
-		/* If stat fails, we have a broken symlink;
-		 * in that case, don't follow the link. */
-		/* FALLTHROUGH */
-	default:
-		/* 'P': Don't descend through a symlink to dir. */
-		descend = tree_current_is_physical_dir(t);
-		/* 'P': Don't follow symlinks to files. */
-		a->symlink_mode = 'P';
-		a->follow_symlinks = 0;
-		/* 'P': Archive symlinks as symlinks. */
-		st = lst;
-		break;
-	}
-
-	if (update_current_filesystem(a, st->st_dev) != ARCHIVE_OK) {
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		tree_enter_initial_dir(t);
-		return (ARCHIVE_FATAL);
-	}
-	if (t->initial_filesystem_id == -1)
-		t->initial_filesystem_id = t->current_filesystem_id;
-	if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
-		if (t->initial_filesystem_id != t->current_filesystem_id)
-			descend = 0;
-	}
-	t->descend = descend;
-
-	/*
-	 * Honor nodump flag.
-	 * If the file is marked with nodump flag, do not return this entry.
-	 */
-	if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-		if (st->st_flags & UF_NODUMP)
-			return (ARCHIVE_RETRY);
-#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
-       defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
-      (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
-       defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
-		if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
-			int stflags;
-
-			t->entry_fd = open_on_current_dir(t,
-			    tree_current_access_path(t),
-			    O_RDONLY | O_NONBLOCK | O_CLOEXEC);
-			__archive_ensure_cloexec_flag(t->entry_fd);
-			if (t->entry_fd >= 0) {
-				r = ioctl(t->entry_fd,
-#ifdef FS_IOC_GETFLAGS
-				FS_IOC_GETFLAGS,
-#else
-				EXT2_IOC_GETFLAGS,
-#endif
-					&stflags);
-#ifdef FS_NODUMP_FL
-				if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
-#else
-				if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
-#endif
-					return (ARCHIVE_RETRY);
-			}
-		}
-#endif
-	}
-
-	archive_entry_copy_stat(entry, st);
-
-	/* Save the times to be restored. This must be in before
-	 * calling archive_read_disk_descend() or any chance of it,
-	 * especially, invoking a callback. */
-	t->restore_time.mtime = archive_entry_mtime(entry);
-	t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
-	t->restore_time.atime = archive_entry_atime(entry);
-	t->restore_time.atime_nsec = archive_entry_atime_nsec(entry);
-	t->restore_time.filetype = archive_entry_filetype(entry);
-	t->restore_time.noatime = t->current_filesystem->noatime;
-
-	/*
-	 * Perform time matching.
-	 */
-	if (a->matching) {
-		r = archive_match_time_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/* Lookup uname/gname */
-	name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
-	if (name != NULL)
-		archive_entry_copy_uname(entry, name);
-	name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
-	if (name != NULL)
-		archive_entry_copy_gname(entry, name);
-
-	/*
-	 * Perform owner matching.
-	 */
-	if (a->matching) {
-		r = archive_match_owner_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/*
-	 * Invoke a meta data filter callback.
-	 */
-	if (a->metadata_filter_func) {
-		if (!a->metadata_filter_func(&(a->archive),
-		    a->metadata_filter_data, entry))
-			return (ARCHIVE_RETRY);
-	}
-
-	/*
-	 * Populate the archive_entry with metadata from the disk.
-	 */
-	archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
-	r = archive_read_disk_entry_from_file(&(a->archive), entry,
-		t->entry_fd, st);
-
-	if (r == ARCHIVE_OK) {
-		r = delayed;
-		if (r != ARCHIVE_OK) {
-			archive_string_sprintf(&delayed_str, ": %s",
-			    "File removed before we read it");
-			archive_set_error(&(a->archive), delayed_errno,
-			    "%s", delayed_str.s);
-		}
-	}
-	archive_string_free(&delayed_str);
-
-	return (r);
-}
-
-static int
-_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
-{
-	int ret;
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	*entryp = NULL;
-	ret = _archive_read_next_header2(_a, a->entry);
-	*entryp = a->entry;
-	return ret;
-}
-
-static int
-_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_next_header2");
-
-	t = a->tree;
-	if (t->entry_fd >= 0) {
-		close_and_restore_time(t->entry_fd, t, &t->restore_time);
-		t->entry_fd = -1;
-	}
-
-	archive_entry_clear(entry);
-
-	for (;;) {
-		r = next_entry(a, t, entry);
-		if (t->entry_fd >= 0) {
-			close(t->entry_fd);
-			t->entry_fd = -1;
-		}
-
-		if (r == ARCHIVE_RETRY) {
-			archive_entry_clear(entry);
-			continue;
-		}
-		break;
-	}
-
-	/* Return to the initial directory. */
-	tree_enter_initial_dir(t);
-
-	/*
-	 * EOF and FATAL are persistent at this layer.  By
-	 * modifying the state, we guarantee that future calls to
-	 * read a header or read data will fail.
-	 */
-	switch (r) {
-	case ARCHIVE_EOF:
-		a->archive.state = ARCHIVE_STATE_EOF;
-		break;
-	case ARCHIVE_OK:
-	case ARCHIVE_WARN:
-		/* Overwrite the sourcepath based on the initial directory. */
-		archive_entry_copy_sourcepath(entry, tree_current_path(t));
-		t->entry_total = 0;
-		if (archive_entry_filetype(entry) == AE_IFREG) {
-			t->nlink = archive_entry_nlink(entry);
-			t->entry_remaining_bytes = archive_entry_size(entry);
-			t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0;
-			if (!t->entry_eof &&
-			    setup_sparse(a, entry) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		} else {
-			t->entry_remaining_bytes = 0;
-			t->entry_eof = 1;
-		}
-		a->archive.state = ARCHIVE_STATE_DATA;
-		break;
-	case ARCHIVE_RETRY:
-		break;
-	case ARCHIVE_FATAL:
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		break;
-	}
-
-	__archive_reset_read_data(&a->archive);
-	return (r);
-}
-
-static int
-setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
-{
-	struct tree *t = a->tree;
-	int64_t length, offset;
-	int i;
-
-	t->sparse_count = archive_entry_sparse_reset(entry);
-	if (t->sparse_count+1 > t->sparse_list_size) {
-		free(t->sparse_list);
-		t->sparse_list_size = t->sparse_count + 1;
-		t->sparse_list = malloc(sizeof(t->sparse_list[0]) *
-		    t->sparse_list_size);
-		if (t->sparse_list == NULL) {
-			t->sparse_list_size = 0;
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate data");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	}
-	for (i = 0; i < t->sparse_count; i++) {
-		archive_entry_sparse_next(entry, &offset, &length);
-		t->sparse_list[i].offset = offset;
-		t->sparse_list[i].length = length;
-	}
-	if (i == 0) {
-		t->sparse_list[i].offset = 0;
-		t->sparse_list[i].length = archive_entry_size(entry);
-	} else {
-		t->sparse_list[i].offset = archive_entry_size(entry);
-		t->sparse_list[i].length = 0;
-	}
-	t->current_sparse = t->sparse_list;
-
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
-    void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
-    void *_client_data)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
-	a->matching = _ma;
-	a->excluded_cb_func = _excluded_func;
-	a->excluded_cb_data = _client_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_metadata_filter_callback(struct archive *_a,
-    int (*_metadata_filter_func)(struct archive *, void *,
-    struct archive_entry *), void *_client_data)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
-	    "archive_read_disk_set_metadata_filter_callback");
-
-	a->metadata_filter_func = _metadata_filter_func;
-	a->metadata_filter_data = _client_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_can_descend(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_disk_can_descend");
-
-	return (t->visit_type == TREE_REGULAR && t->descend);
-}
-
-/*
- * Called by the client to mark the directory just returned from
- * tree_next() as needing to be visited.
- */
-int
-archive_read_disk_descend(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_disk_descend");
-
-	if (!archive_read_disk_can_descend(_a))
-		return (ARCHIVE_OK);
-
-	/*
-	 * We must not treat the initial specified path as a physical dir,
-	 * because if we do then we will try and ascend out of it by opening
-	 * ".." which is (a) wrong and (b) causes spurious permissions errors
-	 * if ".." is not readable by us. Instead, treat it as if it were a
-	 * symlink. (This uses an extra fd, but it can only happen once at the
-	 * top level of a traverse.) But we can't necessarily assume t->st is
-	 * valid here (though t->lst is), which complicates the logic a
-	 * little.
-	 */
-	if (tree_current_is_physical_dir(t)) {
-		tree_push(t, t->basename, t->current_filesystem_id,
-		    t->lst.st_dev, t->lst.st_ino, &t->restore_time);
-		if (t->stack->parent->parent != NULL)
-			t->stack->flags |= isDir;
-		else
-			t->stack->flags |= isDirLink;
-	} else if (tree_current_is_dir(t)) {
-		tree_push(t, t->basename, t->current_filesystem_id,
-		    t->st.st_dev, t->st.st_ino, &t->restore_time);
-		t->stack->flags |= isDirLink;
-	}
-	t->descend = 0;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_open(struct archive *_a, const char *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
-	    "archive_read_disk_open");
-	archive_clear_error(&a->archive);
-
-	return (_archive_read_disk_open(_a, pathname));
-}
-
-int
-archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct archive_string path;
-	int ret;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
-	    "archive_read_disk_open_w");
-	archive_clear_error(&a->archive);
-
-	/* Make a char string from a wchar_t string. */
-	archive_string_init(&path);
-	if (archive_string_append_from_wcs(&path, pathname,
-	    wcslen(pathname)) != 0) {
-		if (errno == ENOMEM)
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-		else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't convert a path to a char string");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		ret = ARCHIVE_FATAL;
-	} else
-		ret = _archive_read_disk_open(_a, path.s);
-
-	archive_string_free(&path);
-	return (ret);
-}
-
-static int
-_archive_read_disk_open(struct archive *_a, const char *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	if (a->tree != NULL)
-		a->tree = tree_reopen(a->tree, pathname,
-		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
-	else
-		a->tree = tree_open(pathname, a->symlink_mode,
-		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
-	if (a->tree == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate tar data");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	a->archive.state = ARCHIVE_STATE_HEADER;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return a current filesystem ID which is index of the filesystem entry
- * you've visited through archive_read_disk.
- */
-int
-archive_read_disk_current_filesystem(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem_id);
-}
-
-static int
-update_current_filesystem(struct archive_read_disk *a, int64_t dev)
-{
-	struct tree *t = a->tree;
-	int i, fid;
-
-	if (t->current_filesystem != NULL &&
-	    t->current_filesystem->dev == dev)
-		return (ARCHIVE_OK);
-
-	for (i = 0; i < t->max_filesystem_id; i++) {
-		if (t->filesystem_table[i].dev == dev) {
-			/* There is the filesystem ID we've already generated. */
-			t->current_filesystem_id = i;
-			t->current_filesystem = &(t->filesystem_table[i]);
-			return (ARCHIVE_OK);
-		}
-	}
-
-	/*
-	 * This is the new filesystem which we have to generate a new ID for.
-	 */
-	fid = t->max_filesystem_id++;
-	if (t->max_filesystem_id > t->allocated_filesystem) {
-		size_t s;
-		void *p;
-
-		s = t->max_filesystem_id * 2;
-		p = realloc(t->filesystem_table,
-		        s * sizeof(*t->filesystem_table));
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate tar data");
-			return (ARCHIVE_FATAL);
-		}
-		t->filesystem_table = (struct filesystem *)p;
-		t->allocated_filesystem = s;
-	}
-	t->current_filesystem_id = fid;
-	t->current_filesystem = &(t->filesystem_table[fid]);
-	t->current_filesystem->dev = dev;
-	t->current_filesystem->allocation_ptr = NULL;
-	t->current_filesystem->buff = NULL;
-
-	/* Setup the current filesystem properties which depend on
-	 * platform specific. */
-	return (setup_current_filesystem(a));
-}
-
-/*
- * Returns 1 if current filesystem is generated filesystem, 0 if it is not
- * or -1 if it is unknown.
- */
-int
-archive_read_disk_current_filesystem_is_synthetic(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem->synthetic);
-}
-
-/*
- * Returns 1 if current filesystem is remote filesystem, 0 if it is not
- * or -1 if it is unknown.
- */
-int
-archive_read_disk_current_filesystem_is_remote(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem->remote);
-}
-
-#if defined(_PC_REC_INCR_XFER_SIZE) && defined(_PC_REC_MAX_XFER_SIZE) &&\
-	defined(_PC_REC_MIN_XFER_SIZE) && defined(_PC_REC_XFER_ALIGN)
-static int
-get_xfer_size(struct tree *t, int fd, const char *path)
-{
-	t->current_filesystem->xfer_align = -1;
-	errno = 0;
-	if (fd >= 0) {
-		t->current_filesystem->incr_xfer_size =
-		    fpathconf(fd, _PC_REC_INCR_XFER_SIZE);
-		t->current_filesystem->max_xfer_size =
-		    fpathconf(fd, _PC_REC_MAX_XFER_SIZE);
-		t->current_filesystem->min_xfer_size =
-		    fpathconf(fd, _PC_REC_MIN_XFER_SIZE);
-		t->current_filesystem->xfer_align =
-		    fpathconf(fd, _PC_REC_XFER_ALIGN);
-	} else if (path != NULL) {
-		t->current_filesystem->incr_xfer_size =
-		    pathconf(path, _PC_REC_INCR_XFER_SIZE);
-		t->current_filesystem->max_xfer_size =
-		    pathconf(path, _PC_REC_MAX_XFER_SIZE);
-		t->current_filesystem->min_xfer_size =
-		    pathconf(path, _PC_REC_MIN_XFER_SIZE);
-		t->current_filesystem->xfer_align =
-		    pathconf(path, _PC_REC_XFER_ALIGN);
-	}
-	/* At least we need an alignment size. */
-	if (t->current_filesystem->xfer_align == -1)
-		return ((errno == EINVAL)?1:-1);
-	else
-		return (0);
-}
-#else
-static int
-get_xfer_size(struct tree *t, int fd, const char *path)
-{
-	(void)t; /* UNUSED */
-	(void)fd; /* UNUSED */
-	(void)path; /* UNUSED */
-	return (1);/* Not supported */
-}
-#endif
-
-#if defined(HAVE_STATVFS)
-static inline __LA_UNUSED void
-set_statvfs_transfer_size(struct filesystem *fs, const struct statvfs *sfs)
-{
-	fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1;
-	fs->max_xfer_size = -1;
-#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
-	fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
-	fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
-#else
-	fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
-	fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
-#endif
-}
-#endif
-
-#if defined(HAVE_STRUCT_STATFS)
-static inline __LA_UNUSED void
-set_statfs_transfer_size(struct filesystem *fs, const struct statfs *sfs)
-{
-	fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
-	fs->max_xfer_size = -1;
-#if defined(HAVE_STRUCT_STATFS_F_IOSIZE)
-	fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
-	fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
-#else
-	fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
-	fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
-#endif
-}
-#endif
-
-#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) && \
-    defined(HAVE_FSTATFS) && defined(MNT_LOCAL) && !defined(ST_LOCAL)
-
-/*
- * Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	struct statfs sfs;
-#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
-/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
- * this accurate; some platforms have both and we need the one that's
- * used by getvfsbyname()
- *
- * Then the following would become:
- *  #if defined(GETVFSBYNAME_ARG_TYPE)
- *   GETVFSBYNAME_ARG_TYPE vfc;
- *  #endif
- */
-#  if defined(HAVE_STRUCT_XVFSCONF)
-	struct xvfsconf vfc;
-#  else
-	struct vfsconf vfc;
-#  endif
-#endif
-	int r, xr = 0;
-#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
-	long nm;
-#endif
-
-	t->current_filesystem->synthetic = -1;
-	t->current_filesystem->remote = -1;
-	if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT)
-		/*
-		 * Get file system statistics on any directory
-		 * where current is.
-		 */
-		int fd = openat(tree_current_dir_fd(t),
-		    tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
-		__archive_ensure_cloexec_flag(fd);
-		if (fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "openat failed");
-			return (ARCHIVE_FAILED);
-		}
-		r = fstatfs(fd, &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, fd, NULL);
-		close(fd);
-#else
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-		r = statfs(tree_current_access_path(t), &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, tree_current_access_path(t));
-#endif
-	} else {
-		r = fstatfs(tree_current_dir_fd(t), &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-	}
-	if (r == -1 || xr == -1) {
-		archive_set_error(&a->archive, errno, "statfs failed");
-		return (ARCHIVE_FAILED);
-	} else if (xr == 1) {
-		/* pathconf(_PC_REX_*) operations are not supported. */
-		set_statfs_transfer_size(t->current_filesystem, &sfs);
-	}
-	if (sfs.f_flags & MNT_LOCAL)
-		t->current_filesystem->remote = 0;
-	else
-		t->current_filesystem->remote = 1;
-
-#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
-	r = getvfsbyname(sfs.f_fstypename, &vfc);
-	if (r == -1) {
-		archive_set_error(&a->archive, errno, "getvfsbyname failed");
-		return (ARCHIVE_FAILED);
-	}
-	if (vfc.vfc_flags & VFCF_SYNTHETIC)
-		t->current_filesystem->synthetic = 1;
-	else
-		t->current_filesystem->synthetic = 0;
-#endif
-
-#if defined(MNT_NOATIME)
-	if (sfs.f_flags & MNT_NOATIME)
-		t->current_filesystem->noatime = 1;
-	else
-#endif
-		t->current_filesystem->noatime = 0;
-
-#if defined(USE_READDIR_R)
-	/* Set maximum filename length. */
-#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
-	t->current_filesystem->name_max = sfs.f_namemax;
-#else
-# if defined(_PC_NAME_MAX)
-	/* Mac OS X does not have f_namemax in struct statfs. */
-	if (tree_current_is_symblic_link_target(t)) {
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-		nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
-	} else
-		nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
-# else
-	nm = -1;
-# endif
-	if (nm == -1)
-		t->current_filesystem->name_max = NAME_MAX;
-	else
-		t->current_filesystem->name_max = nm;
-#endif
-	if (t->current_filesystem->name_max == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Cannot determine name_max");
-		return (ARCHIVE_FAILED);
-	}
-#endif /* USE_READDIR_R */
-	return (ARCHIVE_OK);
-}
-
-#elif (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) && defined(ST_LOCAL)
-
-/*
- * Gather current filesystem properties on NetBSD
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	struct statvfs svfs;
-	int r, xr = 0;
-
-	t->current_filesystem->synthetic = -1;
-	if (tree_enter_working_dir(t) != 0) {
-		archive_set_error(&a->archive, errno, "fchdir failed");
-		return (ARCHIVE_FAILED);
-	}
-	if (tree_current_is_symblic_link_target(t)) {
-		r = statvfs(tree_current_access_path(t), &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, tree_current_access_path(t));
-	} else {
-#ifdef HAVE_FSTATVFS
-		r = fstatvfs(tree_current_dir_fd(t), &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-#else
-		r = statvfs(".", &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, ".");
-#endif
-	}
-	if (r == -1 || xr == -1) {
-		t->current_filesystem->remote = -1;
-		archive_set_error(&a->archive, errno, "statvfs failed");
-		return (ARCHIVE_FAILED);
-	} else if (xr == 1) {
-		/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
-		 * for pathconf() function. */
-		set_statvfs_transfer_size(t->current_filesystem, &svfs);
-	}
-	if (svfs.f_flag & ST_LOCAL)
-		t->current_filesystem->remote = 0;
-	else
-		t->current_filesystem->remote = 1;
-
-#if defined(ST_NOATIME)
-	if (svfs.f_flag & ST_NOATIME)
-		t->current_filesystem->noatime = 1;
-	else
-#endif
-		t->current_filesystem->noatime = 0;
-
-	/* Set maximum filename length. */
-	t->current_filesystem->name_max = svfs.f_namemax;
-	return (ARCHIVE_OK);
-}
-
-#elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_LINUX_MAGIC_H) &&\
-	defined(HAVE_STATFS) && defined(HAVE_FSTATFS)
-/*
- * Note: statfs is deprecated since LSB 3.2
- */
-
-#ifndef CIFS_SUPER_MAGIC
-#define CIFS_SUPER_MAGIC 0xFF534D42
-#endif
-#ifndef DEVFS_SUPER_MAGIC
-#define DEVFS_SUPER_MAGIC 0x1373
-#endif
-
-/*
- * Gather current filesystem properties on Linux
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	struct statfs sfs;
-#if defined(HAVE_STATVFS)
-	struct statvfs svfs;
-#endif
-	int r, vr = 0, xr = 0;
-
-	if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT)
-		/*
-		 * Get file system statistics on any directory
-		 * where current is.
-		 */
-		int fd = openat(tree_current_dir_fd(t),
-		    tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
-		__archive_ensure_cloexec_flag(fd);
-		if (fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "openat failed");
-			return (ARCHIVE_FAILED);
-		}
-#if defined(HAVE_FSTATVFS)
-		vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
-#endif
-		r = fstatfs(fd, &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, fd, NULL);
-		close(fd);
-#else
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-#if defined(HAVE_STATVFS)
-		vr = statvfs(tree_current_access_path(t), &svfs);
-#endif
-		r = statfs(tree_current_access_path(t), &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, tree_current_access_path(t));
-#endif
-	} else {
-#ifdef HAVE_FSTATFS
-#if defined(HAVE_FSTATVFS)
-		vr = fstatvfs(tree_current_dir_fd(t), &svfs);
-#endif
-		r = fstatfs(tree_current_dir_fd(t), &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-#else
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-#if defined(HAVE_STATVFS)
-		vr = statvfs(".", &svfs);
-#endif
-		r = statfs(".", &sfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, ".");
-#endif
-	}
-	if (r == -1 || xr == -1 || vr == -1) {
-		t->current_filesystem->synthetic = -1;
-		t->current_filesystem->remote = -1;
-		archive_set_error(&a->archive, errno, "statfs failed");
-		return (ARCHIVE_FAILED);
-	} else if (xr == 1) {
-		/* pathconf(_PC_REX_*) operations are not supported. */
-#if defined(HAVE_STATVFS)
-		set_statvfs_transfer_size(t->current_filesystem, &svfs);
-#else
-		set_statfs_transfer_size(t->current_filesystem, &sfs);
-#endif
-	}
-	switch (sfs.f_type) {
-	case AFS_SUPER_MAGIC:
-	case CIFS_SUPER_MAGIC:
-	case CODA_SUPER_MAGIC:
-	case NCP_SUPER_MAGIC:/* NetWare */
-	case NFS_SUPER_MAGIC:
-	case SMB_SUPER_MAGIC:
-		t->current_filesystem->remote = 1;
-		t->current_filesystem->synthetic = 0;
-		break;
-	case DEVFS_SUPER_MAGIC:
-	case PROC_SUPER_MAGIC:
-	case USBDEVICE_SUPER_MAGIC:
-		t->current_filesystem->remote = 0;
-		t->current_filesystem->synthetic = 1;
-		break;
-	default:
-		t->current_filesystem->remote = 0;
-		t->current_filesystem->synthetic = 0;
-		break;
-	}
-
-#if defined(ST_NOATIME)
-#if defined(HAVE_STATVFS)
-	if (svfs.f_flag & ST_NOATIME)
-#else
-	if (sfs.f_flags & ST_NOATIME)
-#endif
-		t->current_filesystem->noatime = 1;
-	else
-#endif
-		t->current_filesystem->noatime = 0;
-
-#if defined(USE_READDIR_R)
-	/* Set maximum filename length. */
-#if defined(HAVE_STATVFS)
-	t->current_filesystem->name_max = svfs.f_namemax;
-#else
-	t->current_filesystem->name_max = sfs.f_namelen;
-#endif
-	if (t->current_filesystem->name_max == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Cannot determine name_max");
-		return (ARCHIVE_FAILED);
-	}
-#endif
-	return (ARCHIVE_OK);
-}
-
-#elif defined(HAVE_SYS_STATVFS_H) &&\
-	(defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS))
-
-/*
- * Gather current filesystem properties on other posix platform.
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	struct statvfs svfs;
-	int r, xr = 0;
-
-	t->current_filesystem->synthetic = -1;/* Not supported */
-	t->current_filesystem->remote = -1;/* Not supported */
-	if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT)
-		/*
-		 * Get file system statistics on any directory
-		 * where current is.
-		 */
-		int fd = openat(tree_current_dir_fd(t),
-		    tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
-		__archive_ensure_cloexec_flag(fd);
-		if (fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "openat failed");
-			return (ARCHIVE_FAILED);
-		}
-		r = fstatvfs(fd, &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, fd, NULL);
-		close(fd);
-#else
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-		r = statvfs(tree_current_access_path(t), &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, tree_current_access_path(t));
-#endif
-	} else {
-#ifdef HAVE_FSTATVFS
-		r = fstatvfs(tree_current_dir_fd(t), &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-#else
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-		r = statvfs(".", &svfs);
-		if (r == 0)
-			xr = get_xfer_size(t, -1, ".");
-#endif
-	}
-	if (r == -1 || xr == -1) {
-		t->current_filesystem->synthetic = -1;
-		t->current_filesystem->remote = -1;
-		archive_set_error(&a->archive, errno, "statvfs failed");
-		return (ARCHIVE_FAILED);
-	} else if (xr == 1) {
-		/* pathconf(_PC_REX_*) operations are not supported. */
-		set_statvfs_transfer_size(t->current_filesystem, &svfs);
-	}
-
-#if defined(ST_NOATIME)
-	if (svfs.f_flag & ST_NOATIME)
-		t->current_filesystem->noatime = 1;
-	else
-#endif
-		t->current_filesystem->noatime = 0;
-
-#if defined(USE_READDIR_R)
-	/* Set maximum filename length. */
-	t->current_filesystem->name_max = svfs.f_namemax;
-	if (t->current_filesystem->name_max == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Cannot determine name_max");
-		return (ARCHIVE_FAILED);
-	}
-#endif
-	return (ARCHIVE_OK);
-}
-
-#else
-
-/*
- * Generic: Gather current filesystem properties.
- * TODO: Is this generic function really needed?
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
-	long nm;
-#endif
-	t->current_filesystem->synthetic = -1;/* Not supported */
-	t->current_filesystem->remote = -1;/* Not supported */
-	t->current_filesystem->noatime = 0;
-	(void)get_xfer_size(t, -1, ".");/* Dummy call to avoid build error. */
-	t->current_filesystem->xfer_align = -1;/* Unknown */
-	t->current_filesystem->max_xfer_size = -1;
-	t->current_filesystem->min_xfer_size = -1;
-	t->current_filesystem->incr_xfer_size = -1;
-
-#if defined(USE_READDIR_R)
-	/* Set maximum filename length. */
-#  if defined(_PC_NAME_MAX)
-	if (tree_current_is_symblic_link_target(t)) {
-		if (tree_enter_working_dir(t) != 0) {
-			archive_set_error(&a->archive, errno, "fchdir failed");
-			return (ARCHIVE_FAILED);
-		}
-		nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
-	} else
-		nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
-	if (nm == -1)
-#  endif /* _PC_NAME_MAX */
-		/*
-		 * Some systems (HP-UX or others?) incorrectly defined
-		 * NAME_MAX macro to be a smaller value.
-		 */
-#  if defined(NAME_MAX) && NAME_MAX >= 255
-		t->current_filesystem->name_max = NAME_MAX;
-#  else
-		/* No way to get a trusted value of maximum filename
-		 * length. */
-		t->current_filesystem->name_max = PATH_MAX;
-#  endif /* NAME_MAX */
-#  if defined(_PC_NAME_MAX)
-	else
-		t->current_filesystem->name_max = nm;
-#  endif /* _PC_NAME_MAX */
-	if (t->current_filesystem->name_max == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Cannot determine name_max");
-		return (ARCHIVE_FAILED);
-	}
-#endif /* USE_READDIR_R */
-	return (ARCHIVE_OK);
-}
-
-#endif
-
-static int
-close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
-{
-#ifndef HAVE_UTIMES
-	(void)t; /* UNUSED */
-	(void)rt; /* UNUSED */
-	return (close(fd));
-#else
-#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
-	struct timespec timespecs[2];
-#endif
-	struct timeval times[2];
-
-	if ((t->flags & needsRestoreTimes) == 0 || rt->noatime) {
-		if (fd >= 0)
-			return (close(fd));
-		else
-			return (0);
-	}
-
-#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
-	timespecs[1].tv_sec = rt->mtime;
-	timespecs[1].tv_nsec = rt->mtime_nsec;
-
-	timespecs[0].tv_sec = rt->atime;
-	timespecs[0].tv_nsec = rt->atime_nsec;
-	/* futimens() is defined in POSIX.1-2008. */
-	if (futimens(fd, timespecs) == 0)
-		return (close(fd));
-#endif
-
-	times[1].tv_sec = rt->mtime;
-	times[1].tv_usec = rt->mtime_nsec / 1000;
-
-	times[0].tv_sec = rt->atime;
-	times[0].tv_usec = rt->atime_nsec / 1000;
-
-#if !defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES) && !defined(__CYGWIN__)
-	if (futimes(fd, times) == 0)
-		return (close(fd));
-#endif
-	close(fd);
-#if defined(HAVE_FUTIMESAT)
-	if (futimesat(tree_current_dir_fd(t), rt->name, times) == 0)
-		return (0);
-#endif
-#ifdef HAVE_LUTIMES
-	if (lutimes(rt->name, times) != 0)
-#else
-	if (AE_IFLNK != rt->filetype && utimes(rt->name, times) != 0)
-#endif
-		return (-1);
-#endif
-	return (0);
-}
-
-static int
-open_on_current_dir(struct tree *t, const char *path, int flags)
-{
-#ifdef HAVE_OPENAT
-	return (openat(tree_current_dir_fd(t), path, flags));
-#else
-	if (tree_enter_working_dir(t) != 0)
-		return (-1);
-	return (open(path, flags));
-#endif
-}
-
-static int
-tree_dup(int fd)
-{
-	int new_fd;
-#ifdef F_DUPFD_CLOEXEC
-	static volatile int can_dupfd_cloexec = 1;
-
-	if (can_dupfd_cloexec) {
-		new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
-		if (new_fd != -1)
-			return (new_fd);
-		/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
-		 * but it cannot be used. So we have to try dup(). */
-		/* We won't try F_DUPFD_CLOEXEC. */
-		can_dupfd_cloexec = 0;
-	}
-#endif /* F_DUPFD_CLOEXEC */
-	new_fd = dup(fd);
-	__archive_ensure_cloexec_flag(new_fd);
-	return (new_fd);
-}
-
-/*
- * Add a directory path to the current stack.
- */
-static void
-tree_push(struct tree *t, const char *path, int filesystem_id,
-    int64_t dev, int64_t ino, struct restore_time *rt)
-{
-	struct tree_entry *te;
-
-	te = calloc(1, sizeof(*te));
-	if (te == NULL)
-		__archive_errx(1, "Out of memory");
-	te->next = t->stack;
-	te->parent = t->current;
-	if (te->parent)
-		te->depth = te->parent->depth + 1;
-	t->stack = te;
-	archive_string_init(&te->name);
-	te->symlink_parent_fd = -1;
-	archive_strcpy(&te->name, path);
-	te->flags = needsDescent | needsOpen | needsAscent;
-	te->filesystem_id = filesystem_id;
-	te->dev = dev;
-	te->ino = ino;
-	te->dirname_length = t->dirname_length;
-	te->restore_time.name = te->name.s;
-	if (rt != NULL) {
-		te->restore_time.mtime = rt->mtime;
-		te->restore_time.mtime_nsec = rt->mtime_nsec;
-		te->restore_time.atime = rt->atime;
-		te->restore_time.atime_nsec = rt->atime_nsec;
-		te->restore_time.filetype = rt->filetype;
-		te->restore_time.noatime = rt->noatime;
-	}
-}
-
-/*
- * Append a name to the current dir path.
- */
-static void
-tree_append(struct tree *t, const char *name, size_t name_length)
-{
-	size_t size_needed;
-
-	t->path.s[t->dirname_length] = '\0';
-	t->path.length = t->dirname_length;
-	/* Strip trailing '/' from name, unless entire name is "/". */
-	while (name_length > 1 && name[name_length - 1] == '/')
-		name_length--;
-
-	/* Resize pathname buffer as needed. */
-	size_needed = name_length + t->dirname_length + 2;
-	archive_string_ensure(&t->path, size_needed);
-	/* Add a separating '/' if it's needed. */
-	if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != '/')
-		archive_strappend_char(&t->path, '/');
-	t->basename = t->path.s + archive_strlen(&t->path);
-	archive_strncat(&t->path, name, name_length);
-	t->restore_time.name = t->basename;
-}
-
-/*
- * Open a directory tree for traversal.
- */
-static struct tree *
-tree_open(const char *path, int symlink_mode, int restore_time)
-{
-	struct tree *t;
-
-	if ((t = calloc(1, sizeof(*t))) == NULL)
-		return (NULL);
-	archive_string_init(&t->path);
-	archive_string_ensure(&t->path, 31);
-	t->initial_symlink_mode = symlink_mode;
-	return (tree_reopen(t, path, restore_time));
-}
-
-static struct tree *
-tree_reopen(struct tree *t, const char *path, int restore_time)
-{
-#if defined(O_PATH)
-	/* Linux */
-	const int o_flag = O_PATH;
-#elif defined(O_SEARCH)
-	/* SunOS */
-	const int o_flag = O_SEARCH;
-#elif defined(__FreeBSD__) && defined(O_EXEC)
-	/* FreeBSD */
-	const int o_flag = O_EXEC;
-#endif
-
-	t->flags = (restore_time != 0)?needsRestoreTimes:0;
-	t->flags |= onInitialDir;
-	t->visit_type = 0;
-	t->tree_errno = 0;
-	t->dirname_length = 0;
-	t->depth = 0;
-	t->descend = 0;
-	t->current = NULL;
-	t->d = INVALID_DIR_HANDLE;
-	t->symlink_mode = t->initial_symlink_mode;
-	archive_string_empty(&t->path);
-	t->entry_fd = -1;
-	t->entry_eof = 0;
-	t->entry_remaining_bytes = 0;
-	t->initial_filesystem_id = -1;
-
-	/* First item is set up a lot like a symlink traversal. */
-	tree_push(t, path, 0, 0, 0, NULL);
-	t->stack->flags = needsFirstVisit;
-	t->maxOpenCount = t->openCount = 1;
-	t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
-#if defined(O_PATH) || defined(O_SEARCH) || \
- (defined(__FreeBSD__) && defined(O_EXEC))
-	/*
-	 * Most likely reason to fail opening "." is that it's not readable,
-	 * so try again for execute. The consequences of not opening this are
-	 * unhelpful and unnecessary errors later.
-	 */
-	if (t->initial_dir_fd < 0)
-		t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
-#endif
-	__archive_ensure_cloexec_flag(t->initial_dir_fd);
-	t->working_dir_fd = tree_dup(t->initial_dir_fd);
-	return (t);
-}
-
-static int
-tree_descent(struct tree *t)
-{
-	int flag, new_fd, r = 0;
-
-	t->dirname_length = archive_strlen(&t->path);
-	flag = O_RDONLY | O_CLOEXEC;
-#if defined(O_DIRECTORY)
-	flag |= O_DIRECTORY;
-#endif
-	new_fd = open_on_current_dir(t, t->stack->name.s, flag);
-	__archive_ensure_cloexec_flag(new_fd);
-	if (new_fd < 0) {
-		t->tree_errno = errno;
-		r = TREE_ERROR_DIR;
-	} else {
-		t->depth++;
-		/* If it is a link, set up fd for the ascent. */
-		if (t->stack->flags & isDirLink) {
-			t->stack->symlink_parent_fd = t->working_dir_fd;
-			t->openCount++;
-			if (t->openCount > t->maxOpenCount)
-				t->maxOpenCount = t->openCount;
-		} else
-			close(t->working_dir_fd);
-		/* Renew the current working directory. */
-		t->working_dir_fd = new_fd;
-		t->flags &= ~onWorkingDir;
-	}
-	return (r);
-}
-
-/*
- * We've finished a directory; ascend back to the parent.
- */
-static int
-tree_ascend(struct tree *t)
-{
-	struct tree_entry *te;
-	int new_fd, r = 0, prev_dir_fd;
-
-	te = t->stack;
-	prev_dir_fd = t->working_dir_fd;
-	if (te->flags & isDirLink)
-		new_fd = te->symlink_parent_fd;
-	else {
-		new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
-		__archive_ensure_cloexec_flag(new_fd);
-	}
-	if (new_fd < 0) {
-		t->tree_errno = errno;
-		r = TREE_ERROR_FATAL;
-	} else {
-		/* Renew the current working directory. */
-		t->working_dir_fd = new_fd;
-		t->flags &= ~onWorkingDir;
-		/* Current directory has been changed, we should
-		 * close an fd of previous working directory. */
-		close_and_restore_time(prev_dir_fd, t, &te->restore_time);
-		if (te->flags & isDirLink) {
-			t->openCount--;
-			te->symlink_parent_fd = -1;
-		}
-		t->depth--;
-	}
-	return (r);
-}
-
-/*
- * Return to the initial directory where tree_open() was performed.
- */
-static int
-tree_enter_initial_dir(struct tree *t)
-{
-	int r = 0;
-
-	if ((t->flags & onInitialDir) == 0) {
-		r = fchdir(t->initial_dir_fd);
-		if (r == 0) {
-			t->flags &= ~onWorkingDir;
-			t->flags |= onInitialDir;
-		}
-	}
-	return (r);
-}
-
-/*
- * Restore working directory of directory traversals.
- */
-static int
-tree_enter_working_dir(struct tree *t)
-{
-	int r = 0;
-
-	/*
-	 * Change the current directory if really needed.
-	 * Sometimes this is unneeded when we did not do
-	 * descent.
-	 */
-	if (t->depth > 0 && (t->flags & onWorkingDir) == 0) {
-		r = fchdir(t->working_dir_fd);
-		if (r == 0) {
-			t->flags &= ~onInitialDir;
-			t->flags |= onWorkingDir;
-		}
-	}
-	return (r);
-}
-
-static int
-tree_current_dir_fd(struct tree *t)
-{
-	return (t->working_dir_fd);
-}
-
-/*
- * Pop the working stack.
- */
-static void
-tree_pop(struct tree *t)
-{
-	struct tree_entry *te;
-
-	t->path.s[t->dirname_length] = '\0';
-	t->path.length = t->dirname_length;
-	if (t->stack == t->current && t->current != NULL)
-		t->current = t->current->parent;
-	te = t->stack;
-	t->stack = te->next;
-	t->dirname_length = te->dirname_length;
-	t->basename = t->path.s + t->dirname_length;
-	while (t->basename[0] == '/')
-		t->basename++;
-	archive_string_free(&te->name);
-	free(te);
-}
-
-/*
- * Get the next item in the tree traversal.
- */
-static int
-tree_next(struct tree *t)
-{
-	int r;
-
-	while (t->stack != NULL) {
-		/* If there's an open dir, get the next entry from there. */
-		if (t->d != INVALID_DIR_HANDLE) {
-			r = tree_dir_next_posix(t);
-			if (r == 0)
-				continue;
-			return (r);
-		}
-
-		if (t->stack->flags & needsFirstVisit) {
-			/* Top stack item needs a regular visit. */
-			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
-			    archive_strlen(&(t->stack->name)));
-			/* t->dirname_length = t->path_length; */
-			/* tree_pop(t); */
-			t->stack->flags &= ~needsFirstVisit;
-			return (t->visit_type = TREE_REGULAR);
-		} else if (t->stack->flags & needsDescent) {
-			/* Top stack item is dir to descend into. */
-			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
-			    archive_strlen(&(t->stack->name)));
-			t->stack->flags &= ~needsDescent;
-			r = tree_descent(t);
-			if (r != 0) {
-				tree_pop(t);
-				t->visit_type = r;
-			} else
-				t->visit_type = TREE_POSTDESCENT;
-			return (t->visit_type);
-		} else if (t->stack->flags & needsOpen) {
-			t->stack->flags &= ~needsOpen;
-			r = tree_dir_next_posix(t);
-			if (r == 0)
-				continue;
-			return (r);
-		} else if (t->stack->flags & needsAscent) {
-		        /* Top stack item is dir and we're done with it. */
-			r = tree_ascend(t);
-			tree_pop(t);
-			t->visit_type = r != 0 ? r : TREE_POSTASCENT;
-			return (t->visit_type);
-		} else {
-			/* Top item on stack is dead. */
-			tree_pop(t);
-			t->flags &= ~hasLstat;
-			t->flags &= ~hasStat;
-		}
-	}
-	return (t->visit_type = 0);
-}
-
-static int
-tree_dir_next_posix(struct tree *t)
-{
-	int r;
-	const char *name;
-	size_t namelen;
-
-	if (t->d == NULL) {
-#if defined(USE_READDIR_R)
-		size_t dirent_size;
-#endif
-
-#if defined(HAVE_FDOPENDIR)
-		t->d = fdopendir(tree_dup(t->working_dir_fd));
-#else /* HAVE_FDOPENDIR */
-		if (tree_enter_working_dir(t) == 0) {
-			t->d = opendir(".");
-#ifdef HAVE_DIRFD
-			__archive_ensure_cloexec_flag(dirfd(t->d));
-#endif
-		}
-#endif /* HAVE_FDOPENDIR */
-		if (t->d == NULL) {
-			r = tree_ascend(t); /* Undo "chdir" */
-			tree_pop(t);
-			t->tree_errno = errno;
-			t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
-			return (t->visit_type);
-		}
-#if defined(USE_READDIR_R)
-		dirent_size = offsetof(struct dirent, d_name) +
-		  t->filesystem_table[t->current->filesystem_id].name_max + 1;
-		if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
-			free(t->dirent);
-			t->dirent = malloc(dirent_size);
-			if (t->dirent == NULL) {
-				closedir(t->d);
-				t->d = INVALID_DIR_HANDLE;
-				(void)tree_ascend(t);
-				tree_pop(t);
-				t->tree_errno = ENOMEM;
-				t->visit_type = TREE_ERROR_DIR;
-				return (t->visit_type);
-			}
-			t->dirent_allocated = dirent_size;
-		}
-#endif /* USE_READDIR_R */
-	}
-	for (;;) {
-		errno = 0;
-#if defined(USE_READDIR_R)
-		r = readdir_r(t->d, t->dirent, &t->de);
-#ifdef _AIX
-		/* Note: According to the man page, return value 9 indicates
-		 * that the readdir_r was not successful and the error code
-		 * is set to the global errno variable. And then if the end
-		 * of directory entries was reached, the return value is 9
-		 * and the third parameter is set to NULL and errno is
-		 * unchanged. */
-		if (r == 9)
-			r = errno;
-#endif /* _AIX */
-		if (r != 0 || t->de == NULL) {
-#else
-		t->de = readdir(t->d);
-		if (t->de == NULL) {
-			r = errno;
-#endif
-			closedir(t->d);
-			t->d = INVALID_DIR_HANDLE;
-			if (r != 0) {
-				t->tree_errno = r;
-				t->visit_type = TREE_ERROR_DIR;
-				return (t->visit_type);
-			} else
-				return (0);
-		}
-		name = t->de->d_name;
-		namelen = D_NAMELEN(t->de);
-		t->flags &= ~hasLstat;
-		t->flags &= ~hasStat;
-		if (name[0] == '.' && name[1] == '\0')
-			continue;
-		if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
-			continue;
-		tree_append(t, name, namelen);
-		return (t->visit_type = TREE_REGULAR);
-	}
-}
-
-
-/*
- * Get the stat() data for the entry just returned from tree_next().
- */
-static const struct stat *
-tree_current_stat(struct tree *t)
-{
-	if (!(t->flags & hasStat)) {
-#ifdef HAVE_FSTATAT
-		if (fstatat(tree_current_dir_fd(t),
-		    tree_current_access_path(t), &t->st, 0) != 0)
-#else
-		if (tree_enter_working_dir(t) != 0)
-			return NULL;
-		if (la_stat(tree_current_access_path(t), &t->st) != 0)
-#endif
-			return NULL;
-		t->flags |= hasStat;
-	}
-	return (&t->st);
-}
-
-/*
- * Get the lstat() data for the entry just returned from tree_next().
- */
-static const struct stat *
-tree_current_lstat(struct tree *t)
-{
-	if (!(t->flags & hasLstat)) {
-#ifdef HAVE_FSTATAT
-		if (fstatat(tree_current_dir_fd(t),
-		    tree_current_access_path(t), &t->lst,
-		    AT_SYMLINK_NOFOLLOW) != 0)
-#else
-		if (tree_enter_working_dir(t) != 0)
-			return NULL;
-#ifdef HAVE_LSTAT
-		if (lstat(tree_current_access_path(t), &t->lst) != 0)
-#else
-		if (la_stat(tree_current_access_path(t), &t->lst) != 0)
-#endif
-#endif
-			return NULL;
-		t->flags |= hasLstat;
-	}
-	return (&t->lst);
-}
-
-/*
- * Test whether current entry is a dir or link to a dir.
- */
-static int
-tree_current_is_dir(struct tree *t)
-{
-	const struct stat *st;
-	/*
-	 * If we already have lstat() info, then try some
-	 * cheap tests to determine if this is a dir.
-	 */
-	if (t->flags & hasLstat) {
-		/* If lstat() says it's a dir, it must be a dir. */
-		st = tree_current_lstat(t);
-		if (st == NULL)
-			return 0;
-		if (S_ISDIR(st->st_mode))
-			return 1;
-		/* Not a dir; might be a link to a dir. */
-		/* If it's not a link, then it's not a link to a dir. */
-		if (!S_ISLNK(st->st_mode))
-			return 0;
-		/*
-		 * It's a link, but we don't know what it's a link to,
-		 * so we'll have to use stat().
-		 */
-	}
-
-	st = tree_current_stat(t);
-	/* If we can't stat it, it's not a dir. */
-	if (st == NULL)
-		return 0;
-	/* Use the definitive test.  Hopefully this is cached. */
-	return (S_ISDIR(st->st_mode));
-}
-
-/*
- * Test whether current entry is a physical directory.  Usually, we
- * already have at least one of stat() or lstat() in memory, so we
- * use tricks to try to avoid an extra trip to the disk.
- */
-static int
-tree_current_is_physical_dir(struct tree *t)
-{
-	const struct stat *st;
-
-	/*
-	 * If stat() says it isn't a dir, then it's not a dir.
-	 * If stat() data is cached, this check is free, so do it first.
-	 */
-	if (t->flags & hasStat) {
-		st = tree_current_stat(t);
-		if (st == NULL)
-			return (0);
-		if (!S_ISDIR(st->st_mode))
-			return (0);
-	}
-
-	/*
-	 * Either stat() said it was a dir (in which case, we have
-	 * to determine whether it's really a link to a dir) or
-	 * stat() info wasn't available.  So we use lstat(), which
-	 * hopefully is already cached.
-	 */
-
-	st = tree_current_lstat(t);
-	/* If we can't stat it, it's not a dir. */
-	if (st == NULL)
-		return 0;
-	/* Use the definitive test.  Hopefully this is cached. */
-	return (S_ISDIR(st->st_mode));
-}
-
-/*
- * Test whether the same file has been in the tree as its parent.
- */
-static int
-tree_target_is_same_as_parent(struct tree *t, const struct stat *st)
-{
-	struct tree_entry *te;
-
-	for (te = t->current->parent; te != NULL; te = te->parent) {
-		if (te->dev == (int64_t)st->st_dev &&
-		    te->ino == (int64_t)st->st_ino)
-			return (1);
-	}
-	return (0);
-}
-
-/*
- * Test whether the current file is symbolic link target and
- * on the other filesystem.
- */
-static int
-tree_current_is_symblic_link_target(struct tree *t)
-{
-	static const struct stat *lst, *st;
-
-	lst = tree_current_lstat(t);
-	st = tree_current_stat(t);
-	return (st != NULL && lst != NULL &&
-	    (int64_t)st->st_dev == t->current_filesystem->dev &&
-	    st->st_dev != lst->st_dev);
-}
-
-/*
- * Return the access path for the entry just returned from tree_next().
- */
-static const char *
-tree_current_access_path(struct tree *t)
-{
-	return (t->basename);
-}
-
-/*
- * Return the full path for the entry just returned from tree_next().
- */
-static const char *
-tree_current_path(struct tree *t)
-{
-	return (t->path.s);
-}
-
-/*
- * Terminate the traversal.
- */
-static void
-tree_close(struct tree *t)
-{
-
-	if (t == NULL)
-		return;
-	if (t->entry_fd >= 0) {
-		close_and_restore_time(t->entry_fd, t, &t->restore_time);
-		t->entry_fd = -1;
-	}
-	/* Close the handle of readdir(). */
-	if (t->d != INVALID_DIR_HANDLE) {
-		closedir(t->d);
-		t->d = INVALID_DIR_HANDLE;
-	}
-	/* Release anything remaining in the stack. */
-	while (t->stack != NULL) {
-		if (t->stack->flags & isDirLink)
-			close(t->stack->symlink_parent_fd);
-		tree_pop(t);
-	}
-	if (t->working_dir_fd >= 0) {
-		close(t->working_dir_fd);
-		t->working_dir_fd = -1;
-	}
-	if (t->initial_dir_fd >= 0) {
-		close(t->initial_dir_fd);
-		t->initial_dir_fd = -1;
-	}
-}
-
-/*
- * Release any resources.
- */
-static void
-tree_free(struct tree *t)
-{
-	int i;
-
-	if (t == NULL)
-		return;
-	archive_string_free(&t->path);
-#if defined(USE_READDIR_R)
-	free(t->dirent);
-#endif
-	free(t->sparse_list);
-	for (i = 0; i < t->max_filesystem_id; i++)
-		free(t->filesystem_table[i].allocation_ptr);
-	free(t->filesystem_table);
-	free(t);
-}
-
-#endif
diff --git a/c/archive_read_disk_private.h b/c/archive_read_disk_private.h
deleted file mode 100644
--- a/c/archive_read_disk_private.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_read_disk_private.h 201105 2009-12-28 03:20:54Z kientzle $
- */
-
-#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
-#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include "archive_platform_acl.h"
-
-struct tree;
-struct archive_entry;
-
-struct archive_read_disk {
-	struct archive	archive;
-
-	/* Reused by archive_read_next_header() */
-	struct archive_entry *entry;
-
-	/*
-	 * Symlink mode is one of 'L'ogical, 'P'hysical, or 'H'ybrid,
-	 * following an old BSD convention.  'L' follows all symlinks,
-	 * 'P' follows none, 'H' follows symlinks only for the first
-	 * item.
-	 */
-	char	symlink_mode;
-
-	/*
-	 * Since symlink interaction changes, we need to track whether
-	 * we're following symlinks for the current item.  'L' mode above
-	 * sets this true, 'P' sets it false, 'H' changes it as we traverse.
-	 */
-	char	follow_symlinks;  /* Either 'L' or 'P'. */
-
-	/* Directory traversals. */
-	struct tree *tree;
-	int	(*open_on_current_dir)(struct tree*, const char *, int);
-	int	(*tree_current_dir_fd)(struct tree*);
-	int	(*tree_enter_working_dir)(struct tree*);
-
-	/* Bitfield with ARCHIVE_READDISK_* tunables */
-	int	flags;
-
-	const char * (*lookup_gname)(void *private, int64_t gid);
-	void	(*cleanup_gname)(void *private);
-	void	 *lookup_gname_data;
-	const char * (*lookup_uname)(void *private, int64_t uid);
-	void	(*cleanup_uname)(void *private);
-	void	 *lookup_uname_data;
-
-	int	(*metadata_filter_func)(struct archive *, void *,
-			struct archive_entry *);
-	void	*metadata_filter_data;
-
-	/* ARCHIVE_MATCH object. */
-	struct archive	*matching;
-	/* Callback function, this will be invoked when ARCHIVE_MATCH
-	 * archive_match_*_excluded_ae return true. */
-	void	(*excluded_cb_func)(struct archive *, void *,
-			 struct archive_entry *);
-	void	*excluded_cb_data;
-};
-
-const char *
-archive_read_disk_entry_setup_path(struct archive_read_disk *,
-    struct archive_entry *, int *);
-
-int
-archive_read_disk_entry_setup_acls(struct archive_read_disk *,
-    struct archive_entry *, int *);
-#endif
diff --git a/c/archive_read_disk_set_standard_lookup.c b/c/archive_read_disk_set_standard_lookup.c
deleted file mode 100644
--- a/c/archive_read_disk_set_standard_lookup.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_set_standard_lookup.c 201109 2009-12-28 03:30:31Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-int
-archive_read_disk_set_standard_lookup(struct archive *a)
-{
-	archive_set_error(a, -1, "Standard lookups not available on Windows");
-	return (ARCHIVE_FATAL);
-}
-#else /* ! (_WIN32 && !__CYGWIN__) */
-#define	name_cache_size 127
-
-static const char * const NO_NAME = "(noname)";
-
-struct name_cache {
-	struct archive *archive;
-	char   *buff;
-	size_t  buff_size;
-	int	probes;
-	int	hits;
-	size_t	size;
-	struct {
-		id_t id;
-		const char *name;
-	} cache[name_cache_size];
-};
-
-static const char *	lookup_gname(void *, int64_t);
-static const char *	lookup_uname(void *, int64_t);
-static void	cleanup(void *);
-static const char *	lookup_gname_helper(struct name_cache *, id_t gid);
-static const char *	lookup_uname_helper(struct name_cache *, id_t uid);
-
-/*
- * Installs functions that use getpwuid()/getgrgid()---along with
- * a simple cache to accelerate such lookups---into the archive_read_disk
- * object.  This is in a separate file because getpwuid()/getgrgid()
- * can pull in a LOT of library code (including NIS/LDAP functions, which
- * pull in DNS resolvers, etc).  This can easily top 500kB, which makes
- * it inappropriate for some space-constrained applications.
- *
- * Applications that are size-sensitive may want to just use the
- * real default functions (defined in archive_read_disk.c) that just
- * use the uid/gid without the lookup.  Or define your own custom functions
- * if you prefer.
- */
-int
-archive_read_disk_set_standard_lookup(struct archive *a)
-{
-	struct name_cache *ucache = malloc(sizeof(struct name_cache));
-	struct name_cache *gcache = malloc(sizeof(struct name_cache));
-
-	if (ucache == NULL || gcache == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate uname/gname lookup cache");
-		free(ucache);
-		free(gcache);
-		return (ARCHIVE_FATAL);
-	}
-
-	memset(ucache, 0, sizeof(*ucache));
-	ucache->archive = a;
-	ucache->size = name_cache_size;
-	memset(gcache, 0, sizeof(*gcache));
-	gcache->archive = a;
-	gcache->size = name_cache_size;
-
-	archive_read_disk_set_gname_lookup(a, gcache, lookup_gname, cleanup);
-	archive_read_disk_set_uname_lookup(a, ucache, lookup_uname, cleanup);
-
-	return (ARCHIVE_OK);
-}
-
-static void
-cleanup(void *data)
-{
-	struct name_cache *cache = (struct name_cache *)data;
-	size_t i;
-
-	if (cache != NULL) {
-		for (i = 0; i < cache->size; i++) {
-			if (cache->cache[i].name != NULL &&
-			    cache->cache[i].name != NO_NAME)
-				free((void *)(uintptr_t)cache->cache[i].name);
-		}
-		free(cache->buff);
-		free(cache);
-	}
-}
-
-/*
- * Lookup uid/gid from uname/gname, return NULL if no match.
- */
-static const char *
-lookup_name(struct name_cache *cache,
-    const char * (*lookup_fn)(struct name_cache *, id_t), id_t id)
-{
-	const char *name;
-	int slot;
-
-
-	cache->probes++;
-
-	slot = id % cache->size;
-	if (cache->cache[slot].name != NULL) {
-		if (cache->cache[slot].id == id) {
-			cache->hits++;
-			if (cache->cache[slot].name == NO_NAME)
-				return (NULL);
-			return (cache->cache[slot].name);
-		}
-		if (cache->cache[slot].name != NO_NAME)
-			free((void *)(uintptr_t)cache->cache[slot].name);
-		cache->cache[slot].name = NULL;
-	}
-
-	name = (lookup_fn)(cache, id);
-	if (name == NULL) {
-		/* Cache and return the negative response. */
-		cache->cache[slot].name = NO_NAME;
-		cache->cache[slot].id = id;
-		return (NULL);
-	}
-
-	cache->cache[slot].name = name;
-	cache->cache[slot].id = id;
-	return (cache->cache[slot].name);
-}
-
-static const char *
-lookup_uname(void *data, int64_t uid)
-{
-	struct name_cache *uname_cache = (struct name_cache *)data;
-	return (lookup_name(uname_cache,
-		    &lookup_uname_helper, (id_t)uid));
-}
-
-#if HAVE_GETPWUID_R
-static const char *
-lookup_uname_helper(struct name_cache *cache, id_t id)
-{
-	struct passwd	pwent, *result;
-	char * nbuff;
-	size_t nbuff_size;
-	int r;
-
-	if (cache->buff_size == 0) {
-		cache->buff_size = 256;
-		cache->buff = malloc(cache->buff_size);
-	}
-	if (cache->buff == NULL)
-		return (NULL);
-	for (;;) {
-		result = &pwent; /* Old getpwuid_r ignores last arg. */
-		r = getpwuid_r((uid_t)id, &pwent,
-			       cache->buff, cache->buff_size, &result);
-		if (r == 0)
-			break;
-		if (r != ERANGE)
-			break;
-		/* ERANGE means our buffer was too small, but POSIX
-		 * doesn't tell us how big the buffer should be, so
-		 * we just double it and try again.  Because the buffer
-		 * is kept around in the cache object, we shouldn't
-		 * have to do this very often. */
-		nbuff_size = cache->buff_size * 2;
-		nbuff = realloc(cache->buff, nbuff_size);
-		if (nbuff == NULL)
-			break;
-		cache->buff = nbuff;
-		cache->buff_size = nbuff_size;
-	}
-	if (r != 0) {
-		archive_set_error(cache->archive, errno,
-		    "Can't lookup user for id %d", (int)id);
-		return (NULL);
-	}
-	if (result == NULL)
-		return (NULL);
-
-	return strdup(result->pw_name);
-}
-#else
-static const char *
-lookup_uname_helper(struct name_cache *cache, id_t id)
-{
-	struct passwd	*result;
-	(void)cache; /* UNUSED */
-
-	result = getpwuid((uid_t)id);
-
-	if (result == NULL)
-		return (NULL);
-
-	return strdup(result->pw_name);
-}
-#endif
-
-static const char *
-lookup_gname(void *data, int64_t gid)
-{
-	struct name_cache *gname_cache = (struct name_cache *)data;
-	return (lookup_name(gname_cache,
-		    &lookup_gname_helper, (id_t)gid));
-}
-
-#if HAVE_GETGRGID_R
-static const char *
-lookup_gname_helper(struct name_cache *cache, id_t id)
-{
-	struct group	grent, *result;
-	char * nbuff;
-	size_t nbuff_size;
-	int r;
-
-	if (cache->buff_size == 0) {
-		cache->buff_size = 256;
-		cache->buff = malloc(cache->buff_size);
-	}
-	if (cache->buff == NULL)
-		return (NULL);
-	for (;;) {
-		result = &grent; /* Old getgrgid_r ignores last arg. */
-		r = getgrgid_r((gid_t)id, &grent,
-			       cache->buff, cache->buff_size, &result);
-		if (r == 0)
-			break;
-		if (r != ERANGE)
-			break;
-		/* ERANGE means our buffer was too small, but POSIX
-		 * doesn't tell us how big the buffer should be, so
-		 * we just double it and try again. */
-		nbuff_size = cache->buff_size * 2;
-		nbuff = realloc(cache->buff, nbuff_size);
-		if (nbuff == NULL)
-			break;
-		cache->buff = nbuff;
-		cache->buff_size = nbuff_size;
-	}
-	if (r != 0) {
-		archive_set_error(cache->archive, errno,
-		    "Can't lookup group for id %d", (int)id);
-		return (NULL);
-	}
-	if (result == NULL)
-		return (NULL);
-
-	return strdup(result->gr_name);
-}
-#else
-static const char *
-lookup_gname_helper(struct name_cache *cache, id_t id)
-{
-	struct group	*result;
-	(void)cache; /* UNUSED */
-
-	result = getgrgid((gid_t)id);
-
-	if (result == NULL)
-		return (NULL);
-
-	return strdup(result->gr_name);
-}
-#endif
-
-#endif /* ! (_WIN32 && !__CYGWIN__) */
diff --git a/c/archive_read_disk_windows.c b/c/archive_read_disk_windows.c
deleted file mode 100644
--- a/c/archive_read_disk_windows.c
+++ /dev/null
@@ -1,2547 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <winioctl.h>
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_disk_private.h"
-
-#ifndef O_BINARY
-#define O_BINARY	0
-#endif
-#ifndef IO_REPARSE_TAG_SYMLINK
-/* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
-#define	IO_REPARSE_TAG_SYMLINK 0xA000000CL
-#endif
-
-/*-
- * This is a new directory-walking system that addresses a number
- * of problems I've had with fts(3).  In particular, it has no
- * pathname-length limits (other than the size of 'int'), handles
- * deep logical traversals, uses considerably less memory, and has
- * an opaque interface (easier to modify in the future).
- *
- * Internally, it keeps a single list of "tree_entry" items that
- * represent filesystem objects that require further attention.
- * Non-directories are not kept in memory: they are pulled from
- * readdir(), returned to the client, then freed as soon as possible.
- * Any directory entry to be traversed gets pushed onto the stack.
- *
- * There is surprisingly little information that needs to be kept for
- * each item on the stack.  Just the name, depth (represented here as the
- * string length of the parent directory's pathname), and some markers
- * indicating how to get back to the parent (via chdir("..") for a
- * regular dir or via fchdir(2) for a symlink).
- */
-
-struct restore_time {
-	const wchar_t		*full_path;
-	FILETIME		 lastWriteTime;
-	FILETIME		 lastAccessTime;
-	mode_t			 filetype;
-};
-
-struct tree_entry {
-	int			 depth;
-	struct tree_entry	*next;
-	struct tree_entry	*parent;
-	size_t			 full_path_dir_length;
-	struct archive_wstring	 name;
-	struct archive_wstring	 full_path;
-	size_t			 dirname_length;
-	int64_t			 dev;
-	int64_t			 ino;
-	int			 flags;
-	int			 filesystem_id;
-	/* How to restore time of a directory. */
-	struct restore_time	 restore_time;
-};
-
-struct filesystem {
-	int64_t		dev;
-	int		synthetic;
-	int		remote;
-	DWORD		bytesPerSector;
-};
-
-/* Definitions for tree_entry.flags bitmap. */
-#define	isDir		1  /* This entry is a regular directory. */
-#define	isDirLink	2  /* This entry is a symbolic link to a directory. */
-#define	needsFirstVisit	4  /* This is an initial entry. */
-#define	needsDescent	8  /* This entry needs to be previsited. */
-#define	needsOpen	16 /* This is a directory that needs to be opened. */
-#define	needsAscent	32 /* This entry needs to be postvisited. */
-
-/*
- * On Windows, "first visit" is handled as a pattern to be handed to
- * _findfirst().  This is consistent with Windows conventions that
- * file patterns are handled within the application.  On Posix,
- * "first visit" is just returned to the client.
- */
-
-#define MAX_OVERLAPPED	8
-#define READ_BUFFER_SIZE	(1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
-#define DIRECT_IO	0/* Disabled */
-#define ASYNC_IO	1/* Enabled */
-
-/*
- * Local data for this package.
- */
-struct tree {
-	struct tree_entry	*stack;
-	struct tree_entry	*current;
-	HANDLE d;
-	WIN32_FIND_DATAW	_findData;
-	WIN32_FIND_DATAW	*findData;
-	int			 flags;
-	int			 visit_type;
-	/* Error code from last failed operation. */
-	int			 tree_errno;
-
-	/* A full path with "\\?\" prefix. */
-	struct archive_wstring	 full_path;
-	size_t			 full_path_dir_length;
-	/* Dynamically-sized buffer for holding path */
-	struct archive_wstring	 path;
-
-	/* Last path element */
-	const wchar_t		*basename;
-	/* Leading dir length */
-	size_t			 dirname_length;
-
-	int	 depth;
-
-	BY_HANDLE_FILE_INFORMATION	lst;
-	BY_HANDLE_FILE_INFORMATION	st;
-	int			 descend;
-	/* How to restore time of a file. */
-	struct restore_time	restore_time;
-
-	struct entry_sparse {
-		int64_t		 length;
-		int64_t		 offset;
-	}			*sparse_list, *current_sparse;
-	int			 sparse_count;
-	int			 sparse_list_size;
-
-	char			 initial_symlink_mode;
-	char			 symlink_mode;
-	struct filesystem	*current_filesystem;
-	struct filesystem	*filesystem_table;
-	int			 initial_filesystem_id;
-	int			 current_filesystem_id;
-	int			 max_filesystem_id;
-	int			 allocated_filesystem;
-
-	HANDLE			 entry_fh;
-	int			 entry_eof;
-	int64_t			 entry_remaining_bytes;
-	int64_t			 entry_total;
-
-	int			 ol_idx_doing;
-	int			 ol_idx_done;
-	int			 ol_num_doing;
-	int			 ol_num_done;
-	int64_t			 ol_remaining_bytes;
-	int64_t			 ol_total;
-	struct la_overlapped {
-		OVERLAPPED	 ol;
-		struct archive * _a;
-		unsigned char	*buff;
-		size_t		 buff_size;
-		int64_t		 offset;
-		size_t		 bytes_expected;
-		size_t		 bytes_transferred;
-	}			 ol[MAX_OVERLAPPED];
-	int			 direct_io;
-	int			 async_io;
-};
-
-#define bhfi_dev(bhfi)	((bhfi)->dwVolumeSerialNumber)
-/* Treat FileIndex as i-node. We should remove a sequence number
- * which is high-16-bits of nFileIndexHigh. */
-#define bhfi_ino(bhfi)	\
-	((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \
-    + (bhfi)->nFileIndexLow)
-
-/* Definitions for tree.flags bitmap. */
-#define	hasStat		16 /* The st entry is valid. */
-#define	hasLstat	32 /* The lst entry is valid. */
-#define	needsRestoreTimes 128
-
-static int
-tree_dir_next_windows(struct tree *t, const wchar_t *pattern);
-
-/* Initiate/terminate a tree traversal. */
-static struct tree *tree_open(const wchar_t *, int, int);
-static struct tree *tree_reopen(struct tree *, const wchar_t *, int);
-static void tree_close(struct tree *);
-static void tree_free(struct tree *);
-static void tree_push(struct tree *, const wchar_t *, const wchar_t *,
-		int, int64_t, int64_t, struct restore_time *);
-
-/*
- * tree_next() returns Zero if there is no next entry, non-zero if
- * there is.  Note that directories are visited three times.
- * Directories are always visited first as part of enumerating their
- * parent; that is a "regular" visit.  If tree_descend() is invoked at
- * that time, the directory is added to a work list and will
- * subsequently be visited two more times: once just after descending
- * into the directory ("postdescent") and again just after ascending
- * back to the parent ("postascent").
- *
- * TREE_ERROR_DIR is returned if the descent failed (because the
- * directory couldn't be opened, for instance).  This is returned
- * instead of TREE_POSTDESCENT/TREE_POSTASCENT.  TREE_ERROR_DIR is not a
- * fatal error, but it does imply that the relevant subtree won't be
- * visited.  TREE_ERROR_FATAL is returned for an error that left the
- * traversal completely hosed.  Right now, this is only returned for
- * chdir() failures during ascent.
- */
-#define	TREE_REGULAR		1
-#define	TREE_POSTDESCENT	2
-#define	TREE_POSTASCENT		3
-#define	TREE_ERROR_DIR		-1
-#define	TREE_ERROR_FATAL	-2
-
-static int tree_next(struct tree *);
-
-/*
- * Return information about the current entry.
- */
-
-/*
- * The current full pathname, length of the full pathname, and a name
- * that can be used to access the file.  Because tree does use chdir
- * extensively, the access path is almost never the same as the full
- * current path.
- *
- */
-static const wchar_t *tree_current_path(struct tree *);
-static const wchar_t *tree_current_access_path(struct tree *);
-
-/*
- * Request the lstat() or stat() data for the current path.  Since the
- * tree package needs to do some of this anyway, and caches the
- * results, you should take advantage of it here if you need it rather
- * than make a redundant stat() or lstat() call of your own.
- */
-static const BY_HANDLE_FILE_INFORMATION *tree_current_stat(struct tree *);
-static const BY_HANDLE_FILE_INFORMATION *tree_current_lstat(struct tree *);
-
-/* The following functions use tricks to avoid a certain number of
- * stat()/lstat() calls. */
-/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
-static int tree_current_is_physical_dir(struct tree *);
-/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */
-static int tree_current_is_physical_link(struct tree *);
-/* Instead of archive_entry_copy_stat for BY_HANDLE_FILE_INFORMATION */
-static void tree_archive_entry_copy_bhfi(struct archive_entry *,
-		    struct tree *, const BY_HANDLE_FILE_INFORMATION *);
-/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
-static int tree_current_is_dir(struct tree *);
-static int update_current_filesystem(struct archive_read_disk *a,
-		    int64_t dev);
-static int setup_current_filesystem(struct archive_read_disk *);
-static int tree_target_is_same_as_parent(struct tree *,
-		    const BY_HANDLE_FILE_INFORMATION *);
-
-static int	_archive_read_disk_open_w(struct archive *, const wchar_t *);
-static int	_archive_read_free(struct archive *);
-static int	_archive_read_close(struct archive *);
-static int	_archive_read_data_block(struct archive *,
-		    const void **, size_t *, int64_t *);
-static int	_archive_read_next_header(struct archive *,
-		    struct archive_entry **);
-static int	_archive_read_next_header2(struct archive *,
-		    struct archive_entry *);
-static const char *trivial_lookup_gname(void *, int64_t gid);
-static const char *trivial_lookup_uname(void *, int64_t uid);
-static int	setup_sparse(struct archive_read_disk *, struct archive_entry *);
-static int	close_and_restore_time(HANDLE, struct tree *,
-		    struct restore_time *);
-static int	setup_sparse_from_disk(struct archive_read_disk *,
-		    struct archive_entry *, HANDLE);
-static int	la_linkname_from_handle(HANDLE, wchar_t **, int *);
-static int	la_linkname_from_pathw(const wchar_t *, wchar_t **, int *);
-static void	entry_symlink_from_pathw(struct archive_entry *,
-		    const wchar_t *path);
-
-typedef struct _REPARSE_DATA_BUFFER {
-	ULONG	ReparseTag;
-	USHORT ReparseDataLength;
-	USHORT	Reserved;
-	union {
-		struct {
-			USHORT	SubstituteNameOffset;
-			USHORT	SubstituteNameLength;
-			USHORT	PrintNameOffset;
-			USHORT	PrintNameLength;
-			ULONG	Flags;
-			WCHAR	PathBuffer[1];
-		} SymbolicLinkReparseBuffer;
-		struct {
-			USHORT	SubstituteNameOffset;
-			USHORT	SubstituteNameLength;
-			USHORT	PrintNameOffset;
-			USHORT	PrintNameLength;
-			WCHAR	PathBuffer[1];
-		} MountPointReparseBuffer;
-		struct {
-			UCHAR	DataBuffer[1];
-		} GenericReparseBuffer;
-	} DUMMYUNIONNAME;
-} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
-
-/*
- * Reads the target of a symbolic link
- *
- * Returns 0 on success and -1 on failure
- * outbuf is allocated in the function
- */
-static int
-la_linkname_from_handle(HANDLE h, wchar_t **linkname, int *linktype)
-{
-	DWORD inbytes;
-	REPARSE_DATA_BUFFER *buf;
-	BY_HANDLE_FILE_INFORMATION st;
-	size_t len;
-	BOOL ret;
-	BYTE *indata;
-	wchar_t *tbuf;
-
-	ret = GetFileInformationByHandle(h, &st);
-	if (ret == 0 ||
-	    (st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
-		return (-1);
-	}
-
-	indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-	ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
-	    1024, &inbytes, NULL);
-	if (ret == 0) {
-		la_dosmaperr(GetLastError());
-		free(indata);
-		return (-1);
-	}
-
-	buf = (REPARSE_DATA_BUFFER *) indata;
-	if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
-		free(indata);
-		/* File is not a symbolic link */
-		errno = EINVAL;
-		return (-1);
-	}
-
-	len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
-	if (len <= 0) {
-		free(indata);
-		return (-1);
-	}
-
-	tbuf = malloc(len + 1 * sizeof(wchar_t));
-	if (tbuf == NULL) {
-		free(indata);
-		return (-1);
-	}
-
-	memcpy(tbuf, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer)
-	    [buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len);
-	free(indata);
-
-	tbuf[len / sizeof(wchar_t)] = L'\0';
-
-	*linkname = tbuf;
-
-	/*
-	 * Translate backslashes to slashes for libarchive internal use
-	 */
-	while(*tbuf != L'\0') {
-		if (*tbuf == L'\\')
-			*tbuf = L'/';
-		tbuf++;
-	}
-
-	if ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
-		*linktype = AE_SYMLINK_TYPE_FILE;
-	else
-		*linktype = AE_SYMLINK_TYPE_DIRECTORY;
-
-	return (0);
-}
-
-/*
- * Returns AE_SYMLINK_TYPE_FILE, AE_SYMLINK_TYPE_DIRECTORY or -1 on error
- */
-static int
-la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
-{
-	HANDLE h;
-	const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
-	    FILE_FLAG_OPEN_REPARSE_POINT;
-	int ret;
-
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-	ZeroMemory(&createExParams, sizeof(createExParams));
-	createExParams.dwSize = sizeof(createExParams);
-	createExParams.dwFileFlags = flag;
-	h = CreateFile2(path, 0,
-	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-	    OPEN_EXISTING, &createExParams);
-#else
-	h = CreateFileW(path, 0,
-	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
-	    OPEN_EXISTING, flag, NULL);
-#endif
-	if (h == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-
-	ret = la_linkname_from_handle(h, outbuf, linktype);
-	CloseHandle(h);
-
-	return (ret);
-}
-
-static void
-entry_symlink_from_pathw(struct archive_entry *entry, const wchar_t *path)
-{
-	wchar_t *linkname = NULL;
-	int ret, linktype;
-
-	ret = la_linkname_from_pathw(path, &linkname, &linktype);
-	if (ret != 0)
-		return;
-	if (linktype >= 0) {
-		archive_entry_copy_symlink_w(entry, linkname);
-		archive_entry_set_symlink_type(entry, linktype);
-	}
-	free(linkname);
-
-	return;
-}
-
-static const struct archive_vtable
-archive_read_disk_vtable = {
-	.archive_free = _archive_read_free,
-	.archive_close = _archive_read_close,
-	.archive_read_data_block = _archive_read_data_block,
-	.archive_read_next_header = _archive_read_next_header,
-	.archive_read_next_header2 = _archive_read_next_header2,
-};
-
-const char *
-archive_read_disk_gname(struct archive *_a, la_int64_t gid)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-		ARCHIVE_STATE_ANY, "archive_read_disk_gname"))
-		return (NULL);
-	if (a->lookup_gname == NULL)
-		return (NULL);
-	return ((*a->lookup_gname)(a->lookup_gname_data, gid));
-}
-
-const char *
-archive_read_disk_uname(struct archive *_a, la_int64_t uid)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-		ARCHIVE_STATE_ANY, "archive_read_disk_uname"))
-		return (NULL);
-	if (a->lookup_uname == NULL)
-		return (NULL);
-	return ((*a->lookup_uname)(a->lookup_uname_data, uid));
-}
-
-int
-archive_read_disk_set_gname_lookup(struct archive *_a,
-    void *private_data,
-    const char * (*lookup_gname)(void *private, la_int64_t gid),
-    void (*cleanup_gname)(void *private))
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup");
-
-	if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
-		(a->cleanup_gname)(a->lookup_gname_data);
-
-	a->lookup_gname = lookup_gname;
-	a->cleanup_gname = cleanup_gname;
-	a->lookup_gname_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_uname_lookup(struct archive *_a,
-    void *private_data,
-    const char * (*lookup_uname)(void *private, int64_t uid),
-    void (*cleanup_uname)(void *private))
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup");
-
-	if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
-		(a->cleanup_uname)(a->lookup_uname_data);
-
-	a->lookup_uname = lookup_uname;
-	a->cleanup_uname = cleanup_uname;
-	a->lookup_uname_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Create a new archive_read_disk object and initialize it with global state.
- */
-struct archive *
-archive_read_disk_new(void)
-{
-	struct archive_read_disk *a;
-
-	a = (struct archive_read_disk *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
-	a->archive.state = ARCHIVE_STATE_NEW;
-	a->archive.vtable = &archive_read_disk_vtable;
-	a->entry = archive_entry_new2(&a->archive);
-	a->lookup_uname = trivial_lookup_uname;
-	a->lookup_gname = trivial_lookup_gname;
-	a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
-	return (&a->archive);
-}
-
-static int
-_archive_read_free(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	int r;
-
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
-
-	if (a->archive.state != ARCHIVE_STATE_CLOSED)
-		r = _archive_read_close(&a->archive);
-	else
-		r = ARCHIVE_OK;
-
-	tree_free(a->tree);
-	if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
-		(a->cleanup_gname)(a->lookup_gname_data);
-	if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
-		(a->cleanup_uname)(a->lookup_uname_data);
-	archive_string_free(&a->archive.error_string);
-	archive_entry_free(a->entry);
-	a->archive.magic = 0;
-	free(a);
-	return (r);
-}
-
-static int
-_archive_read_close(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
-
-	if (a->archive.state != ARCHIVE_STATE_FATAL)
-		a->archive.state = ARCHIVE_STATE_CLOSED;
-
-	tree_close(a->tree);
-
-	return (ARCHIVE_OK);
-}
-
-static void
-setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, 
-    int follow_symlinks)
-{
-	a->symlink_mode = symlink_mode;
-	a->follow_symlinks = follow_symlinks;
-	if (a->tree != NULL) {
-		a->tree->initial_symlink_mode = a->symlink_mode;
-		a->tree->symlink_mode = a->symlink_mode;
-	}
-}
-
-int
-archive_read_disk_set_symlink_logical(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical");
-	setup_symlink_mode(a, 'L', 1);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_symlink_physical(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical");
-	setup_symlink_mode(a, 'P', 0);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_symlink_hybrid(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid");
-	setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_atime_restored(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
-	a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
-	if (a->tree != NULL)
-		a->tree->flags |= needsRestoreTimes;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_behavior(struct archive *_a, int flags)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	int r = ARCHIVE_OK;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
-
-	a->flags = flags;
-
-	if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
-		r = archive_read_disk_set_atime_restored(_a);
-	else {
-		if (a->tree != NULL)
-			a->tree->flags &= ~needsRestoreTimes;
-	}
-	return (r);
-}
-
-/*
- * Trivial implementations of gname/uname lookup functions.
- * These are normally overridden by the client, but these stub
- * versions ensure that we always have something that works.
- */
-static const char *
-trivial_lookup_gname(void *private_data, int64_t gid)
-{
-	(void)private_data; /* UNUSED */
-	(void)gid; /* UNUSED */
-	return (NULL);
-}
-
-static const char *
-trivial_lookup_uname(void *private_data, int64_t uid)
-{
-	(void)private_data; /* UNUSED */
-	(void)uid; /* UNUSED */
-	return (NULL);
-}
-
-static int64_t
-align_num_per_sector(struct tree *t, int64_t size)
-{
-	int64_t surplus;
-
-	size += t->current_filesystem->bytesPerSector -1;
-	surplus = size % t->current_filesystem->bytesPerSector;
-	size -= surplus;
-	return (size);
-}
-
-static int
-start_next_async_read(struct archive_read_disk *a, struct tree *t)
-{
-	struct la_overlapped *olp;
-	DWORD buffbytes, rbytes;
-
-	if (t->ol_remaining_bytes == 0)
-		return (ARCHIVE_EOF);
-
-	olp = &(t->ol[t->ol_idx_doing]);
-	t->ol_idx_doing = (t->ol_idx_doing + 1) % MAX_OVERLAPPED;
-
-	/* Allocate read buffer. */
-	if (olp->buff == NULL) {
-		void *p;
-		size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
-		p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Couldn't allocate memory");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-		olp->buff = p;
-		olp->buff_size = s;
-		olp->_a = &a->archive;
-		olp->ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
-		if (olp->ol.hEvent == NULL) {
-			la_dosmaperr(GetLastError());
-			archive_set_error(&a->archive, errno,
-			    "CreateEvent failed");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	} else
-		ResetEvent(olp->ol.hEvent);
-
-	buffbytes = (DWORD)olp->buff_size;
-	if (buffbytes > t->current_sparse->length)
-		buffbytes = (DWORD)t->current_sparse->length;
-
-	/* Skip hole. */
-	if (t->current_sparse->offset > t->ol_total) {
-		t->ol_remaining_bytes -=
-			t->current_sparse->offset - t->ol_total;
-	}
-
-	olp->offset = t->current_sparse->offset;
-	olp->ol.Offset = (DWORD)(olp->offset & 0xffffffff);
-	olp->ol.OffsetHigh = (DWORD)(olp->offset >> 32);
-
-	if (t->ol_remaining_bytes > buffbytes) {
-		olp->bytes_expected = buffbytes;
-		t->ol_remaining_bytes -= buffbytes;
-	} else {
-		olp->bytes_expected = (size_t)t->ol_remaining_bytes;
-		t->ol_remaining_bytes = 0;
-	}
-	olp->bytes_transferred = 0;
-	t->current_sparse->offset += buffbytes;
-	t->current_sparse->length -= buffbytes;
-	t->ol_total = t->current_sparse->offset;
-	if (t->current_sparse->length == 0 && t->ol_remaining_bytes > 0)
-		t->current_sparse++;
-
-	if (!ReadFile(t->entry_fh, olp->buff, buffbytes, &rbytes, &(olp->ol))) {
-		DWORD lasterr;
-
-		lasterr = GetLastError();
-		if (lasterr == ERROR_HANDLE_EOF) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Reading file truncated");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		} else if (lasterr != ERROR_IO_PENDING) {
-			if (lasterr == ERROR_NO_DATA)
-				errno = EAGAIN;
-			else if (lasterr == ERROR_ACCESS_DENIED)
-				errno = EBADF;
-			else
-				la_dosmaperr(lasterr);
-			archive_set_error(&a->archive, errno, "Read error");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	} else
-		olp->bytes_transferred = rbytes;
-	t->ol_num_doing++;
-
-	return (t->ol_remaining_bytes == 0)? ARCHIVE_EOF: ARCHIVE_OK;
-}
-
-static void
-cancel_async(struct tree *t)
-{
-	if (t->ol_num_doing != t->ol_num_done) {
-		CancelIo(t->entry_fh);
-		t->ol_num_doing = t->ol_num_done = 0;
-	}
-}
-
-static int
-_archive_read_data_block(struct archive *_a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-	struct la_overlapped *olp;
-	DWORD bytes_transferred;
-	int r = ARCHIVE_FATAL;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_data_block");
-
-	if (t->entry_eof || t->entry_remaining_bytes <= 0) {
-		r = ARCHIVE_EOF;
-		goto abort_read_data;
-	}
-
-	/*
-	 * Make a request to read the file in asynchronous.
-	 */
-	if (t->ol_num_doing == 0) {
-		do {
-			r = start_next_async_read(a, t);
-			if (r == ARCHIVE_FATAL)
-				goto abort_read_data;
-			if (!t->async_io)
-				break;
-		} while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
-	} else {
-		if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
-			goto abort_read_data;
-	}
-
-	olp = &(t->ol[t->ol_idx_done]);
-	t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED;
-	if (olp->bytes_transferred)
-		bytes_transferred = (DWORD)olp->bytes_transferred;
-	else if (!GetOverlappedResult(t->entry_fh, &(olp->ol),
-	    &bytes_transferred, TRUE)) {
-		la_dosmaperr(GetLastError());
-		archive_set_error(&a->archive, errno,
-		    "GetOverlappedResult failed");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		r = ARCHIVE_FATAL;
-		goto abort_read_data;
-	}
-	t->ol_num_done++;
-
-	if (bytes_transferred == 0 ||
-	    olp->bytes_expected != bytes_transferred) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Reading file truncated");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		r = ARCHIVE_FATAL;
-		goto abort_read_data;
-	}
-
-	*buff = olp->buff;
-	*size = bytes_transferred;
-	*offset = olp->offset;
-	if (olp->offset > t->entry_total)
-		t->entry_remaining_bytes -= olp->offset - t->entry_total;
-	t->entry_total = olp->offset + *size;
-	t->entry_remaining_bytes -= *size;
-	if (t->entry_remaining_bytes == 0) {
-		/* Close the current file descriptor */
-		close_and_restore_time(t->entry_fh, t, &t->restore_time);
-		t->entry_fh = INVALID_HANDLE_VALUE;
-		t->entry_eof = 1;
-	}
-	return (ARCHIVE_OK);
-
-abort_read_data:
-	*buff = NULL;
-	*size = 0;
-	*offset = t->entry_total;
-	if (t->entry_fh != INVALID_HANDLE_VALUE) {
-		cancel_async(t);
-		/* Close the current file descriptor */
-		close_and_restore_time(t->entry_fh, t, &t->restore_time);
-		t->entry_fh = INVALID_HANDLE_VALUE;
-	}
-	return (r);
-}
-
-static int
-next_entry(struct archive_read_disk *a, struct tree *t,
-    struct archive_entry *entry)
-{
-	const BY_HANDLE_FILE_INFORMATION *st;
-	const BY_HANDLE_FILE_INFORMATION *lst;
-	const char*name;
-	int descend, r;
-
-	st = NULL;
-	lst = NULL;
-	t->descend = 0;
-	do {
-		switch (tree_next(t)) {
-		case TREE_ERROR_FATAL:
-			archive_set_error(&a->archive, t->tree_errno,
-			    "%ls: Unable to continue traversing directory tree",
-			    tree_current_path(t));
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		case TREE_ERROR_DIR:
-			archive_set_error(&a->archive, t->tree_errno,
-			    "%ls: Couldn't visit directory",
-			    tree_current_path(t));
-			return (ARCHIVE_FAILED);
-		case 0:
-			return (ARCHIVE_EOF);
-		case TREE_POSTDESCENT:
-		case TREE_POSTASCENT:
-			break;
-		case TREE_REGULAR:
-			lst = tree_current_lstat(t);
-			if (lst == NULL) {
-				archive_set_error(&a->archive, t->tree_errno,
-				    "%ls: Cannot stat",
-				    tree_current_path(t));
-				return (ARCHIVE_FAILED);
-			}
-			break;
-		}	
-	} while (lst == NULL);
-
-	archive_entry_copy_pathname_w(entry, tree_current_path(t));
-
-	/*
-	 * Perform path matching.
-	 */
-	if (a->matching) {
-		r = archive_match_path_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/*
-	 * Distinguish 'L'/'P'/'H' symlink following.
-	 */
-	switch(t->symlink_mode) {
-	case 'H':
-		/* 'H': After the first item, rest like 'P'. */
-		t->symlink_mode = 'P';
-		/* 'H': First item (from command line) like 'L'. */
-		/* FALLTHROUGH */
-	case 'L':
-		/* 'L': Do descend through a symlink to dir. */
-		descend = tree_current_is_dir(t);
-		/* 'L': Follow symlinks to files. */
-		a->symlink_mode = 'L';
-		a->follow_symlinks = 1;
-		/* 'L': Archive symlinks as targets, if we can. */
-		st = tree_current_stat(t);
-		if (st != NULL && !tree_target_is_same_as_parent(t, st))
-			break;
-		/* If stat fails, we have a broken symlink;
-		 * in that case, don't follow the link. */
-		/* FALLTHROUGH */
-	default:
-		/* 'P': Don't descend through a symlink to dir. */
-		descend = tree_current_is_physical_dir(t);
-		/* 'P': Don't follow symlinks to files. */
-		a->symlink_mode = 'P';
-		a->follow_symlinks = 0;
-		/* 'P': Archive symlinks as symlinks. */
-		st = lst;
-		break;
-	}
-
-	if (update_current_filesystem(a, bhfi_dev(st)) != ARCHIVE_OK) {
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	if (t->initial_filesystem_id == -1)
-		t->initial_filesystem_id = t->current_filesystem_id;
-	if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
-		if (t->initial_filesystem_id != t->current_filesystem_id)
-			return (ARCHIVE_RETRY);
-	}
-	t->descend = descend;
-
-	tree_archive_entry_copy_bhfi(entry, t, st);
-
-	/* Save the times to be restored. This must be in before
-	 * calling archive_read_disk_descend() or any chance of it,
-	 * especially, invoking a callback. */
-	t->restore_time.lastWriteTime = st->ftLastWriteTime;
-	t->restore_time.lastAccessTime = st->ftLastAccessTime;
-	t->restore_time.filetype = archive_entry_filetype(entry);
-
-	/*
-	 * Perform time matching.
-	 */
-	if (a->matching) {
-		r = archive_match_time_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/* Lookup uname/gname */
-	name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
-	if (name != NULL)
-		archive_entry_copy_uname(entry, name);
-	name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
-	if (name != NULL)
-		archive_entry_copy_gname(entry, name);
-
-	/*
-	 * Perform owner matching.
-	 */
-	if (a->matching) {
-		r = archive_match_owner_excluded(a->matching, entry);
-		if (r < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Failed : %s", archive_error_string(a->matching));
-			return (r);
-		}
-		if (r) {
-			if (a->excluded_cb_func)
-				a->excluded_cb_func(&(a->archive),
-				    a->excluded_cb_data, entry);
-			return (ARCHIVE_RETRY);
-		}
-	}
-
-	/*
-	 * File attributes
-	 */
-	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
-		const int supported_attrs =
-		    FILE_ATTRIBUTE_READONLY |
-		    FILE_ATTRIBUTE_HIDDEN |
-		    FILE_ATTRIBUTE_SYSTEM;
-		DWORD file_attrs = st->dwFileAttributes & supported_attrs;
-		if (file_attrs != 0)
-			archive_entry_set_fflags(entry, file_attrs, 0);
-	}
-
-	/*
-	 * Invoke a meta data filter callback.
-	 */
-	if (a->metadata_filter_func) {
-		if (!a->metadata_filter_func(&(a->archive),
-		    a->metadata_filter_data, entry))
-			return (ARCHIVE_RETRY);
-	}
-
-	archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t));
-
-	r = ARCHIVE_OK;
-	if (archive_entry_filetype(entry) == AE_IFREG &&
-	    archive_entry_size(entry) > 0) {
-		DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
-#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-		if (t->async_io)
-			flags |= FILE_FLAG_OVERLAPPED;
-		if (t->direct_io)
-			flags |= FILE_FLAG_NO_BUFFERING;
-		else
-			flags |= FILE_FLAG_SEQUENTIAL_SCAN;
-#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		ZeroMemory(&createExParams, sizeof(createExParams));
-		createExParams.dwSize = sizeof(createExParams);
-		createExParams.dwFileFlags = flags;
-		t->entry_fh = CreateFile2(tree_current_access_path(t),
-		    GENERIC_READ,
-		    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-		    OPEN_EXISTING, &createExParams);
-#else
-		t->entry_fh = CreateFileW(tree_current_access_path(t),
-		    GENERIC_READ,
-		    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-		    NULL, OPEN_EXISTING, flags, NULL);
-#endif
-		if (t->entry_fh == INVALID_HANDLE_VALUE) {
-			la_dosmaperr(GetLastError());
-			archive_set_error(&a->archive, errno,
-			    "Couldn't open %ls", tree_current_path(a->tree));
-			return (ARCHIVE_FAILED);
-		}
-
-		/* Find sparse data from the disk. */
-		if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
-			if (archive_entry_hardlink(entry) == NULL &&
-			    (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0)
-				r = setup_sparse_from_disk(a, entry, t->entry_fh);
-		}
-	}
-	return (r);
-}
-
-static int
-_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
-{
-       int ret;
-       struct archive_read_disk *a = (struct archive_read_disk *)_a;
-       *entryp = NULL;
-       ret = _archive_read_next_header2(_a, a->entry);
-       *entryp = a->entry;
-       return ret;
-}
-
-static int
-_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_next_header2");
-
-	t = a->tree;
-	if (t->entry_fh != INVALID_HANDLE_VALUE) {
-		cancel_async(t);
-		close_and_restore_time(t->entry_fh, t, &t->restore_time);
-		t->entry_fh = INVALID_HANDLE_VALUE;
-	}
-
-	archive_entry_clear(entry);
-
-	while ((r = next_entry(a, t, entry)) == ARCHIVE_RETRY)
-		archive_entry_clear(entry);
-
-	/*
-	 * EOF and FATAL are persistent at this layer.  By
-	 * modifying the state, we guarantee that future calls to
-	 * read a header or read data will fail.
-	 */
-	switch (r) {
-	case ARCHIVE_EOF:
-		a->archive.state = ARCHIVE_STATE_EOF;
-		break;
-	case ARCHIVE_OK:
-	case ARCHIVE_WARN:
-		t->entry_total = 0;
-		if (archive_entry_filetype(entry) == AE_IFREG) {
-			t->entry_remaining_bytes = archive_entry_size(entry);
-			t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0;
-			if (!t->entry_eof &&
-			    setup_sparse(a, entry) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		} else {
-			t->entry_remaining_bytes = 0;
-			t->entry_eof = 1;
-		}
-		t->ol_idx_doing = t->ol_idx_done = 0;
-		t->ol_num_doing = t->ol_num_done = 0;
-		t->ol_remaining_bytes = t->entry_remaining_bytes;
-		t->ol_total = 0;
-		a->archive.state = ARCHIVE_STATE_DATA;
-		break;
-	case ARCHIVE_RETRY:
-		break;
-	case ARCHIVE_FATAL:
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		break;
-	}
-
-	__archive_reset_read_data(&a->archive);
-	return (r);
-}
-
-static int
-setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
-{
-	struct tree *t = a->tree;
-	int64_t aligned, length, offset;
-	int i;
-
-	t->sparse_count = archive_entry_sparse_reset(entry);
-	if (t->sparse_count+1 > t->sparse_list_size) {
-		free(t->sparse_list);
-		t->sparse_list_size = t->sparse_count + 1;
-		t->sparse_list = malloc(sizeof(t->sparse_list[0]) *
-		    t->sparse_list_size);
-		if (t->sparse_list == NULL) {
-			t->sparse_list_size = 0;
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate data");
-			a->archive.state = ARCHIVE_STATE_FATAL;
-			return (ARCHIVE_FATAL);
-		}
-	}
-	/*
-	 * Get sparse list and make sure those offsets and lengths are
-	 * aligned by a sector size.
-	 */
-	for (i = 0; i < t->sparse_count; i++) {
-		archive_entry_sparse_next(entry, &offset, &length);
-		aligned = align_num_per_sector(t, offset);
-		if (aligned != offset) {
-			aligned -= t->current_filesystem->bytesPerSector;
-			length += offset - aligned;
-		}
-		t->sparse_list[i].offset = aligned;
-		aligned = align_num_per_sector(t, length);
-		t->sparse_list[i].length = aligned;
-	}
-
-	aligned = align_num_per_sector(t, archive_entry_size(entry));
-	if (i == 0) {
-		t->sparse_list[i].offset = 0;
-		t->sparse_list[i].length = aligned;
-	} else {
-		int j, last = i;
-
-		t->sparse_list[i].offset = aligned;
-		t->sparse_list[i].length = 0;
-		for (i = 0; i < last; i++) {
-			if ((t->sparse_list[i].offset +
-			       t->sparse_list[i].length) <= 
-					t->sparse_list[i+1].offset)
-				continue;
-			/*
-			 * Now sparse_list[i+1] is overlapped by sparse_list[i].
-			 * Merge those two.
-			 */
-			length = t->sparse_list[i+1].offset -
-					t->sparse_list[i].offset;
-			t->sparse_list[i+1].offset = t->sparse_list[i].offset;
-			t->sparse_list[i+1].length += length;
-			/* Remove sparse_list[i]. */
-			for (j = i; j < last; j++) {
-				t->sparse_list[j].offset =
-				    t->sparse_list[j+1].offset;
-				t->sparse_list[j].length =
-				    t->sparse_list[j+1].length;
-			}
-			last--;
-		}
-	}
-	t->current_sparse = t->sparse_list;
-
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
-    void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
-    void *_client_data)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
-	a->matching = _ma;
-	a->excluded_cb_func = _excluded_func;
-	a->excluded_cb_data = _client_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_set_metadata_filter_callback(struct archive *_a,
-    int (*_metadata_filter_func)(struct archive *, void *,
-    struct archive_entry *), void *_client_data)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
-	    "archive_read_disk_set_metadata_filter_callback");
-
-	a->metadata_filter_func = _metadata_filter_func;
-	a->metadata_filter_data = _client_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_can_descend(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_disk_can_descend");
-
-	return (t->visit_type == TREE_REGULAR && t->descend);
-}
-
-/*
- * Called by the client to mark the directory just returned from
- * tree_next() as needing to be visited.
- */
-int
-archive_read_disk_descend(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct tree *t = a->tree;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_read_disk_descend");
-
-	if (!archive_read_disk_can_descend(_a))
-		return (ARCHIVE_OK);
-
-	if (tree_current_is_physical_dir(t)) {
-		tree_push(t, t->basename, t->full_path.s,
-		    t->current_filesystem_id,
-		    bhfi_dev(&(t->lst)), bhfi_ino(&(t->lst)),
-		    &t->restore_time);
-		t->stack->flags |= isDir;
-	} else if (tree_current_is_dir(t)) {
-		tree_push(t, t->basename, t->full_path.s,
-		    t->current_filesystem_id,
-		    bhfi_dev(&(t->st)), bhfi_ino(&(t->st)),
-		    &t->restore_time);
-		t->stack->flags |= isDirLink;
-	}
-	t->descend = 0;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_disk_open(struct archive *_a, const char *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	struct archive_wstring wpath;
-	int ret;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
-	    "archive_read_disk_open");
-	archive_clear_error(&a->archive);
-
-	/* Make a wchar_t string from a char string. */
-	archive_string_init(&wpath);
-	if (archive_wstring_append_from_mbs(&wpath, pathname,
-	    strlen(pathname)) != 0) {
-		if (errno == ENOMEM)
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-		else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't convert a path to a wchar_t string");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		ret = ARCHIVE_FATAL;
-	} else
-		ret = _archive_read_disk_open_w(_a, wpath.s);
-
-	archive_wstring_free(&wpath);
-	return (ret);
-}
-
-int
-archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
-	    ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
-	    "archive_read_disk_open_w");
-	archive_clear_error(&a->archive);
-
-	return (_archive_read_disk_open_w(_a, pathname));
-}
-
-static int
-_archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	if (a->tree != NULL)
-		a->tree = tree_reopen(a->tree, pathname,
-		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
-	else
-		a->tree = tree_open(pathname, a->symlink_mode,
-		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
-	if (a->tree == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate directory traversal data");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	a->archive.state = ARCHIVE_STATE_HEADER;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return a current filesystem ID which is index of the filesystem entry
- * you've visited through archive_read_disk.
- */
-int
-archive_read_disk_current_filesystem(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem_id);
-}
-
-static int
-update_current_filesystem(struct archive_read_disk *a, int64_t dev)
-{
-	struct tree *t = a->tree;
-	int i, fid;
-
-	if (t->current_filesystem != NULL &&
-	    t->current_filesystem->dev == dev)
-		return (ARCHIVE_OK);
-
-	for (i = 0; i < t->max_filesystem_id; i++) {
-		if (t->filesystem_table[i].dev == dev) {
-			/* There is the filesystem ID we've already generated. */
-			t->current_filesystem_id = i;
-			t->current_filesystem = &(t->filesystem_table[i]);
-			return (ARCHIVE_OK);
-		}
-	}
-
-	/*
-	 * There is a new filesystem, we generate a new ID for.
-	 */
-	fid = t->max_filesystem_id++;
-	if (t->max_filesystem_id > t->allocated_filesystem) {
-		size_t s;
-		void *p;
-
-		s = t->max_filesystem_id * 2;
-		p = realloc(t->filesystem_table,
-			s * sizeof(*t->filesystem_table));
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate tar data");
-			return (ARCHIVE_FATAL);
-		}
-		t->filesystem_table = (struct filesystem *)p;
-		t->allocated_filesystem = (int)s;
-	}
-	t->current_filesystem_id = fid;
-	t->current_filesystem = &(t->filesystem_table[fid]);
-	t->current_filesystem->dev = dev;
-
-	return (setup_current_filesystem(a));
-}
-
-/*
- * Returns 1 if current filesystem is generated filesystem, 0 if it is not
- * or -1 if it is unknown.
- */
-int
-archive_read_disk_current_filesystem_is_synthetic(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem->synthetic);
-}
-
-/*
- * Returns 1 if current filesystem is remote filesystem, 0 if it is not
- * or -1 if it is unknown.
- */
-int
-archive_read_disk_current_filesystem_is_remote(struct archive *_a)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-
-	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
-	    "archive_read_disk_current_filesystem");
-
-	return (a->tree->current_filesystem->remote);
-}
-
-/*
- * If symlink is broken, statfs or statvfs will fail.
- * Use its directory path instead.
- */
-static wchar_t *
-safe_path_for_statfs(struct tree *t)
-{
-	const wchar_t *path;
-	wchar_t *cp, *p = NULL;
-
-	path = tree_current_access_path(t);
-	if (tree_current_stat(t) == NULL) {
-		p = _wcsdup(path);
-		cp = wcsrchr(p, '/');
-		if (cp != NULL && wcslen(cp) >= 2) {
-			cp[1] = '.';
-			cp[2] = '\0';
-			path = p;
-		}
-	} else
-		p = _wcsdup(path);
-	return (p);
-}
-
-/*
- * Get conditions of synthetic and remote on Windows
- */
-static int
-setup_current_filesystem(struct archive_read_disk *a)
-{
-	struct tree *t = a->tree;
-	wchar_t vol[256];
-	wchar_t *path;
-
-	t->current_filesystem->synthetic = -1;/* Not supported */
-	path = safe_path_for_statfs(t);
-	if (!GetVolumePathNameW(path, vol, sizeof(vol)/sizeof(vol[0]))) {
-		free(path);
-		t->current_filesystem->remote = -1;
-		t->current_filesystem->bytesPerSector = 0;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-                        "GetVolumePathName failed: %d", (int)GetLastError());
-		return (ARCHIVE_FAILED);
-	}
-	free(path);
-	switch (GetDriveTypeW(vol)) {
-	case DRIVE_UNKNOWN:
-	case DRIVE_NO_ROOT_DIR:
-		t->current_filesystem->remote = -1;
-		break;
-	case DRIVE_REMOTE:
-		t->current_filesystem->remote = 1;
-		break;
-	default:
-		t->current_filesystem->remote = 0;
-		break;
-	}
-
-	if (!GetDiskFreeSpaceW(vol, NULL,
-	    &(t->current_filesystem->bytesPerSector), NULL, NULL)) {
-		t->current_filesystem->bytesPerSector = 0;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-                        "GetDiskFreeSpace failed: %d", (int)GetLastError());
-		return (ARCHIVE_FAILED);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
-{
-	HANDLE handle;
-	int r = 0;
-#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-	if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
-		return (0);
-
-	/* Close a file descriptor.
-	 * It will not be used for SetFileTime() because it has been opened
-	 * by a read only mode.
-	 */
-	if (h != INVALID_HANDLE_VALUE)
-		CloseHandle(h);
-	if ((t->flags & needsRestoreTimes) == 0)
-		return (r);
-
-#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	ZeroMemory(&createExParams, sizeof(createExParams));
-	createExParams.dwSize = sizeof(createExParams);
-	createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
-	handle = CreateFile2(rt->full_path, FILE_WRITE_ATTRIBUTES,
-		    0, OPEN_EXISTING, &createExParams);
-#else
-	handle = CreateFileW(rt->full_path, FILE_WRITE_ATTRIBUTES,
-		    0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-#endif
-	if (handle == INVALID_HANDLE_VALUE) {
-		errno = EINVAL;
-		return (-1);
-	}
-
-	if (SetFileTime(handle, NULL, &rt->lastAccessTime,
-	    &rt->lastWriteTime) == 0) {
-		errno = EINVAL;
-		r = -1;
-	} else
-		r = 0;
-	CloseHandle(handle);
-	return (r);
-}
-
-/*
- * Add a directory path to the current stack.
- */
-static void
-tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
-    int filesystem_id, int64_t dev, int64_t ino, struct restore_time *rt)
-{
-	struct tree_entry *te;
-
-	te = calloc(1, sizeof(*te));
-	te->next = t->stack;
-	te->parent = t->current;
-	if (te->parent)
-		te->depth = te->parent->depth + 1;
-	t->stack = te;
-	archive_string_init(&te->name);
-	archive_wstrcpy(&te->name, path);
-	archive_string_init(&te->full_path);
-	archive_wstrcpy(&te->full_path, full_path);
-	te->flags = needsDescent | needsOpen | needsAscent;
-	te->filesystem_id = filesystem_id;
-	te->dev = dev;
-	te->ino = ino;
-	te->dirname_length = t->dirname_length;
-	te->full_path_dir_length = t->full_path_dir_length;
-	te->restore_time.full_path = te->full_path.s;
-	if (rt != NULL) {
-		te->restore_time.lastWriteTime = rt->lastWriteTime;
-		te->restore_time.lastAccessTime = rt->lastAccessTime;
-		te->restore_time.filetype = rt->filetype;
-	}
-}
-
-/*
- * Append a name to the current dir path.
- */
-static void
-tree_append(struct tree *t, const wchar_t *name, size_t name_length)
-{
-	size_t size_needed;
-
-	t->path.s[t->dirname_length] = L'\0';
-	t->path.length = t->dirname_length;
-	/* Strip trailing '/' from name, unless entire name is "/". */
-	while (name_length > 1 && name[name_length - 1] == L'/')
-		name_length--;
-
-	/* Resize pathname buffer as needed. */
-	size_needed = name_length + t->dirname_length + 2;
-	archive_wstring_ensure(&t->path, size_needed);
-	/* Add a separating '/' if it's needed. */
-	if (t->dirname_length > 0 &&
-	    t->path.s[archive_strlen(&t->path)-1] != L'/')
-		archive_wstrappend_wchar(&t->path, L'/');
-	t->basename = t->path.s + archive_strlen(&t->path);
-	archive_wstrncat(&t->path, name, name_length);
-	t->restore_time.full_path = t->basename;
-	if (t->full_path_dir_length > 0) {
-		t->full_path.s[t->full_path_dir_length] = L'\0';
-		t->full_path.length = t->full_path_dir_length;
-		size_needed = name_length + t->full_path_dir_length + 2;
-		archive_wstring_ensure(&t->full_path, size_needed);
-		/* Add a separating '\' if it's needed. */
-		if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\')
-			archive_wstrappend_wchar(&t->full_path, L'\\');
-		archive_wstrncat(&t->full_path, name, name_length);
-		t->restore_time.full_path = t->full_path.s;
-	}
-}
-
-/*
- * Open a directory tree for traversal.
- */
-static struct tree *
-tree_open(const wchar_t *path, int symlink_mode, int restore_time)
-{
-	struct tree *t;
-
-	t = calloc(1, sizeof(*t));
-	archive_string_init(&(t->full_path));
-	archive_string_init(&t->path);
-	archive_wstring_ensure(&t->path, 15);
-	t->initial_symlink_mode = symlink_mode;
-	return (tree_reopen(t, path, restore_time));
-}
-
-static struct tree *
-tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
-{
-	struct archive_wstring ws;
-	wchar_t *pathname, *p, *base;
-
-	t->flags = (restore_time != 0)?needsRestoreTimes:0;
-	t->visit_type = 0;
-	t->tree_errno = 0;
-	t->full_path_dir_length = 0;
-	t->dirname_length = 0;
-	t->depth = 0;
-	t->descend = 0;
-	t->current = NULL;
-	t->d = INVALID_HANDLE_VALUE;
-	t->symlink_mode = t->initial_symlink_mode;
-	archive_string_empty(&(t->full_path));
-	archive_string_empty(&t->path);
-	t->entry_fh = INVALID_HANDLE_VALUE;
-	t->entry_eof = 0;
-	t->entry_remaining_bytes = 0;
-	t->initial_filesystem_id = -1;
-
-	/* Get wchar_t strings from char strings. */
-	archive_string_init(&ws);
-	archive_wstrcpy(&ws, path);
-	pathname = ws.s;
-	/* Get a full-path-name. */
-	p = __la_win_permissive_name_w(pathname);
-	if (p == NULL)
-		goto failed;
-	archive_wstrcpy(&(t->full_path), p);
-	free(p);
-
-	/* Convert path separators from '\' to '/' */
-	for (p = pathname; *p != L'\0'; ++p) {
-		if (*p == L'\\')
-			*p = L'/';
-	}
-	base = pathname;
-
-	/* First item is set up a lot like a symlink traversal. */
-	/* printf("Looking for wildcard in %s\n", path); */
-	if ((base[0] == L'/' && base[1] == L'/' &&
-	     base[2] == L'?' && base[3] == L'/' &&
-	     (wcschr(base+4, L'*') || wcschr(base+4, L'?'))) ||
-	    (!(base[0] == L'/' && base[1] == L'/' &&
-	       base[2] == L'?' && base[3] == L'/') &&
-	       (wcschr(base, L'*') || wcschr(base, L'?')))) {
-		// It has a wildcard in it...
-		// Separate the last element.
-		p = wcsrchr(base, L'/');
-		if (p != NULL) {
-			*p = L'\0';
-			tree_append(t, base, p - base);
-			t->dirname_length = archive_strlen(&t->path);
-			base = p + 1;
-		}
-		p = wcsrchr(t->full_path.s, L'\\');
-		if (p != NULL) {
-			*p = L'\0';
-			t->full_path.length = wcslen(t->full_path.s);
-			t->full_path_dir_length = archive_strlen(&t->full_path);
-		}
-	}
-	tree_push(t, base, t->full_path.s, 0, 0, 0, NULL);
-	archive_wstring_free(&ws);
-	t->stack->flags = needsFirstVisit;
-	/*
-	 * Debug flag for Direct IO(No buffering) or Async IO.
-	 * Those dependent on environment variable switches
-	 * will be removed until next release.
-	 */
-	{
-		const char *e;
-		if ((e = getenv("LIBARCHIVE_DIRECT_IO")) != NULL) {
-			if (e[0] == '0')
-				t->direct_io = 0;
-			else
-				t->direct_io = 1;
-			fprintf(stderr, "LIBARCHIVE_DIRECT_IO=%s\n",
-				(t->direct_io)?"Enabled":"Disabled");
-		} else
-			t->direct_io = DIRECT_IO;
-		if ((e = getenv("LIBARCHIVE_ASYNC_IO")) != NULL) {
-			if (e[0] == '0')
-				t->async_io = 0;
-			else
-				t->async_io = 1;
-			fprintf(stderr, "LIBARCHIVE_ASYNC_IO=%s\n",
-			    (t->async_io)?"Enabled":"Disabled");
-		} else
-			t->async_io = ASYNC_IO;
-	}
-	return (t);
-failed:
-	archive_wstring_free(&ws);
-	tree_free(t);
-	return (NULL);
-}
-
-static int
-tree_descent(struct tree *t)
-{
-	t->dirname_length = archive_strlen(&t->path);
-	t->full_path_dir_length = archive_strlen(&t->full_path);
-	t->depth++;
-	return (0);
-}
-
-/*
- * We've finished a directory; ascend back to the parent.
- */
-static int
-tree_ascend(struct tree *t)
-{
-	struct tree_entry *te;
-
-	te = t->stack;
-	t->depth--;
-	close_and_restore_time(INVALID_HANDLE_VALUE, t, &te->restore_time);
-	return (0);
-}
-
-/*
- * Pop the working stack.
- */
-static void
-tree_pop(struct tree *t)
-{
-	struct tree_entry *te;
-
-	t->full_path.s[t->full_path_dir_length] = L'\0';
-	t->full_path.length = t->full_path_dir_length;
-	t->path.s[t->dirname_length] = L'\0';
-	t->path.length = t->dirname_length;
-	if (t->stack == t->current && t->current != NULL)
-		t->current = t->current->parent;
-	te = t->stack;
-	t->stack = te->next;
-	t->dirname_length = te->dirname_length;
-	t->basename = t->path.s + t->dirname_length;
-	t->full_path_dir_length = te->full_path_dir_length;
-	while (t->basename[0] == L'/')
-		t->basename++;
-	archive_wstring_free(&te->name);
-	archive_wstring_free(&te->full_path);
-	free(te);
-}
-
-/*
- * Get the next item in the tree traversal.
- */
-static int
-tree_next(struct tree *t)
-{
-	int r;
-
-	while (t->stack != NULL) {
-		/* If there's an open dir, get the next entry from there. */
-		if (t->d != INVALID_HANDLE_VALUE) {
-			r = tree_dir_next_windows(t, NULL);
-			if (r == 0)
-				continue;
-			return (r);
-		}
-
-		if (t->stack->flags & needsFirstVisit) {
-			wchar_t *d = t->stack->name.s;
-			t->stack->flags &= ~needsFirstVisit;
-			if (!(d[0] == L'/' && d[1] == L'/' &&
-			      d[2] == L'?' && d[3] == L'/') &&
-			    (wcschr(d, L'*') || wcschr(d, L'?'))) {
-				r = tree_dir_next_windows(t, d);
-				if (r == 0)
-					continue;
-				return (r);
-			} else {
-				HANDLE h = FindFirstFileW(t->stack->full_path.s, &t->_findData);
-				if (h == INVALID_HANDLE_VALUE) {
-					la_dosmaperr(GetLastError());
-					t->tree_errno = errno;
-					t->visit_type = TREE_ERROR_DIR;
-					return (t->visit_type);
-				}
-				t->findData = &t->_findData;
-				FindClose(h);
-			}
-			/* Top stack item needs a regular visit. */
-			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
-			    archive_strlen(&(t->stack->name)));
-			//t->dirname_length = t->path_length;
-			//tree_pop(t);
-			t->stack->flags &= ~needsFirstVisit;
-			return (t->visit_type = TREE_REGULAR);
-		} else if (t->stack->flags & needsDescent) {
-			/* Top stack item is dir to descend into. */
-			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
-			    archive_strlen(&(t->stack->name)));
-			t->stack->flags &= ~needsDescent;
-			r = tree_descent(t);
-			if (r != 0) {
-				tree_pop(t);
-				t->visit_type = r;
-			} else
-				t->visit_type = TREE_POSTDESCENT;
-			return (t->visit_type);
-		} else if (t->stack->flags & needsOpen) {
-			t->stack->flags &= ~needsOpen;
-			r = tree_dir_next_windows(t, L"*");
-			if (r == 0)
-				continue;
-			return (r);
-		} else if (t->stack->flags & needsAscent) {
-		        /* Top stack item is dir and we're done with it. */
-			r = tree_ascend(t);
-			tree_pop(t);
-			t->visit_type = r != 0 ? r : TREE_POSTASCENT;
-			return (t->visit_type);
-		} else {
-			/* Top item on stack is dead. */
-			tree_pop(t);
-			t->flags &= ~hasLstat;
-			t->flags &= ~hasStat;
-		}
-	}
-	return (t->visit_type = 0);
-}
-
-static int
-tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
-{
-	const wchar_t *name;
-	size_t namelen;
-	int r;
-
-	for (;;) {
-		if (pattern != NULL) {
-			struct archive_wstring pt;
-
-			archive_string_init(&pt);
-			archive_wstring_ensure(&pt,
-			    archive_strlen(&(t->full_path))
-			      + 2 + wcslen(pattern));
-			archive_wstring_copy(&pt, &(t->full_path));
-			archive_wstrappend_wchar(&pt, L'\\');
-			archive_wstrcat(&pt, pattern);
-			t->d = FindFirstFileW(pt.s, &t->_findData);
-			archive_wstring_free(&pt);
-			if (t->d == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				t->tree_errno = errno;
-				r = tree_ascend(t); /* Undo "chdir" */
-				tree_pop(t);
-				t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
-				return (t->visit_type);
-			}
-			t->findData = &t->_findData;
-			pattern = NULL;
-		} else if (!FindNextFileW(t->d, &t->_findData)) {
-			FindClose(t->d);
-			t->d = INVALID_HANDLE_VALUE;
-			t->findData = NULL;
-			return (0);
-		}
-		name = t->findData->cFileName;
-		namelen = wcslen(name);
-		t->flags &= ~hasLstat;
-		t->flags &= ~hasStat;
-		if (name[0] == L'.' && name[1] == L'\0')
-			continue;
-		if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0')
-			continue;
-		tree_append(t, name, namelen);
-		return (t->visit_type = TREE_REGULAR);
-	}
-}
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		/* milli seconds base */
-		*t = (time_t)(utc.QuadPart / 10000000);
-		/* nano seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
-static void
-entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
-	const WIN32_FIND_DATAW *findData,
-	const BY_HANDLE_FILE_INFORMATION *bhfi)
-{
-	time_t secs;
-	long nsecs;
-	mode_t mode;
-
-	fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
-	archive_entry_set_atime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
-	archive_entry_set_mtime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
-	archive_entry_set_birthtime(entry, secs, nsecs);
-	archive_entry_set_ctime(entry, secs, nsecs);
-	archive_entry_set_dev(entry, bhfi_dev(bhfi));
-	archive_entry_set_ino64(entry, bhfi_ino(bhfi));
-	if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-		archive_entry_set_nlink(entry, bhfi->nNumberOfLinks + 1);
-	else
-		archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
-	archive_entry_set_size(entry,
-	    (((int64_t)bhfi->nFileSizeHigh) << 32)
-	    + bhfi->nFileSizeLow);
-	archive_entry_set_uid(entry, 0);
-	archive_entry_set_gid(entry, 0);
-	archive_entry_set_rdev(entry, 0);
-
-	mode = S_IRUSR | S_IRGRP | S_IROTH;
-	if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
-		mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-	if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
-	    findData != NULL &&
-	    findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
-		mode |= S_IFLNK;
-		entry_symlink_from_pathw(entry, path);
-	} else if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-		mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
-	else {
-		const wchar_t *p;
-
-		mode |= S_IFREG;
-		p = wcsrchr(path, L'.');
-		if (p != NULL && wcslen(p) == 4) {
-			switch (p[1]) {
-			case L'B': case L'b':
-				if ((p[2] == L'A' || p[2] == L'a' ) &&
-				    (p[3] == L'T' || p[3] == L't' ))
-					mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			case L'C': case L'c':
-				if (((p[2] == L'M' || p[2] == L'm' ) &&
-				    (p[3] == L'D' || p[3] == L'd' )))
-					mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			case L'E': case L'e':
-				if ((p[2] == L'X' || p[2] == L'x' ) &&
-				    (p[3] == L'E' || p[3] == L'e' ))
-					mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			default:
-				break;
-			}
-		}
-	}
-	archive_entry_set_mode(entry, mode);
-}
-
-static void
-tree_archive_entry_copy_bhfi(struct archive_entry *entry, struct tree *t,
-	const BY_HANDLE_FILE_INFORMATION *bhfi)
-{
-	entry_copy_bhfi(entry, tree_current_path(t), t->findData, bhfi);
-}
-
-static int
-tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
- int sim_lstat)
-{
-	HANDLE h;
-	int r;
-	DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-	if (sim_lstat && tree_current_is_physical_link(t))
-		flag |= FILE_FLAG_OPEN_REPARSE_POINT;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	ZeroMemory(&createExParams, sizeof(createExParams));
-	createExParams.dwSize = sizeof(createExParams);
-	createExParams.dwFileFlags = flag;
-	h = CreateFile2(tree_current_access_path(t), 0,
-	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-	    OPEN_EXISTING, &createExParams);
-#else
-	h = CreateFileW(tree_current_access_path(t), 0,
-	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
-	    OPEN_EXISTING, flag, NULL);
-#endif
-	if (h == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		t->tree_errno = errno;
-		return (0);
-	}
-	r = GetFileInformationByHandle(h, st);
-	CloseHandle(h);
-	return (r);
-}
-
-/*
- * Get the stat() data for the entry just returned from tree_next().
- */
-static const BY_HANDLE_FILE_INFORMATION *
-tree_current_stat(struct tree *t)
-{
-	if (!(t->flags & hasStat)) {
-		if (!tree_current_file_information(t, &t->st, 0))
-			return NULL;
-		t->flags |= hasStat;
-	}
-	return (&t->st);
-}
-
-/*
- * Get the lstat() data for the entry just returned from tree_next().
- */
-static const BY_HANDLE_FILE_INFORMATION *
-tree_current_lstat(struct tree *t)
-{
-	if (!(t->flags & hasLstat)) {
-		if (!tree_current_file_information(t, &t->lst, 1))
-			return NULL;
-		t->flags |= hasLstat;
-	}
-	return (&t->lst);
-}
-
-/*
- * Test whether current entry is a dir or link to a dir.
- */
-static int
-tree_current_is_dir(struct tree *t)
-{
-	if (t->findData)
-		return (t->findData->dwFileAttributes
-		    & FILE_ATTRIBUTE_DIRECTORY);
-	return (0);
-}
-
-/*
- * Test whether current entry is a physical directory.  Usually, we
- * already have at least one of stat() or lstat() in memory, so we
- * use tricks to try to avoid an extra trip to the disk.
- */
-static int
-tree_current_is_physical_dir(struct tree *t)
-{
-	if (tree_current_is_physical_link(t))
-		return (0);
-	return (tree_current_is_dir(t));
-}
-
-/*
- * Test whether current entry is a symbolic link.
- */
-static int
-tree_current_is_physical_link(struct tree *t)
-{
-	if (t->findData)
-		return ((t->findData->dwFileAttributes
-			        & FILE_ATTRIBUTE_REPARSE_POINT) &&
-			(t->findData->dwReserved0
-			    == IO_REPARSE_TAG_SYMLINK));
-	return (0);
-}
-
-/*
- * Test whether the same file has been in the tree as its parent.
- */
-static int
-tree_target_is_same_as_parent(struct tree *t,
-    const BY_HANDLE_FILE_INFORMATION *st)
-{
-	struct tree_entry *te;
-	int64_t dev = bhfi_dev(st);
-	int64_t ino = bhfi_ino(st);
-
-	for (te = t->current->parent; te != NULL; te = te->parent) {
-		if (te->dev == dev && te->ino == ino)
-			return (1);
-	}
-	return (0);
-}
-
-/*
- * Return the access path for the entry just returned from tree_next().
- */
-static const wchar_t *
-tree_current_access_path(struct tree *t)
-{
-	return (t->full_path.s);
-}
-
-/*
- * Return the full path for the entry just returned from tree_next().
- */
-static const wchar_t *
-tree_current_path(struct tree *t)
-{
-	return (t->path.s);
-}
-
-/*
- * Terminate the traversal.
- */
-static void
-tree_close(struct tree *t)
-{
-
-	if (t == NULL)
-		return;
-	if (t->entry_fh != INVALID_HANDLE_VALUE) {
-		cancel_async(t);
-		close_and_restore_time(t->entry_fh, t, &t->restore_time);
-		t->entry_fh = INVALID_HANDLE_VALUE;
-	}
-	/* Close the handle of FindFirstFileW */
-	if (t->d != INVALID_HANDLE_VALUE) {
-		FindClose(t->d);
-		t->d = INVALID_HANDLE_VALUE;
-		t->findData = NULL;
-	}
-	/* Release anything remaining in the stack. */
-	while (t->stack != NULL)
-		tree_pop(t);
-}
-
-/*
- * Release any resources.
- */
-static void
-tree_free(struct tree *t)
-{
-	int i;
-
-	if (t == NULL)
-		return;
-	archive_wstring_free(&t->path);
-	archive_wstring_free(&t->full_path);
-	free(t->sparse_list);
-	free(t->filesystem_table);
-	for (i = 0; i < MAX_OVERLAPPED; i++) {
-		if (t->ol[i].buff)
-			VirtualFree(t->ol[i].buff, 0, MEM_RELEASE);
-		CloseHandle(t->ol[i].ol.hEvent);
-	}
-	free(t);
-}
-
-
-/*
- * Populate the archive_entry with metadata from the disk.
- */
-int
-archive_read_disk_entry_from_file(struct archive *_a,
-    struct archive_entry *entry, int fd, const struct stat *st)
-{
-	struct archive_read_disk *a = (struct archive_read_disk *)_a;
-	const wchar_t *path;
-	const wchar_t *wname;
-	const char *name;
-	HANDLE h;
-	BY_HANDLE_FILE_INFORMATION bhfi;
-	DWORD fileAttributes = 0;
-	int r;
-
-	archive_clear_error(_a);
-	wname = archive_entry_sourcepath_w(entry);
-	if (wname == NULL)
-		wname = archive_entry_pathname_w(entry);
-	if (wname == NULL) {
-		archive_set_error(&a->archive, EINVAL,
-		    "Can't get a wide character version of the path");
-		return (ARCHIVE_FAILED);
-	}
-	path = __la_win_permissive_name_w(wname);
-
-	if (st == NULL) {
-		/*
-		 * Get metadata through GetFileInformationByHandle().
-		 */
-		if (fd >= 0) {
-			h = (HANDLE)_get_osfhandle(fd);
-			r = GetFileInformationByHandle(h, &bhfi);
-			if (r == 0) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Can't GetFileInformationByHandle");
-				return (ARCHIVE_FAILED);
-			}
-			entry_copy_bhfi(entry, path, NULL, &bhfi);
-		} else {
-			WIN32_FIND_DATAW findData;
-			DWORD flag, desiredAccess;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-			CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-			h = FindFirstFileW(path, &findData);
-			if (h == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Can't FindFirstFileW");
-				return (ARCHIVE_FAILED);
-			}
-			FindClose(h);
-
-			flag = FILE_FLAG_BACKUP_SEMANTICS;
-			if (!a->follow_symlinks &&
-			    (findData.dwFileAttributes
-			      & FILE_ATTRIBUTE_REPARSE_POINT) &&
-				  (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
-				flag |= FILE_FLAG_OPEN_REPARSE_POINT;
-				desiredAccess = 0;
-			} else if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-				desiredAccess = 0;
-			} else
-				desiredAccess = GENERIC_READ;
-
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-			ZeroMemory(&createExParams, sizeof(createExParams));
-			createExParams.dwSize = sizeof(createExParams);
-			createExParams.dwFileFlags = flag;
-			h = CreateFile2(path, desiredAccess,
-			    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-			    OPEN_EXISTING, &createExParams);
-#else
-			h = CreateFileW(path, desiredAccess,
-			    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
-			    OPEN_EXISTING, flag, NULL);
-#endif
-			if (h == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Can't CreateFileW");
-				return (ARCHIVE_FAILED);
-			}
-			r = GetFileInformationByHandle(h, &bhfi);
-			if (r == 0) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Can't GetFileInformationByHandle");
-				CloseHandle(h);
-				return (ARCHIVE_FAILED);
-			}
-			entry_copy_bhfi(entry, path, &findData, &bhfi);
-		}
-		fileAttributes = bhfi.dwFileAttributes;
-	} else {
-		archive_entry_copy_stat(entry, st);
-		if (st->st_mode & S_IFLNK)
-			entry_symlink_from_pathw(entry, path);
-		h = INVALID_HANDLE_VALUE;
-	}
-
-	/* Lookup uname/gname */
-	name = archive_read_disk_uname(_a, archive_entry_uid(entry));
-	if (name != NULL)
-		archive_entry_copy_uname(entry, name);
-	name = archive_read_disk_gname(_a, archive_entry_gid(entry));
-	if (name != NULL)
-		archive_entry_copy_gname(entry, name);
-
-	/*
-	 * File attributes
-	 */
-	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
-		const int supported_attrs =
-		    FILE_ATTRIBUTE_READONLY |
-		    FILE_ATTRIBUTE_HIDDEN |
-		    FILE_ATTRIBUTE_SYSTEM;
-		DWORD file_attrs = fileAttributes & supported_attrs;
-		if (file_attrs != 0)
-			archive_entry_set_fflags(entry, file_attrs, 0);
-	}
-
-	/*
-	 * Can this file be sparse file ?
-	 */
-	if (archive_entry_filetype(entry) != AE_IFREG
-	    || archive_entry_size(entry) <= 0
-		|| archive_entry_hardlink(entry) != NULL) {
-		if (h != INVALID_HANDLE_VALUE && fd < 0)
-			CloseHandle(h);
-		return (ARCHIVE_OK);
-	}
-
-	if (h == INVALID_HANDLE_VALUE) {
-		if (fd >= 0) {
-			h = (HANDLE)_get_osfhandle(fd);
-		} else {
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-			CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-			ZeroMemory(&createExParams, sizeof(createExParams));
-			createExParams.dwSize = sizeof(createExParams);
-			createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
-			h = CreateFile2(path, GENERIC_READ,
-			    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-			    OPEN_EXISTING, &createExParams);
-#else
-			h = CreateFileW(path, GENERIC_READ,
-			    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
-			    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-#endif
-			if (h == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Can't CreateFileW");
-				return (ARCHIVE_FAILED);
-			}
-		}
-		r = GetFileInformationByHandle(h, &bhfi);
-		if (r == 0) {
-			la_dosmaperr(GetLastError());
-			archive_set_error(&a->archive, errno,
-			    "Can't GetFileInformationByHandle");
-			if (h != INVALID_HANDLE_VALUE && fd < 0)
-				CloseHandle(h);
-			return (ARCHIVE_FAILED);
-		}
-		fileAttributes = bhfi.dwFileAttributes;
-	}
-
-	/* Sparse file must be set a mark, FILE_ATTRIBUTE_SPARSE_FILE */
-	if ((fileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
-		if (fd < 0)
-			CloseHandle(h);
-		return (ARCHIVE_OK);
-	}
-
-	if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
-		r = setup_sparse_from_disk(a, entry, h);
-		if (fd < 0)
-			CloseHandle(h);
-	}
-
-	return (r);
-}
-
-/*
- * Windows sparse interface.
- */
-#if defined(__MINGW32__) && !defined(FSCTL_QUERY_ALLOCATED_RANGES)
-#define FSCTL_QUERY_ALLOCATED_RANGES 0x940CF
-typedef struct {
-	LARGE_INTEGER FileOffset;
-	LARGE_INTEGER Length;
-} FILE_ALLOCATED_RANGE_BUFFER;
-#endif
-
-static int
-setup_sparse_from_disk(struct archive_read_disk *a,
-    struct archive_entry *entry, HANDLE handle)
-{
-	FILE_ALLOCATED_RANGE_BUFFER range, *outranges = NULL;
-	size_t outranges_size;
-	int64_t entry_size = archive_entry_size(entry);
-	int exit_sts = ARCHIVE_OK;
-
-	range.FileOffset.QuadPart = 0;
-	range.Length.QuadPart = entry_size;
-	outranges_size = 2048;
-	outranges = (FILE_ALLOCATED_RANGE_BUFFER *)malloc(outranges_size);
-	if (outranges == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-			"Couldn't allocate memory");
-		exit_sts = ARCHIVE_FATAL;
-		goto exit_setup_sparse;
-	}
-
-	for (;;) {
-		DWORD retbytes;
-		BOOL ret;
-
-		for (;;) {
-			ret = DeviceIoControl(handle,
-			    FSCTL_QUERY_ALLOCATED_RANGES,
-			    &range, sizeof(range), outranges,
-			    (DWORD)outranges_size, &retbytes, NULL);
-			if (ret == 0 && GetLastError() == ERROR_MORE_DATA) {
-				free(outranges);
-				outranges_size *= 2;
-				outranges = (FILE_ALLOCATED_RANGE_BUFFER *)
-				    malloc(outranges_size);
-				if (outranges == NULL) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Couldn't allocate memory");
-					exit_sts = ARCHIVE_FATAL;
-					goto exit_setup_sparse;
-				}
-				continue;
-			} else
-				break;
-		}
-		if (ret != 0) {
-			if (retbytes > 0) {
-				DWORD i, n;
-
-				n = retbytes / sizeof(outranges[0]);
-				if (n == 1 &&
-				    outranges[0].FileOffset.QuadPart == 0 &&
-				    outranges[0].Length.QuadPart == entry_size)
-					break;/* This is not sparse. */
-				for (i = 0; i < n; i++)
-					archive_entry_sparse_add_entry(entry,
-					    outranges[i].FileOffset.QuadPart,
-						outranges[i].Length.QuadPart);
-				range.FileOffset.QuadPart =
-				    outranges[n-1].FileOffset.QuadPart
-				    + outranges[n-1].Length.QuadPart;
-				range.Length.QuadPart =
-				    entry_size - range.FileOffset.QuadPart;
-				if (range.Length.QuadPart > 0)
-					continue;
-			} else {
-				/* The entire file is a hole. Add one data block of size 0 at the end. */
-				archive_entry_sparse_add_entry(entry,
-				    entry_size,
-				    0);
-			}
-			break;
-		} else {
-			la_dosmaperr(GetLastError());
-			archive_set_error(&a->archive, errno,
-			    "DeviceIoControl Failed: %lu", GetLastError());
-			exit_sts = ARCHIVE_FAILED;
-			goto exit_setup_sparse;
-		}
-	}
-exit_setup_sparse:
-	free(outranges);
-
-	return (exit_sts);
-}
-
-#endif
diff --git a/c/archive_read_extract.c b/c/archive_read_extract.c
deleted file mode 100644
--- a/c/archive_read_extract.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-int
-archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
-{
-	struct archive_read_extract *extract;
-	struct archive_read * a = (struct archive_read *)_a;
-
-	extract = __archive_read_get_extract(a);
-	if (extract == NULL)
-		return (ARCHIVE_FATAL);
-
-	/* If we haven't initialized the archive_write_disk object, do it now. */
-	if (extract->ad == NULL) {
-		extract->ad = archive_write_disk_new();
-		if (extract->ad == NULL) {
-			archive_set_error(&a->archive, ENOMEM, "Can't extract");
-			return (ARCHIVE_FATAL);
-		}
-		archive_write_disk_set_standard_lookup(extract->ad);
-	}
-
-	archive_write_disk_set_options(extract->ad, flags);
-	return (archive_read_extract2(&a->archive, entry, extract->ad));
-}
diff --git a/c/archive_read_extract2.c b/c/archive_read_extract2.c
deleted file mode 100644
--- a/c/archive_read_extract2.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-static int	copy_data(struct archive *ar, struct archive *aw);
-static int	archive_read_extract_cleanup(struct archive_read *);
-
-
-/* Retrieve an extract object without initialising the associated
- * archive_write_disk object.
- */
-struct archive_read_extract *
-__archive_read_get_extract(struct archive_read *a)
-{
-	if (a->extract == NULL) {
-		a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract));
-		if (a->extract == NULL) {
-			archive_set_error(&a->archive, ENOMEM, "Can't extract");
-			return (NULL);
-		}
-		a->cleanup_archive_extract = archive_read_extract_cleanup;
-	}
-	return (a->extract);
-}
-
-/*
- * Cleanup function for archive_extract.
- */
-static int
-archive_read_extract_cleanup(struct archive_read *a)
-{
-	int ret = ARCHIVE_OK;
-
-	if (a->extract->ad != NULL) {
-		ret = archive_write_free(a->extract->ad);
-	}
-	free(a->extract);
-	a->extract = NULL;
-	return (ret);
-}
-
-int
-archive_read_extract2(struct archive *_a, struct archive_entry *entry,
-    struct archive *ad)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int r, r2;
-
-	/* Set up for this particular entry. */
-	if (a->skip_file_set)
-		archive_write_disk_set_skip_file(ad,
-		    a->skip_file_dev, a->skip_file_ino);
-	r = archive_write_header(ad, entry);
-	if (r < ARCHIVE_WARN)
-		r = ARCHIVE_WARN;
-	if (r != ARCHIVE_OK)
-		/* If _write_header failed, copy the error. */
- 		archive_copy_error(&a->archive, ad);
-	else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
-		/* Otherwise, pour data into the entry. */
-		r = copy_data(_a, ad);
-	r2 = archive_write_finish_entry(ad);
-	if (r2 < ARCHIVE_WARN)
-		r2 = ARCHIVE_WARN;
-	/* Use the first message. */
-	if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
-		archive_copy_error(&a->archive, ad);
-	/* Use the worst error return. */
-	if (r2 < r)
-		r = r2;
-	return (r);
-}
-
-void
-archive_read_extract_set_progress_callback(struct archive *_a,
-    void (*progress_func)(void *), void *user_data)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct archive_read_extract *extract = __archive_read_get_extract(a);
-	if (extract != NULL) {
-		extract->extract_progress = progress_func;
-		extract->extract_progress_user_data = user_data;
-	}
-}
-
-static int
-copy_data(struct archive *ar, struct archive *aw)
-{
-	int64_t offset;
-	const void *buff;
-	struct archive_read_extract *extract;
-	size_t size;
-	int r;
-
-	extract = __archive_read_get_extract((struct archive_read *)ar);
-	if (extract == NULL)
-		return (ARCHIVE_FATAL);
-	for (;;) {
-		r = archive_read_data_block(ar, &buff, &size, &offset);
-		if (r == ARCHIVE_EOF)
-			return (ARCHIVE_OK);
-		if (r != ARCHIVE_OK)
-			return (r);
-		r = (int)archive_write_data_block(aw, buff, size, offset);
-		if (r < ARCHIVE_WARN)
-			r = ARCHIVE_WARN;
-		if (r < ARCHIVE_OK) {
-			archive_set_error(ar, archive_errno(aw),
-			    "%s", archive_error_string(aw));
-			return (r);
-		}
-		if (extract->extract_progress)
-			(extract->extract_progress)
-			    (extract->extract_progress_user_data);
-	}
-}
diff --git a/c/archive_read_open_fd.c b/c/archive_read_open_fd.c
deleted file mode 100644
--- a/c/archive_read_open_fd.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_fd.c 201103 2009-12-28 03:13:49Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-
-struct read_fd_data {
-	int	 fd;
-	size_t	 block_size;
-	char	 use_lseek;
-	void	*buffer;
-};
-
-static int	file_close(struct archive *, void *);
-static ssize_t	file_read(struct archive *, void *, const void **buff);
-static int64_t	file_seek(struct archive *, void *, int64_t request, int);
-static int64_t	file_skip(struct archive *, void *, int64_t request);
-
-int
-archive_read_open_fd(struct archive *a, int fd, size_t block_size)
-{
-	struct stat st;
-	struct read_fd_data *mine;
-	void *b;
-
-	archive_clear_error(a);
-	if (fstat(fd, &st) != 0) {
-		archive_set_error(a, errno, "Can't stat fd %d", fd);
-		return (ARCHIVE_FATAL);
-	}
-
-	mine = (struct read_fd_data *)calloc(1, sizeof(*mine));
-	b = malloc(block_size);
-	if (mine == NULL || b == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		free(mine);
-		free(b);
-		return (ARCHIVE_FATAL);
-	}
-	mine->block_size = block_size;
-	mine->buffer = b;
-	mine->fd = fd;
-	/*
-	 * Skip support is a performance optimization for anything
-	 * that supports lseek().  On FreeBSD, only regular files and
-	 * raw disk devices support lseek() and there's no portable
-	 * way to determine if a device is a raw disk device, so we
-	 * only enable this optimization for regular files.
-	 */
-	if (S_ISREG(st.st_mode)) {
-		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
-		mine->use_lseek = 1;
-	}
-#if defined(__CYGWIN__) || defined(_WIN32)
-	setmode(mine->fd, O_BINARY);
-#endif
-
-	archive_read_set_read_callback(a, file_read);
-	archive_read_set_skip_callback(a, file_skip);
-	archive_read_set_seek_callback(a, file_seek);
-	archive_read_set_close_callback(a, file_close);
-	archive_read_set_callback_data(a, mine);
-	return (archive_read_open1(a));
-}
-
-static ssize_t
-file_read(struct archive *a, void *client_data, const void **buff)
-{
-	struct read_fd_data *mine = (struct read_fd_data *)client_data;
-	ssize_t bytes_read;
-
-	*buff = mine->buffer;
-	for (;;) {
-		bytes_read = read(mine->fd, mine->buffer, mine->block_size);
-		if (bytes_read < 0) {
-			if (errno == EINTR)
-				continue;
-			archive_set_error(a, errno, "Error reading fd %d",
-			    mine->fd);
-		}
-		return (bytes_read);
-	}
-}
-
-static int64_t
-file_skip(struct archive *a, void *client_data, int64_t request)
-{
-	struct read_fd_data *mine = (struct read_fd_data *)client_data;
-	int64_t skip = request;
-	int64_t old_offset, new_offset;
-	int skip_bits = sizeof(skip) * 8 - 1;  /* off_t is a signed type. */
-
-	if (!mine->use_lseek)
-		return (0);
-
-	/* Reduce a request that would overflow the 'skip' variable. */
-	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
-		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
-		if (request > max_skip)
-			skip = max_skip;
-	}
-
-	/* Reduce request to the next smallest multiple of block_size */
-	request = (request / mine->block_size) * mine->block_size;
-	if (request == 0)
-		return (0);
-
-	if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
-	    ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
-		return (new_offset - old_offset);
-
-	/* If seek failed once, it will probably fail again. */
-	mine->use_lseek = 0;
-
-	/* Let libarchive recover with read+discard. */
-	if (errno == ESPIPE)
-		return (0);
-
-	/*
-	 * There's been an error other than ESPIPE. This is most
-	 * likely caused by a programmer error (too large request)
-	 * or a corrupted archive file.
-	 */
-	archive_set_error(a, errno, "Error seeking");
-	return (-1);
-}
-
-/*
- * TODO: Store the offset and use it in the read callback.
- */
-static int64_t
-file_seek(struct archive *a, void *client_data, int64_t request, int whence)
-{
-	struct read_fd_data *mine = (struct read_fd_data *)client_data;
-	int64_t r;
-
-	/* We use off_t here because lseek() is declared that way. */
-	/* See above for notes about when off_t is less than 64 bits. */
-	r = lseek(mine->fd, request, whence);
-	if (r >= 0)
-		return r;
-
-	if (errno == ESPIPE) {
-		archive_set_error(a, errno,
-		    "A file descriptor(%d) is not seekable(PIPE)", mine->fd);
-		return (ARCHIVE_FAILED);
-	} else {
-		/* If the input is corrupted or truncated, fail. */
-		archive_set_error(a, errno,
-		    "Error seeking in a file descriptor(%d)", mine->fd);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-file_close(struct archive *a, void *client_data)
-{
-	struct read_fd_data *mine = (struct read_fd_data *)client_data;
-
-	(void)a; /* UNUSED */
-	free(mine->buffer);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_open_file.c b/c/archive_read_open_file.c
deleted file mode 100644
--- a/c/archive_read_open_file.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_file.c 201093 2009-12-28 02:28:44Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-
-struct read_FILE_data {
-	FILE    *f;
-	size_t	 block_size;
-	void	*buffer;
-	char	 can_skip;
-};
-
-static int	file_close(struct archive *, void *);
-static ssize_t	file_read(struct archive *, void *, const void **buff);
-static int64_t	file_skip(struct archive *, void *, int64_t request);
-
-int
-archive_read_open_FILE(struct archive *a, FILE *f)
-{
-	struct stat st;
-	struct read_FILE_data *mine;
-	size_t block_size = 128 * 1024;
-	void *b;
-
-	archive_clear_error(a);
-	mine = (struct read_FILE_data *)malloc(sizeof(*mine));
-	b = malloc(block_size);
-	if (mine == NULL || b == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		free(mine);
-		free(b);
-		return (ARCHIVE_FATAL);
-	}
-	mine->block_size = block_size;
-	mine->buffer = b;
-	mine->f = f;
-	/*
-	 * If we can't fstat() the file, it may just be that it's not
-	 * a file.  (On some platforms, FILE * objects can wrap I/O
-	 * streams that don't support fileno()).  As a result, fileno()
-	 * should be used cautiously.)
-	 */
-	if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
-		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
-		/* Enable the seek optimization only for regular files. */
-		mine->can_skip = 1;
-	} else
-		mine->can_skip = 0;
-
-#if defined(__CYGWIN__) || defined(_WIN32)
-	setmode(fileno(mine->f), O_BINARY);
-#endif
-
-	archive_read_set_read_callback(a, file_read);
-	archive_read_set_skip_callback(a, file_skip);
-	archive_read_set_close_callback(a, file_close);
-	archive_read_set_callback_data(a, mine);
-	return (archive_read_open1(a));
-}
-
-static ssize_t
-file_read(struct archive *a, void *client_data, const void **buff)
-{
-	struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
-	size_t bytes_read;
-
-	*buff = mine->buffer;
-	bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
-	if (bytes_read < mine->block_size && ferror(mine->f)) {
-		archive_set_error(a, errno, "Error reading file");
-	}
-	return (bytes_read);
-}
-
-static int64_t
-file_skip(struct archive *a, void *client_data, int64_t request)
-{
-	struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
-#if HAVE_FSEEKO
-	off_t skip = (off_t)request;
-#elif HAVE__FSEEKI64
-	int64_t skip = request;
-#else
-	long skip = (long)request;
-#endif
-	int skip_bits = sizeof(skip) * 8 - 1;
-
-	(void)a; /* UNUSED */
-
-	/*
-	 * If we can't skip, return 0 as the amount we did step and
-	 * the caller will work around by reading and discarding.
-	 */
-	if (!mine->can_skip)
-		return (0);
-	if (request == 0)
-		return (0);
-
-	/* If request is too big for a long or an off_t, reduce it. */
-	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
-		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
-		if (request > max_skip)
-			skip = max_skip;
-	}
-
-#ifdef __ANDROID__
-        /* fileno() isn't safe on all platforms ... see above. */
-	if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
-#elif HAVE__FSEEKI64
-	if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
-#elif HAVE_FSEEKO
-	if (fseeko(mine->f, skip, SEEK_CUR) != 0)
-#else
-	if (fseek(mine->f, skip, SEEK_CUR) != 0)
-#endif
-	{
-		mine->can_skip = 0;
-		return (0);
-	}
-	return (request);
-}
-
-static int
-file_close(struct archive *a, void *client_data)
-{
-	struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
-
-	(void)a; /* UNUSED */
-	free(mine->buffer);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_open_filename.c b/c/archive_read_open_filename.c
deleted file mode 100644
--- a/c/archive_read_open_filename.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009-12-28 02:28:44Z kientzle $");
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <sys/disk.h>
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/disklabel.h>
-#include <sys/dkio.h>
-#elif defined(__DragonFly__)
-#include <sys/diskslice.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-struct read_file_data {
-	int	 fd;
-	size_t	 block_size;
-	void	*buffer;
-	mode_t	 st_mode;  /* Mode bits for opened file. */
-	char	 use_lseek;
-	enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
-	union {
-		char	 m[1];/* MBS filename. */
-		wchar_t	 w[1];/* WCS filename. */
-	} filename; /* Must be last! */
-};
-
-static int	file_open(struct archive *, void *);
-static int	file_close(struct archive *, void *);
-static int file_close2(struct archive *, void *);
-static int file_switch(struct archive *, void *, void *);
-static ssize_t	file_read(struct archive *, void *, const void **buff);
-static int64_t	file_seek(struct archive *, void *, int64_t request, int);
-static int64_t	file_skip(struct archive *, void *, int64_t request);
-static int64_t	file_skip_lseek(struct archive *, void *, int64_t request);
-
-int
-archive_read_open_file(struct archive *a, const char *filename,
-    size_t block_size)
-{
-	return (archive_read_open_filename(a, filename, block_size));
-}
-
-int
-archive_read_open_filename(struct archive *a, const char *filename,
-    size_t block_size)
-{
-	const char *filenames[2];
-	filenames[0] = filename;
-	filenames[1] = NULL;
-	return archive_read_open_filenames(a, filenames, block_size);
-}
-
-int
-archive_read_open_filenames(struct archive *a, const char **filenames,
-    size_t block_size)
-{
-	struct read_file_data *mine;
-	const char *filename = NULL;
-	if (filenames)
-		filename = *(filenames++);
-
-	archive_clear_error(a);
-	do
-	{
-		if (filename == NULL)
-			filename = "";
-		mine = (struct read_file_data *)calloc(1,
-			sizeof(*mine) + strlen(filename));
-		if (mine == NULL)
-			goto no_memory;
-		strcpy(mine->filename.m, filename);
-		mine->block_size = block_size;
-		mine->fd = -1;
-		mine->buffer = NULL;
-		mine->st_mode = mine->use_lseek = 0;
-		if (filename == NULL || filename[0] == '\0') {
-			mine->filename_type = FNT_STDIN;
-		} else
-			mine->filename_type = FNT_MBS;
-		if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
-			return (ARCHIVE_FATAL);
-		if (filenames == NULL)
-			break;
-		filename = *(filenames++);
-	} while (filename != NULL && filename[0] != '\0');
-	archive_read_set_open_callback(a, file_open);
-	archive_read_set_read_callback(a, file_read);
-	archive_read_set_skip_callback(a, file_skip);
-	archive_read_set_close_callback(a, file_close);
-	archive_read_set_switch_callback(a, file_switch);
-	archive_read_set_seek_callback(a, file_seek);
-
-	return (archive_read_open1(a));
-no_memory:
-	archive_set_error(a, ENOMEM, "No memory");
-	return (ARCHIVE_FATAL);
-}
-
-int
-archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
-    size_t block_size)
-{
-	struct read_file_data *mine = (struct read_file_data *)calloc(1,
-		sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
-	if (!mine)
-	{
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	mine->fd = -1;
-	mine->block_size = block_size;
-
-	if (wfilename == NULL || wfilename[0] == L'\0') {
-		mine->filename_type = FNT_STDIN;
-	} else {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		mine->filename_type = FNT_WCS;
-		wcscpy(mine->filename.w, wfilename);
-#else
-		/*
-		 * POSIX system does not support a wchar_t interface for
-		 * open() system call, so we have to translate a wchar_t
-		 * filename to multi-byte one and use it.
-		 */
-		struct archive_string fn;
-
-		archive_string_init(&fn);
-		if (archive_string_append_from_wcs(&fn, wfilename,
-		    wcslen(wfilename)) != 0) {
-			if (errno == ENOMEM)
-				archive_set_error(a, errno,
-				    "Can't allocate memory");
-			else
-				archive_set_error(a, EINVAL,
-				    "Failed to convert a wide-character"
-				    " filename to a multi-byte filename");
-			archive_string_free(&fn);
-			free(mine);
-			return (ARCHIVE_FATAL);
-		}
-		mine->filename_type = FNT_MBS;
-		strcpy(mine->filename.m, fn.s);
-		archive_string_free(&fn);
-#endif
-	}
-	if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
-		return (ARCHIVE_FATAL);
-	archive_read_set_open_callback(a, file_open);
-	archive_read_set_read_callback(a, file_read);
-	archive_read_set_skip_callback(a, file_skip);
-	archive_read_set_close_callback(a, file_close);
-	archive_read_set_switch_callback(a, file_switch);
-	archive_read_set_seek_callback(a, file_seek);
-
-	return (archive_read_open1(a));
-}
-
-static int
-file_open(struct archive *a, void *client_data)
-{
-	struct stat st;
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-	void *buffer;
-	const char *filename = NULL;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	const wchar_t *wfilename = NULL;
-#endif
-	int fd = -1;
-	int is_disk_like = 0;
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-	off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	struct disklabel dl;
-#elif defined(__DragonFly__)
-	struct partinfo pi;
-#endif
-
-	archive_clear_error(a);
-	if (mine->filename_type == FNT_STDIN) {
-		/* We used to delegate stdin support by
-		 * directly calling archive_read_open_fd(a,0,block_size)
-		 * here, but that doesn't (and shouldn't) handle the
-		 * end-of-file flush when reading stdout from a pipe.
-		 * Basically, read_open_fd() is intended for folks who
-		 * are willing to handle such details themselves.  This
-		 * API is intended to be a little smarter for folks who
-		 * want easy handling of the common case.
-		 */
-		fd = 0;
-#if defined(__CYGWIN__) || defined(_WIN32)
-		setmode(0, O_BINARY);
-#endif
-		filename = "";
-	} else if (mine->filename_type == FNT_MBS) {
-		filename = mine->filename.m;
-		fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC);
-		__archive_ensure_cloexec_flag(fd);
-		if (fd < 0) {
-			archive_set_error(a, errno,
-			    "Failed to open '%s'", filename);
-			return (ARCHIVE_FATAL);
-		}
-	} else {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		wfilename = mine->filename.w;
-		fd = _wopen(wfilename, O_RDONLY | O_BINARY);
-		if (fd < 0 && errno == ENOENT) {
-			wchar_t *fullpath;
-			fullpath = __la_win_permissive_name_w(wfilename);
-			if (fullpath != NULL) {
-				fd = _wopen(fullpath, O_RDONLY | O_BINARY);
-				free(fullpath);
-			}
-		}
-		if (fd < 0) {
-			archive_set_error(a, errno,
-			    "Failed to open '%S'", wfilename);
-			return (ARCHIVE_FATAL);
-		}
-#else
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Unexpedted operation in archive_read_open_filename");
-		goto fail;
-#endif
-	}
-	if (fstat(fd, &st) != 0) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		if (mine->filename_type == FNT_WCS)
-			archive_set_error(a, errno, "Can't stat '%S'",
-			    wfilename);
-		else
-#endif
-			archive_set_error(a, errno, "Can't stat '%s'",
-			    filename);
-		goto fail;
-	}
-
-	/*
-	 * Determine whether the input looks like a disk device or a
-	 * tape device.  The results are used below to select an I/O
-	 * strategy:
-	 *  = "disk-like" devices support arbitrary lseek() and will
-	 *    support I/O requests of any size.  So we get easy skipping
-	 *    and can cheat on block sizes to get better performance.
-	 *  = "tape-like" devices require strict blocking and use
-	 *    specialized ioctls for seeking.
-	 *  = "socket-like" devices cannot seek at all but can improve
-	 *    performance by using nonblocking I/O to read "whatever is
-	 *    available right now".
-	 *
-	 * Right now, we only specially recognize disk-like devices,
-	 * but it should be straightforward to add probes and strategy
-	 * here for tape-like and socket-like devices.
-	 */
-	if (S_ISREG(st.st_mode)) {
-		/* Safety:  Tell the extractor not to overwrite the input. */
-		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
-		/* Regular files act like disks. */
-		is_disk_like = 1;
-	}
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-	/* FreeBSD: if it supports DIOCGMEDIASIZE ioctl, it's disk-like. */
-	else if (S_ISCHR(st.st_mode) &&
-	    ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 &&
-	    mediasize > 0) {
-		is_disk_like = 1;
-	}
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	/* Net/OpenBSD: if it supports DIOCGDINFO ioctl, it's disk-like. */
-	else if ((S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) &&
-	    ioctl(fd, DIOCGDINFO, &dl) == 0 &&
-	    dl.d_partitions[DISKPART(st.st_rdev)].p_size > 0) {
-		is_disk_like = 1;
-	}
-#elif defined(__DragonFly__)
-	/* DragonFly BSD:  if it supports DIOCGPART ioctl, it's disk-like. */
-	else if (S_ISCHR(st.st_mode) &&
-	    ioctl(fd, DIOCGPART, &pi) == 0 &&
-	    pi.media_size > 0) {
-		is_disk_like = 1;
-	}
-#elif defined(__linux__)
-	/* Linux:  All block devices are disk-like. */
-	else if (S_ISBLK(st.st_mode) &&
-	    lseek(fd, 0, SEEK_CUR) == 0 &&
-	    lseek(fd, 0, SEEK_SET) == 0 &&
-	    lseek(fd, 0, SEEK_END) > 0 &&
-	    lseek(fd, 0, SEEK_SET) == 0) {
-		is_disk_like = 1;
-	}
-#endif
-	/* TODO: Add an "is_tape_like" variable and appropriate tests. */
-
-	/* Disk-like devices prefer power-of-two block sizes.  */
-	/* Use provided block_size as a guide so users have some control. */
-	if (is_disk_like) {
-		size_t new_block_size = 64 * 1024;
-		while (new_block_size < mine->block_size
-		    && new_block_size < 64 * 1024 * 1024)
-			new_block_size *= 2;
-		mine->block_size = new_block_size;
-	}
-	buffer = malloc(mine->block_size);
-	if (buffer == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		goto fail;
-	}
-	mine->buffer = buffer;
-	mine->fd = fd;
-	/* Remember mode so close can decide whether to flush. */
-	mine->st_mode = st.st_mode;
-
-	/* Disk-like inputs can use lseek(). */
-	if (is_disk_like)
-		mine->use_lseek = 1;
-
-	return (ARCHIVE_OK);
-fail:
-	/*
-	 * Don't close file descriptors not opened or ones pointing referring
-	 * to `FNT_STDIN`.
-	 */
-	if (fd != -1 && fd != 0)
-		close(fd);
-	return (ARCHIVE_FATAL);
-}
-
-static ssize_t
-file_read(struct archive *a, void *client_data, const void **buff)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-	ssize_t bytes_read;
-
-	/* TODO: If a recent lseek() operation has left us
-	 * mis-aligned, read and return a short block to try to get
-	 * us back in alignment. */
-
-	/* TODO: Someday, try mmap() here; if that succeeds, give
-	 * the entire file to libarchive as a single block.  That
-	 * could be a lot faster than block-by-block manual I/O. */
-
-	/* TODO: We might be able to improve performance on pipes and
-	 * sockets by setting non-blocking I/O and just accepting
-	 * whatever we get here instead of waiting for a full block
-	 * worth of data. */
-
-	*buff = mine->buffer;
-	for (;;) {
-		bytes_read = read(mine->fd, mine->buffer, mine->block_size);
-		if (bytes_read < 0) {
-			if (errno == EINTR)
-				continue;
-			else if (mine->filename_type == FNT_STDIN)
-				archive_set_error(a, errno,
-				    "Error reading stdin");
-			else if (mine->filename_type == FNT_MBS)
-				archive_set_error(a, errno,
-				    "Error reading '%s'", mine->filename.m);
-			else
-				archive_set_error(a, errno,
-				    "Error reading '%S'", mine->filename.w);
-		}
-		return (bytes_read);
-	}
-}
-
-/*
- * Regular files and disk-like block devices can use simple lseek
- * without needing to round the request to the block size.
- *
- * TODO: This can leave future reads mis-aligned.  Since we know the
- * offset here, we should store it and use it in file_read() above
- * to determine whether we should perform a short read to get back
- * into alignment.  Long series of mis-aligned reads can negatively
- * impact disk throughput.  (Of course, the performance impact should
- * be carefully tested; extra code complexity is only worthwhile if
- * it does provide measurable improvement.)
- *
- * TODO: Be lazy about the actual seek.  There are a few pathological
- * cases where libarchive makes a bunch of seek requests in a row
- * without any intervening reads.  This isn't a huge performance
- * problem, since the kernel handles seeks lazily already, but
- * it would be very slightly faster if we simply remembered the
- * seek request here and then actually performed the seek at the
- * top of the read callback above.
- */
-static int64_t
-file_skip_lseek(struct archive *a, void *client_data, int64_t request)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* We use _lseeki64() on Windows. */
-	int64_t old_offset, new_offset;
-#else
-	off_t old_offset, new_offset;
-#endif
-
-	/* We use off_t here because lseek() is declared that way. */
-
-	/* TODO: Deal with case where off_t isn't 64 bits.
-	 * This shouldn't be a problem on Linux or other POSIX
-	 * systems, since the configuration logic for libarchive
-	 * tries to obtain a 64-bit off_t.
-	 */
-	if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
-	    (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
-		return (new_offset - old_offset);
-
-	/* If lseek() fails, don't bother trying again. */
-	mine->use_lseek = 0;
-
-	/* Let libarchive recover with read+discard */
-	if (errno == ESPIPE)
-		return (0);
-
-	/* If the input is corrupted or truncated, fail. */
-	if (mine->filename_type == FNT_STDIN)
-		archive_set_error(a, errno, "Error seeking in stdin");
-	else if (mine->filename_type == FNT_MBS)
-		archive_set_error(a, errno, "Error seeking in '%s'",
-		    mine->filename.m);
-	else
-		archive_set_error(a, errno, "Error seeking in '%S'",
-		    mine->filename.w);
-	return (-1);
-}
-
-
-/*
- * TODO: Implement another file_skip_XXXX that uses MTIO ioctls to
- * accelerate operation on tape drives.
- */
-
-static int64_t
-file_skip(struct archive *a, void *client_data, int64_t request)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-
-	/* Delegate skip requests. */
-	if (mine->use_lseek)
-		return (file_skip_lseek(a, client_data, request));
-
-	/* If we can't skip, return 0; libarchive will read+discard instead. */
-	return (0);
-}
-
-/*
- * TODO: Store the offset and use it in the read callback.
- */
-static int64_t
-file_seek(struct archive *a, void *client_data, int64_t request, int whence)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-	int64_t r;
-
-	/* We use off_t here because lseek() is declared that way. */
-	/* See above for notes about when off_t is less than 64 bits. */
-	r = lseek(mine->fd, request, whence);
-	if (r >= 0)
-		return r;
-
-	/* If the input is corrupted or truncated, fail. */
-	if (mine->filename_type == FNT_STDIN)
-		archive_set_error(a, errno, "Error seeking in stdin");
-	else if (mine->filename_type == FNT_MBS)
-		archive_set_error(a, errno, "Error seeking in '%s'",
-		    mine->filename.m);
-	else
-		archive_set_error(a, errno, "Error seeking in '%S'",
-		    mine->filename.w);
-	return (ARCHIVE_FATAL);
-}
-
-static int
-file_close2(struct archive *a, void *client_data)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-
-	(void)a; /* UNUSED */
-
-	/* Only flush and close if open succeeded. */
-	if (mine->fd >= 0) {
-		/*
-		 * Sometimes, we should flush the input before closing.
-		 *   Regular files: faster to just close without flush.
-		 *   Disk-like devices:  Ditto.
-		 *   Tapes: must not flush (user might need to
-		 *      read the "next" item on a non-rewind device).
-		 *   Pipes and sockets:  must flush (otherwise, the
-		 *      program feeding the pipe or socket may complain).
-		 * Here, I flush everything except for regular files and
-		 * device nodes.
-		 */
-		if (!S_ISREG(mine->st_mode)
-		    && !S_ISCHR(mine->st_mode)
-		    && !S_ISBLK(mine->st_mode)) {
-			ssize_t bytesRead;
-			do {
-				bytesRead = read(mine->fd, mine->buffer,
-				    mine->block_size);
-			} while (bytesRead > 0);
-		}
-		/* If a named file was opened, then it needs to be closed. */
-		if (mine->filename_type != FNT_STDIN)
-			close(mine->fd);
-	}
-	free(mine->buffer);
-	mine->buffer = NULL;
-	mine->fd = -1;
-	return (ARCHIVE_OK);
-}
-
-static int
-file_close(struct archive *a, void *client_data)
-{
-	struct read_file_data *mine = (struct read_file_data *)client_data;
-	file_close2(a, client_data);
-	free(mine);
-	return (ARCHIVE_OK);
-}
-
-static int
-file_switch(struct archive *a, void *client_data1, void *client_data2)
-{
-	file_close2(a, client_data1);
-	return file_open(a, client_data2);
-}
diff --git a/c/archive_read_open_memory.c b/c/archive_read_open_memory.c
deleted file mode 100644
--- a/c/archive_read_open_memory.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_memory.c,v 1.6 2007/07/06 15:51:59 kientzle Exp $");
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "archive.h"
-
-/*
- * Glue to read an archive from a block of memory.
- *
- * This is mostly a huge help in building test harnesses;
- * test programs can build archives in memory and read them
- * back again without having to mess with files on disk.
- */
-
-struct read_memory_data {
-	const unsigned char	*start;
-	const unsigned char	*p;
-	const unsigned char	*end;
-	ssize_t	 read_size;
-};
-
-static int	memory_read_close(struct archive *, void *);
-static int	memory_read_open(struct archive *, void *);
-static int64_t	memory_read_seek(struct archive *, void *, int64_t offset, int whence);
-static int64_t	memory_read_skip(struct archive *, void *, int64_t request);
-static ssize_t	memory_read(struct archive *, void *, const void **buff);
-
-int
-archive_read_open_memory(struct archive *a, const void *buff, size_t size)
-{
-	return archive_read_open_memory2(a, buff, size, size);
-}
-
-/*
- * Don't use _open_memory2() in production code; the archive_read_open_memory()
- * version is the one you really want.  This is just here so that
- * test harnesses can exercise block operations inside the library.
- */
-int
-archive_read_open_memory2(struct archive *a, const void *buff,
-    size_t size, size_t read_size)
-{
-	struct read_memory_data *mine;
-
-	mine = (struct read_memory_data *)calloc(1, sizeof(*mine));
-	if (mine == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	mine->start = mine->p = (const unsigned char *)buff;
-	mine->end = mine->start + size;
-	mine->read_size = read_size;
-	archive_read_set_open_callback(a, memory_read_open);
-	archive_read_set_read_callback(a, memory_read);
-	archive_read_set_seek_callback(a, memory_read_seek);
-	archive_read_set_skip_callback(a, memory_read_skip);
-	archive_read_set_close_callback(a, memory_read_close);
-	archive_read_set_callback_data(a, mine);
-	return (archive_read_open1(a));
-}
-
-/*
- * There's nothing to open.
- */
-static int
-memory_read_open(struct archive *a, void *client_data)
-{
-	(void)a; /* UNUSED */
-	(void)client_data; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-/*
- * This is scary simple:  Just advance a pointer.  Limiting
- * to read_size is not technically necessary, but it exercises
- * more of the internal logic when used with a small block size
- * in a test harness.  Production use should not specify a block
- * size; then this is much faster.
- */
-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;
-
-	(void)a; /* UNUSED */
-	*buff = mine->p;
-	size = mine->end - mine->p;
-	if (size > mine->read_size)
-		size = mine->read_size;
-        mine->p += size;
-	return (size);
-}
-
-/*
- * Advancing is just as simple.  Again, this is doing more than
- * necessary in order to better exercise internal code when used
- * as a test harness.
- */
-static int64_t
-memory_read_skip(struct archive *a, void *client_data, int64_t skip)
-{
-	struct read_memory_data *mine = (struct read_memory_data *)client_data;
-
-	(void)a; /* UNUSED */
-	if ((int64_t)skip > (int64_t)(mine->end - mine->p))
-		skip = mine->end - mine->p;
-	/* Round down to block size. */
-	skip /= mine->read_size;
-	skip *= mine->read_size;
-	mine->p += skip;
-	return (skip);
-}
-
-/*
- * Seeking.
- */
-static int64_t
-memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence)
-{
-	struct read_memory_data *mine = (struct read_memory_data *)client_data;
-
-	(void)a; /* UNUSED */
-	switch (whence) {
-	case SEEK_SET:
-		mine->p = mine->start + offset;
-		break;
-	case SEEK_CUR:
-		mine->p += offset;
-		break;
-	case SEEK_END:
-		mine->p = mine->end + offset;
-		break;
-	default:
-		return ARCHIVE_FATAL;
-	}
-	if (mine->p < mine->start) {
-		mine->p = mine->start;
-		return ARCHIVE_FAILED;
-	}
-	if (mine->p > mine->end) {
-		mine->p = mine->end;
-		return ARCHIVE_FAILED;
-	}
-	return (mine->p - mine->start);
-}
-
-/*
- * Close is just cleaning up our one small bit of data.
- */
-static int
-memory_read_close(struct archive *a, void *client_data)
-{
-	struct read_memory_data *mine = (struct read_memory_data *)client_data;
-	(void)a; /* UNUSED */
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_private.h b/c/archive_read_private.h
deleted file mode 100644
--- a/c/archive_read_private.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_read_private.h 201088 2009-12-28 02:18:55Z kientzle $
- */
-
-#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
-#define ARCHIVE_READ_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_private.h"
-
-struct archive_read;
-struct archive_read_filter_bidder;
-struct archive_read_filter;
-
-struct archive_read_filter_bidder_vtable {
-	/* Taste the upstream filter to see if we handle this. */
-	int (*bid)(struct archive_read_filter_bidder *,
-	    struct archive_read_filter *);
-	/* Initialize a newly-created filter. */
-	int (*init)(struct archive_read_filter *);
-	/* Release the bidder's configuration data. */
-	void (*free)(struct archive_read_filter_bidder *);
-};
-
-/*
- * How bidding works for filters:
- *   * The bid manager initializes the client-provided reader as the
- *     first filter.
- *   * It invokes the bidder for each registered filter with the
- *     current head filter.
- *   * The bidders can use archive_read_filter_ahead() to peek ahead
- *     at the incoming data to compose their bids.
- *   * The bid manager creates a new filter structure for the winning
- *     bidder and gives the winning bidder a chance to initialize it.
- *   * The new filter becomes the new top filter and we repeat the
- *     process.
- * This ends only when no bidder provides a non-zero bid.  Then
- * we perform a similar dance with the registered format handlers.
- */
-struct archive_read_filter_bidder {
-	/* Configuration data for the bidder. */
-	void *data;
-	/* Name of the filter */
-	const char *name;
-	const struct archive_read_filter_bidder_vtable *vtable;
-};
-
-struct archive_read_filter_vtable {
-	/* Return next block. */
-	ssize_t (*read)(struct archive_read_filter *, const void **);
-	/* Close (just this filter) and free(self). */
-	int (*close)(struct archive_read_filter *self);
-	/* Read any header metadata if available. */
-	int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
-};
-
-/*
- * This structure is allocated within the archive_read core
- * and initialized by archive_read and the init() method of the
- * corresponding bidder above.
- */
-struct archive_read_filter {
-	int64_t position;
-	/* Essentially all filters will need these values, so
-	 * just declare them here. */
-	struct archive_read_filter_bidder *bidder; /* My bidder. */
-	struct archive_read_filter *upstream; /* Who I read from. */
-	struct archive_read *archive; /* Associated archive. */
-	const struct archive_read_filter_vtable *vtable;
-	/* My private data. */
-	void *data;
-
-	const char	*name;
-	int		 code;
-	int		 can_skip;
-	int		 can_seek;
-
-	/* Used by reblocking logic. */
-	char		*buffer;
-	size_t		 buffer_size;
-	char		*next;		/* Current read location. */
-	size_t		 avail;		/* Bytes in my buffer. */
-	const void	*client_buff;	/* Client buffer information. */
-	size_t		 client_total;
-	const char	*client_next;
-	size_t		 client_avail;
-	char		 end_of_file;
-	char		 closed;
-	char		 fatal;
-};
-
-/*
- * The client looks a lot like a filter, so we just wrap it here.
- *
- * TODO: Make archive_read_filter and archive_read_client identical so
- * that users of the library can easily register their own
- * transformation filters.  This will probably break the API/ABI and
- * so should be deferred at least until libarchive 3.0.
- */
-struct archive_read_data_node {
-	int64_t begin_position;
-	int64_t total_size;
-	void *data;
-};
-struct archive_read_client {
-	archive_open_callback	*opener;
-	archive_read_callback	*reader;
-	archive_skip_callback	*skipper;
-	archive_seek_callback	*seeker;
-	archive_close_callback	*closer;
-	archive_switch_callback *switcher;
-	unsigned int nodes;
-	unsigned int cursor;
-	int64_t position;
-	struct archive_read_data_node *dataset;
-};
-struct archive_read_passphrase {
-	char	*passphrase;
-	struct archive_read_passphrase *next;
-};
-
-struct archive_read_extract {
-	struct archive *ad; /* archive_write_disk object */
-
-	/* Progress function invoked during extract. */
-	void			(*extract_progress)(void *);
-	void			 *extract_progress_user_data;
-};
-
-struct archive_read {
-	struct archive	archive;
-
-	struct archive_entry	*entry;
-
-	/* Dev/ino of the archive being read/written. */
-	int		  skip_file_set;
-	int64_t		  skip_file_dev;
-	int64_t		  skip_file_ino;
-
-	/* Callbacks to open/read/write/close client archive streams. */
-	struct archive_read_client client;
-
-	/* Registered filter bidders. */
-	struct archive_read_filter_bidder bidders[16];
-
-	/* Last filter in chain */
-	struct archive_read_filter *filter;
-
-	/* Whether to bypass filter bidding process */
-	int bypass_filter_bidding;
-
-	/* File offset of beginning of most recently-read header. */
-	int64_t		  header_position;
-
-	/* Nodes and offsets of compressed data block */
-	unsigned int data_start_node;
-	unsigned int data_end_node;
-
-	/*
-	 * Format detection is mostly the same as compression
-	 * detection, with one significant difference: The bidders
-	 * use the read_ahead calls above to examine the stream rather
-	 * than having the supervisor hand them a block of data to
-	 * examine.
-	 */
-
-	struct archive_format_descriptor {
-		void	 *data;
-		const char *name;
-		int	(*bid)(struct archive_read *, int best_bid);
-		int	(*options)(struct archive_read *, const char *key,
-		    const char *value);
-		int	(*read_header)(struct archive_read *, struct archive_entry *);
-		int	(*read_data)(struct archive_read *, const void **, size_t *, int64_t *);
-		int	(*read_data_skip)(struct archive_read *);
-		int64_t	(*seek_data)(struct archive_read *, int64_t, int);
-		int	(*cleanup)(struct archive_read *);
-		int	(*format_capabilties)(struct archive_read *);
-		int	(*has_encrypted_entries)(struct archive_read *);
-	}	formats[16];
-	struct archive_format_descriptor	*format; /* Active format. */
-
-	/*
-	 * Various information needed by archive_extract.
-	 */
-	struct archive_read_extract		*extract;
-	int			(*cleanup_archive_extract)(struct archive_read *);
-
-	/*
-	 * Decryption passphrase.
-	 */
-	struct {
-		struct archive_read_passphrase *first;
-		struct archive_read_passphrase **last;
-		int candidate;
-		archive_passphrase_callback *callback;
-		void *client_data;
-	}		passphrases;
-};
-
-int	__archive_read_register_format(struct archive_read *a,
-		void *format_data,
-		const char *name,
-		int (*bid)(struct archive_read *, int),
-		int (*options)(struct archive_read *, const char *, const char *),
-		int (*read_header)(struct archive_read *, struct archive_entry *),
-		int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
-		int (*read_data_skip)(struct archive_read *),
-		int64_t (*seek_data)(struct archive_read *, int64_t, int),
-		int (*cleanup)(struct archive_read *),
-		int (*format_capabilities)(struct archive_read *),
-		int (*has_encrypted_entries)(struct archive_read *));
-
-int __archive_read_register_bidder(struct archive_read *a,
-		void *bidder_data,
-		const char *name,
-		const struct archive_read_filter_bidder_vtable *vtable);
-
-const void *__archive_read_ahead(struct archive_read *, size_t, ssize_t *);
-const void *__archive_read_filter_ahead(struct archive_read_filter *,
-    size_t, ssize_t *);
-int64_t	__archive_read_seek(struct archive_read*, int64_t, int);
-int64_t	__archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
-int64_t	__archive_read_consume(struct archive_read *, int64_t);
-int64_t	__archive_read_filter_consume(struct archive_read_filter *, int64_t);
-int __archive_read_header(struct archive_read *, struct archive_entry *);
-int __archive_read_program(struct archive_read_filter *, const char *);
-void __archive_read_free_filters(struct archive_read *);
-struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
-
-
-/*
- * Get a decryption passphrase.
- */
-void __archive_read_reset_passphrase(struct archive_read *a);
-const char * __archive_read_next_passphrase(struct archive_read *a);
-#endif
diff --git a/c/archive_read_set_format.c b/c/archive_read_set_format.c
deleted file mode 100644
--- a/c/archive_read_set_format.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-
- * Copyright (c) 2003-2012 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-int
-archive_read_set_format(struct archive *_a, int code)
-{
-  int r1, r2, slots, i;
-  char str[10];
-  struct archive_read *a = (struct archive_read *)_a;
-
-  if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
-    return r1;
-
-  r1 = r2 = (ARCHIVE_OK);
-  if (a->format)
-    r2 = (ARCHIVE_WARN);
-  switch (code & ARCHIVE_FORMAT_BASE_MASK)
-  {
-    case ARCHIVE_FORMAT_7ZIP:
-      strcpy(str, "7zip");
-      break;
-    case ARCHIVE_FORMAT_AR:
-      strcpy(str, "ar");
-      break;
-    case ARCHIVE_FORMAT_CAB:
-      strcpy(str, "cab");
-      break;
-    case ARCHIVE_FORMAT_CPIO:
-      strcpy(str, "cpio");
-      break;
-    case ARCHIVE_FORMAT_EMPTY:
-      strcpy(str, "empty");
-      break;
-    case ARCHIVE_FORMAT_ISO9660:
-      strcpy(str, "iso9660");
-      break;
-    case ARCHIVE_FORMAT_LHA:
-      strcpy(str, "lha");
-      break;
-    case ARCHIVE_FORMAT_MTREE:
-      strcpy(str, "mtree");
-      break;
-    case ARCHIVE_FORMAT_RAR:
-      strcpy(str, "rar");
-      break;
-    case ARCHIVE_FORMAT_RAR_V5:
-      strcpy(str, "rar5");
-      break;
-    case ARCHIVE_FORMAT_RAW:
-      strcpy(str, "raw");
-      break;
-    case ARCHIVE_FORMAT_TAR:
-      strcpy(str, "tar");
-      break;
-    case ARCHIVE_FORMAT_WARC:
-      strcpy(str, "warc");
-      break;
-    case ARCHIVE_FORMAT_XAR:
-      strcpy(str, "xar");
-      break;
-    case ARCHIVE_FORMAT_ZIP:
-      strcpy(str, "zip");
-      break;
-    default:
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-          "Invalid format code specified");
-      return (ARCHIVE_FATAL);
-  }
-
-  slots = sizeof(a->formats) / sizeof(a->formats[0]);
-  a->format = &(a->formats[0]);
-  for (i = 0; i < slots; i++, a->format++) {
-    if (!a->format->name || !strcmp(a->format->name, str))
-      break;
-  }
-  if (!a->format->name || strcmp(a->format->name, str))
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-        "Internal error: Unable to set format");
-    r1 = (ARCHIVE_FATAL);
-  }
-
-  return (r1 < r2) ? r1 : r2;
-}
diff --git a/c/archive_read_set_options.c b/c/archive_read_set_options.c
deleted file mode 100644
--- a/c/archive_read_set_options.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*-
- * Copyright (c) 2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive_read_private.h"
-#include "archive_options_private.h"
-
-static int	archive_set_format_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-static int	archive_set_filter_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-static int	archive_set_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-
-int
-archive_read_set_format_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_READ_MAGIC, "archive_read_set_format_option",
-	    archive_set_format_option);
-}
-
-int
-archive_read_set_filter_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_READ_MAGIC, "archive_read_set_filter_option",
-	    archive_set_filter_option);
-}
-
-int
-archive_read_set_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_READ_MAGIC, "archive_read_set_option",
-	    archive_set_option);
-}
-
-int
-archive_read_set_options(struct archive *a, const char *options)
-{
-	return _archive_set_options(a, options,
-	    ARCHIVE_READ_MAGIC, "archive_read_set_options",
-	    archive_set_option);
-}
-
-static int
-archive_set_format_option(struct archive *_a, const char *m, const char *o,
-    const char *v)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	size_t i;
-	int r, rv = ARCHIVE_WARN, matched_modules = 0;
-
-	for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
-		struct archive_format_descriptor *format = &a->formats[i];
-
-		if (format->options == NULL || format->name == NULL)
-			/* This format does not support option. */
-			continue;
-		if (m != NULL) {
-			if (strcmp(format->name, m) != 0)
-				continue;
-			++matched_modules;
-		}
-
-		a->format = format;
-		r = format->options(a, o, v);
-		a->format = NULL;
-
-		if (r == ARCHIVE_FATAL)
-			return (ARCHIVE_FATAL);
-
-		if (r == ARCHIVE_OK)
-			rv = ARCHIVE_OK;
-	}
-	/* If the format name didn't match, return a special code for
-	 * _archive_set_option[s]. */
-	if (m != NULL && matched_modules == 0)
-		return ARCHIVE_WARN - 1;
-	return (rv);
-}
-
-static int
-archive_set_filter_option(struct archive *_a, const char *m, const char *o,
-    const char *v)
-{
-	(void)_a; /* UNUSED */
-	(void)o; /* UNUSED */
-	(void)v; /* UNUSED */
-
-	/* If the filter name didn't match, return a special code for
-	 * _archive_set_option[s]. */
-	if (m != NULL)
-		return ARCHIVE_WARN - 1;
-	return ARCHIVE_WARN;
-}
-
-static int
-archive_set_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_either_option(a, m, o, v,
-	    archive_set_format_option,
-	    archive_set_filter_option);
-}
diff --git a/c/archive_read_support_filter_all.c b/c/archive_read_support_filter_all.c
deleted file mode 100644
--- a/c/archive_read_support_filter_all.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * Copyright (c) 2003-2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive.h"
-#include "archive_private.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_all(struct archive *a)
-{
-	return archive_read_support_filter_all(a);
-}
-#endif
-
-int
-archive_read_support_filter_all(struct archive *a)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_filter_all");
-
-	/* Bzip falls back to "bunzip2" command-line */
-	archive_read_support_filter_bzip2(a);
-	/* The decompress code doesn't use an outside library. */
-	archive_read_support_filter_compress(a);
-	/* Gzip decompress falls back to "gzip -d" command-line. */
-	archive_read_support_filter_gzip(a);
-	/* Lzip falls back to "unlzip" command-line program. */
-	archive_read_support_filter_lzip(a);
-	/* The LZMA file format has a very weak signature, so it
-	 * may not be feasible to keep this here, but we'll try.
-	 * This will come back out if there are problems. */
-	/* Lzma falls back to "unlzma" command-line program. */
-	archive_read_support_filter_lzma(a);
-	/* Xz falls back to "unxz" command-line program. */
-	archive_read_support_filter_xz(a);
-	/* The decode code doesn't use an outside library. */
-	archive_read_support_filter_uu(a);
-	/* The decode code doesn't use an outside library. */
-	archive_read_support_filter_rpm(a);
-	/* The decode code always uses "lrzip -q -d" command-line. */
-	archive_read_support_filter_lrzip(a);
-	/* Lzop decompress falls back to "lzop -d" command-line. */
-	archive_read_support_filter_lzop(a);
-	/* The decode code always uses "grzip -d" command-line. */
-	archive_read_support_filter_grzip(a);
-	/* Lz4 falls back to "lz4 -d" command-line program. */
-	archive_read_support_filter_lz4(a);
-	/* Zstd falls back to "zstd -d" command-line program. */
-	archive_read_support_filter_zstd(a);
-
-	/* Note: We always return ARCHIVE_OK here, even if some of the
-	 * above return ARCHIVE_WARN.  The intent here is to enable
-	 * "as much as possible."  Clients who need specific
-	 * compression should enable those individually so they can
-	 * verify the level of support. */
-	/* Clear any warning messages set by the above functions. */
-	archive_clear_error(a);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_support_filter_by_code.c b/c/archive_read_support_filter_by_code.c
deleted file mode 100644
--- a/c/archive_read_support_filter_by_code.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 2020 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive.h"
-#include "archive_private.h"
-
-int
-archive_read_support_filter_by_code(struct archive *a, int filter_code)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_filter_by_code");
-
-	switch (filter_code) {
-	case ARCHIVE_FILTER_NONE:
-		return archive_read_support_filter_none(a);
-		break;
-	case ARCHIVE_FILTER_GZIP:
-		return archive_read_support_filter_gzip(a);
-		break;
-	case ARCHIVE_FILTER_BZIP2:
-		return archive_read_support_filter_bzip2(a);
-		break;
-	case ARCHIVE_FILTER_COMPRESS:
-		return archive_read_support_filter_compress(a);
-		break;
-	case ARCHIVE_FILTER_LZMA:
-		return archive_read_support_filter_lzma(a);
-		break;
-	case ARCHIVE_FILTER_XZ:
-		return archive_read_support_filter_xz(a);
-		break;
-	case ARCHIVE_FILTER_UU:
-		return archive_read_support_filter_uu(a);
-		break;
-	case ARCHIVE_FILTER_RPM:
-		return archive_read_support_filter_rpm(a);
-		break;
-	case ARCHIVE_FILTER_LZIP:
-		return archive_read_support_filter_lzip(a);
-		break;
-	case ARCHIVE_FILTER_LRZIP:
-		return archive_read_support_filter_lrzip(a);
-		break;
-	case ARCHIVE_FILTER_LZOP:
-		return archive_read_support_filter_lzop(a);
-		break;
-	case ARCHIVE_FILTER_GRZIP:
-		return archive_read_support_filter_grzip(a);
-		break;
-	case ARCHIVE_FILTER_LZ4:
-		return archive_read_support_filter_lz4(a);
-		break;
-	case ARCHIVE_FILTER_ZSTD:
-		return archive_read_support_filter_zstd(a);
-		break;
-	}
-	return (ARCHIVE_FATAL);
-}
diff --git a/c/archive_read_support_filter_bzip2.c b/c/archive_read_support_filter_bzip2.c
deleted file mode 100644
--- a/c/archive_read_support_filter_bzip2.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-struct private_data {
-	bz_stream	 stream;
-	char		*out_block;
-	size_t		 out_block_size;
-	char		 valid; /* True = decompressor is initialized */
-	char		 eof; /* True = found end of compressed data. */
-};
-
-/* Bzip2 filter */
-static ssize_t	bzip2_filter_read(struct archive_read_filter *, const void **);
-static int	bzip2_filter_close(struct archive_read_filter *);
-#endif
-
-/*
- * Note that we can detect bzip2 archives even if we can't decompress
- * them.  (In fact, we like detecting them because we can give better
- * error messages.)  So the bid framework here gets compiled even
- * if bzlib is unavailable.
- */
-static int	bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
-static int	bzip2_reader_init(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_bzip2(struct archive *a)
-{
-	return archive_read_support_filter_bzip2(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-bzip2_bidder_vtable = {
-	.bid = bzip2_reader_bid,
-	.init = bzip2_reader_init,
-};
-
-int
-archive_read_support_filter_bzip2(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "bzip2",
-				&bzip2_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external bzip2 program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Test whether we can handle this data.
- *
- * This logic returns zero if any part of the signature fails.  It
- * also tries to Do The Right Thing if a very short buffer prevents us
- * from verifying as much as we would like.
- */
-static int
-bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	int bits_checked;
-
-	(void)self; /* UNUSED */
-
-	/* Minimal bzip2 archive is 14 bytes. */
-	buffer = __archive_read_filter_ahead(filter, 14, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	/* First three bytes must be "BZh" */
-	bits_checked = 0;
-	if (memcmp(buffer, "BZh", 3) != 0)
-		return (0);
-	bits_checked += 24;
-
-	/* Next follows a compression flag which must be an ASCII digit. */
-	if (buffer[3] < '1' || buffer[3] > '9')
-		return (0);
-	bits_checked += 5;
-
-	/* After BZh[1-9], there must be either a data block
-	 * which begins with 0x314159265359 or an end-of-data
-	 * marker of 0x177245385090. */
-	if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0)
-		bits_checked += 48;
-	else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0)
-		bits_checked += 48;
-	else
-		return (0);
-
-	return (bits_checked);
-}
-
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-
-/*
- * If we don't have the library on this system, we can't actually do the
- * decompression.  We can, however, still detect compressed archives
- * and emit a useful message.
- */
-static int
-bzip2_reader_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "bzip2 -d");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_BZIP2;
-	self->name = "bzip2";
-	return (r);
-}
-
-
-#else
-
-static const struct archive_read_filter_vtable
-bzip2_reader_vtable = {
-	.read = bzip2_filter_read,
-	.close = bzip2_filter_close,
-};
-
-/*
- * Setup the callbacks.
- */
-static int
-bzip2_reader_init(struct archive_read_filter *self)
-{
-	static const size_t out_block_size = 64 * 1024;
-	void *out_block;
-	struct private_data *state;
-
-	self->code = ARCHIVE_FILTER_BZIP2;
-	self->name = "bzip2";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = (unsigned char *)malloc(out_block_size);
-	if (state == NULL || out_block == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for bzip2 decompression");
-		free(out_block);
-		free(state);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	self->vtable = &bzip2_reader_vtable;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-bzip2_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state;
-	size_t decompressed;
-	const char *read_buf;
-	ssize_t ret;
-
-	state = (struct private_data *)self->data;
-
-	if (state->eof) {
-		*p = NULL;
-		return (0);
-	}
-
-	/* Empty our output buffer. */
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = (uint32_t)state->out_block_size;
-
-	/* Try to fill the output buffer. */
-	for (;;) {
-		if (!state->valid) {
-			if (bzip2_reader_bid(self->bidder, self->upstream) == 0) {
-				state->eof = 1;
-				*p = state->out_block;
-				decompressed = state->stream.next_out
-				    - state->out_block;
-				return (decompressed);
-			}
-			/* Initialize compression library. */
-			ret = BZ2_bzDecompressInit(&(state->stream),
-					   0 /* library verbosity */,
-					   0 /* don't use low-mem algorithm */);
-
-			/* If init fails, try low-memory algorithm instead. */
-			if (ret == BZ_MEM_ERROR)
-				ret = BZ2_bzDecompressInit(&(state->stream),
-					   0 /* library verbosity */,
-					   1 /* do use low-mem algo */);
-
-			if (ret != BZ_OK) {
-				const char *detail = NULL;
-				int err = ARCHIVE_ERRNO_MISC;
-				switch (ret) {
-				case BZ_PARAM_ERROR:
-					detail = "invalid setup parameter";
-					break;
-				case BZ_MEM_ERROR:
-					err = ENOMEM;
-					detail = "out of memory";
-					break;
-				case BZ_CONFIG_ERROR:
-					detail = "mis-compiled library";
-					break;
-				}
-				archive_set_error(&self->archive->archive, err,
-				    "Internal error initializing decompressor%s%s",
-				    detail == NULL ? "" : ": ",
-				    detail);
-				return (ARCHIVE_FATAL);
-			}
-			state->valid = 1;
-		}
-
-		/* stream.next_in is really const, but bzlib
-		 * doesn't declare it so. <sigh> */
-		read_buf =
-		    __archive_read_filter_ahead(self->upstream, 1, &ret);
-		if (read_buf == NULL) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated bzip2 input");
-			return (ARCHIVE_FATAL);
-		}
-		state->stream.next_in = (char *)(uintptr_t)read_buf;
-		state->stream.avail_in = (uint32_t)ret;
-		/* There is no more data, return whatever we have. */
-		if (ret == 0) {
-			state->eof = 1;
-			*p = state->out_block;
-			decompressed = state->stream.next_out
-			    - state->out_block;
-			return (decompressed);
-		}
-
-		/* Decompress as much as we can in one pass. */
-		ret = BZ2_bzDecompress(&(state->stream));
-		__archive_read_filter_consume(self->upstream,
-		    state->stream.next_in - read_buf);
-
-		switch (ret) {
-		case BZ_STREAM_END: /* Found end of stream. */
-			switch (BZ2_bzDecompressEnd(&(state->stream))) {
-			case BZ_OK:
-				break;
-			default:
-				archive_set_error(&(self->archive->archive),
-					  ARCHIVE_ERRNO_MISC,
-					  "Failed to clean up decompressor");
-				return (ARCHIVE_FATAL);
-			}
-			state->valid = 0;
-			/* FALLTHROUGH */
-		case BZ_OK: /* Decompressor made some progress. */
-			/* If we filled our buffer, update stats and return. */
-			if (state->stream.avail_out == 0) {
-				*p = state->out_block;
-				decompressed = state->stream.next_out
-				    - state->out_block;
-				return (decompressed);
-			}
-			break;
-		default: /* Return an error. */
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC, "bzip decompression failed");
-			return (ARCHIVE_FATAL);
-		}
-	}
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-bzip2_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	int ret = ARCHIVE_OK;
-
-	state = (struct private_data *)self->data;
-
-	if (state->valid) {
-		switch (BZ2_bzDecompressEnd(&state->stream)) {
-		case BZ_OK:
-			break;
-		default:
-			archive_set_error(&self->archive->archive,
-					  ARCHIVE_ERRNO_MISC,
-					  "Failed to clean up decompressor");
-			ret = ARCHIVE_FATAL;
-		}
-		state->valid = 0;
-	}
-
-	free(state->out_block);
-	free(state);
-	return (ret);
-}
-
-#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
diff --git a/c/archive_read_support_filter_compress.c b/c/archive_read_support_filter_compress.c
deleted file mode 100644
--- a/c/archive_read_support_filter_compress.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code borrows heavily from "compress" source code, which is
- * protected by the following copyright.  (Clause 3 dropped by request
- * of the Regents.)
- */
-
-/*-
- * Copyright (c) 1985, 1986, 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Diomidis Spinellis and James A. Woods, derived from original
- * work by Spencer Thomas and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-/*
- * Because LZW decompression is pretty simple, I've just implemented
- * the whole decompressor here (cribbing from "compress" source code,
- * of course), rather than relying on an external library.  I have
- * made an effort to clarify and simplify the algorithm, so the
- * names and structure here don't exactly match those used by compress.
- */
-
-struct private_data {
-	/* Input variables. */
-	const unsigned char	*next_in;
-	size_t			 avail_in;
-	size_t			 consume_unnotified;
-	int			 bit_buffer;
-	int			 bits_avail;
-	size_t			 bytes_in_section;
-
-	/* Output variables. */
-	size_t			 out_block_size;
-	void			*out_block;
-
-	/* Decompression status variables. */
-	int			 use_reset_code;
-	int			 end_of_stream;	/* EOF status. */
-	int			 maxcode;	/* Largest code. */
-	int			 maxcode_bits;	/* Length of largest code. */
-	int			 section_end_code; /* When to increase bits. */
-	int			 bits;		/* Current code length. */
-	int			 oldcode;	/* Previous code. */
-	int			 finbyte;	/* Last byte of prev code. */
-
-	/* Dictionary. */
-	int			 free_ent;       /* Next dictionary entry. */
-	unsigned char		 suffix[65536];
-	uint16_t		 prefix[65536];
-
-	/*
-	 * Scratch area for expanding dictionary entries.  Note:
-	 * "worst" case here comes from compressing /dev/zero: the
-	 * last code in the dictionary will code a sequence of
-	 * 65536-256 zero bytes.  Thus, we need stack space to expand
-	 * a 65280-byte dictionary entry.  (Of course, 32640:1
-	 * compression could also be considered the "best" case. ;-)
-	 */
-	unsigned char		*stackp;
-	unsigned char		 stack[65300];
-};
-
-static int	compress_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
-static int	compress_bidder_init(struct archive_read_filter *);
-
-static ssize_t	compress_filter_read(struct archive_read_filter *, const void **);
-static int	compress_filter_close(struct archive_read_filter *);
-
-static int	getbits(struct archive_read_filter *, int n);
-static int	next_code(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_compress(struct archive *a)
-{
-	return archive_read_support_filter_compress(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-compress_bidder_vtable = {
-	.bid = compress_bidder_bid,
-	.init = compress_bidder_init,
-};
-
-int
-archive_read_support_filter_compress(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	return __archive_read_register_bidder(a, NULL, "compress (.Z)",
-			&compress_bidder_vtable);
-}
-
-/*
- * Test whether we can handle this data.
- * This logic returns zero if any part of the signature fails.
- */
-static int
-compress_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	int bits_checked;
-
-	(void)self; /* UNUSED */
-
-	/* Shortest valid compress file is 3 bytes. */
-	buffer = __archive_read_filter_ahead(filter, 3, &avail);
-
-	if (buffer == NULL)
-		return (0);
-
-	bits_checked = 0;
-	/* First two bytes are the magic value */
-	if (buffer[0] != 0x1F || buffer[1] != 0x9D)
-		return (0);
-	/* Third byte holds compression parameters. */
-	if (buffer[2] & 0x20) /* Reserved bit, must be zero. */
-		return (0);
-	if (buffer[2] & 0x40) /* Reserved bit, must be zero. */
-		return (0);
-	bits_checked += 18;
-
-	return (bits_checked);
-}
-
-static const struct archive_read_filter_vtable
-compress_reader_vtable = {
-	.read = compress_filter_read,
-	.close = compress_filter_close,
-};
-
-/*
- * Setup the callbacks.
- */
-static int
-compress_bidder_init(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	static const size_t out_block_size = 64 * 1024;
-	void *out_block;
-	int code;
-
-	self->code = ARCHIVE_FILTER_COMPRESS;
-	self->name = "compress (.Z)";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = malloc(out_block_size);
-	if (state == NULL || out_block == NULL) {
-		free(out_block);
-		free(state);
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for %s decompression",
-		    self->name);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	self->vtable = &compress_reader_vtable;
-
-	/* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */
-
-	(void)getbits(self, 8); /* Skip first signature byte. */
-	(void)getbits(self, 8); /* Skip second signature byte. */
-
-	/* Get compression parameters. */
-	code = getbits(self, 8);
-	if ((code & 0x1f) > 16) {
-		archive_set_error(&self->archive->archive, -1,
-		    "Invalid compressed data");
-		return (ARCHIVE_FATAL);
-	}
-	state->maxcode_bits = code & 0x1f;
-	state->maxcode = (1 << state->maxcode_bits);
-	state->use_reset_code = code & 0x80;
-
-	/* Initialize decompressor. */
-	state->free_ent = 256;
-	state->stackp = state->stack;
-	if (state->use_reset_code)
-		state->free_ent++;
-	state->bits = 9;
-	state->section_end_code = (1<<state->bits) - 1;
-	state->oldcode = -1;
-	for (code = 255; code >= 0; code--) {
-		state->prefix[code] = 0;
-		state->suffix[code] = code;
-	}
-	next_code(self);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return a block of data from the decompression buffer.  Decompress more
- * as necessary.
- */
-static ssize_t
-compress_filter_read(struct archive_read_filter *self, const void **pblock)
-{
-	struct private_data *state;
-	unsigned char *p, *start, *end;
-	int ret;
-
-	state = (struct private_data *)self->data;
-	if (state->end_of_stream) {
-		*pblock = NULL;
-		return (0);
-	}
-	p = start = (unsigned char *)state->out_block;
-	end = start + state->out_block_size;
-
-	while (p < end && !state->end_of_stream) {
-		if (state->stackp > state->stack) {
-			*p++ = *--state->stackp;
-		} else {
-			ret = next_code(self);
-			if (ret == -1)
-				state->end_of_stream = ret;
-			else if (ret != ARCHIVE_OK)
-				return (ret);
-		}
-	}
-
-	*pblock = start;
-	return (p - start);
-}
-
-/*
- * Close and release the filter.
- */
-static int
-compress_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state = (struct private_data *)self->data;
-
-	free(state->out_block);
-	free(state);
-	return (ARCHIVE_OK);
-}
-
-/*
- * Process the next code and fill the stack with the expansion
- * of the code.  Returns ARCHIVE_FATAL if there is a fatal I/O or
- * format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise.
- */
-static int
-next_code(struct archive_read_filter *self)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	int code, newcode;
-
-	static int debug_buff[1024];
-	static unsigned debug_index;
-
-	code = newcode = getbits(self, state->bits);
-	if (code < 0)
-		return (code);
-
-	debug_buff[debug_index++] = code;
-	if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0]))
-		debug_index = 0;
-
-	/* If it's a reset code, reset the dictionary. */
-	if ((code == 256) && state->use_reset_code) {
-		/*
-		 * The original 'compress' implementation blocked its
-		 * I/O in a manner that resulted in junk bytes being
-		 * inserted after every reset.  The next section skips
-		 * this junk.  (Yes, the number of *bytes* to skip is
-		 * a function of the current *bit* length.)
-		 */
-		int skip_bytes =  state->bits -
-		    (state->bytes_in_section % state->bits);
-		skip_bytes %= state->bits;
-		state->bits_avail = 0; /* Discard rest of this byte. */
-		while (skip_bytes-- > 0) {
-			code = getbits(self, 8);
-			if (code < 0)
-				return (code);
-		}
-		/* Now, actually do the reset. */
-		state->bytes_in_section = 0;
-		state->bits = 9;
-		state->section_end_code = (1 << state->bits) - 1;
-		state->free_ent = 257;
-		state->oldcode = -1;
-		return (next_code(self));
-	}
-
-	if (code > state->free_ent
-	    || (code == state->free_ent && state->oldcode < 0)) {
-		/* An invalid code is a fatal error. */
-		archive_set_error(&(self->archive->archive), -1,
-		    "Invalid compressed data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Special case for KwKwK string. */
-	if (code >= state->free_ent) {
-		*state->stackp++ = state->finbyte;
-		code = state->oldcode;
-	}
-
-	/* Generate output characters in reverse order. */
-	while (code >= 256) {
-		*state->stackp++ = state->suffix[code];
-		code = state->prefix[code];
-	}
-	*state->stackp++ = state->finbyte = code;
-
-	/* Generate the new entry. */
-	code = state->free_ent;
-	if (code < state->maxcode && state->oldcode >= 0) {
-		state->prefix[code] = state->oldcode;
-		state->suffix[code] = state->finbyte;
-		++state->free_ent;
-	}
-	if (state->free_ent > state->section_end_code) {
-		state->bits++;
-		state->bytes_in_section = 0;
-		if (state->bits == state->maxcode_bits)
-			state->section_end_code = state->maxcode;
-		else
-			state->section_end_code = (1 << state->bits) - 1;
-	}
-
-	/* Remember previous code. */
-	state->oldcode = newcode;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return next 'n' bits from stream.
- *
- * -1 indicates end of available data.
- */
-static int
-getbits(struct archive_read_filter *self, int n)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	int code;
-	ssize_t ret;
-	static const int mask[] = {
-		0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
-		0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-	};
-
-	while (state->bits_avail < n) {
-		if (state->avail_in <= 0) {
-			if (state->consume_unnotified) {
-				__archive_read_filter_consume(self->upstream,
-					state->consume_unnotified);
-				state->consume_unnotified = 0;
-			}
-			state->next_in
-			    = __archive_read_filter_ahead(self->upstream,
-				1, &ret);
-			if (ret == 0)
-				return (-1);
-			if (ret < 0 || state->next_in == NULL)
-				return (ARCHIVE_FATAL);
-			state->consume_unnotified = state->avail_in = ret;
-		}
-		state->bit_buffer |= *state->next_in++ << state->bits_avail;
-		state->avail_in--;
-		state->bits_avail += 8;
-		state->bytes_in_section++;
-	}
-
-	code = state->bit_buffer;
-	state->bit_buffer >>= n;
-	state->bits_avail -= n;
-
-	return (code & mask[n]);
-}
diff --git a/c/archive_read_support_filter_grzip.c b/c/archive_read_support_filter_grzip.c
deleted file mode 100644
--- a/c/archive_read_support_filter_grzip.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-static const unsigned char grzip_magic[] = {
-	0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00,
-	0x02, 0x04, 0x3a, 0x29 };
-
-static int	grzip_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	grzip_bidder_init(struct archive_read_filter *);
-
-
-static const struct archive_read_filter_bidder_vtable
-grzip_bidder_vtable = {
-	.bid = grzip_bidder_bid,
-	.init = grzip_bidder_init,
-};
-
-int
-archive_read_support_filter_grzip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, NULL,
-				&grzip_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* This filter always uses an external program. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external grzip program for grzip decompression");
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Bidder just verifies the header and returns the number of verified bits.
- */
-static int
-grzip_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *p;
-	ssize_t avail;
-
-	(void)self; /* UNUSED */
-
-	p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail);
-	if (p == NULL || avail == 0)
-		return (0);
-
-	if (memcmp(p, grzip_magic, sizeof(grzip_magic)))
-		return (0);
-
-	return (sizeof(grzip_magic) * 8);
-}
-
-static int
-grzip_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "grzip -d");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_GRZIP;
-	self->name = "grzip";
-	return (r);
-}
diff --git a/c/archive_read_support_filter_gzip.c b/c/archive_read_support_filter_gzip.c
deleted file mode 100644
--- a/c/archive_read_support_filter_gzip.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#ifdef HAVE_ZLIB_H
-struct private_data {
-	z_stream	 stream;
-	char		 in_stream;
-	unsigned char	*out_block;
-	size_t		 out_block_size;
-	int64_t		 total_out;
-	unsigned long	 crc;
-	uint32_t	 mtime;
-	char		*name;
-	char		 eof; /* True = found end of compressed data. */
-};
-
-/* Gzip Filter. */
-static ssize_t	gzip_filter_read(struct archive_read_filter *, const void **);
-static int	gzip_filter_close(struct archive_read_filter *);
-#endif
-
-/*
- * Note that we can detect gzip archives even if we can't decompress
- * them.  (In fact, we like detecting them because we can give better
- * error messages.)  So the bid framework here gets compiled even
- * if zlib is unavailable.
- *
- * TODO: If zlib is unavailable, gzip_bidder_init() should
- * use the compress_program framework to try to fire up an external
- * gzip program.
- */
-static int	gzip_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	gzip_bidder_init(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_gzip(struct archive *a)
-{
-	return archive_read_support_filter_gzip(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-gzip_bidder_vtable = {
-	.bid = gzip_bidder_bid,
-	.init = gzip_bidder_init,
-};
-
-int
-archive_read_support_filter_gzip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "gzip",
-				&gzip_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Signal the extent of gzip support with the return value here. */
-#if HAVE_ZLIB_H
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external gzip program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Read and verify the header.
- *
- * Returns zero if the header couldn't be validated, else returns
- * number of bytes in header.  If pbits is non-NULL, it receives a
- * count of bits verified, suitable for use by bidder.
- */
-static ssize_t
-peek_at_header(struct archive_read_filter *filter, int *pbits,
-#ifdef HAVE_ZLIB_H
-	       struct private_data *state
-#else
-	       void *state
-#endif
-	      )
-{
-	const unsigned char *p;
-	ssize_t avail, len;
-	int bits = 0;
-	int header_flags;
-#ifndef HAVE_ZLIB_H
-	(void)state; /* UNUSED */
-#endif
-
-	/* Start by looking at the first ten bytes of the header, which
-	 * is all fixed layout. */
-	len = 10;
-	p = __archive_read_filter_ahead(filter, len, &avail);
-	if (p == NULL || avail == 0)
-		return (0);
-	/* We only support deflation- third byte must be 0x08. */
-	if (memcmp(p, "\x1F\x8B\x08", 3) != 0)
-		return (0);
-	bits += 24;
-	if ((p[3] & 0xE0)!= 0)	/* No reserved flags set. */
-		return (0);
-	bits += 3;
-	header_flags = p[3];
-	/* Bytes 4-7 are mod time in little endian. */
-#ifdef HAVE_ZLIB_H
-	if (state)
-		state->mtime = archive_le32dec(p + 4);
-#endif
-	/* Byte 8 is deflate flags. */
-	/* XXXX TODO: return deflate flags back to consume_header for use
-	   in initializing the decompressor. */
-	/* Byte 9 is OS. */
-
-	/* Optional extra data:  2 byte length plus variable body. */
-	if (header_flags & 4) {
-		p = __archive_read_filter_ahead(filter, len + 2, &avail);
-		if (p == NULL)
-			return (0);
-		len += ((int)p[len + 1] << 8) | (int)p[len];
-		len += 2;
-	}
-
-	/* Null-terminated optional filename. */
-	if (header_flags & 8) {
-#ifdef HAVE_ZLIB_H
-		ssize_t file_start = len;
-#endif
-		do {
-			++len;
-			if (avail < len)
-				p = __archive_read_filter_ahead(filter,
-				    len, &avail);
-			if (p == NULL)
-				return (0);
-		} while (p[len - 1] != 0);
-
-#ifdef HAVE_ZLIB_H
-		if (state) {
-			/* Reset the name in case of repeat header reads. */
-			free(state->name);
-			state->name = strdup((const char *)&p[file_start]);
-		}
-#endif
-	}
-
-	/* Null-terminated optional comment. */
-	if (header_flags & 16) {
-		do {
-			++len;
-			if (avail < len)
-				p = __archive_read_filter_ahead(filter,
-				    len, &avail);
-			if (p == NULL)
-				return (0);
-		} while (p[len - 1] != 0);
-	}
-
-	/* Optional header CRC */
-	if ((header_flags & 2)) {
-		p = __archive_read_filter_ahead(filter, len + 2, &avail);
-		if (p == NULL)
-			return (0);
-#if 0
-	int hcrc = ((int)p[len + 1] << 8) | (int)p[len];
-	int crc = /* XXX TODO: Compute header CRC. */;
-	if (crc != hcrc)
-		return (0);
-	bits += 16;
-#endif
-		len += 2;
-	}
-
-	if (pbits != NULL)
-		*pbits = bits;
-	return (len);
-}
-
-/*
- * Bidder just verifies the header and returns the number of verified bits.
- */
-static int
-gzip_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	int bits_checked;
-
-	(void)self; /* UNUSED */
-
-	if (peek_at_header(filter, &bits_checked, NULL))
-		return (bits_checked);
-	return (0);
-}
-
-#ifndef HAVE_ZLIB_H
-
-/*
- * If we don't have the library on this system, we can't do the
- * decompression directly.  We can, however, try to run "gzip -d"
- * in case that's available.
- */
-static int
-gzip_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "gzip -d");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_GZIP;
-	self->name = "gzip";
-	return (r);
-}
-
-#else
-
-static int
-gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry)
-{
-	struct private_data *state;
-
-	state = (struct private_data *)self->data;
-
-	/* A mtime of 0 is considered invalid/missing. */
-	if (state->mtime != 0)
-		archive_entry_set_mtime(entry, state->mtime, 0);
-
-	/* If the name is available, extract it. */
-	if (state->name)
-		archive_entry_set_pathname(entry, state->name);
-
-	return (ARCHIVE_OK);
-}
-
-static const struct archive_read_filter_vtable
-gzip_reader_vtable = {
-	.read = gzip_filter_read,
-	.close = gzip_filter_close,
-#ifdef HAVE_ZLIB_H
-	.read_header = gzip_read_header,
-#endif
-};
-
-/*
- * Initialize the filter object.
- */
-static int
-gzip_bidder_init(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	static const size_t out_block_size = 64 * 1024;
-	void *out_block;
-
-	self->code = ARCHIVE_FILTER_GZIP;
-	self->name = "gzip";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = (unsigned char *)malloc(out_block_size);
-	if (state == NULL || out_block == NULL) {
-		free(out_block);
-		free(state);
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for gzip decompression");
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	self->vtable = &gzip_reader_vtable;
-
-	state->in_stream = 0; /* We're not actually within a stream yet. */
-
-	return (ARCHIVE_OK);
-}
-
-static int
-consume_header(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	ssize_t avail;
-	size_t len;
-	int ret;
-
-	state = (struct private_data *)self->data;
-
-	/* If this is a real header, consume it. */
-	len = peek_at_header(self->upstream, NULL, state);
-	if (len == 0)
-		return (ARCHIVE_EOF);
-	__archive_read_filter_consume(self->upstream, len);
-
-	/* Initialize CRC accumulator. */
-	state->crc = crc32(0L, NULL, 0);
-
-	/* Initialize compression library. */
-	state->stream.next_in = (unsigned char *)(uintptr_t)
-	    __archive_read_filter_ahead(self->upstream, 1, &avail);
-	state->stream.avail_in = (uInt)avail;
-	ret = inflateInit2(&(state->stream),
-	    -15 /* Don't check for zlib header */);
-
-	/* Decipher the error code. */
-	switch (ret) {
-	case Z_OK:
-		state->in_stream = 1;
-		return (ARCHIVE_OK);
-	case Z_STREAM_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "invalid setup parameter");
-		break;
-	case Z_MEM_ERROR:
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "out of memory");
-		break;
-	case Z_VERSION_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "invalid library version");
-		break;
-	default:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    " Zlib error %d", ret);
-		break;
-	}
-	return (ARCHIVE_FATAL);
-}
-
-static int
-consume_trailer(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	const unsigned char *p;
-	ssize_t avail;
-
-	state = (struct private_data *)self->data;
-
-	state->in_stream = 0;
-	switch (inflateEnd(&(state->stream))) {
-	case Z_OK:
-		break;
-	default:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up gzip decompressor");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* GZip trailer is a fixed 8 byte structure. */
-	p = __archive_read_filter_ahead(self->upstream, 8, &avail);
-	if (p == NULL || avail == 0)
-		return (ARCHIVE_FATAL);
-
-	/* XXX TODO: Verify the length and CRC. */
-
-	/* We've verified the trailer, so consume it now. */
-	__archive_read_filter_consume(self->upstream, 8);
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-gzip_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state;
-	size_t decompressed;
-	ssize_t avail_in, max_in;
-	int ret;
-
-	state = (struct private_data *)self->data;
-
-	/* Empty our output buffer. */
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = (uInt)state->out_block_size;
-
-	/* Try to fill the output buffer. */
-	while (state->stream.avail_out > 0 && !state->eof) {
-		/* If we're not in a stream, read a header
-		 * and initialize the decompression library. */
-		if (!state->in_stream) {
-			ret = consume_header(self);
-			if (ret == ARCHIVE_EOF) {
-				state->eof = 1;
-				break;
-			}
-			if (ret < ARCHIVE_OK)
-				return (ret);
-		}
-
-		/* Peek at the next available data. */
-		/* ZLib treats stream.next_in as const but doesn't declare
-		 * it so, hence this ugly cast. */
-		state->stream.next_in = (unsigned char *)(uintptr_t)
-		    __archive_read_filter_ahead(self->upstream, 1, &avail_in);
-		if (state->stream.next_in == NULL) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated gzip input");
-			return (ARCHIVE_FATAL);
-		}
-		if (UINT_MAX >= SSIZE_MAX)
-			max_in = SSIZE_MAX;
-		else
-			max_in = UINT_MAX;
-		if (avail_in > max_in)
-			avail_in = max_in;
-		state->stream.avail_in = (uInt)avail_in;
-
-		/* Decompress and consume some of that data. */
-		ret = inflate(&(state->stream), 0);
-		switch (ret) {
-		case Z_OK: /* Decompressor made some progress. */
-			__archive_read_filter_consume(self->upstream,
-			    avail_in - state->stream.avail_in);
-			break;
-		case Z_STREAM_END: /* Found end of stream. */
-			__archive_read_filter_consume(self->upstream,
-			    avail_in - state->stream.avail_in);
-			/* Consume the stream trailer; release the
-			 * decompression library. */
-			ret = consume_trailer(self);
-			if (ret < ARCHIVE_OK)
-				return (ret);
-			break;
-		default:
-			/* Return an error. */
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "gzip decompression failed");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	/* We've read as much as we can. */
-	decompressed = state->stream.next_out - state->out_block;
-	state->total_out += decompressed;
-	if (decompressed == 0)
-		*p = NULL;
-	else
-		*p = state->out_block;
-	return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-gzip_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	int ret;
-
-	state = (struct private_data *)self->data;
-	ret = ARCHIVE_OK;
-
-	if (state->in_stream) {
-		switch (inflateEnd(&(state->stream))) {
-		case Z_OK:
-			break;
-		default:
-			archive_set_error(&(self->archive->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up gzip compressor");
-			ret = ARCHIVE_FATAL;
-		}
-	}
-
-	free(state->name);
-	free(state->out_block);
-	free(state);
-	return (ret);
-}
-
-#endif /* HAVE_ZLIB_H */
diff --git a/c/archive_read_support_filter_lrzip.c b/c/archive_read_support_filter_lrzip.c
deleted file mode 100644
--- a/c/archive_read_support_filter_lrzip.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#define LRZIP_HEADER_MAGIC "LRZI"
-#define LRZIP_HEADER_MAGIC_LEN 4
-
-static int	lrzip_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	lrzip_bidder_init(struct archive_read_filter *);
-
-
-static const struct archive_read_filter_bidder_vtable
-lrzip_bidder_vtable = {
-	.bid = lrzip_bidder_bid,
-	.init = lrzip_bidder_init,
-};
-
-int
-archive_read_support_filter_lrzip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "lrzip",
-				&lrzip_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* This filter always uses an external program. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lrzip program for lrzip decompression");
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Bidder just verifies the header and returns the number of verified bits.
- */
-static int
-lrzip_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *p;
-	ssize_t avail, len;
-	int i;
-
-	(void)self; /* UNUSED */
-	/* Start by looking at the first six bytes of the header, which
-	 * is all fixed layout. */
-	len = 6;
-	p = __archive_read_filter_ahead(filter, len, &avail);
-	if (p == NULL || avail == 0)
-		return (0);
-
-	if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
-		return (0);
-
-	/* current major version is always 0, verify this */
-	if (p[LRZIP_HEADER_MAGIC_LEN])
-		return 0;
-	/* support only v0.6+ lrzip for sanity */
-	i = p[LRZIP_HEADER_MAGIC_LEN + 1];
-	if ((i < 6) || (i > 10))
-		return 0;
-
-	return (int)len;
-}
-
-static int
-lrzip_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "lrzip -d -q");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_LRZIP;
-	self->name = "lrzip";
-	return (r);
-}
diff --git a/c/archive_read_support_filter_lz4.c b/c/archive_read_support_filter_lz4.c
deleted file mode 100644
--- a/c/archive_read_support_filter_lz4.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_LZ4_H
-#include <lz4.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_xxhash.h"
-
-#define LZ4_MAGICNUMBER		0x184d2204
-#define LZ4_SKIPPABLED		0x184d2a50
-#define LZ4_LEGACY		0x184c2102
-
-#if defined(HAVE_LIBLZ4)
-struct private_data {
-	enum {  SELECT_STREAM,
-		READ_DEFAULT_STREAM,
-		READ_DEFAULT_BLOCK,
-		READ_LEGACY_STREAM,
-		READ_LEGACY_BLOCK,
-	}		stage;
-	struct {
-		unsigned block_independence:1;
-		unsigned block_checksum:3;
-		unsigned stream_size:1;
-		unsigned stream_checksum:1;
-		unsigned preset_dictionary:1;
-		int	 block_maximum_size;
-	} flags;
-	int64_t		 stream_size;
-	uint32_t	 dict_id;
-	char		*out_block;
-	size_t		 out_block_size;
-
-	/* Bytes read but not yet consumed via __archive_read_consume() */
-	size_t		 unconsumed;
-	size_t		 decoded_size;
-	void		*xxh32_state;
-
-	char		 valid; /* True = decompressor is initialized */
-	char		 eof; /* True = found end of compressed data. */
-};
-
-#define LEGACY_BLOCK_SIZE	(8 * 1024 * 1024)
-
-/* Lz4 filter */
-static ssize_t	lz4_filter_read(struct archive_read_filter *, const void **);
-static int	lz4_filter_close(struct archive_read_filter *);
-#endif
-
-/*
- * Note that we can detect lz4 archives even if we can't decompress
- * them.  (In fact, we like detecting them because we can give better
- * error messages.)  So the bid framework here gets compiled even
- * if liblz4 is unavailable.
- */
-static int	lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
-static int	lz4_reader_init(struct archive_read_filter *);
-#if defined(HAVE_LIBLZ4)
-static ssize_t  lz4_filter_read_default_stream(struct archive_read_filter *,
-		    const void **);
-static ssize_t  lz4_filter_read_legacy_stream(struct archive_read_filter *,
-		    const void **);
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-lz4_bidder_vtable = {
-	.bid = lz4_reader_bid,
-	.init = lz4_reader_init,
-};
-
-int
-archive_read_support_filter_lz4(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "lz4",
-				&lz4_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if defined(HAVE_LIBLZ4)
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lz4 program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Test whether we can handle this data.
- *
- * This logic returns zero if any part of the signature fails.  It
- * also tries to Do The Right Thing if a very short buffer prevents us
- * from verifying as much as we would like.
- */
-static int
-lz4_reader_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	int bits_checked;
-	uint32_t number;
-
-	(void)self; /* UNUSED */
-
-	/* Minimal lz4 archive is 11 bytes. */
-	buffer = __archive_read_filter_ahead(filter, 11, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	/* First four bytes must be LZ4 magic numbers. */
-	bits_checked = 0;
-	if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) {
-		unsigned char flag, BD;
-
-		bits_checked += 32;
-		/* Next follows a stream descriptor. */
-		/* Descriptor Flags. */
-		flag = buffer[4];
-		/* A version number must be "01". */
-		if (((flag & 0xc0) >> 6) != 1)
-			return (0);
-		/* A reserved bit must be "0". */
-		if (flag & 2)
-			return (0);
-		bits_checked += 8;
-		BD = buffer[5];
-		/* A block maximum size should be more than 3. */
-		if (((BD & 0x70) >> 4) < 4)
-			return (0);
-		/* Reserved bits must be "0". */
-		if (BD & ~0x70)
-			return (0);
-		bits_checked += 8;
-	} else if (number == LZ4_LEGACY) {
-		bits_checked += 32;
-	}
-	
-	return (bits_checked);
-}
-
-#if !defined(HAVE_LIBLZ4)
-
-/*
- * If we don't have the library on this system, we can't actually do the
- * decompression.  We can, however, still detect compressed archives
- * and emit a useful message.
- */
-static int
-lz4_reader_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "lz4 -d -q");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_LZ4;
-	self->name = "lz4";
-	return (r);
-}
-
-
-#else
-
-static const struct archive_read_filter_vtable
-lz4_reader_vtable = {
-	.read = lz4_filter_read,
-	.close = lz4_filter_close,
-};
-
-/*
- * Setup the callbacks.
- */
-static int
-lz4_reader_init(struct archive_read_filter *self)
-{
-	struct private_data *state;
-
-	self->code = ARCHIVE_FILTER_LZ4;
-	self->name = "lz4";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	if (state == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for lz4 decompression");
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->stage = SELECT_STREAM;
-	self->vtable = &lz4_reader_vtable;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-lz4_allocate_out_block(struct archive_read_filter *self)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	size_t out_block_size = state->flags.block_maximum_size;
-	void *out_block;
-
-	if (!state->flags.block_independence)
-		out_block_size += 64 * 1024;
-	if (state->out_block_size < out_block_size) {
-		free(state->out_block);
-		out_block = (unsigned char *)malloc(out_block_size);
-		state->out_block_size = out_block_size;
-		if (out_block == NULL) {
-			archive_set_error(&self->archive->archive, ENOMEM,
-			    "Can't allocate data for lz4 decompression");
-			return (ARCHIVE_FATAL);
-		}
-		state->out_block = out_block;
-	}
-	if (!state->flags.block_independence)
-		memset(state->out_block, 0, 64 * 1024);
-	return (ARCHIVE_OK);
-}
-
-static int
-lz4_allocate_out_block_for_legacy(struct archive_read_filter *self)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	size_t out_block_size = LEGACY_BLOCK_SIZE;
-	void *out_block;
-
-	if (state->out_block_size < out_block_size) {
-		free(state->out_block);
-		out_block = (unsigned char *)malloc(out_block_size);
-		state->out_block_size = out_block_size;
-		if (out_block == NULL) {
-			archive_set_error(&self->archive->archive, ENOMEM,
-			    "Can't allocate data for lz4 decompression");
-			return (ARCHIVE_FATAL);
-		}
-		state->out_block = out_block;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-lz4_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	ssize_t ret;
-
-	if (state->eof) {
-		*p = NULL;
-		return (0);
-	}
-
-	__archive_read_filter_consume(self->upstream, state->unconsumed);
-	state->unconsumed = 0;
-
-	switch (state->stage) {
-	case SELECT_STREAM:
-		break;
-	case READ_DEFAULT_STREAM:
-	case READ_LEGACY_STREAM:
-		/* Reading a lz4 stream already failed. */
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC, "Invalid sequence.");
-		return (ARCHIVE_FATAL);
-	case READ_DEFAULT_BLOCK:
-		ret = lz4_filter_read_default_stream(self, p);
-		if (ret != 0 || state->stage != SELECT_STREAM)
-			return ret;
-		break;
-	case READ_LEGACY_BLOCK:
-		ret = lz4_filter_read_legacy_stream(self, p);
-		if (ret != 0 || state->stage != SELECT_STREAM)
-			return ret;
-		break;
-	default:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC, "Program error.");
-		return (ARCHIVE_FATAL);
-		break;
-	}
-
-	while (state->stage == SELECT_STREAM) {
-		const char *read_buf;
-
-		/* Read a magic number. */
-		read_buf = __archive_read_filter_ahead(self->upstream, 4,
-				NULL);
-		if (read_buf == NULL) {
-			state->eof = 1;
-			*p = NULL;
-			return (0);
-		}
-		uint32_t number = archive_le32dec(read_buf);
-		__archive_read_filter_consume(self->upstream, 4);
-		if (number == LZ4_MAGICNUMBER)
-			return lz4_filter_read_default_stream(self, p);
-		else if (number == LZ4_LEGACY)
-			return lz4_filter_read_legacy_stream(self, p);
-		else if ((number & ~0xF) == LZ4_SKIPPABLED) {
-			read_buf = __archive_read_filter_ahead(
-				self->upstream, 4, NULL);
-			if (read_buf == NULL) {
-				archive_set_error(
-				    &self->archive->archive,
-		    		    ARCHIVE_ERRNO_MISC,
-				    "Malformed lz4 data");
-				return (ARCHIVE_FATAL);
-			}
-			uint32_t skip_bytes = archive_le32dec(read_buf);
-			__archive_read_filter_consume(self->upstream,
-				4 + skip_bytes);
-		} else {
-			/* Ignore following unrecognized data. */
-			state->eof = 1;
-			*p = NULL;
-			return (0);
-		}
-	}
-	state->eof = 1;
-	*p = NULL;
-	return (0);
-}
-
-static int
-lz4_filter_read_descriptor(struct archive_read_filter *self)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	const char *read_buf;
-	ssize_t bytes_remaining;
-	ssize_t descriptor_bytes;
-	unsigned char flag, bd;
-	unsigned int chsum, chsum_verifier;
-
-	/* Make sure we have 2 bytes for flags. */
-	read_buf = __archive_read_filter_ahead(self->upstream, 2,
-	    &bytes_remaining);
-	if (read_buf == NULL) {
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "truncated lz4 input");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	   Parse flags.
-	 */
-	flag = (unsigned char)read_buf[0];
-	/* Verify version number. */
-	if ((flag & 0xc0) != 1<<6)
-		goto malformed_error;
-	/* A reserved bit must be zero. */
-	if (flag & 0x02)
-		goto malformed_error;
-	state->flags.block_independence = (flag & 0x20) != 0;
-	state->flags.block_checksum = (flag & 0x10)?4:0;
-	state->flags.stream_size = (flag & 0x08) != 0;
-	state->flags.stream_checksum = (flag & 0x04) != 0;
-	state->flags.preset_dictionary = (flag & 0x01) != 0;
-
-	/* BD */
-	bd = (unsigned char)read_buf[1];
-	/* Reserved bits must be zero. */
-	if (bd & 0x8f)
-		goto malformed_error;
-	/* Get a maximum block size. */
-	switch (read_buf[1] >> 4) {
-	case 4: /* 64 KB */
-		state->flags.block_maximum_size = 64 * 1024;
-		break;
-	case 5: /* 256 KB */
-		state->flags.block_maximum_size = 256 * 1024;
-		break;
-	case 6: /* 1 MB */
-		state->flags.block_maximum_size = 1024 * 1024;
-		break;
-	case 7: /* 4 MB */
-		state->flags.block_maximum_size = 4 * 1024 * 1024;
-		break;
-	default:
-		goto malformed_error;
-	}
-
-	/* Read the whole descriptor in a stream block. */
-	descriptor_bytes = 3;
-	if (state->flags.stream_size)
-		descriptor_bytes += 8;
-	if (state->flags.preset_dictionary)
-		descriptor_bytes += 4;
-	if (bytes_remaining < descriptor_bytes) {
-		read_buf = __archive_read_filter_ahead(self->upstream,
-		    descriptor_bytes, &bytes_remaining);
-		if (read_buf == NULL) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated lz4 input");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	/* Check if a descriptor is corrupted */
-	chsum = __archive_xxhash.XXH32(read_buf, (int)descriptor_bytes -1, 0);
-	chsum = (chsum >> 8) & 0xff;
-	chsum_verifier = read_buf[descriptor_bytes-1] & 0xff;
-	if (chsum != chsum_verifier)
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		goto malformed_error;
-#endif
-
-	__archive_read_filter_consume(self->upstream, descriptor_bytes);
-
-	/* Make sure we have a large enough buffer for uncompressed data. */
-	if (lz4_allocate_out_block(self) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	if (state->flags.stream_checksum)
-		state->xxh32_state = __archive_xxhash.XXH32_init(0);
-
-	state->decoded_size = 0;
-	/* Success */
-	return (ARCHIVE_OK);
-malformed_error:
-	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-	    "malformed lz4 data");
-	return (ARCHIVE_FATAL);
-}
-
-static ssize_t
-lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	ssize_t compressed_size;
-	const char *read_buf;
-	ssize_t bytes_remaining;
-	int checksum_size;
-	ssize_t uncompressed_size;
-	size_t prefix64k;
-
-	*p = NULL;
-
-	/* Make sure we have 4 bytes for a block size. */
-	read_buf = __archive_read_filter_ahead(self->upstream, 4,
-	    &bytes_remaining);
-	if (read_buf == NULL)
-		goto truncated_error;
-	compressed_size = archive_le32dec(read_buf);
-	if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size)
-		goto malformed_error;
-	/* A compressed size == 0 means the end of stream blocks. */
-	if (compressed_size == 0) {
-		__archive_read_filter_consume(self->upstream, 4);
-		return 0;
-	}
-
-	checksum_size = state->flags.block_checksum;
-	/* Check if the block is uncompressed. */
-	if (compressed_size & 0x80000000U) {
-		compressed_size &= 0x7fffffff;
-		uncompressed_size = compressed_size;
-	} else
-		uncompressed_size = 0;/* Unknown yet. */
-
-	/*
-	  Unfortunately, lz4 decompression API requires a whole block
-	  for its decompression speed, so we read a whole block and allocate
-	  a huge buffer used for decoded data.
-	*/
-	read_buf = __archive_read_filter_ahead(self->upstream,
-	    4 + compressed_size + checksum_size, &bytes_remaining);
-	if (read_buf == NULL)
-		goto truncated_error;
-
-	/* Optional processing, checking a block sum. */
-	if (checksum_size) {
-		unsigned int chsum = __archive_xxhash.XXH32(
-			read_buf + 4, (int)compressed_size, 0);
-		unsigned int chsum_block =
-		    archive_le32dec(read_buf + 4 + compressed_size);
-		if (chsum != chsum_block)
-#ifndef DONT_FAIL_ON_CRC_ERROR
-			goto malformed_error;
-#endif
-	}
-
-
-	/* If the block is uncompressed, there is nothing to do. */
-	if (uncompressed_size) {
-		/* Prepare a prefix 64k block for next block. */
-		if (!state->flags.block_independence) {
-			prefix64k = 64 * 1024;
-			if (uncompressed_size < (ssize_t)prefix64k) {
-				memcpy(state->out_block
-					+ prefix64k - uncompressed_size,
-				    read_buf + 4,
-				    uncompressed_size);
-				memset(state->out_block, 0,
-				    prefix64k - uncompressed_size);
-			} else {
-				memcpy(state->out_block,
-				    read_buf + 4
-					+ uncompressed_size - prefix64k,
-				    prefix64k);
-			}
-			state->decoded_size = 0;
-		}
-		state->unconsumed = 4 + uncompressed_size + checksum_size;
-		*p = read_buf + 4;
-		return uncompressed_size;
-	}
-
-	/*
-	   Decompress a block data.
-	 */
-	if (state->flags.block_independence) {
-		prefix64k = 0;
-		uncompressed_size = LZ4_decompress_safe(read_buf + 4,
-		    state->out_block, (int)compressed_size,
-		    state->flags.block_maximum_size);
-	} else {
-		prefix64k = 64 * 1024;
-		if (state->decoded_size) {
-			if (state->decoded_size < prefix64k) {
-				memmove(state->out_block
-					+ prefix64k - state->decoded_size,
-				    state->out_block + prefix64k,
-				    state->decoded_size);
-				memset(state->out_block, 0,
-				    prefix64k - state->decoded_size);
-			} else {
-				memmove(state->out_block,
-				    state->out_block + state->decoded_size,
-				    prefix64k);
-			}
-		}
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-		uncompressed_size = LZ4_decompress_safe_usingDict(
-		    read_buf + 4,
-		    state->out_block + prefix64k, (int)compressed_size,
-		    state->flags.block_maximum_size,
-		    state->out_block,
-		    (int)prefix64k);
-#else
-		uncompressed_size = LZ4_decompress_safe_withPrefix64k(
-		    read_buf + 4,
-		    state->out_block + prefix64k, (int)compressed_size,
-		    state->flags.block_maximum_size);
-#endif
-	}
-
-	/* Check if an error occurred in the decompression process. */
-	if (uncompressed_size < 0) {
-		archive_set_error(&(self->archive->archive),
-		    ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
-		return (ARCHIVE_FATAL);
-	}
-
-	state->unconsumed = 4 + compressed_size + checksum_size;
-	*p = state->out_block + prefix64k;
-	state->decoded_size = uncompressed_size;
-	return uncompressed_size;
-
-malformed_error:
-	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-	    "malformed lz4 data");
-	return (ARCHIVE_FATAL);
-truncated_error:
-	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-	    "truncated lz4 input");
-	return (ARCHIVE_FATAL);
-}
-
-static ssize_t
-lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	const char *read_buf;
-	ssize_t bytes_remaining;
-	ssize_t ret;
-
-	if (state->stage == SELECT_STREAM) {
-		state->stage = READ_DEFAULT_STREAM;
-		/* First, read a descriptor. */
-		if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK)
-			return (ret);
-		state->stage = READ_DEFAULT_BLOCK;
-	}
-	/* Decompress a block. */
-	ret = lz4_filter_read_data_block(self, p);
-
-	/* If the end of block is detected, change the filter status
-	   to read next stream. */
-	if (ret == 0 && *p == NULL)
-		state->stage = SELECT_STREAM;
-
-	/* Optional processing, checking a stream sum. */
-	if (state->flags.stream_checksum) {
-		if (state->stage == SELECT_STREAM) {
-			unsigned int checksum;
-			unsigned int checksum_stream;
-			read_buf = __archive_read_filter_ahead(self->upstream,
-			    4, &bytes_remaining);
-			if (read_buf == NULL) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC, "truncated lz4 input");
-				return (ARCHIVE_FATAL);
-			}
-			checksum = archive_le32dec(read_buf);
-			__archive_read_filter_consume(self->upstream, 4);
-			checksum_stream = __archive_xxhash.XXH32_digest(
-			    state->xxh32_state);
-			state->xxh32_state = NULL;
-			if (checksum != checksum_stream) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "lz4 stream checksum error");
-				return (ARCHIVE_FATAL);
-#endif
-			}
-		} else if (ret > 0)
-			__archive_xxhash.XXH32_update(state->xxh32_state,
-			    *p, (int)ret);
-	}
-	return (ret);
-}
-
-static ssize_t
-lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state = (struct private_data *)self->data;
-	uint32_t compressed;
-	const char *read_buf;
-	ssize_t ret;
-
-	*p = NULL;
-	ret = lz4_allocate_out_block_for_legacy(self);
-	if (ret != ARCHIVE_OK)
-		return ret;
-
-	/* Make sure we have 4 bytes for a block size. */
-	read_buf = __archive_read_filter_ahead(self->upstream, 4, NULL);
-	if (read_buf == NULL) {
-		if (state->stage == SELECT_STREAM) {
-			state->stage = READ_LEGACY_STREAM;
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated lz4 input");
-			return (ARCHIVE_FATAL);
-		}
-		state->stage = SELECT_STREAM;
-		return 0;
-	}
-	state->stage = READ_LEGACY_BLOCK;
-	compressed = archive_le32dec(read_buf);
-	if (compressed > LZ4_COMPRESSBOUND(LEGACY_BLOCK_SIZE)) {
-		state->stage = SELECT_STREAM;
-		return 0;
-	}
-
-	/* Make sure we have a whole block. */
-	read_buf = __archive_read_filter_ahead(self->upstream,
-	    4 + compressed, NULL);
-	if (read_buf == NULL) {
-		archive_set_error(&(self->archive->archive),
-		    ARCHIVE_ERRNO_MISC, "truncated lz4 input");
-		return (ARCHIVE_FATAL);
-	}
-	ret = LZ4_decompress_safe(read_buf + 4, state->out_block,
-	    compressed, (int)state->out_block_size);
-	if (ret < 0) {
-		archive_set_error(&(self->archive->archive),
-		    ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
-		return (ARCHIVE_FATAL);
-	}
-	*p = state->out_block;
-	state->unconsumed = 4 + compressed;
-	return ret;
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lz4_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	int ret = ARCHIVE_OK;
-
-	state = (struct private_data *)self->data;
-	free(state->xxh32_state);
-	free(state->out_block);
-	free(state);
-	return (ret);
-}
-
-#endif /* HAVE_LIBLZ4 */
diff --git a/c/archive_read_support_filter_lzop.c b/c/archive_read_support_filter_lzop.c
deleted file mode 100644
--- a/c/archive_read_support_filter_lzop.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_LZO_LZOCONF_H
-#include <lzo/lzoconf.h>
-#endif
-#ifdef HAVE_LZO_LZO1X_H
-#include <lzo/lzo1x.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h> /* for crc32 and adler32 */
-#endif
-
-#include "archive.h"
-#if !defined(HAVE_ZLIB_H) &&\
-     defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-#include "archive_crc32.h"
-#endif
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#ifndef HAVE_ZLIB_H
-#define adler32	lzo_adler32
-#endif
-
-#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
-#define LZOP_HEADER_MAGIC_LEN 9
-
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-struct read_lzop {
-	unsigned char	*out_block;
-	size_t		 out_block_size;
-	int64_t		 total_out;
-	int		 flags;
-	uint32_t	 compressed_cksum;
-	uint32_t	 uncompressed_cksum;
-	size_t		 compressed_size;
-	size_t		 uncompressed_size;
-	size_t		 unconsumed_bytes;
-	char		 in_stream;
-	char		 eof; /* True = found end of compressed data. */
-};
-
-#define FILTER			0x0800
-#define CRC32_HEADER		0x1000
-#define EXTRA_FIELD		0x0040
-#define ADLER32_UNCOMPRESSED	0x0001
-#define ADLER32_COMPRESSED	0x0002
-#define CRC32_UNCOMPRESSED	0x0100
-#define CRC32_COMPRESSED	0x0200
-#define MAX_BLOCK_SIZE		(64 * 1024 * 1024)
-
-static ssize_t  lzop_filter_read(struct archive_read_filter *, const void **);
-static int	lzop_filter_close(struct archive_read_filter *);
-#endif
-
-static int lzop_bidder_bid(struct archive_read_filter_bidder *,
-    struct archive_read_filter *);
-static int lzop_bidder_init(struct archive_read_filter *);
-
-static const struct archive_read_filter_bidder_vtable
-lzop_bidder_vtable = {
-	.bid = lzop_bidder_bid,
-	.init = lzop_bidder_init,
-};
-
-int
-archive_read_support_filter_lzop(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, NULL,
-				&lzop_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Signal the extent of lzop support with the return value here. */
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-	return (ARCHIVE_OK);
-#else
-	/* Return ARCHIVE_WARN since this always uses an external program. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lzop program for lzop decompression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Bidder just verifies the header and returns the number of verified bits.
- */
-static int
-lzop_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *p;
-	ssize_t avail;
-
-	(void)self; /* UNUSED */
-
-	p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail);
-	if (p == NULL || avail == 0)
-		return (0);
-
-	if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
-		return (0);
-
-	return (LZOP_HEADER_MAGIC_LEN * 8);
-}
-
-#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H)
-/*
- * If we don't have the library on this system, we can't do the
- * decompression directly.  We can, however, try to run "lzop -d"
- * in case that's available.
- */
-static int
-lzop_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "lzop -d");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_LZOP;
-	self->name = "lzop";
-	return (r);
-}
-#else
-
-static const struct archive_read_filter_vtable
-lzop_reader_vtable = {
-	.read = lzop_filter_read,
-	.close = lzop_filter_close
-};
-
-/*
- * Initialize the filter object.
- */
-static int
-lzop_bidder_init(struct archive_read_filter *self)
-{
-	struct read_lzop *state;
-
-	self->code = ARCHIVE_FILTER_LZOP;
-	self->name = "lzop";
-
-	state = (struct read_lzop *)calloc(sizeof(*state), 1);
-	if (state == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for lzop decompression");
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	self->vtable = &lzop_reader_vtable;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-consume_header(struct archive_read_filter *self)
-{
-	struct read_lzop *state = (struct read_lzop *)self->data;
-	const unsigned char *p, *_p;
-	unsigned checksum, flags, len, method, version;
-
-	/*
-	 * Check LZOP magic code.
-	 */
-	p = __archive_read_filter_ahead(self->upstream,
-		LZOP_HEADER_MAGIC_LEN, NULL);
-	if (p == NULL)
-		return (ARCHIVE_EOF);
-
-	if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
-		return (ARCHIVE_EOF);
-	__archive_read_filter_consume(self->upstream,
-	    LZOP_HEADER_MAGIC_LEN);
-
-	p = __archive_read_filter_ahead(self->upstream, 29, NULL);
-	if (p == NULL)
-		goto truncated;
-	_p = p;
-	version = archive_be16dec(p);
-	p += 4;/* version(2 bytes) + library version(2 bytes) */
-
-	if (version >= 0x940) {
-		unsigned reqversion = archive_be16dec(p); p += 2;
-		if (reqversion < 0x900) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC, "Invalid required version");
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	method = *p++;
-	if (method < 1 || method > 3) {
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Unsupported method");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (version >= 0x940) {
-		unsigned level = *p++;
-#if 0
-		unsigned default_level[] = {0, 3, 1, 9};
-#endif
-		if (level == 0)
-			/* Method is 1..3 here due to check above. */
-#if 0	/* Avoid an error Clang Static Analyzer claims
-	  "Value stored to 'level' is never read". */
-			level = default_level[method];
-#else
-			;/* NOP */
-#endif
-		else if (level > 9) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC, "Invalid level");
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	flags = archive_be32dec(p); p += 4;
-
-	if (flags & FILTER)
-		p += 4; /* Skip filter */
-	p += 4; /* Skip mode */
-	if (version >= 0x940)
-		p += 8; /* Skip mtime */
-	else
-		p += 4; /* Skip mtime */
-	len = *p++; /* Read filename length */
-	len += p - _p;
-	/* Make sure we have all bytes we need to calculate checksum. */
-	p = __archive_read_filter_ahead(self->upstream, len + 4, NULL);
-	if (p == NULL)
-		goto truncated;
-	if (flags & CRC32_HEADER)
-		checksum = crc32(crc32(0, NULL, 0), p, len);
-	else
-		checksum = adler32(adler32(0, NULL, 0), p, len);
-	if (archive_be32dec(p + len) != checksum)
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		goto corrupted;
-#endif
-	__archive_read_filter_consume(self->upstream, len + 4);
-	if (flags & EXTRA_FIELD) {
-		/* Skip extra field */
-		p = __archive_read_filter_ahead(self->upstream, 4, NULL);
-		if (p == NULL)
-			goto truncated;
-		len = archive_be32dec(p);
-		__archive_read_filter_consume(self->upstream, len + 4 + 4);
-	}
-	state->flags = flags;
-	state->in_stream = 1;
-	return (ARCHIVE_OK);
-truncated:
-	archive_set_error(&self->archive->archive,
-	    ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
-	return (ARCHIVE_FAILED);
-corrupted:
-	archive_set_error(&self->archive->archive,
-	    ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
-	return (ARCHIVE_FAILED);
-}
-
-static int
-consume_block_info(struct archive_read_filter *self)
-{
-	struct read_lzop *state = (struct read_lzop *)self->data;
-	const unsigned char *p;
-	unsigned flags = state->flags;
-
-	p = __archive_read_filter_ahead(self->upstream, 4, NULL);
-	if (p == NULL)
-		goto truncated;
-	state->uncompressed_size = archive_be32dec(p);
-	__archive_read_filter_consume(self->upstream, 4);
-	if (state->uncompressed_size == 0)
-		return (ARCHIVE_EOF);
-	if (state->uncompressed_size > MAX_BLOCK_SIZE)
-		goto corrupted;
-
-	p = __archive_read_filter_ahead(self->upstream, 4, NULL);
-	if (p == NULL)
-		goto truncated;
-	state->compressed_size = archive_be32dec(p);
-	__archive_read_filter_consume(self->upstream, 4);
-	if (state->compressed_size > state->uncompressed_size)
-		goto corrupted;
-
-	if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) {
-		p = __archive_read_filter_ahead(self->upstream, 4, NULL);
-		if (p == NULL)
-			goto truncated;
-		state->compressed_cksum = state->uncompressed_cksum =
-		    archive_be32dec(p);
-		__archive_read_filter_consume(self->upstream, 4);
-	}
-	if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) &&
-	    state->compressed_size < state->uncompressed_size) {
-		p = __archive_read_filter_ahead(self->upstream, 4, NULL);
-		if (p == NULL)
-			goto truncated;
-		state->compressed_cksum = archive_be32dec(p);
-		__archive_read_filter_consume(self->upstream, 4);
-	}
-	return (ARCHIVE_OK);
-truncated:
-	archive_set_error(&self->archive->archive,
-	    ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
-	return (ARCHIVE_FAILED);
-corrupted:
-	archive_set_error(&self->archive->archive,
-	    ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
-	return (ARCHIVE_FAILED);
-}
-
-static ssize_t
-lzop_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct read_lzop *state = (struct read_lzop *)self->data;
-	const void *b;
-	lzo_uint out_size;
-	uint32_t cksum;
-	int ret, r;
-
-	if (state->unconsumed_bytes) {
-		__archive_read_filter_consume(self->upstream,
-		    state->unconsumed_bytes);
-		state->unconsumed_bytes = 0;
-	}
-	if (state->eof)
-		return (0);
-
-	for (;;) {
-		if (!state->in_stream) {
-			ret = consume_header(self);
-			if (ret < ARCHIVE_OK)
-				return (ret);
-			if (ret == ARCHIVE_EOF) {
-				state->eof = 1;
-				return (0);
-			}
-		}
-		ret = consume_block_info(self);
-		if (ret < ARCHIVE_OK)
-			return (ret);
-		if (ret == ARCHIVE_EOF)
-			state->in_stream = 0;
-		else
-			break;
-	}
-
-	if (state->out_block == NULL ||
-	    state->out_block_size < state->uncompressed_size) {
-		void *new_block;
-
-		new_block = realloc(state->out_block, state->uncompressed_size);
-		if (new_block == NULL) {
-			archive_set_error(&self->archive->archive, ENOMEM,
-			    "Can't allocate data for lzop decompression");
-			return (ARCHIVE_FATAL);
-		}
-		state->out_block = new_block;
-		state->out_block_size = state->uncompressed_size;
-	}
-
-	b = __archive_read_filter_ahead(self->upstream,
-		state->compressed_size, NULL);
-	if (b == NULL) {
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
-		return (ARCHIVE_FATAL);
-	}
-	if (state->flags & CRC32_COMPRESSED)
-		cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size);
-	else if (state->flags & ADLER32_COMPRESSED)
-		cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size);
-	else
-		cksum = state->compressed_cksum;
-	if (cksum != state->compressed_cksum) {
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC, "Corrupted data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * If the both uncompressed size and compressed size are the same,
-	 * we do not decompress this block.
-	 */
-	if (state->uncompressed_size == state->compressed_size) {
-		*p = b;
-		state->total_out += state->compressed_size;
-		state->unconsumed_bytes = state->compressed_size;
-		return ((ssize_t)state->uncompressed_size);
-	}
-
-	/*
-	 * Drive lzo uncompression.
-	 */
-	out_size = (lzo_uint)state->uncompressed_size;
-	r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
-		state->out_block, &out_size, NULL);
-	switch (r) {
-	case LZO_E_OK:
-		if (out_size == state->uncompressed_size)
-			break;
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC, "Corrupted data");
-		return (ARCHIVE_FATAL);
-	case LZO_E_OUT_OF_MEMORY:
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "lzop decompression failed: out of memory");
-		return (ARCHIVE_FATAL);
-	default:
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "lzop decompression failed: %d", r);
-		return (ARCHIVE_FATAL);
-	}
-
-	if (state->flags & CRC32_UNCOMPRESSED)
-		cksum = crc32(crc32(0, NULL, 0), state->out_block,
-		    state->uncompressed_size);
-	else if (state->flags & ADLER32_UNCOMPRESSED)
-		cksum = adler32(adler32(0, NULL, 0), state->out_block,
-		    state->uncompressed_size);
-	else
-		cksum = state->uncompressed_cksum;
-	if (cksum != state->uncompressed_cksum) {
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC, "Corrupted data");
-		return (ARCHIVE_FATAL);
-	}
-
-	__archive_read_filter_consume(self->upstream, state->compressed_size);
-	*p = state->out_block;
-	state->total_out += out_size;
-	return ((ssize_t)out_size);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lzop_filter_close(struct archive_read_filter *self)
-{
-	struct read_lzop *state = (struct read_lzop *)self->data;
-
-	free(state->out_block);
-	free(state);
-	return (ARCHIVE_OK);
-}
-
-#endif
diff --git a/c/archive_read_support_filter_none.c b/c/archive_read_support_filter_none.c
deleted file mode 100644
--- a/c/archive_read_support_filter_none.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive.h"
-#include "archive_private.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_none(struct archive *a)
-{
-	return archive_read_support_filter_none(a);
-}
-#endif
-
-/*
- * Uncompressed streams are handled implicitly by the read core,
- * so this is now a no-op.
- */
-int
-archive_read_support_filter_none(struct archive *a)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_filter_none");
-
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_support_filter_program.c b/c/archive_read_support_filter_program.c
deleted file mode 100644
--- a/c/archive_read_support_filter_program.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*-
- * Copyright (c) 2007 Joerg Sonnenberger
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_SYS_WAIT_H
-#  include <sys/wait.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#  include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#  include <fcntl.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#  include <signal.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#  include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_read_private.h"
-#include "filter_fork.h"
-
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_program(struct archive *a, const char *cmd)
-{
-	return archive_read_support_filter_program(a, cmd);
-}
-
-int
-archive_read_support_compression_program_signature(struct archive *a,
-    const char *cmd, const void *signature, size_t signature_len)
-{
-	return archive_read_support_filter_program_signature(a,
-	    cmd, signature, signature_len);
-}
-#endif
-
-int
-archive_read_support_filter_program(struct archive *a, const char *cmd)
-{
-	return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
-}
-
-/*
- * The bidder object stores the command and the signature to watch for.
- * The 'inhibit' entry here is used to ensure that unchecked filters never
- * bid twice in the same pipeline.
- */
-struct program_bidder {
-	char *description;
-	char *cmd;
-	void *signature;
-	size_t signature_len;
-	int inhibit;
-};
-
-static int	program_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *upstream);
-static int	program_bidder_init(struct archive_read_filter *);
-static void	program_bidder_free(struct archive_read_filter_bidder *);
-
-/*
- * The actual filter needs to track input and output data.
- */
-struct program_filter {
-	struct archive_string description;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	HANDLE		 child;
-#else
-	pid_t		 child;
-#endif
-	int		 exit_status;
-	int		 waitpid_return;
-	int		 child_stdin, child_stdout;
-
-	char		*out_buf;
-	size_t		 out_buf_len;
-};
-
-static ssize_t	program_filter_read(struct archive_read_filter *,
-		    const void **);
-static int	program_filter_close(struct archive_read_filter *);
-static void	free_state(struct program_bidder *);
-
-static const struct archive_read_filter_bidder_vtable
-program_bidder_vtable = {
-	.bid = program_bidder_bid,
-	.init = program_bidder_init,
-	.free = program_bidder_free,
-};
-
-int
-archive_read_support_filter_program_signature(struct archive *_a,
-    const char *cmd, const void *signature, size_t signature_len)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct program_bidder *state;
-
-	/*
-	 * Allocate our private state.
-	 */
-	state = (struct program_bidder *)calloc(1, sizeof (*state));
-	if (state == NULL)
-		goto memerr;
-	state->cmd = strdup(cmd);
-	if (state->cmd == NULL)
-		goto memerr;
-
-	if (signature != NULL && signature_len > 0) {
-		state->signature_len = signature_len;
-		state->signature = malloc(signature_len);
-		memcpy(state->signature, signature, signature_len);
-	}
-
-	if (__archive_read_register_bidder(a, state, NULL,
-				&program_bidder_vtable) != ARCHIVE_OK) {
-		free_state(state);
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-
-memerr:
-	free_state(state);
-	archive_set_error(_a, ENOMEM, "Can't allocate memory");
-	return (ARCHIVE_FATAL);
-}
-
-static void
-program_bidder_free(struct archive_read_filter_bidder *self)
-{
-	struct program_bidder *state = (struct program_bidder *)self->data;
-
-	free_state(state);
-}
-
-static void
-free_state(struct program_bidder *state)
-{
-
-	if (state) {
-		free(state->cmd);
-		free(state->signature);
-		free(state);
-	}
-}
-
-/*
- * If we do have a signature, bid only if that matches.
- *
- * If there's no signature, we bid INT_MAX the first time
- * we're called, then never bid again.
- */
-static int
-program_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *upstream)
-{
-	struct program_bidder *state = self->data;
-	const char *p;
-
-	/* If we have a signature, use that to match. */
-	if (state->signature_len > 0) {
-		p = __archive_read_filter_ahead(upstream,
-		    state->signature_len, NULL);
-		if (p == NULL)
-			return (0);
-		/* No match, so don't bid. */
-		if (memcmp(p, state->signature, state->signature_len) != 0)
-			return (0);
-		return ((int)state->signature_len * 8);
-	}
-
-	/* Otherwise, bid once and then never bid again. */
-	if (state->inhibit)
-		return (0);
-	state->inhibit = 1;
-	return (INT_MAX);
-}
-
-/*
- * Shut down the child, return ARCHIVE_OK if it exited normally.
- *
- * Note that the return value is sticky; if we're called again,
- * we won't reap the child again, but we will return the same status
- * (including error message if the child came to a bad end).
- */
-static int
-child_stop(struct archive_read_filter *self, struct program_filter *state)
-{
-	/* Close our side of the I/O with the child. */
-	if (state->child_stdin != -1) {
-		close(state->child_stdin);
-		state->child_stdin = -1;
-	}
-	if (state->child_stdout != -1) {
-		close(state->child_stdout);
-		state->child_stdout = -1;
-	}
-
-	if (state->child != 0) {
-		/* Reap the child. */
-		do {
-			state->waitpid_return
-			    = waitpid(state->child, &state->exit_status, 0);
-		} while (state->waitpid_return == -1 && errno == EINTR);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		CloseHandle(state->child);
-#endif
-		state->child = 0;
-	}
-
-	if (state->waitpid_return < 0) {
-		/* waitpid() failed?  This is ugly. */
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Child process exited badly");
-		return (ARCHIVE_WARN);
-	}
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-	if (WIFSIGNALED(state->exit_status)) {
-#ifdef SIGPIPE
-		/* If the child died because we stopped reading before
-		 * it was done, that's okay.  Some archive formats
-		 * have padding at the end that we routinely ignore. */
-		/* The alternative to this would be to add a step
-		 * before close(child_stdout) above to read from the
-		 * child until the child has no more to write. */
-		if (WTERMSIG(state->exit_status) == SIGPIPE)
-			return (ARCHIVE_OK);
-#endif
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Child process exited with signal %d",
-		    WTERMSIG(state->exit_status));
-		return (ARCHIVE_WARN);
-	}
-#endif /* !_WIN32 || __CYGWIN__ */
-
-	if (WIFEXITED(state->exit_status)) {
-		if (WEXITSTATUS(state->exit_status) == 0)
-			return (ARCHIVE_OK);
-
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Child process exited with status %d",
-		    WEXITSTATUS(state->exit_status));
-		return (ARCHIVE_WARN);
-	}
-
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Use select() to decide whether the child is ready for read or write.
- */
-static ssize_t
-child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
-{
-	struct program_filter *state = self->data;
-	ssize_t ret, requested, avail;
-	const char *p;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout);
-#endif
-
-	requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
-
-	for (;;) {
-		do {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-			/* Avoid infinity wait.
-			 * Note: If there is no data in the pipe, ReadFile()
-			 * called in read() never returns and so we won't
-			 * write remaining encoded data to the pipe.
-			 * Note: This way may cause performance problem.
-			 * we are looking forward to great code to resolve
-			 * this.  */
-			DWORD pipe_avail = -1;
-			int cnt = 2;
-
-			while (PeekNamedPipe(handle, NULL, 0, NULL,
-			    &pipe_avail, NULL) != 0 && pipe_avail == 0 &&
-			    cnt--)
-				Sleep(5);
-			if (pipe_avail == 0) {
-				ret = -1;
-				errno = EAGAIN;
-				break;
-			}
-#endif
-			ret = read(state->child_stdout, buf, requested);
-		} while (ret == -1 && errno == EINTR);
-
-		if (ret > 0)
-			return (ret);
-		if (ret == 0 || (ret == -1 && errno == EPIPE))
-			/* Child has closed its output; reap the child
-			 * and return the status. */
-			return (child_stop(self, state));
-		if (ret == -1 && errno != EAGAIN)
-			return (-1);
-
-		if (state->child_stdin == -1) {
-			/* Block until child has some I/O ready. */
-			__archive_check_child(state->child_stdin,
-			    state->child_stdout);
-			continue;
-		}
-
-		/* Get some more data from upstream. */
-		p = __archive_read_filter_ahead(self->upstream, 1, &avail);
-		if (p == NULL) {
-			close(state->child_stdin);
-			state->child_stdin = -1;
-			fcntl(state->child_stdout, F_SETFL, 0);
-			if (avail < 0)
-				return (avail);
-			continue;
-		}
-
-		do {
-			ret = write(state->child_stdin, p, avail);
-		} while (ret == -1 && errno == EINTR);
-
-		if (ret > 0) {
-			/* Consume whatever we managed to write. */
-			__archive_read_filter_consume(self->upstream, ret);
-		} else if (ret == -1 && errno == EAGAIN) {
-			/* Block until child has some I/O ready. */
-			__archive_check_child(state->child_stdin,
-			    state->child_stdout);
-		} else {
-			/* Write failed. */
-			close(state->child_stdin);
-			state->child_stdin = -1;
-			fcntl(state->child_stdout, F_SETFL, 0);
-			/* If it was a bad error, we're done; otherwise
-			 * it was EPIPE or EOF, and we can still read
-			 * from the child. */
-			if (ret == -1 && errno != EPIPE)
-				return (-1);
-		}
-	}
-}
-
-static const struct archive_read_filter_vtable
-program_reader_vtable = {
-	.read = program_filter_read,
-	.close = program_filter_close,
-};
-
-int
-__archive_read_program(struct archive_read_filter *self, const char *cmd)
-{
-	struct program_filter	*state;
-	static const size_t out_buf_len = 65536;
-	char *out_buf;
-	const char *prefix = "Program: ";
-	int ret;
-	size_t l;
-
-	l = strlen(prefix) + strlen(cmd) + 1;
-	state = (struct program_filter *)calloc(1, sizeof(*state));
-	out_buf = (char *)malloc(out_buf_len);
-	if (state == NULL || out_buf == NULL ||
-	    archive_string_ensure(&state->description, l) == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate input data");
-		if (state != NULL) {
-			archive_string_free(&state->description);
-			free(state);
-		}
-		free(out_buf);
-		return (ARCHIVE_FATAL);
-	}
-	archive_strcpy(&state->description, prefix);
-	archive_strcat(&state->description, cmd);
-
-	self->code = ARCHIVE_FILTER_PROGRAM;
-	self->name = state->description.s;
-
-	state->out_buf = out_buf;
-	state->out_buf_len = out_buf_len;
-
-	ret = __archive_create_child(cmd, &state->child_stdin,
-	    &state->child_stdout, &state->child);
-	if (ret != ARCHIVE_OK) {
-		free(state->out_buf);
-		archive_string_free(&state->description);
-		free(state);
-		archive_set_error(&self->archive->archive, EINVAL,
-		    "Can't initialize filter; unable to run program \"%s\"",
-		    cmd);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	self->vtable = &program_reader_vtable;
-
-	/* XXX Check that we can read at least one byte? */
-	return (ARCHIVE_OK);
-}
-
-static int
-program_bidder_init(struct archive_read_filter *self)
-{
-	struct program_bidder   *bidder_state;
-
-	bidder_state = (struct program_bidder *)self->bidder->data;
-	return (__archive_read_program(self, bidder_state->cmd));
-}
-
-static ssize_t
-program_filter_read(struct archive_read_filter *self, const void **buff)
-{
-	struct program_filter *state;
-	ssize_t bytes;
-	size_t total;
-	char *p;
-
-	state = (struct program_filter *)self->data;
-
-	total = 0;
-	p = state->out_buf;
-	while (state->child_stdout != -1 && total < state->out_buf_len) {
-		bytes = child_read(self, p, state->out_buf_len - total);
-		if (bytes < 0)
-			/* No recovery is possible if we can no longer
-			 * read from the child. */
-			return (ARCHIVE_FATAL);
-		if (bytes == 0)
-			/* We got EOF from the child. */
-			break;
-		total += bytes;
-		p += bytes;
-	}
-
-	*buff = state->out_buf;
-	return (total);
-}
-
-static int
-program_filter_close(struct archive_read_filter *self)
-{
-	struct program_filter	*state;
-	int e;
-
-	state = (struct program_filter *)self->data;
-	e = child_stop(self, state);
-
-	/* Release our private data. */
-	free(state->out_buf);
-	archive_string_free(&state->description);
-	free(state);
-
-	return (e);
-}
diff --git a/c/archive_read_support_filter_rpm.c b/c/archive_read_support_filter_rpm.c
deleted file mode 100644
--- a/c/archive_read_support_filter_rpm.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*-
- * Copyright (c) 2009 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-struct rpm {
-	int64_t		 total_in;
-	size_t		 hpos;
-	size_t		 hlen;
-	unsigned char	 header[16];
-	enum {
-		ST_LEAD,	/* Skipping 'Lead' section. */
-		ST_HEADER,	/* Reading 'Header' section;
-				 * first 16 bytes. */
-		ST_HEADER_DATA,	/* Skipping 'Header' section. */
-		ST_PADDING,	/* Skipping padding data after the
-				 * 'Header' section. */
-		ST_ARCHIVE	/* Reading 'Archive' section. */
-	}		 state;
-	int		 first_header;
-};
-#define RPM_LEAD_SIZE	96	/* Size of 'Lead' section. */
-
-static int	rpm_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	rpm_bidder_init(struct archive_read_filter *);
-
-static ssize_t	rpm_filter_read(struct archive_read_filter *,
-		    const void **);
-static int	rpm_filter_close(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_rpm(struct archive *a)
-{
-	return archive_read_support_filter_rpm(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-rpm_bidder_vtable = {
-	.bid = rpm_bidder_bid,
-	.init = rpm_bidder_init,
-};
-
-int
-archive_read_support_filter_rpm(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	return __archive_read_register_bidder(a, NULL, "rpm",
-			&rpm_bidder_vtable);
-}
-
-static int
-rpm_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *b;
-	ssize_t avail;
-	int bits_checked;
-
-	(void)self; /* UNUSED */
-
-	b = __archive_read_filter_ahead(filter, 8, &avail);
-	if (b == NULL)
-		return (0);
-
-	bits_checked = 0;
-	/*
-	 * Verify Header Magic Bytes : 0XED 0XAB 0XEE 0XDB
-	 */
-	if (memcmp(b, "\xED\xAB\xEE\xDB", 4) != 0)
-		return (0);
-	bits_checked += 32;
-	/*
-	 * Check major version.
-	 */
-	if (b[4] != 3 && b[4] != 4)
-		return (0);
-	bits_checked += 8;
-	/*
-	 * Check package type; binary or source.
-	 */
-	if (b[6] != 0)
-		return (0);
-	bits_checked += 8;
-	if (b[7] != 0 && b[7] != 1)
-		return (0);
-	bits_checked += 8;
-
-	return (bits_checked);
-}
-
-static const struct archive_read_filter_vtable
-rpm_reader_vtable = {
-	.read = rpm_filter_read,
-	.close = rpm_filter_close,
-};
-
-static int
-rpm_bidder_init(struct archive_read_filter *self)
-{
-	struct rpm   *rpm;
-
-	self->code = ARCHIVE_FILTER_RPM;
-	self->name = "rpm";
-
-	rpm = (struct rpm *)calloc(sizeof(*rpm), 1);
-	if (rpm == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for rpm");
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = rpm;
-	rpm->state = ST_LEAD;
-	self->vtable = &rpm_reader_vtable;
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-rpm_filter_read(struct archive_read_filter *self, const void **buff)
-{
-	struct rpm *rpm;
-	const unsigned char *b;
-	ssize_t avail_in, total;
-	size_t used, n;
-	uint32_t section;
-	uint32_t bytes;
-
-	rpm = (struct rpm *)self->data;
-	*buff = NULL;
-	total = avail_in = 0;
-	b = NULL;
-	used = 0;
-	do {
-		if (b == NULL) {
-			b = __archive_read_filter_ahead(self->upstream, 1,
-			    &avail_in);
-			if (b == NULL) {
-				if (avail_in < 0)
-					return (ARCHIVE_FATAL);
-				else
-					break;
-			}
-		}
-
-		switch (rpm->state) {
-		case ST_LEAD:
-			if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
-				used += avail_in;
-			else {
-				n = (size_t)(RPM_LEAD_SIZE - rpm->total_in);
-				used += n;
-				b += n;
-				rpm->state = ST_HEADER;
-				rpm->hpos = 0;
-				rpm->hlen = 0;
-				rpm->first_header = 1;
-			}
-			break;
-		case ST_HEADER:
-			n = 16 - rpm->hpos;
-			if (n > avail_in - used)
-				n = avail_in - used;
-			memcpy(rpm->header+rpm->hpos, b, n);
-			b += n;
-			used += n;
-			rpm->hpos += n;
-
-			if (rpm->hpos == 16) {
-				if (rpm->header[0] != 0x8e ||
-				    rpm->header[1] != 0xad ||
-				    rpm->header[2] != 0xe8 ||
-				    rpm->header[3] != 0x01) {
-					if (rpm->first_header) {
-						archive_set_error(
-						    &self->archive->archive,
-						    ARCHIVE_ERRNO_FILE_FORMAT,
-						    "Unrecognized rpm header");
-						return (ARCHIVE_FATAL);
-					}
-					rpm->state = ST_ARCHIVE;
-					*buff = rpm->header;
-					total = rpm->hpos;
-					break;
-				}
-				/* Calculate 'Header' length. */
-				section = archive_be32dec(rpm->header+8);
-				bytes = archive_be32dec(rpm->header+12);
-				rpm->hlen = 16 + section * 16 + bytes;
-				rpm->state = ST_HEADER_DATA;
-				rpm->first_header = 0;
-			}
-			break;
-		case ST_HEADER_DATA:
-			n = rpm->hlen - rpm->hpos;
-			if (n > avail_in - used)
-				n = avail_in - used;
-			b += n;
-			used += n;
-			rpm->hpos += n;
-			if (rpm->hpos == rpm->hlen)
-				rpm->state = ST_PADDING;
-			break;
-		case ST_PADDING:
-			while (used < (size_t)avail_in) {
-				if (*b != 0) {
-					/* Read next header. */
-					rpm->state = ST_HEADER;
-					rpm->hpos = 0;
-					rpm->hlen = 0;
-					break;
-				}
-				b++;
-				used++;
-			}
-			break;
-		case ST_ARCHIVE:
-			*buff = b;
-			total = avail_in;
-			used = avail_in;
-			break;
-		}
-		if (used == (size_t)avail_in) {
-			rpm->total_in += used;
-			__archive_read_filter_consume(self->upstream, used);
-			b = NULL;
-			used = 0;
-		}
-	} while (total == 0 && avail_in > 0);
-
-	if (used > 0 && b != NULL) {
-		rpm->total_in += used;
-		__archive_read_filter_consume(self->upstream, used);
-	}
-	return (total);
-}
-
-static int
-rpm_filter_close(struct archive_read_filter *self)
-{
-	struct rpm *rpm;
-
-	rpm = (struct rpm *)self->data;
-	free(rpm);
-
-	return (ARCHIVE_OK);
-}
-
diff --git a/c/archive_read_support_filter_uu.c b/c/archive_read_support_filter_uu.c
deleted file mode 100644
--- a/c/archive_read_support_filter_uu.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*-
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-/* Maximum lookahead during bid phase */
-#define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */
-
-struct uudecode {
-	int64_t		 total;
-	unsigned char	*in_buff;
-#define IN_BUFF_SIZE	(1024)
-	int		 in_cnt;
-	size_t		 in_allocated;
-	unsigned char	*out_buff;
-#define OUT_BUFF_SIZE	(64 * 1024)
-	int		 state;
-#define ST_FIND_HEAD	0
-#define ST_READ_UU	1
-#define ST_UUEND	2
-#define ST_READ_BASE64	3
-#define ST_IGNORE	4
-};
-
-static int	uudecode_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *filter);
-static int	uudecode_bidder_init(struct archive_read_filter *);
-
-static ssize_t	uudecode_filter_read(struct archive_read_filter *,
-		    const void **);
-static int	uudecode_filter_close(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_uu(struct archive *a)
-{
-	return archive_read_support_filter_uu(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-uudecode_bidder_vtable = {
-	.bid = uudecode_bidder_bid,
-	.init = uudecode_bidder_init,
-};
-
-int
-archive_read_support_filter_uu(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	return __archive_read_register_bidder(a, NULL, "uu",
-			&uudecode_bidder_vtable);
-}
-
-static const unsigned char ascii[256] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, '\r', 0, 0, /* 00 - 0F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-};
-
-static const unsigned char uuchar[256] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
-	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-};
-
-static const unsigned char base64[256] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, /* 20 - 2F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 30 - 3F */
-	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 50 - 5F */
-	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 - 7F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-};
-
-static const int base64num[128] = {
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0, /* 00 - 0F */
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0, /* 10 - 1F */
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0, 62,  0,  0,  0, 63, /* 20 - 2F */
-	52, 53, 54, 55, 56, 57, 58, 59,
-	60, 61,  0,  0,  0,  0,  0,  0, /* 30 - 3F */
-	 0,  0,  1,  2,  3,  4,  5,  6,
-	 7,  8,  9, 10, 11, 12, 13, 14, /* 40 - 4F */
-	15, 16, 17, 18, 19, 20, 21, 22,
-	23, 24, 25,  0,  0,  0,  0,  0, /* 50 - 5F */
-	 0, 26, 27, 28, 29, 30, 31, 32,
-	33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */
-	41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51,  0,  0,  0,  0,  0, /* 70 - 7F */
-};
-
-static ssize_t
-get_line(const unsigned char *b, ssize_t avail, ssize_t *nlsize)
-{
-	ssize_t len;
-
-	len = 0;
-	while (len < avail) {
-		switch (ascii[*b]) {
-		case 0:	/* Non-ascii character or control character. */
-			if (nlsize != NULL)
-				*nlsize = 0;
-			return (-1);
-		case '\r':
-			if (avail-len > 1 && b[1] == '\n') {
-				if (nlsize != NULL)
-					*nlsize = 2;
-				return (len+2);
-			}
-			/* FALL THROUGH */
-		case '\n':
-			if (nlsize != NULL)
-				*nlsize = 1;
-			return (len+1);
-		case 1:
-			b++;
-			len++;
-			break;
-		}
-	}
-	if (nlsize != NULL)
-		*nlsize = 0;
-	return (avail);
-}
-
-static ssize_t
-bid_get_line(struct archive_read_filter *filter,
-    const unsigned char **b, ssize_t *avail, ssize_t *ravail,
-    ssize_t *nl, size_t* nbytes_read)
-{
-	ssize_t len;
-	int quit;
-	
-	quit = 0;
-	if (*avail == 0) {
-		*nl = 0;
-		len = 0;
-	} else
-		len = get_line(*b, *avail, nl);
-
-	/*
-	 * Read bytes more while it does not reach the end of line.
-	 */
-	while (*nl == 0 && len == *avail && !quit &&
-	    *nbytes_read < UUENCODE_BID_MAX_READ) {
-		ssize_t diff = *ravail - *avail;
-		size_t nbytes_req = (*ravail+1023) & ~1023U;
-		ssize_t tested;
-
-		/* Increase reading bytes if it is not enough to at least
-		 * new two lines. */
-		if (nbytes_req < (size_t)*ravail + 160)
-			nbytes_req <<= 1;
-
-		*b = __archive_read_filter_ahead(filter, nbytes_req, avail);
-		if (*b == NULL) {
-			if (*ravail >= *avail)
-				return (0);
-			/* Reading bytes reaches the end of a stream. */
-			*b = __archive_read_filter_ahead(filter, *avail, avail);
-			quit = 1;
-		}
-		*nbytes_read = *avail;
-		*ravail = *avail;
-		*b += diff;
-		*avail -= diff;
-		tested = len;/* Skip some bytes we already determined. */
-		len = get_line(*b + tested, *avail - tested, nl);
-		if (len >= 0)
-			len += tested;
-	}
-	return (len);
-}
-
-#define UUDECODE(c) (((c) - 0x20) & 0x3f)
-
-static int
-uudecode_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *b;
-	ssize_t avail, ravail;
-	ssize_t len, nl;
-	int l;
-	int firstline;
-	size_t nbytes_read;
-
-	(void)self; /* UNUSED */
-
-	b = __archive_read_filter_ahead(filter, 1, &avail);
-	if (b == NULL)
-		return (0);
-
-	firstline = 20;
-	ravail = avail;
-	nbytes_read = avail;
-	for (;;) {
-		len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read);
-		if (len < 0 || nl == 0)
-			return (0); /* No match found. */
-		if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
-			l = 6;
-		else if (len -nl >= 18 && memcmp(b, "begin-base64 ", 13) == 0)
-			l = 13;
-		else
-			l = 0;
-
-		if (l > 0 && (b[l] < '0' || b[l] > '7' ||
-		    b[l+1] < '0' || b[l+1] > '7' ||
-		    b[l+2] < '0' || b[l+2] > '7' || b[l+3] != ' '))
-			l = 0;
-
-		b += len;
-		avail -= len;
-		if (l)
-			break;
-		firstline = 0;
-
-		/* Do not read more than UUENCODE_BID_MAX_READ bytes */
-		if (nbytes_read >= UUENCODE_BID_MAX_READ)
-			return (0);
-	}
-	if (!avail)
-		return (0);
-	len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read);
-	if (len < 0 || nl == 0)
-		return (0);/* There are non-ascii characters. */
-	avail -= len;
-
-	if (l == 6) {
-		/* "begin " */
-		if (!uuchar[*b])
-			return (0);
-		/* Get a length of decoded bytes. */
-		l = UUDECODE(*b++); len--;
-		if (l > 45)
-			/* Normally, maximum length is 45(character 'M'). */
-			return (0);
-		if (l > len - nl)
-			return (0); /* Line too short. */
-		while (l) {
-			if (!uuchar[*b++])
-				return (0);
-			--len;
-			--l;
-		}
-		if (len-nl == 1 &&
-		    (uuchar[*b] ||		 /* Check sum. */
-		     (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
-			++b;
-			--len;
-		}
-		b += nl;
-		if (avail && uuchar[*b])
-			return (firstline+30);
-	} else if (l == 13) {
-		/* "begin-base64 " */
-		while (len-nl > 0) {
-			if (!base64[*b++])
-				return (0);
-			--len;
-		}
-		b += nl;
-
-		if (avail >= 5 && memcmp(b, "====\n", 5) == 0)
-			return (firstline+40);
-		if (avail >= 6 && memcmp(b, "====\r\n", 6) == 0)
-			return (firstline+40);
-		if (avail > 0 && base64[*b])
-			return (firstline+30);
-	}
-
-	return (0);
-}
-
-static const struct archive_read_filter_vtable
-uudecode_reader_vtable = {
-	.read = uudecode_filter_read,
-	.close = uudecode_filter_close,
-};
-
-static int
-uudecode_bidder_init(struct archive_read_filter *self)
-{
-	struct uudecode   *uudecode;
-	void *out_buff;
-	void *in_buff;
-
-	self->code = ARCHIVE_FILTER_UU;
-	self->name = "uu";
-
-	uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1);
-	out_buff = malloc(OUT_BUFF_SIZE);
-	in_buff = malloc(IN_BUFF_SIZE);
-	if (uudecode == NULL || out_buff == NULL || in_buff == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for uudecode");
-		free(uudecode);
-		free(out_buff);
-		free(in_buff);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = uudecode;
-	uudecode->in_buff = in_buff;
-	uudecode->in_cnt = 0;
-	uudecode->in_allocated = IN_BUFF_SIZE;
-	uudecode->out_buff = out_buff;
-	uudecode->state = ST_FIND_HEAD;
-	self->vtable = &uudecode_reader_vtable;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-ensure_in_buff_size(struct archive_read_filter *self,
-    struct uudecode *uudecode, size_t size)
-{
-
-	if (size > uudecode->in_allocated) {
-		unsigned char *ptr;
-		size_t newsize;
-
-		/*
-		 * Calculate a new buffer size for in_buff.
-		 * Increase its value until it has enough size we need.
-		 */
-		newsize = uudecode->in_allocated;
-		do {
-			if (newsize < IN_BUFF_SIZE*32)
-				newsize <<= 1;
-			else
-				newsize += IN_BUFF_SIZE;
-		} while (size > newsize);
-		/* Allocate the new buffer. */
-		ptr = malloc(newsize);
-		if (ptr == NULL) {
-			free(ptr);
-			archive_set_error(&self->archive->archive,
-			    ENOMEM,
-    			    "Can't allocate data for uudecode");
-			return (ARCHIVE_FATAL);
-		}
-		/* Move the remaining data in in_buff into the new buffer. */
-		if (uudecode->in_cnt)
-			memmove(ptr, uudecode->in_buff, uudecode->in_cnt);
-		/* Replace in_buff with the new buffer. */
-		free(uudecode->in_buff);
-		uudecode->in_buff = ptr;
-		uudecode->in_allocated = newsize;
-	}
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-uudecode_filter_read(struct archive_read_filter *self, const void **buff)
-{
-	struct uudecode *uudecode;
-	const unsigned char *b, *d;
-	unsigned char *out;
-	ssize_t avail_in, ravail;
-	ssize_t used;
-	ssize_t total;
-	ssize_t len, llen, nl;
-
-	uudecode = (struct uudecode *)self->data;
-
-read_more:
-	d = __archive_read_filter_ahead(self->upstream, 1, &avail_in);
-	if (d == NULL && avail_in < 0)
-		return (ARCHIVE_FATAL);
-	/* Quiet a code analyzer; make sure avail_in must be zero
-	 * when d is NULL. */
-	if (d == NULL)
-		avail_in = 0;
-	used = 0;
-	total = 0;
-	out = uudecode->out_buff;
-	ravail = avail_in;
-	if (uudecode->state == ST_IGNORE) {
-		used = avail_in;
-		goto finish;
-	}
-	if (uudecode->in_cnt) {
-		/*
-		 * If there is remaining data which is saved by
-		 * previous calling, use it first.
-		 */
-		if (ensure_in_buff_size(self, uudecode,
-		    avail_in + uudecode->in_cnt) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		memcpy(uudecode->in_buff + uudecode->in_cnt,
-		    d, avail_in);
-		d = uudecode->in_buff;
-		avail_in += uudecode->in_cnt;
-		uudecode->in_cnt = 0;
-	}
-	for (;used < avail_in; d += llen, used += llen) {
-		int64_t l, body;
-
-		b = d;
-		len = get_line(b, avail_in - used, &nl);
-		if (len < 0) {
-			/* Non-ascii character is found. */
-			if (uudecode->state == ST_FIND_HEAD &&
-			    (uudecode->total > 0 || total > 0)) {
-				uudecode->state = ST_IGNORE;
-				used = avail_in;
-				goto finish;
-			}
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Insufficient compressed data");
-			return (ARCHIVE_FATAL);
-		}
-		llen = len;
-		if ((nl == 0) && (uudecode->state != ST_UUEND)) {
-			if (total == 0 && ravail <= 0) {
-				/* There is nothing more to read, fail */
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Missing format data");
-				return (ARCHIVE_FATAL);
-			}
-			/*
-			 * Save remaining data which does not contain
-			 * NL('\n','\r').
-			 */
-			if (ensure_in_buff_size(self, uudecode, len)
-			    != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			if (uudecode->in_buff != b)
-				memmove(uudecode->in_buff, b, len);
-			uudecode->in_cnt = (int)len;
-			if (total == 0) {
-				/* Do not return 0; it means end-of-file.
-				 * We should try to read bytes more. */
-				__archive_read_filter_consume(
-				    self->upstream, ravail);
-				goto read_more;
-			}
-			used += len;
-			break;
-		}
-		switch (uudecode->state) {
-		default:
-		case ST_FIND_HEAD:
-			/* Do not read more than UUENCODE_BID_MAX_READ bytes */
-			if (total + len >= UUENCODE_BID_MAX_READ) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Invalid format data");
-				return (ARCHIVE_FATAL);
-			}
-			if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
-				l = 6;
-			else if (len - nl >= 18 &&
-			    memcmp(b, "begin-base64 ", 13) == 0)
-				l = 13;
-			else
-				l = 0;
-			if (l != 0 && b[l] >= '0' && b[l] <= '7' &&
-			    b[l+1] >= '0' && b[l+1] <= '7' &&
-			    b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') {
-				if (l == 6)
-					uudecode->state = ST_READ_UU;
-				else
-					uudecode->state = ST_READ_BASE64;
-			}
-			break;
-		case ST_READ_UU:
-			if (total + len * 2 > OUT_BUFF_SIZE)
-				goto finish;
-			body = len - nl;
-			if (!uuchar[*b] || body <= 0) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Insufficient compressed data");
-				return (ARCHIVE_FATAL);
-			}
-			/* Get length of undecoded bytes of current line. */
-			l = UUDECODE(*b++);
-			body--;
-			if (l > body) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Insufficient compressed data");
-				return (ARCHIVE_FATAL);
-			}
-			if (l == 0) {
-				uudecode->state = ST_UUEND;
-				break;
-			}
-			while (l > 0) {
-				int n = 0;
-
-				if (!uuchar[b[0]] || !uuchar[b[1]])
-					break;
-				n = UUDECODE(*b++) << 18;
-				n |= UUDECODE(*b++) << 12;
-				*out++ = n >> 16; total++;
-				--l;
-
-				if (l > 0) {
-					if (!uuchar[b[0]])
-						break;
-					n |= UUDECODE(*b++) << 6;
-					*out++ = (n >> 8) & 0xFF; total++;
-					--l;
-				}
-				if (l > 0) {
-					if (!uuchar[b[0]])
-						break;
-					n |= UUDECODE(*b++);
-					*out++ = n & 0xFF; total++;
-					--l;
-				}
-			}
-			if (l) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Insufficient compressed data");
-				return (ARCHIVE_FATAL);
-			}
-			break;
-		case ST_UUEND:
-			if (len - nl == 3 && memcmp(b, "end ", 3) == 0)
-				uudecode->state = ST_FIND_HEAD;
-			else {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Insufficient compressed data");
-				return (ARCHIVE_FATAL);
-			}
-			break;
-		case ST_READ_BASE64:
-			if (total + len * 2 > OUT_BUFF_SIZE)
-				goto finish;
-			l = len - nl;
-			if (l >= 3 && b[0] == '=' && b[1] == '=' &&
-			    b[2] == '=') {
-				uudecode->state = ST_FIND_HEAD;
-				break;
-			}
-			while (l > 0) {
-				int n = 0;
-
-				if (!base64[b[0]] || !base64[b[1]])
-					break;
-				n = base64num[*b++] << 18;
-				n |= base64num[*b++] << 12;
-				*out++ = n >> 16; total++;
-				l -= 2;
-
-				if (l > 0) {
-					if (*b == '=')
-						break;
-					if (!base64[*b])
-						break;
-					n |= base64num[*b++] << 6;
-					*out++ = (n >> 8) & 0xFF; total++;
-					--l;
-				}
-				if (l > 0) {
-					if (*b == '=')
-						break;
-					if (!base64[*b])
-						break;
-					n |= base64num[*b++];
-					*out++ = n & 0xFF; total++;
-					--l;
-				}
-			}
-			if (l && *b != '=') {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Insufficient compressed data");
-				return (ARCHIVE_FATAL);
-			}
-			break;
-		}
-	}
-finish:
-	if (ravail < avail_in)
-		used -= avail_in - ravail;
-	__archive_read_filter_consume(self->upstream, used);
-
-	*buff = uudecode->out_buff;
-	uudecode->total += total;
-	return (total);
-}
-
-static int
-uudecode_filter_close(struct archive_read_filter *self)
-{
-	struct uudecode *uudecode;
-
-	uudecode = (struct uudecode *)self->data;
-	free(uudecode->in_buff);
-	free(uudecode->out_buff);
-	free(uudecode);
-
-	return (ARCHIVE_OK);
-}
-
diff --git a/c/archive_read_support_filter_xz.c b/c/archive_read_support_filter_xz.c
deleted file mode 100644
--- a/c/archive_read_support_filter_xz.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*-
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
- * Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_LZMA_H
-#include <lzma.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-
-struct private_data {
-	lzma_stream	 stream;
-	unsigned char	*out_block;
-	size_t		 out_block_size;
-	int64_t		 total_out;
-	char		 eof; /* True = found end of compressed data. */
-	char		 in_stream;
-
-	/* Following variables are used for lzip only. */
-	char		 lzip_ver;
-	uint32_t	 crc32;
-	int64_t		 member_in;
-	int64_t		 member_out;
-};
-
-#if LZMA_VERSION_MAJOR >= 5
-/* Effectively disable the limiter. */
-#define LZMA_MEMLIMIT	UINT64_MAX
-#else
-/* NOTE: This needs to check memory size which running system has. */
-#define LZMA_MEMLIMIT	(1U << 30)
-#endif
-
-/* Combined lzip/lzma/xz filter */
-static ssize_t	xz_filter_read(struct archive_read_filter *, const void **);
-static int	xz_filter_close(struct archive_read_filter *);
-static int	xz_lzma_bidder_init(struct archive_read_filter *);
-
-#endif
-
-/*
- * Note that we can detect xz and lzma compressed files even if we
- * can't decompress them.  (In fact, we like detecting them because we
- * can give better error messages.)  So the bid framework here gets
- * compiled even if no lzma library is available.
- */
-static int	xz_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	xz_bidder_init(struct archive_read_filter *);
-static int	lzma_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	lzma_bidder_init(struct archive_read_filter *);
-static int	lzip_has_member(struct archive_read_filter *);
-static int	lzip_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	lzip_bidder_init(struct archive_read_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* Deprecated; remove in libarchive 4.0 */
-int
-archive_read_support_compression_xz(struct archive *a)
-{
-	return archive_read_support_filter_xz(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-xz_bidder_vtable = {
-	.bid = xz_bidder_bid,
-	.init = xz_bidder_init,
-};
-
-int
-archive_read_support_filter_xz(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "xz",
-				&xz_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external xz program for xz decompression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_read_support_compression_lzma(struct archive *a)
-{
-	return archive_read_support_filter_lzma(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-lzma_bidder_vtable = {
-	.bid = lzma_bidder_bid,
-	.init = lzma_bidder_init,
-};
-
-int
-archive_read_support_filter_lzma(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "lzma",
-				&lzma_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lzma program for lzma decompression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_read_support_compression_lzip(struct archive *a)
-{
-	return archive_read_support_filter_lzip(a);
-}
-#endif
-
-static const struct archive_read_filter_bidder_vtable
-lzip_bidder_vtable = {
-	.bid = lzip_bidder_bid,
-	.init = lzip_bidder_init,
-};
-
-int
-archive_read_support_filter_lzip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "lzip",
-				&lzip_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lzip program for lzip decompression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Test whether we can handle this data.
- */
-static int
-xz_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-
-	(void)self; /* UNUSED */
-
-	buffer = __archive_read_filter_ahead(filter, 6, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	/*
-	 * Verify Header Magic Bytes : FD 37 7A 58 5A 00
-	 */
-	if (memcmp(buffer, "\xFD\x37\x7A\x58\x5A\x00", 6) != 0)
-		return (0);
-
-	return (48);
-}
-
-/*
- * Test whether we can handle this data.
- *
- * <sigh> LZMA has a rather poor file signature.  Zeros do not
- * make good signature bytes as a rule, and the only non-zero byte
- * here is an ASCII character.  For example, an uncompressed tar
- * archive whose first file is ']' would satisfy this check.  It may
- * be necessary to exclude LZMA from compression_all() because of
- * this.  Clients of libarchive would then have to explicitly enable
- * LZMA checking instead of (or in addition to) compression_all() when
- * they have other evidence (file name, command-line option) to go on.
- */
-static int
-lzma_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	uint32_t dicsize;
-	uint64_t uncompressed_size;
-	int bits_checked;
-
-	(void)self; /* UNUSED */
-
-	buffer = __archive_read_filter_ahead(filter, 14, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	/* First byte of raw LZMA stream is commonly 0x5d.
-	 * The first byte is a special number, which consists of
-	 * three parameters of LZMA compression, a number of literal
-	 * context bits(which is from 0 to 8, default is 3), a number
-	 * of literal pos bits(which is from 0 to 4, default is 0),
-	 * a number of pos bits(which is from 0 to 4, default is 2).
-	 * The first byte is made by
-	 * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit,
-	 * and so the default value in this field is
-	 * (2 * 5 + 0) * 9 + 3 = 0x5d.
-	 * lzma of LZMA SDK has options to change those parameters.
-	 * It means a range of this field is from 0 to 224. And lzma of
-	 * XZ Utils with option -e records 0x5e in this field. */
-	/* NOTE: If this checking of the first byte increases false
-	 * recognition, we should allow only 0x5d and 0x5e for the first
-	 * byte of LZMA stream. */
-	bits_checked = 0;
-	if (buffer[0] > (4 * 5 + 4) * 9 + 8)
-		return (0);
-	/* Most likely value in the first byte of LZMA stream. */
-	if (buffer[0] == 0x5d || buffer[0] == 0x5e)
-		bits_checked += 8;
-
-	/* Sixth through fourteenth bytes are uncompressed size,
-	 * stored in little-endian order. `-1' means uncompressed
-	 * size is unknown and lzma of XZ Utils always records `-1'
-	 * in this field. */
-	uncompressed_size = archive_le64dec(buffer+5);
-	if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1))
-		bits_checked += 64;
-
-	/* Second through fifth bytes are dictionary size, stored in
-	 * little-endian order. The minimum dictionary size is
-	 * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
-	 * -d12 and the maximum dictionary size is 1 << 29(512MiB)
-	 * which the one uses with option -d29.
-	 * NOTE: A comment of LZMA SDK source code says this dictionary
-	 * range is from 1 << 12 to 1 << 30. */
-	dicsize = archive_le32dec(buffer+1);
-	switch (dicsize) {
-	case 0x00001000:/* lzma of LZMA SDK option -d12. */
-	case 0x00002000:/* lzma of LZMA SDK option -d13. */
-	case 0x00004000:/* lzma of LZMA SDK option -d14. */
-	case 0x00008000:/* lzma of LZMA SDK option -d15. */
-	case 0x00010000:/* lzma of XZ Utils option -0 and -1.
-			 * lzma of LZMA SDK option -d16. */
-	case 0x00020000:/* lzma of LZMA SDK option -d17. */
-	case 0x00040000:/* lzma of LZMA SDK option -d18. */
-	case 0x00080000:/* lzma of XZ Utils option -2.
-			 * lzma of LZMA SDK option -d19. */
-	case 0x00100000:/* lzma of XZ Utils option -3.
-			 * lzma of LZMA SDK option -d20. */
-	case 0x00200000:/* lzma of XZ Utils option -4.
-			 * lzma of LZMA SDK option -d21. */
-	case 0x00400000:/* lzma of XZ Utils option -5.
-			 * lzma of LZMA SDK option -d22. */
-	case 0x00800000:/* lzma of XZ Utils option -6.
-			 * lzma of LZMA SDK option -d23. */
-	case 0x01000000:/* lzma of XZ Utils option -7.
-			 * lzma of LZMA SDK option -d24. */
-	case 0x02000000:/* lzma of XZ Utils option -8.
-			 * lzma of LZMA SDK option -d25. */
-	case 0x04000000:/* lzma of XZ Utils option -9.
-			 * lzma of LZMA SDK option -d26. */
-	case 0x08000000:/* lzma of LZMA SDK option -d27. */
-		bits_checked += 32;
-		break;
-	default:
-		/* If a memory usage for encoding was not enough on
-		 * the platform where LZMA stream was made, lzma of
-		 * XZ Utils automatically decreased the dictionary
-		 * size to enough memory for encoding by 1Mi bytes
-		 * (1 << 20).*/
-		if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 &&
-		    (dicsize & ((1 << 20)-1)) == 0 &&
-		    bits_checked == 8 + 64) {
-			bits_checked += 32;
-			break;
-		}
-		/* Otherwise dictionary size is unlikely. But it is
-		 * possible that someone makes lzma stream with
-		 * liblzma/LZMA SDK in one's dictionary size. */
-		return (0);
-	}
-
-	/* TODO: The above test is still very weak.  It would be
-	 * good to do better. */
-
-	return (bits_checked);
-}
-
-static int
-lzip_has_member(struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	int bits_checked;
-	int log2dic;
-
-	buffer = __archive_read_filter_ahead(filter, 6, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	/*
-	 * Verify Header Magic Bytes : 4C 5A 49 50 (`LZIP')
-	 */
-	bits_checked = 0;
-	if (memcmp(buffer, "LZIP", 4) != 0)
-		return (0);
-	bits_checked += 32;
-
-	/* A version number must be 0 or 1 */
-	if (buffer[4] != 0 && buffer[4] != 1)
-		return (0);
-	bits_checked += 8;
-
-	/* Dictionary size. */
-	log2dic = buffer[5] & 0x1f;
-	if (log2dic < 12 || log2dic > 29)
-		return (0);
-	bits_checked += 8;
-
-	return (bits_checked);
-}
-
-static int
-lzip_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-
-	(void)self; /* UNUSED */
-	return (lzip_has_member(filter));
-}
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-
-/*
- * liblzma 4.999.7 and later support both lzma and xz streams.
- */
-static int
-xz_bidder_init(struct archive_read_filter *self)
-{
-	self->code = ARCHIVE_FILTER_XZ;
-	self->name = "xz";
-	return (xz_lzma_bidder_init(self));
-}
-
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
-	self->code = ARCHIVE_FILTER_LZMA;
-	self->name = "lzma";
-	return (xz_lzma_bidder_init(self));
-}
-
-static int
-lzip_bidder_init(struct archive_read_filter *self)
-{
-	self->code = ARCHIVE_FILTER_LZIP;
-	self->name = "lzip";
-	return (xz_lzma_bidder_init(self));
-}
-
-/*
- * Set an error code and choose an error message
- */
-static void
-set_error(struct archive_read_filter *self, int ret)
-{
-
-	switch (ret) {
-	case LZMA_STREAM_END: /* Found end of stream. */
-	case LZMA_OK: /* Decompressor made some progress. */
-		break;
-	case LZMA_MEM_ERROR:
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Lzma library error: Cannot allocate memory");
-		break;
-	case LZMA_MEMLIMIT_ERROR:
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Lzma library error: Out of memory");
-		break;
-	case LZMA_FORMAT_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: format not recognized");
-		break;
-	case LZMA_OPTIONS_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: Invalid options");
-		break;
-	case LZMA_DATA_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: Corrupted input data");
-		break;
-	case LZMA_BUF_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error:  No progress is possible");
-		break;
-	default:
-		/* Return an error. */
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma decompression failed:  Unknown error");
-		break;
-	}
-}
-
-static const struct archive_read_filter_vtable
-xz_lzma_reader_vtable = {
-	.read = xz_filter_read,
-	.close = xz_filter_close,
-};
-
-/*
- * Setup the callbacks.
- */
-static int
-xz_lzma_bidder_init(struct archive_read_filter *self)
-{
-	static const size_t out_block_size = 64 * 1024;
-	void *out_block;
-	struct private_data *state;
-	int ret;
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = (unsigned char *)malloc(out_block_size);
-	if (state == NULL || out_block == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for xz decompression");
-		free(out_block);
-		free(state);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	self->vtable = &xz_lzma_reader_vtable;
-
-	state->stream.avail_in = 0;
-
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = state->out_block_size;
-
-	state->crc32 = 0;
-	if (self->code == ARCHIVE_FILTER_LZIP) {
-		/*
-		 * We have to read a lzip header and use it to initialize
-		 * compression library, thus we cannot initialize the
-		 * library for lzip here.
-		 */
-		state->in_stream = 0;
-		return (ARCHIVE_OK);
-	} else
-		state->in_stream = 1;
-
-	/* Initialize compression library. */
-	if (self->code == ARCHIVE_FILTER_XZ)
-		ret = lzma_stream_decoder(&(state->stream),
-		    LZMA_MEMLIMIT,/* memlimit */
-		    LZMA_CONCATENATED);
-	else
-		ret = lzma_alone_decoder(&(state->stream),
-		    LZMA_MEMLIMIT);/* memlimit */
-
-	if (ret == LZMA_OK)
-		return (ARCHIVE_OK);
-
-	/* Library setup failed: Choose an error message and clean up. */
-	set_error(self, ret);
-
-	free(state->out_block);
-	free(state);
-	self->data = NULL;
-	return (ARCHIVE_FATAL);
-}
-
-static int
-lzip_init(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	const unsigned char *h;
-	lzma_filter filters[2];
-	unsigned char props[5];
-	ssize_t avail_in;
-	uint32_t dicsize;
-	int log2dic, ret;
-
-	state = (struct private_data *)self->data;
-	h = __archive_read_filter_ahead(self->upstream, 6, &avail_in);
-	if (h == NULL)
-		return (ARCHIVE_FATAL);
-
-	/* Get a version number. */
-	state->lzip_ver = h[4];
-
-	/*
-	 * Setup lzma property.
-	 */
-	props[0] = 0x5d;
-
-	/* Get dictionary size. */
-	log2dic = h[5] & 0x1f;
-	if (log2dic < 12 || log2dic > 29)
-		return (ARCHIVE_FATAL);
-	dicsize = 1U << log2dic;
-	if (log2dic > 12)
-		dicsize -= (dicsize / 16) * (h[5] >> 5);
-	archive_le32enc(props+1, dicsize);
-
-	/* Consume lzip header. */
-	__archive_read_filter_consume(self->upstream, 6);
-	state->member_in = 6;
-
-	filters[0].id = LZMA_FILTER_LZMA1;
-	filters[0].options = NULL;
-	filters[1].id = LZMA_VLI_UNKNOWN;
-	filters[1].options = NULL;
-
-	ret = lzma_properties_decode(&filters[0], NULL, props, sizeof(props));
-	if (ret != LZMA_OK) {
-		set_error(self, ret);
-		return (ARCHIVE_FATAL);
-	}
-	ret = lzma_raw_decoder(&(state->stream), filters);
-	free(filters[0].options);
-	if (ret != LZMA_OK) {
-		set_error(self, ret);
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-lzip_tail(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	const unsigned char *f;
-	ssize_t avail_in;
-	int tail;
-
-	state = (struct private_data *)self->data;
-	if (state->lzip_ver == 0)
-		tail = 12;
-	else
-		tail = 20;
-	f = __archive_read_filter_ahead(self->upstream, tail, &avail_in);
-	if (f == NULL && avail_in < 0)
-		return (ARCHIVE_FATAL);
-	if (f == NULL || avail_in < tail) {
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Lzip: Remaining data is less bytes");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Check the crc32 value of the uncompressed data of the current
-	 * member */
-	if (state->crc32 != archive_le32dec(f)) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Lzip: CRC32 error");
-		return (ARCHIVE_FAILED);
-#endif
-	}
-
-	/* Check the uncompressed size of the current member */
-	if ((uint64_t)state->member_out != archive_le64dec(f + 4)) {
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Lzip: Uncompressed size error");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Check the total size of the current member */
-	if (state->lzip_ver == 1 &&
-	    (uint64_t)state->member_in + tail != archive_le64dec(f + 12)) {
-		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-		    "Lzip: Member size error");
-		return (ARCHIVE_FAILED);
-	}
-	__archive_read_filter_consume(self->upstream, tail);
-
-	/* If current lzip data consists of multi member, try decompressing
-	 * a next member. */
-	if (lzip_has_member(self->upstream) != 0) {
-		state->in_stream = 0;
-		state->crc32 = 0;
-		state->member_out = 0;
-		state->member_in = 0;
-		state->eof = 0;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-xz_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state;
-	size_t decompressed;
-	ssize_t avail_in;
-	int ret;
-
-	state = (struct private_data *)self->data;
-
-	/* Empty our output buffer. */
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = state->out_block_size;
-
-	/* Try to fill the output buffer. */
-	while (state->stream.avail_out > 0 && !state->eof) {
-		if (!state->in_stream) {
-			/*
-			 * Initialize liblzma for lzip
-			 */
-			ret = lzip_init(self);
-			if (ret != ARCHIVE_OK)
-				return (ret);
-			state->in_stream = 1;
-		}
-		state->stream.next_in =
-		    __archive_read_filter_ahead(self->upstream, 1, &avail_in);
-		if (state->stream.next_in == NULL && avail_in < 0) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated input");
-			return (ARCHIVE_FATAL);
-		}
-		state->stream.avail_in = avail_in;
-
-		/* Decompress as much as we can in one pass. */
-		ret = lzma_code(&(state->stream),
-		    (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN);
-		switch (ret) {
-		case LZMA_STREAM_END: /* Found end of stream. */
-			state->eof = 1;
-			/* FALL THROUGH */
-		case LZMA_OK: /* Decompressor made some progress. */
-			__archive_read_filter_consume(self->upstream,
-			    avail_in - state->stream.avail_in);
-			state->member_in +=
-			    avail_in - state->stream.avail_in;
-			break;
-		default:
-			set_error(self, ret);
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	decompressed = state->stream.next_out - state->out_block;
-	state->total_out += decompressed;
-	state->member_out += decompressed;
-	if (decompressed == 0)
-		*p = NULL;
-	else {
-		*p = state->out_block;
-		if (self->code == ARCHIVE_FILTER_LZIP) {
-			state->crc32 = lzma_crc32(state->out_block,
-			    decompressed, state->crc32);
-			if (state->eof) {
-				ret = lzip_tail(self);
-				if (ret != ARCHIVE_OK)
-					return (ret);
-			}
-		}
-	}
-	return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-xz_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-
-	state = (struct private_data *)self->data;
-	lzma_end(&(state->stream));
-	free(state->out_block);
-	free(state);
-	return (ARCHIVE_OK);
-}
-
-#else
-
-/*
- *
- * If we have no suitable library on this system, we can't actually do
- * the decompression.  We can, however, still detect compressed
- * archives and emit a useful message.
- *
- */
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "lzma -d -qq");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_LZMA;
-	self->name = "lzma";
-	return (r);
-}
-
-static int
-xz_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "xz -d -qq");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_XZ;
-	self->name = "xz";
-	return (r);
-}
-
-static int
-lzip_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "lzip -d -q");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_LZIP;
-	self->name = "lzip";
-	return (r);
-}
-
-#endif /* HAVE_LZMA_H */
diff --git a/c/archive_read_support_filter_zstd.c b/c/archive_read_support_filter_zstd.c
deleted file mode 100644
--- a/c/archive_read_support_filter_zstd.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*-
- * Copyright (c) 2009-2011 Sean Purcell
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ZSTD_H
-#include <zstd.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-
-struct private_data {
-	ZSTD_DStream	*dstream;
-	unsigned char	*out_block;
-	size_t		 out_block_size;
-	int64_t		 total_out;
-	char		 in_frame; /* True = in the middle of a zstd frame. */
-	char		 eof; /* True = found end of compressed data. */
-};
-
-/* Zstd Filter. */
-static ssize_t	zstd_filter_read(struct archive_read_filter *, const void**);
-static int	zstd_filter_close(struct archive_read_filter *);
-#endif
-
-/*
- * Note that we can detect zstd compressed files even if we can't decompress
- * them.  (In fact, we like detecting them because we can give better error
- * messages.)  So the bid framework here gets compiled even if no zstd library
- * is available.
- */
-static int	zstd_bidder_bid(struct archive_read_filter_bidder *,
-		    struct archive_read_filter *);
-static int	zstd_bidder_init(struct archive_read_filter *);
-
-static const struct archive_read_filter_bidder_vtable
-zstd_bidder_vtable = {
-	.bid = zstd_bidder_bid,
-	.init = zstd_bidder_init,
-};
-
-int
-archive_read_support_filter_zstd(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-
-	if (__archive_read_register_bidder(a, NULL, "zstd",
-				&zstd_bidder_vtable) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-	return (ARCHIVE_OK);
-#else
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external zstd program for zstd decompression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Test whether we can handle this data.
- */
-static int
-zstd_bidder_bid(struct archive_read_filter_bidder *self,
-    struct archive_read_filter *filter)
-{
-	const unsigned char *buffer;
-	ssize_t avail;
-	unsigned prefix;
-
-	/* Zstd frame magic values */
-	unsigned zstd_magic = 0xFD2FB528U;
-	unsigned zstd_magic_skippable_start = 0x184D2A50U;
-	unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
-
-	(void) self; /* UNUSED */
-
-	buffer = __archive_read_filter_ahead(filter, 4, &avail);
-	if (buffer == NULL)
-		return (0);
-
-	prefix = archive_le32dec(buffer);
-	if (prefix == zstd_magic)
-		return (32);
-	if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
-		return (32);
-
-	return (0);
-}
-
-#if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
-
-/*
- * If we don't have the library on this system, we can't do the
- * decompression directly.  We can, however, try to run "zstd -d"
- * in case that's available.
- */
-static int
-zstd_bidder_init(struct archive_read_filter *self)
-{
-	int r;
-
-	r = __archive_read_program(self, "zstd -d -qq");
-	/* Note: We set the format here even if __archive_read_program()
-	 * above fails.  We do, after all, know what the format is
-	 * even if we weren't able to read it. */
-	self->code = ARCHIVE_FILTER_ZSTD;
-	self->name = "zstd";
-	return (r);
-}
-
-#else
-
-static const struct archive_read_filter_vtable
-zstd_reader_vtable = {
-	.read = zstd_filter_read,
-	.close = zstd_filter_close,
-};
-
-/*
- * Initialize the filter object
- */
-static int
-zstd_bidder_init(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	size_t out_block_size = ZSTD_DStreamOutSize();
-	void *out_block;
-	ZSTD_DStream *dstream;
-
-	self->code = ARCHIVE_FILTER_ZSTD;
-	self->name = "zstd";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = (unsigned char *)malloc(out_block_size);
-	dstream = ZSTD_createDStream();
-
-	if (state == NULL || out_block == NULL || dstream == NULL) {
-		free(out_block);
-		free(state);
-		ZSTD_freeDStream(dstream); /* supports free on NULL */
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for zstd decompression");
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	state->dstream = dstream;
-	self->vtable = &zstd_reader_vtable;
-
-	state->eof = 0;
-	state->in_frame = 0;
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-zstd_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state;
-	size_t decompressed;
-	ssize_t avail_in;
-	ZSTD_outBuffer out;
-	ZSTD_inBuffer in;
-	size_t ret;
-
-	state = (struct private_data *)self->data;
-
-	out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
-
-	/* Try to fill the output buffer. */
-	while (out.pos < out.size && !state->eof) {
-		if (!state->in_frame) {
-			ret = ZSTD_initDStream(state->dstream);
-			if (ZSTD_isError(ret)) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Error initializing zstd decompressor: %s",
-				    ZSTD_getErrorName(ret));
-				return (ARCHIVE_FATAL);
-			}
-		}
-		in.src = __archive_read_filter_ahead(self->upstream, 1,
-		    &avail_in);
-		if (avail_in < 0) {
-			return avail_in;
-		}
-		if (in.src == NULL && avail_in == 0) {
-			if (!state->in_frame) {
-				/* end of stream */
-				state->eof = 1;
-				break;
-			} else {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Truncated zstd input");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		in.size = avail_in;
-		in.pos = 0;
-
-		{
-			ret = ZSTD_decompressStream(state->dstream, &out, &in);
-
-			if (ZSTD_isError(ret)) {
-				archive_set_error(&self->archive->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Zstd decompression failed: %s",
-				    ZSTD_getErrorName(ret));
-				return (ARCHIVE_FATAL);
-			}
-
-			/* Decompressor made some progress */
-			__archive_read_filter_consume(self->upstream, in.pos);
-
-			/* ret guaranteed to be > 0 if frame isn't done yet */
-			state->in_frame = (ret != 0);
-		}
-	}
-
-	decompressed = out.pos;
-	state->total_out += decompressed;
-	if (decompressed == 0)
-		*p = NULL;
-	else
-		*p = state->out_block;
-	return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-zstd_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-
-	state = (struct private_data *)self->data;
-
-	ZSTD_freeDStream(state->dstream);
-	free(state->out_block);
-	free(state);
-
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
diff --git a/c/archive_read_support_format_7zip.c b/c/archive_read_support_format_7zip.c
deleted file mode 100644
--- a/c/archive_read_support_format_7zip.c
+++ /dev/null
@@ -1,4074 +0,0 @@
-/*-
- * Copyright (c) 2011 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_ZSTD_H
-#include <zstd.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_ppmd7_private.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_endian.h"
-
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-
-#define _7ZIP_SIGNATURE	"7z\xBC\xAF\x27\x1C"
-#define SFX_MIN_ADDR	0x27000
-#define SFX_MAX_ADDR	0x60000
-
-
-/*
- * Codec ID
- */
-#define _7Z_COPY	0
-#define _7Z_LZMA	0x030101
-#define _7Z_LZMA2	0x21
-#define _7Z_DEFLATE	0x040108
-#define _7Z_BZ2		0x040202
-#define _7Z_PPMD	0x030401
-#define _7Z_DELTA	0x03
-#define _7Z_CRYPTO_MAIN_ZIP			0x06F10101 /* Main Zip crypto algo */
-#define _7Z_CRYPTO_RAR_29			0x06F10303 /* Rar29 AES-128 + (modified SHA-1) */
-#define _7Z_CRYPTO_AES_256_SHA_256	0x06F10701 /* AES-256 + SHA-256 */
-
-
-#define _7Z_X86		0x03030103
-#define _7Z_X86_BCJ2	0x0303011B
-#define _7Z_POWERPC	0x03030205
-#define _7Z_IA64	0x03030401
-#define _7Z_ARM		0x03030501
-#define _7Z_ARMTHUMB	0x03030701
-#define _7Z_ARM64	0xa
-#define _7Z_SPARC	0x03030805
-
-#define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
-
-/*
- * 7-Zip header property IDs.
- */
-#define kEnd			0x00
-#define kHeader			0x01
-#define kArchiveProperties	0x02
-#define kAdditionalStreamsInfo	0x03
-#define kMainStreamsInfo	0x04
-#define kFilesInfo		0x05
-#define kPackInfo		0x06
-#define kUnPackInfo		0x07
-#define kSubStreamsInfo		0x08
-#define kSize			0x09
-#define kCRC			0x0A
-#define kFolder			0x0B
-#define kCodersUnPackSize	0x0C
-#define kNumUnPackStream	0x0D
-#define kEmptyStream		0x0E
-#define kEmptyFile		0x0F
-#define kAnti			0x10
-#define kName			0x11
-#define kCTime			0x12
-#define kATime			0x13
-#define kMTime			0x14
-#define kAttributes		0x15
-#define kEncodedHeader		0x17
-#define kDummy			0x19
-
-struct _7z_digests {
-	unsigned char	*defineds;
-	uint32_t	*digests;
-};
-
-
-struct _7z_folder {
-	uint64_t		 numCoders;
-	struct _7z_coder {
-		unsigned long	 codec;
-		uint64_t	 numInStreams;
-		uint64_t	 numOutStreams;
-		uint64_t	 propertiesSize;
-		unsigned char	*properties;
-	} *coders;
-	uint64_t		 numBindPairs;
-	struct {
-		uint64_t	 inIndex;
-		uint64_t	 outIndex;
-	} *bindPairs;
-	uint64_t		 numPackedStreams;
-	uint64_t		*packedStreams;
-	uint64_t		 numInStreams;
-	uint64_t		 numOutStreams;
-	uint64_t		*unPackSize;
-	unsigned char		 digest_defined;
-	uint32_t		 digest;
-	uint64_t		 numUnpackStreams;
-	uint32_t		 packIndex;
-	/* Unoperated bytes. */
-	uint64_t		 skipped_bytes;
-};
-
-struct _7z_coders_info {
-	uint64_t		 numFolders;
-	struct _7z_folder	*folders;
-	uint64_t		 dataStreamIndex;
-};
-
-struct _7z_pack_info {
-	uint64_t		 pos;
-	uint64_t		 numPackStreams;
-	uint64_t		*sizes;
-	struct _7z_digests	 digest;
-	/* Calculated from pos and numPackStreams. */
-	uint64_t		*positions;
-};
-
-struct _7z_substream_info {
-	size_t			 unpack_streams;
-	uint64_t		*unpackSizes;
-	unsigned char		*digestsDefined;
-	uint32_t		*digests;
-};
-
-struct _7z_stream_info {
-	struct _7z_pack_info	 pi;
-	struct _7z_coders_info	 ci;
-	struct _7z_substream_info ss;
-};
-
-struct _7z_header_info {
-	uint64_t		 dataIndex;
-
-	unsigned char		*emptyStreamBools;
-	unsigned char		*emptyFileBools;
-	unsigned char		*antiBools;
-	unsigned char		*attrBools;
-};
-
-struct _7zip_entry {
-	size_t			 name_len;
-	unsigned char		*utf16name;
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
-	const wchar_t		*wname;
-#endif
-	uint32_t		 folderIndex;
-	uint32_t		 ssIndex;
-	unsigned		 flg;
-#define MTIME_IS_SET	(1<<0)
-#define ATIME_IS_SET	(1<<1)
-#define CTIME_IS_SET	(1<<2)
-#define CRC32_IS_SET	(1<<3)
-#define HAS_STREAM	(1<<4)
-
-	time_t			 mtime;
-	time_t			 atime;
-	time_t			 ctime;
-	long			 mtime_ns;
-	long			 atime_ns;
-	long			 ctime_ns;
-	uint32_t		 mode;
-	uint32_t		 attr;
-};
-
-struct _7zip {
-	/* Structural information about the archive. */
-	struct _7z_stream_info	 si;
-
-	int			 header_is_being_read;
-	int			 header_is_encoded;
-	uint64_t		 header_bytes_remaining;
-	unsigned long		 header_crc32;
-	/* Header offset to check that reading points of the file contents
-	 * will not exceed the header. */
-	uint64_t		 header_offset;
-	/* Base offset of the archive file for a seek in case reading SFX. */
-	uint64_t		 seek_base;
-
-	/* List of entries */
-	size_t			 entries_remaining;
-	uint64_t		 numFiles;
-	struct _7zip_entry	*entries;
-	struct _7zip_entry	*entry;
-	unsigned char		*entry_names;
-
-	/* entry_bytes_remaining is the number of bytes we expect. */
-	int64_t			 entry_offset;
-	uint64_t		 entry_bytes_remaining;
-
-	/* Running CRC32 of the decompressed data */
-	unsigned long		 entry_crc32;
-
-	/* Flags to mark progress of decompression. */
-	char			 end_of_entry;
-
-	/* Uncompressed buffer control.  */
-#define UBUFF_SIZE	(64 * 1024)
-	unsigned char 		*uncompressed_buffer;
-	unsigned char 		*uncompressed_buffer_pointer;
-	size_t 			 uncompressed_buffer_size;
-	size_t			 uncompressed_buffer_bytes_remaining;
-
-	/* Offset of the compressed data. */
-	int64_t			 stream_offset;
-
-	/*
-	 * Decompressing control data.
-	 */
-	unsigned		 folder_index;
-	uint64_t		 folder_outbytes_remaining;
-	unsigned		 pack_stream_index;
-	unsigned		 pack_stream_remaining;
-	uint64_t		 pack_stream_inbytes_remaining;
-	size_t			 pack_stream_bytes_unconsumed;
-
-	/* The codec information of a folder. */
-	unsigned long		 codec;
-	unsigned long		 codec2;
-
-	/*
-	 * Decompressor controllers.
-	 */
-	/* Decoding LZMA1 and LZMA2 data. */
-#ifdef HAVE_LZMA_H
-	lzma_stream		 lzstream;
-	int			 lzstream_valid;
-#endif
-	/* Decoding bzip2 data. */
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	bz_stream		 bzstream;
-	int			 bzstream_valid;
-#endif
-	/* Decoding deflate data. */
-#ifdef HAVE_ZLIB_H
-	z_stream		 stream;
-	int			 stream_valid;
-#endif
-	/* Decoding Zstandard data. */
-#if HAVE_ZSTD_H
-	ZSTD_DStream		 *zstd_dstream;
-	int		         zstdstream_valid;
-#endif
-	/* Decoding PPMd data. */
-	int			 ppmd7_stat;
-	CPpmd7			 ppmd7_context;
-	CPpmd7z_RangeDec	 range_dec;
-	IByteIn			 bytein;
-	struct {
-		const unsigned char	*next_in;
-		int64_t			 avail_in;
-		int64_t			 total_in;
-		int64_t			 stream_in;
-		unsigned char		*next_out;
-		int64_t			 avail_out;
-		int64_t			 total_out;
-		int			 overconsumed;
-	} ppstream;
-	int			 ppmd7_valid;
-
-	/* Decoding BCJ and BCJ2 data. */
-	uint32_t		 bcj_state;
-	size_t			 odd_bcj_size;
-	unsigned char		 odd_bcj[4];
-	/* Decoding BCJ data. */
-	size_t			 bcj_prevPosT;
-	uint32_t		 bcj_prevMask;
-	uint32_t		 bcj_ip;
-
-	/* Decoding BCJ2 data. */
-	size_t			 main_stream_bytes_remaining;
-	unsigned char		*sub_stream_buff[3];
-	size_t			 sub_stream_size[3];
-	size_t			 sub_stream_bytes_remaining[3];
-	unsigned char		*tmp_stream_buff;
-	size_t			 tmp_stream_buff_size;
-	size_t			 tmp_stream_bytes_avail;
-	size_t			 tmp_stream_bytes_remaining;
-#ifdef _LZMA_PROB32
-#define CProb uint32_t
-#else
-#define CProb uint16_t
-#endif
-	CProb			 bcj2_p[256 + 2];
-	uint8_t			 bcj2_prevByte;
-	uint32_t		 bcj2_range;
-	uint32_t		 bcj2_code;
-	uint64_t		 bcj2_outPos;
-
-	/* Filename character-set conversion data. */
-	struct archive_string_conv *sconv;
-
-	char			 format_name[64];
-
-	/* Custom value that is non-zero if this archive contains encrypted entries. */
-	int			 has_encrypted_entries;
-};
-
-/* Maximum entry size. This limitation prevents reading intentional
- * corrupted 7-zip files on assuming there are not so many entries in
- * the files. */
-#define UMAX_ENTRY	ARCHIVE_LITERAL_ULL(100000000)
-
-static int	archive_read_format_7zip_has_encrypted_entries(struct archive_read *);
-static int	archive_read_support_format_7zip_capabilities(struct archive_read *a);
-static int	archive_read_format_7zip_bid(struct archive_read *, int);
-static int	archive_read_format_7zip_cleanup(struct archive_read *);
-static int	archive_read_format_7zip_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_7zip_read_data_skip(struct archive_read *);
-static int	archive_read_format_7zip_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	check_7zip_header_in_sfx(const char *);
-static unsigned long decode_codec_id(const unsigned char *, size_t);
-static int	decode_encoded_header_info(struct archive_read *,
-		    struct _7z_stream_info *);
-static int	decompress(struct archive_read *, struct _7zip *,
-		    void *, size_t *, const void *, size_t *);
-static ssize_t	extract_pack_stream(struct archive_read *, size_t);
-static void	fileTimeToUtc(uint64_t, time_t *, long *);
-static uint64_t folder_uncompressed_size(struct _7z_folder *);
-static void	free_CodersInfo(struct _7z_coders_info *);
-static void	free_Digest(struct _7z_digests *);
-static void	free_Folder(struct _7z_folder *);
-static void	free_Header(struct _7z_header_info *);
-static void	free_PackInfo(struct _7z_pack_info *);
-static void	free_StreamsInfo(struct _7z_stream_info *);
-static void	free_SubStreamsInfo(struct _7z_substream_info *);
-static int	free_decompression(struct archive_read *, struct _7zip *);
-static ssize_t	get_uncompressed_data(struct archive_read *, const void **,
-		    size_t, size_t);
-static const unsigned char * header_bytes(struct archive_read *, size_t);
-static int	init_decompression(struct archive_read *, struct _7zip *,
-		    const struct _7z_coder *, const struct _7z_coder *);
-static int	parse_7zip_uint64(struct archive_read *, uint64_t *);
-static int	read_Bools(struct archive_read *, unsigned char *, size_t);
-static int	read_CodersInfo(struct archive_read *,
-		    struct _7z_coders_info *);
-static int	read_Digests(struct archive_read *, struct _7z_digests *,
-		    size_t);
-static int	read_Folder(struct archive_read *, struct _7z_folder *);
-static int	read_Header(struct archive_read *, struct _7z_header_info *,
-		    int);
-static int	read_PackInfo(struct archive_read *, struct _7z_pack_info *);
-static int	read_StreamsInfo(struct archive_read *,
-		    struct _7z_stream_info *);
-static int	read_SubStreamsInfo(struct archive_read *,
-		    struct _7z_substream_info *, struct _7z_folder *, size_t);
-static int	read_Times(struct archive_read *, struct _7z_header_info *,
-		    int);
-static void	read_consume(struct archive_read *);
-static ssize_t	read_stream(struct archive_read *, const void **, size_t,
-		    size_t);
-static int	seek_pack(struct archive_read *);
-static int64_t	skip_stream(struct archive_read *, size_t);
-static int	skip_sfx(struct archive_read *, ssize_t);
-static int	slurp_central_directory(struct archive_read *, struct _7zip *,
-		    struct _7z_header_info *);
-static int	setup_decode_folder(struct archive_read *, struct _7z_folder *,
-		    int);
-static void	x86_Init(struct _7zip *);
-static size_t	x86_Convert(struct _7zip *, uint8_t *, size_t);
-static void	arm_Init(struct _7zip *);
-static size_t	arm_Convert(struct _7zip *, uint8_t *, size_t);
-static size_t	arm64_Convert(struct _7zip *, uint8_t *, size_t);
-static ssize_t		Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
-
-
-int
-archive_read_support_format_7zip(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct _7zip *zip;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_7zip");
-
-	zip = calloc(1, sizeof(*zip));
-	if (zip == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate 7zip data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Until enough data has been read, we cannot tell about
-	 * any encrypted entries yet.
-	 */
-	zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-
-
-	r = __archive_read_register_format(a,
-	    zip,
-	    "7zip",
-	    archive_read_format_7zip_bid,
-	    NULL,
-	    archive_read_format_7zip_read_header,
-	    archive_read_format_7zip_read_data,
-	    archive_read_format_7zip_read_data_skip,
-	    NULL,
-	    archive_read_format_7zip_cleanup,
-	    archive_read_support_format_7zip_capabilities,
-	    archive_read_format_7zip_has_encrypted_entries);
-
-	if (r != ARCHIVE_OK)
-		free(zip);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_support_format_7zip_capabilities(struct archive_read * a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
-			ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
-}
-
-
-static int
-archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a)
-{
-	if (_a && _a->format) {
-		struct _7zip * zip = (struct _7zip *)_a->format->data;
-		if (zip) {
-			return zip->has_encrypted_entries;
-		}
-	}
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-}
-
-static int
-archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
-{
-	const char *p;
-
-	/* If someone has already bid more than 32, then avoid
-	   trashing the look-ahead buffers with a seek. */
-	if (best_bid > 32)
-		return (-1);
-
-	if ((p = __archive_read_ahead(a, 6, NULL)) == NULL)
-		return (0);
-
-	/* If first six bytes are the 7-Zip signature,
-	 * return the bid right now. */
-	if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0)
-		return (48);
-
-	/*
-	 * It may a 7-Zip SFX archive file. If first two bytes are
-	 * 'M' and 'Z' available on Windows or first four bytes are
-	 * "\x7F\x45LF" available on posix like system, seek the 7-Zip
-	 * signature. Although we will perform a seek when reading
-	 * a header, what we do not use __archive_read_seek() here is
-	 * due to a bidding performance.
-	 */
-	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
-		ssize_t offset = SFX_MIN_ADDR;
-		ssize_t window = 4096;
-		ssize_t bytes_avail;
-		while (offset + window <= (SFX_MAX_ADDR)) {
-			const char *buff = __archive_read_ahead(a,
-					offset + window, &bytes_avail);
-			if (buff == NULL) {
-				/* Remaining bytes are less than window. */
-				window >>= 1;
-				if (window < 0x40)
-					return (0);
-				continue;
-			}
-			p = buff + offset;
-			while (p + 32 < buff + bytes_avail) {
-				int step = check_7zip_header_in_sfx(p);
-				if (step == 0)
-					return (48);
-				p += step;
-			}
-			offset = p - buff;
-		}
-	}
-	return (0);
-}
-
-static int
-check_7zip_header_in_sfx(const char *p)
-{
-	switch ((unsigned char)p[5]) {
-	case 0x1C:
-		if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0)
-			return (6);
-		/*
-		 * Test the CRC because its extraction code has 7-Zip
-		 * Magic Code, so we should do this in order not to
-		 * make a mis-detection.
-		 */
-		if (crc32(0, (const unsigned char *)p + 12, 20)
-			!= archive_le32dec(p + 8))
-			return (6);
-		/* Hit the header! */
-		return (0);
-	case 0x37: return (5);
-	case 0x7A: return (4);
-	case 0xBC: return (3);
-	case 0xAF: return (2);
-	case 0x27: return (1);
-	default: return (6);
-	}
-}
-
-static int
-skip_sfx(struct archive_read *a, ssize_t bytes_avail)
-{
-	const void *h;
-	const char *p, *q;
-	size_t skip, offset;
-	ssize_t bytes, window;
-
-	/*
-	 * If bytes_avail > SFX_MIN_ADDR we do not have to call
-	 * __archive_read_seek() at this time since we have
-	 * already had enough data.
-	 */
-	if (bytes_avail > SFX_MIN_ADDR)
-		__archive_read_consume(a, SFX_MIN_ADDR);
-	else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0)
-		return (ARCHIVE_FATAL);
-
-	offset = 0;
-	window = 1;
-	while (offset + window <= SFX_MAX_ADDR - SFX_MIN_ADDR) {
-		h = __archive_read_ahead(a, window, &bytes);
-		if (h == NULL) {
-			/* Remaining bytes are less than window. */
-			window >>= 1;
-			if (window < 0x40)
-				goto fatal;
-			continue;
-		}
-		if (bytes < 6) {
-			/* This case might happen when window == 1. */
-			window = 4096;
-			continue;
-		}
-		p = (const char *)h;
-		q = p + bytes;
-
-		/*
-		 * Scan ahead until we find something that looks
-		 * like the 7-Zip header.
-		 */
-		while (p + 32 < q) {
-			int step = check_7zip_header_in_sfx(p);
-			if (step == 0) {
-				struct _7zip *zip =
-				    (struct _7zip *)a->format->data;
-				skip = p - (const char *)h;
-				__archive_read_consume(a, skip);
-				zip->seek_base = SFX_MIN_ADDR + offset + skip;
-				return (ARCHIVE_OK);
-			}
-			p += step;
-		}
-		skip = p - (const char *)h;
-		__archive_read_consume(a, skip);
-		offset += skip;
-		if (window == 1)
-			window = 4096;
-	}
-fatal:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Couldn't find out 7-Zip header");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-archive_read_format_7zip_read_header(struct archive_read *a,
-	struct archive_entry *entry)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	struct _7zip_entry *zip_entry;
-	int r, ret = ARCHIVE_OK;
-	struct _7z_folder *folder = 0;
-	uint64_t fidx = 0;
-
-	/*
-	 * It should be sufficient to call archive_read_next_header() for
-	 * a reader to determine if an entry is encrypted or not. If the
-	 * encryption of an entry is only detectable when calling
-	 * archive_read_data(), so be it. We'll do the same check there
-	 * as well.
-	 */
-	if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-		zip->has_encrypted_entries = 0;
-	}
-
-	a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
-	if (a->archive.archive_format_name == NULL)
-		a->archive.archive_format_name = "7-Zip";
-
-	if (zip->entries == NULL) {
-		struct _7z_header_info header;
-
-		memset(&header, 0, sizeof(header));
-		r = slurp_central_directory(a, zip, &header);
-		free_Header(&header);
-		if (r != ARCHIVE_OK)
-			return (r);
-		zip->entries_remaining = (size_t)zip->numFiles;
-		zip->entry = zip->entries;
-	} else {
-		++zip->entry;
-	}
-	zip_entry = zip->entry;
-
-	if (zip->entries_remaining <= 0 || zip_entry == NULL)
-		return ARCHIVE_EOF;
-	--zip->entries_remaining;
-
-	zip->entry_offset = 0;
-	zip->end_of_entry = 0;
-	zip->entry_crc32 = crc32(0, NULL, 0);
-
-	/* Setup a string conversion for a filename. */
-	if (zip->sconv == NULL) {
-		zip->sconv = archive_string_conversion_from_charset(
-		    &a->archive, "UTF-16LE", 1);
-		if (zip->sconv == NULL)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Figure out if the entry is encrypted by looking at the folder
-	   that is associated to the current 7zip entry. If the folder
-	   has a coder with a _7Z_CRYPTO codec then the folder is encrypted.
-	   Hence the entry must also be encrypted. */
-	if (zip_entry && zip_entry->folderIndex < zip->si.ci.numFolders) {
-		folder = &(zip->si.ci.folders[zip_entry->folderIndex]);
-		for (fidx=0; folder && fidx<folder->numCoders; fidx++) {
-			switch(folder->coders[fidx].codec) {
-				case _7Z_CRYPTO_MAIN_ZIP:
-				case _7Z_CRYPTO_RAR_29:
-				case _7Z_CRYPTO_AES_256_SHA_256: {
-					archive_entry_set_is_data_encrypted(entry, 1);
-					zip->has_encrypted_entries = 1;
-					break;
-				}
-			}
-		}
-	}
-
-	/* Now that we've checked for encryption, if there were still no
-	 * encrypted entries found we can say for sure that there are none.
-	 */
-	if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-		zip->has_encrypted_entries = 0;
-	}
-
-	if (archive_entry_copy_pathname_l(entry,
-	    (const char *)zip_entry->utf16name,
-	    zip_entry->name_len, zip->sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Pathname cannot be converted "
-		    "from %s to current locale.",
-		    archive_string_conversion_charset_name(zip->sconv));
-		ret = ARCHIVE_WARN;
-	}
-
-	/* Populate some additional entry fields: */
-	archive_entry_set_mode(entry, zip_entry->mode);
-	if (zip_entry->flg & MTIME_IS_SET)
-		archive_entry_set_mtime(entry, zip_entry->mtime,
-			zip_entry->mtime_ns);
-	if (zip_entry->flg & CTIME_IS_SET)
-		archive_entry_set_ctime(entry, zip_entry->ctime,
-		    zip_entry->ctime_ns);
-	if (zip_entry->flg & ATIME_IS_SET)
-		archive_entry_set_atime(entry, zip_entry->atime,
-		    zip_entry->atime_ns);
-	if (zip_entry->ssIndex != (uint32_t)-1) {
-		zip->entry_bytes_remaining =
-		    zip->si.ss.unpackSizes[zip_entry->ssIndex];
-		archive_entry_set_size(entry, zip->entry_bytes_remaining);
-	} else {
-		zip->entry_bytes_remaining = 0;
-		archive_entry_set_size(entry, 0);
-	}
-
-	/* If there's no body, force read_data() to return EOF immediately. */
-	if (zip->entry_bytes_remaining < 1)
-		zip->end_of_entry = 1;
-
-	if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) {
-		unsigned char *symname = NULL;
-		size_t symsize = 0;
-
-		/*
-		 * Symbolic-name is recorded as its contents. We have to
-		 * read the contents at this time.
-		 */
-		while (zip->entry_bytes_remaining > 0) {
-			const void *buff;
-			unsigned char *mem;
-			size_t size;
-			int64_t offset;
-
-			r = archive_read_format_7zip_read_data(a, &buff,
-				&size, &offset);
-			if (r < ARCHIVE_WARN) {
-				free(symname);
-				return (r);
-			}
-			mem = realloc(symname, symsize + size + 1);
-			if (mem == NULL) {
-				free(symname);
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Symname");
-				return (ARCHIVE_FATAL);
-			}
-			symname = mem;
-			memcpy(symname+symsize, buff, size);
-			symsize += size;
-		}
-		if (symsize == 0) {
-			/* If there is no symname, handle it as a regular
-			 * file. */
-			zip_entry->mode &= ~AE_IFMT;
-			zip_entry->mode |= AE_IFREG;
-			archive_entry_set_mode(entry, zip_entry->mode);
-		} else {
-			symname[symsize] = '\0';
-			archive_entry_copy_symlink(entry,
-			    (const char *)symname);
-		}
-		free(symname);
-		archive_entry_set_size(entry, 0);
-	}
-
-	/* Set up a more descriptive format name. */
-	snprintf(zip->format_name, sizeof(zip->format_name), "7-Zip");
-	a->archive.archive_format_name = zip->format_name;
-
-	return (ret);
-}
-
-static int
-archive_read_format_7zip_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct _7zip *zip;
-	ssize_t bytes;
-	int ret = ARCHIVE_OK;
-
-	zip = (struct _7zip *)(a->format->data);
-
-	if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-		zip->has_encrypted_entries = 0;
-	}
-
-	if (zip->pack_stream_bytes_unconsumed)
-		read_consume(a);
-
-	*offset = zip->entry_offset;
-	*size = 0;
-	*buff = NULL;
-	/*
-	 * If we hit end-of-entry last time, clean up and return
-	 * ARCHIVE_EOF this time.
-	 */
-	if (zip->end_of_entry)
-		return (ARCHIVE_EOF);
-
-	const uint64_t max_read_size = 16 * 1024 * 1024;  // Don't try to read more than 16 MB at a time
-	size_t bytes_to_read = max_read_size;
-	if ((uint64_t)bytes_to_read > zip->entry_bytes_remaining) {
-		bytes_to_read = zip->entry_bytes_remaining;
-	}
-	bytes = read_stream(a, buff, bytes_to_read, 0);
-	if (bytes < 0)
-		return ((int)bytes);
-	if (bytes == 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated 7-Zip file body");
-		return (ARCHIVE_FATAL);
-	}
-	zip->entry_bytes_remaining -= bytes;
-	if (zip->entry_bytes_remaining == 0)
-		zip->end_of_entry = 1;
-
-	/* Update checksum */
-	if ((zip->entry->flg & CRC32_IS_SET) && bytes)
-		zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
-		    (unsigned)bytes);
-
-	/* If we hit the end, swallow any end-of-data marker. */
-	if (zip->end_of_entry) {
-		/* Check computed CRC against file contents. */
-		if ((zip->entry->flg & CRC32_IS_SET) &&
-			zip->si.ss.digests[zip->entry->ssIndex] !=
-		    zip->entry_crc32) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "7-Zip bad CRC: 0x%lx should be 0x%lx",
-			    (unsigned long)zip->entry_crc32,
-			    (unsigned long)zip->si.ss.digests[
-			    		zip->entry->ssIndex]);
-			ret = ARCHIVE_WARN;
-		}
-	}
-
-	*size = bytes;
-	*offset = zip->entry_offset;
-	zip->entry_offset += bytes;
-
-	return (ret);
-}
-
-static int
-archive_read_format_7zip_read_data_skip(struct archive_read *a)
-{
-	struct _7zip *zip;
-	int64_t bytes_skipped;
-
-	zip = (struct _7zip *)(a->format->data);
-
-	if (zip->pack_stream_bytes_unconsumed)
-		read_consume(a);
-
-	/* If we've already read to end of data, we're done. */
-	if (zip->end_of_entry)
-		return (ARCHIVE_OK);
-
-	/*
-	 * If the length is at the beginning, we can skip the
-	 * compressed data much more quickly.
-	 */
-	bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-	zip->entry_bytes_remaining = 0;
-
-	/* This entry is finished and done. */
-	zip->end_of_entry = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_7zip_cleanup(struct archive_read *a)
-{
-	struct _7zip *zip;
-
-	zip = (struct _7zip *)(a->format->data);
-	free_StreamsInfo(&(zip->si));
-	free(zip->entries);
-	free(zip->entry_names);
-	free_decompression(a, zip);
-	free(zip->uncompressed_buffer);
-	free(zip->sub_stream_buff[0]);
-	free(zip->sub_stream_buff[1]);
-	free(zip->sub_stream_buff[2]);
-	free(zip->tmp_stream_buff);
-	free(zip);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-static void
-read_consume(struct archive_read *a)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-
-	if (zip->pack_stream_bytes_unconsumed) {
-		__archive_read_consume(a, zip->pack_stream_bytes_unconsumed);
-		zip->stream_offset += zip->pack_stream_bytes_unconsumed;
-		zip->pack_stream_bytes_unconsumed = 0;
-	}
-}
-
-#ifdef HAVE_LZMA_H
-
-/*
- * Set an error code and choose an error message for liblzma.
- */
-static void
-set_error(struct archive_read *a, int ret)
-{
-
-	switch (ret) {
-	case LZMA_STREAM_END: /* Found end of stream. */
-	case LZMA_OK: /* Decompressor made some progress. */
-		break;
-	case LZMA_MEM_ERROR:
-		archive_set_error(&a->archive, ENOMEM,
-		    "Lzma library error: Cannot allocate memory");
-		break;
-	case LZMA_MEMLIMIT_ERROR:
-		archive_set_error(&a->archive, ENOMEM,
-		    "Lzma library error: Out of memory");
-		break;
-	case LZMA_FORMAT_ERROR:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: format not recognized");
-		break;
-	case LZMA_OPTIONS_ERROR:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: Invalid options");
-		break;
-	case LZMA_DATA_ERROR:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error: Corrupted input data");
-		break;
-	case LZMA_BUF_ERROR:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma library error:  No progress is possible");
-		break;
-	default:
-		/* Return an error. */
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Lzma decompression failed:  Unknown error");
-		break;
-	}
-}
-
-#endif
-
-static unsigned long
-decode_codec_id(const unsigned char *codecId, size_t id_size)
-{
-	unsigned i;
-	unsigned long id = 0;
-
-	for (i = 0; i < id_size; i++) {
-		id <<= 8;
-		id += codecId[i];
-	}
-	return (id);
-}
-
-static Byte
-ppmd_read(void *p)
-{
-	struct archive_read *a = ((IByteIn*)p)->a;
-	struct _7zip *zip = (struct _7zip *)(a->format->data);
-	Byte b;
-
-	if (zip->ppstream.avail_in <= 0) {
-		/*
-		 * Ppmd7_DecodeSymbol might require reading multiple bytes
-		 * and we are on boundary;
-		 * last resort to read using __archive_read_ahead.
-		 */
-		ssize_t bytes_avail = 0;
-		const uint8_t* data = __archive_read_ahead(a,
-		    zip->ppstream.stream_in+1, &bytes_avail);
-		if(bytes_avail < zip->ppstream.stream_in+1) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated 7z file data");
-			zip->ppstream.overconsumed = 1;
-			return (0);
-		}
-		zip->ppstream.next_in++;
-		b = data[zip->ppstream.stream_in];
-	} else {
-		b = *zip->ppstream.next_in++;
-	}
-	zip->ppstream.avail_in--;
-	zip->ppstream.total_in++;
-	zip->ppstream.stream_in++;
-	return (b);
-}
-
-static int
-init_decompression(struct archive_read *a, struct _7zip *zip,
-    const struct _7z_coder *coder1, const struct _7z_coder *coder2)
-{
-	int r;
-
-	zip->codec = coder1->codec;
-	zip->codec2 = -1;
-
-	switch (zip->codec) {
-	case _7Z_COPY:
-	case _7Z_BZ2:
-	case _7Z_DEFLATE:
-	case _7Z_ZSTD:
-	case _7Z_PPMD:
-		if (coder2 != NULL) {
-			if (coder2->codec != _7Z_X86 &&
-			    coder2->codec != _7Z_X86_BCJ2 &&
-			    coder2->codec != _7Z_ARM &&
-			    coder2->codec != _7Z_ARM64) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Unsupported filter %lx for %lx",
-				    coder2->codec, coder1->codec);
-				return (ARCHIVE_FAILED);
-			}
-			zip->codec2 = coder2->codec;
-			zip->bcj_state = 0;
-			if (coder2->codec == _7Z_X86)
-				x86_Init(zip);
-			else if (coder2->codec == _7Z_ARM)
-				arm_Init(zip);
-		}
-		break;
-	default:
-		break;
-	}
-
-	switch (zip->codec) {
-	case _7Z_COPY:
-		break;
-
-	case _7Z_LZMA: case _7Z_LZMA2:
-#ifdef HAVE_LZMA_H
-#if LZMA_VERSION_MAJOR >= 5
-/* Effectively disable the limiter. */
-#define LZMA_MEMLIMIT   UINT64_MAX
-#else
-/* NOTE: This needs to check memory size which running system has. */
-#define LZMA_MEMLIMIT   (1U << 30)
-#endif
-	{
-		lzma_options_delta delta_opt;
-		lzma_filter filters[LZMA_FILTERS_MAX], *ff;
-		int fi = 0;
-
-		if (zip->lzstream_valid) {
-			lzma_end(&(zip->lzstream));
-			zip->lzstream_valid = 0;
-		}
-
-		/*
-		 * NOTE: liblzma incompletely handle the BCJ+LZMA compressed
-		 * data made by 7-Zip because 7-Zip does not add End-Of-
-		 * Payload Marker(EOPM) at the end of LZMA compressed data,
-		 * and so liblzma cannot know the end of the compressed data
-		 * without EOPM. So consequently liblzma will not return last
-		 * three or four bytes of uncompressed data because
-		 * LZMA_FILTER_X86 filter does not handle input data if its
-		 * data size is less than five bytes. If liblzma detect EOPM
-		 * or know the uncompressed data size, liblzma will flush out
-		 * the remaining that three or four bytes of uncompressed
-		 * data. That is why we have to use our converting program
-		 * for BCJ+LZMA. If we were able to tell the uncompressed
-		 * size to liblzma when using lzma_raw_decoder() liblzma
-		 * could correctly deal with BCJ+LZMA. But unfortunately
-		 * there is no way to do that.
-		 * Discussion about this can be found at XZ Utils forum.
-		 */
-		if (coder2 != NULL) {
-			zip->codec2 = coder2->codec;
-
-			filters[fi].options = NULL;
-			switch (zip->codec2) {
-			case _7Z_X86:
-				if (zip->codec == _7Z_LZMA2) {
-					filters[fi].id = LZMA_FILTER_X86;
-					fi++;
-				} else
-					/* Use our filter. */
-					x86_Init(zip);
-				break;
-			case _7Z_X86_BCJ2:
-				/* Use our filter. */
-				zip->bcj_state = 0;
-				break;
-			case _7Z_DELTA:
-				if (coder2->propertiesSize != 1) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "Invalid Delta parameter");
-					return (ARCHIVE_FAILED);
-				}
-				filters[fi].id = LZMA_FILTER_DELTA;
-				memset(&delta_opt, 0, sizeof(delta_opt));
-				delta_opt.type = LZMA_DELTA_TYPE_BYTE;
-				delta_opt.dist =
-				    (uint32_t)coder2->properties[0] + 1;
-				filters[fi].options = &delta_opt;
-				fi++;
-				break;
-			/* Following filters have not been tested yet. */
-			case _7Z_POWERPC:
-				filters[fi].id = LZMA_FILTER_POWERPC;
-				fi++;
-				break;
-			case _7Z_IA64:
-				filters[fi].id = LZMA_FILTER_IA64;
-				fi++;
-				break;
-			case _7Z_ARM:
-				filters[fi].id = LZMA_FILTER_ARM;
-				fi++;
-				break;
-			case _7Z_ARMTHUMB:
-				filters[fi].id = LZMA_FILTER_ARMTHUMB;
-				fi++;
-				break;
-#ifdef LZMA_FILTER_ARM64
-			case _7Z_ARM64:
-				filters[fi].id = LZMA_FILTER_ARM64;
-				fi++;
-				break;
-#endif
-			case _7Z_SPARC:
-				filters[fi].id = LZMA_FILTER_SPARC;
-				fi++;
-				break;
-			default:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Unexpected codec ID: %lX", zip->codec2);
-				return (ARCHIVE_FAILED);
-			}
-		}
-
-		if (zip->codec == _7Z_LZMA2)
-			filters[fi].id = LZMA_FILTER_LZMA2;
-		else
-			filters[fi].id = LZMA_FILTER_LZMA1;
-		filters[fi].options = NULL;
-		ff = &filters[fi];
-		r = lzma_properties_decode(&filters[fi], NULL,
-		    coder1->properties, (size_t)coder1->propertiesSize);
-		if (r != LZMA_OK) {
-			set_error(a, r);
-			return (ARCHIVE_FAILED);
-		}
-		fi++;
-
-		filters[fi].id = LZMA_VLI_UNKNOWN;
-		filters[fi].options = NULL;
-		r = lzma_raw_decoder(&(zip->lzstream), filters);
-		free(ff->options);
-		if (r != LZMA_OK) {
-			set_error(a, r);
-			return (ARCHIVE_FAILED);
-		}
-		zip->lzstream_valid = 1;
-		zip->lzstream.total_in = 0;
-		zip->lzstream.total_out = 0;
-		break;
-	}
-#else
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "LZMA codec is unsupported");
-		return (ARCHIVE_FAILED);
-#endif
-	case _7Z_BZ2:
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-		if (zip->bzstream_valid) {
-			BZ2_bzDecompressEnd(&(zip->bzstream));
-			zip->bzstream_valid = 0;
-		}
-		r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 0);
-		if (r == BZ_MEM_ERROR)
-			r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 1);
-		if (r != BZ_OK) {
-			int err = ARCHIVE_ERRNO_MISC;
-			const char *detail = NULL;
-			switch (r) {
-			case BZ_PARAM_ERROR:
-				detail = "invalid setup parameter";
-				break;
-			case BZ_MEM_ERROR:
-				err = ENOMEM;
-				detail = "out of memory";
-				break;
-			case BZ_CONFIG_ERROR:
-				detail = "mis-compiled library";
-				break;
-			}
-			archive_set_error(&a->archive, err,
-			    "Internal error initializing decompressor: %s",
-			    detail != NULL ? detail : "??");
-			zip->bzstream_valid = 0;
-			return (ARCHIVE_FAILED);
-		}
-		zip->bzstream_valid = 1;
-		zip->bzstream.total_in_lo32 = 0;
-		zip->bzstream.total_in_hi32 = 0;
-		zip->bzstream.total_out_lo32 = 0;
-		zip->bzstream.total_out_hi32 = 0;
-		break;
-#else
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "BZ2 codec is unsupported");
-		return (ARCHIVE_FAILED);
-#endif
-	case _7Z_ZSTD:
-	{
-#if defined(HAVE_ZSTD_H)
-		if (zip->zstdstream_valid) {
-			ZSTD_freeDStream(zip->zstd_dstream);
-			zip->zstdstream_valid = 0;
-		}
-		zip->zstd_dstream = ZSTD_createDStream();
-		zip->zstdstream_valid = 1;
-		break;
-#else
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"ZSTD codec is unsupported");
-		return (ARCHIVE_FAILED);
-#endif
-	}
-	case _7Z_DEFLATE:
-#ifdef HAVE_ZLIB_H
-		if (zip->stream_valid)
-			r = inflateReset(&(zip->stream));
-		else
-			r = inflateInit2(&(zip->stream),
-			    -15 /* Don't check for zlib header */);
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Couldn't initialize zlib stream.");
-			return (ARCHIVE_FAILED);
-		}
-		zip->stream_valid = 1;
-		zip->stream.total_in = 0;
-		zip->stream.total_out = 0;
-		break;
-#else
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "DEFLATE codec is unsupported");
-		return (ARCHIVE_FAILED);
-#endif
-	case _7Z_PPMD:
-	{
-		unsigned order;
-		uint32_t msize;
-
-		if (zip->ppmd7_valid) {
-			__archive_ppmd7_functions.Ppmd7_Free(
-			    &zip->ppmd7_context);
-			zip->ppmd7_valid = 0;
-		}
-
-		if (coder1->propertiesSize < 5) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Malformed PPMd parameter");
-			return (ARCHIVE_FAILED);
-		}
-		order = coder1->properties[0];
-		msize = archive_le32dec(&(coder1->properties[1]));
-		if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER ||
-		    msize < PPMD7_MIN_MEM_SIZE || msize > PPMD7_MAX_MEM_SIZE) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Malformed PPMd parameter");
-			return (ARCHIVE_FAILED);
-		}
-		__archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context);
-		r = __archive_ppmd7_functions.Ppmd7_Alloc(
-			&zip->ppmd7_context, msize);
-		if (r == 0) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Coludn't allocate memory for PPMd");
-			return (ARCHIVE_FATAL);
-		}
-		__archive_ppmd7_functions.Ppmd7_Init(
-			&zip->ppmd7_context, order);
-		__archive_ppmd7_functions.Ppmd7z_RangeDec_CreateVTable(
-			&zip->range_dec);
-		zip->ppmd7_valid = 1;
-		zip->ppmd7_stat = 0;
-		zip->ppstream.overconsumed = 0;
-		zip->ppstream.total_in = 0;
-		zip->ppstream.total_out = 0;
-		break;
-	}
-	case _7Z_X86:
-	case _7Z_X86_BCJ2:
-	case _7Z_POWERPC:
-	case _7Z_IA64:
-	case _7Z_ARM:
-	case _7Z_ARMTHUMB:
-	case _7Z_SPARC:
-	case _7Z_DELTA:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Unexpected codec ID: %lX", zip->codec);
-		return (ARCHIVE_FAILED);
-	case _7Z_CRYPTO_MAIN_ZIP:
-	case _7Z_CRYPTO_RAR_29:
-	case _7Z_CRYPTO_AES_256_SHA_256:
-		if (a->entry) {
-			archive_entry_set_is_metadata_encrypted(a->entry, 1);
-			archive_entry_set_is_data_encrypted(a->entry, 1);
-			zip->has_encrypted_entries = 1;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Crypto codec not supported yet (ID: 0x%lX)", zip->codec);
-		return (ARCHIVE_FAILED);
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Unknown codec ID: %lX", zip->codec);
-		return (ARCHIVE_FAILED);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-decompress(struct archive_read *a, struct _7zip *zip,
-    void *buff, size_t *outbytes, const void *b, size_t *used)
-{
-	const uint8_t *t_next_in;
-	uint8_t *t_next_out;
-	size_t o_avail_in, o_avail_out;
-	size_t t_avail_in, t_avail_out;
-	uint8_t *bcj2_next_out;
-	size_t bcj2_avail_out;
-	int r, ret = ARCHIVE_OK;
-
-	t_avail_in = o_avail_in = *used;
-	t_avail_out = o_avail_out = *outbytes;
-	t_next_in = b;
-	t_next_out = buff;
-
-	if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) {
-		int i;
-
-		/* Do not copy out the BCJ remaining bytes when the output
-		 * buffer size is less than five bytes. */
-		if (o_avail_in != 0 && t_avail_out < 5 && zip->odd_bcj_size) {
-			*used = 0;
-			*outbytes = 0;
-			return (ret);
-		}
-		for (i = 0; zip->odd_bcj_size > 0 && t_avail_out; i++) {
-			*t_next_out++ = zip->odd_bcj[i];
-			t_avail_out--;
-			zip->odd_bcj_size--;
-		}
-		if (o_avail_in == 0 || t_avail_out == 0) {
-			*used = o_avail_in - t_avail_in;
-			*outbytes = o_avail_out - t_avail_out;
-			if (o_avail_in == 0)
-				ret = ARCHIVE_EOF;
-			return (ret);
-		}
-	}
-
-	bcj2_next_out = t_next_out;
-	bcj2_avail_out = t_avail_out;
-	if (zip->codec2 == _7Z_X86_BCJ2) {
-		/*
-		 * Decord a remaining decompressed main stream for BCJ2.
-		 */
-		if (zip->tmp_stream_bytes_remaining) {
-			ssize_t bytes;
-			size_t remaining = zip->tmp_stream_bytes_remaining;
-			bytes = Bcj2_Decode(zip, t_next_out, t_avail_out);
-			if (bytes < 0) {
-				archive_set_error(&(a->archive),
-				    ARCHIVE_ERRNO_MISC,
-				    "BCJ2 conversion Failed");
-				return (ARCHIVE_FAILED);
-			}
-			zip->main_stream_bytes_remaining -=
-			    remaining - zip->tmp_stream_bytes_remaining;
-			t_avail_out -= bytes;
-			if (o_avail_in == 0 || t_avail_out == 0) {
-				*used = 0;
-				*outbytes = o_avail_out - t_avail_out;
-				if (o_avail_in == 0 &&
-				    zip->tmp_stream_bytes_remaining)
-					ret = ARCHIVE_EOF;
-				return (ret);
-			}
-			t_next_out += bytes;
-			bcj2_next_out = t_next_out;
-			bcj2_avail_out = t_avail_out;
-		}
-		t_next_out = zip->tmp_stream_buff;
-		t_avail_out = zip->tmp_stream_buff_size;
-	}
-
-	switch (zip->codec) {
-	case _7Z_COPY:
-	{
-		size_t bytes =
-		    (t_avail_in > t_avail_out)?t_avail_out:t_avail_in;
-
-		memcpy(t_next_out, t_next_in, bytes);
-		t_avail_in -= bytes;
-		t_avail_out -= bytes;
-		if (o_avail_in == 0)
-			ret = ARCHIVE_EOF;
-		break;
-	}
-#ifdef HAVE_LZMA_H
-	case _7Z_LZMA: case _7Z_LZMA2:
-		zip->lzstream.next_in = t_next_in;
-		zip->lzstream.avail_in = t_avail_in;
-		zip->lzstream.next_out = t_next_out;
-		zip->lzstream.avail_out = t_avail_out;
-
-		r = lzma_code(&(zip->lzstream), LZMA_RUN);
-		switch (r) {
-		case LZMA_STREAM_END: /* Found end of stream. */
-			lzma_end(&(zip->lzstream));
-			zip->lzstream_valid = 0;
-			ret = ARCHIVE_EOF;
-			break;
-		case LZMA_OK: /* Decompressor made some progress. */
-			break;
-		default:
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-				"Decompression failed(%d)",
-			    r);
-			return (ARCHIVE_FAILED);
-		}
-		t_avail_in = zip->lzstream.avail_in;
-		t_avail_out = zip->lzstream.avail_out;
-		break;
-#endif
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	case _7Z_BZ2:
-		zip->bzstream.next_in = (char *)(uintptr_t)t_next_in;
-		zip->bzstream.avail_in = (uint32_t)t_avail_in;
-		zip->bzstream.next_out = (char *)(uintptr_t)t_next_out;
-		zip->bzstream.avail_out = (uint32_t)t_avail_out;
-		r = BZ2_bzDecompress(&(zip->bzstream));
-		switch (r) {
-		case BZ_STREAM_END: /* Found end of stream. */
-			switch (BZ2_bzDecompressEnd(&(zip->bzstream))) {
-			case BZ_OK:
-				break;
-			default:
-				archive_set_error(&(a->archive),
-				    ARCHIVE_ERRNO_MISC,
-				    "Failed to clean up decompressor");
-				return (ARCHIVE_FAILED);
-			}
-			zip->bzstream_valid = 0;
-			ret = ARCHIVE_EOF;
-			break;
-		case BZ_OK: /* Decompressor made some progress. */
-			break;
-		default:
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "bzip decompression failed");
-			return (ARCHIVE_FAILED);
-		}
-		t_avail_in = zip->bzstream.avail_in;
-		t_avail_out = zip->bzstream.avail_out;
-		break;
-#endif
-#ifdef HAVE_ZLIB_H
-	case _7Z_DEFLATE:
-		zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in;
-		zip->stream.avail_in = (uInt)t_avail_in;
-		zip->stream.next_out = t_next_out;
-		zip->stream.avail_out = (uInt)t_avail_out;
-		r = inflate(&(zip->stream), 0);
-		switch (r) {
-		case Z_STREAM_END: /* Found end of stream. */
-			ret = ARCHIVE_EOF;
-			break;
-		case Z_OK: /* Decompressor made some progress.*/
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "File decompression failed (%d)", r);
-			return (ARCHIVE_FAILED);
-		}
-		t_avail_in = zip->stream.avail_in;
-		t_avail_out = zip->stream.avail_out;
-		break;
-#endif
-#ifdef HAVE_ZSTD_H
-	case _7Z_ZSTD:
-	{
-		ZSTD_inBuffer input = { t_next_in, t_avail_in, 0 }; // src, size, pos
-		ZSTD_outBuffer output = { t_next_out, t_avail_out, 0 }; // dst, size, pos
-
-		size_t const zret = ZSTD_decompressStream(zip->zstd_dstream, &output, &input);
-		if (ZSTD_isError(zret)) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Zstd decompression failed: %s", ZSTD_getErrorName(zret));
-			return ARCHIVE_FAILED;
-		}
-		t_avail_in -= input.pos;
-		t_avail_out -= output.pos;
-		break;
-	}
-#endif
-	case _7Z_PPMD:
-	{
-		uint64_t flush_bytes;
-
-		if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 ||
-		    t_avail_out <= 0) {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Decompression internal error");
-			return (ARCHIVE_FAILED);
-		}
-		zip->ppstream.next_in = t_next_in;
-		zip->ppstream.avail_in = t_avail_in;
-		zip->ppstream.stream_in = 0;
-		zip->ppstream.next_out = t_next_out;
-		zip->ppstream.avail_out = t_avail_out;
-		if (zip->ppmd7_stat == 0) {
-			zip->bytein.a = a;
-			zip->bytein.Read = &ppmd_read;
-			zip->range_dec.Stream = &zip->bytein;
-			r = __archive_ppmd7_functions.Ppmd7z_RangeDec_Init(
-				&(zip->range_dec));
-			if (r == 0) {
-				zip->ppmd7_stat = -1;
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Failed to initialize PPMd range decoder");
-				return (ARCHIVE_FAILED);
-			}
-			if (zip->ppstream.overconsumed) {
-				zip->ppmd7_stat = -1;
-				return (ARCHIVE_FAILED);
-			}
-			zip->ppmd7_stat = 1;
-		}
-
-		if (t_avail_in == 0)
-			/* XXX Flush out remaining decoded data XXX */
-			flush_bytes = zip->folder_outbytes_remaining;
-		else
-			flush_bytes = 0;
-
-		do {
-			int sym;
-
-			sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-				&(zip->ppmd7_context), &(zip->range_dec.p));
-			if (sym < 0) {
-				zip->ppmd7_stat = -1;
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Failed to decode PPMd");
-				return (ARCHIVE_FAILED);
-			}
-			if (zip->ppstream.overconsumed) {
-				zip->ppmd7_stat = -1;
-				return (ARCHIVE_FAILED);
-			}
-			*zip->ppstream.next_out++ = (unsigned char)sym;
-			zip->ppstream.avail_out--;
-			zip->ppstream.total_out++;
-			if (flush_bytes)
-				flush_bytes--;
-		} while (zip->ppstream.avail_out &&
-			(zip->ppstream.avail_in || flush_bytes));
-
-		t_avail_in = (size_t)zip->ppstream.avail_in;
-		t_avail_out = (size_t)zip->ppstream.avail_out;
-		break;
-	}
-	default:
-		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-		    "Decompression internal error");
-		return (ARCHIVE_FAILED);
-	}
-	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF)
-		return (ret);
-
-	*used = o_avail_in - t_avail_in;
-	*outbytes = o_avail_out - t_avail_out;
-
-	/*
-	 * Decord BCJ.
-	 */
-	if (zip->codec != _7Z_LZMA2) {
-		if (zip->codec2 == _7Z_X86) {
-			size_t l = x86_Convert(zip, buff, *outbytes);
-
-			zip->odd_bcj_size = *outbytes - l;
-			if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
-		    	o_avail_in && ret != ARCHIVE_EOF) {
-				memcpy(zip->odd_bcj, ((unsigned char *)buff) + l,
-			    	zip->odd_bcj_size);
-				*outbytes = l;
-			} else
-				zip->odd_bcj_size = 0;
-		} else if (zip->codec2 == _7Z_ARM) {
-			*outbytes = arm_Convert(zip, buff, *outbytes);
-		} else if (zip->codec2 == _7Z_ARM64) {
-			*outbytes = arm64_Convert(zip, buff, *outbytes);
-		}
-	}
-
-	/*
-	 * Decord BCJ2 with a decompressed main stream.
-	 */
-	if (zip->codec2 == _7Z_X86_BCJ2) {
-		ssize_t bytes;
-
-		zip->tmp_stream_bytes_avail =
-		    zip->tmp_stream_buff_size - t_avail_out;
-		if (zip->tmp_stream_bytes_avail >
-		      zip->main_stream_bytes_remaining)
-			zip->tmp_stream_bytes_avail =
-			    zip->main_stream_bytes_remaining;
-		zip->tmp_stream_bytes_remaining = zip->tmp_stream_bytes_avail;
-		bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out);
-		if (bytes < 0) {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC, "BCJ2 conversion Failed");
-			return (ARCHIVE_FAILED);
-		}
-		zip->main_stream_bytes_remaining -=
-		    zip->tmp_stream_bytes_avail
-		      - zip->tmp_stream_bytes_remaining;
-		bcj2_avail_out -= bytes;
-		*outbytes = o_avail_out - bcj2_avail_out;
-	}
-
-	return (ret);
-}
-
-static int
-free_decompression(struct archive_read *a, struct _7zip *zip)
-{
-	int r = ARCHIVE_OK;
-
-#if !defined(HAVE_ZLIB_H) &&\
-	!(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR))
-	(void)a;/* UNUSED */
-#endif
-#ifdef HAVE_LZMA_H
-	if (zip->lzstream_valid)
-		lzma_end(&(zip->lzstream));
-#endif
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	if (zip->bzstream_valid) {
-		if (BZ2_bzDecompressEnd(&(zip->bzstream)) != BZ_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up bzip2 decompressor");
-			r = ARCHIVE_FATAL;
-		}
-		zip->bzstream_valid = 0;
-	}
-#endif
-#ifdef HAVE_ZLIB_H
-	if (zip->stream_valid) {
-		if (inflateEnd(&(zip->stream)) != Z_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up zlib decompressor");
-			r = ARCHIVE_FATAL;
-		}
-		zip->stream_valid = 0;
-	}
-#endif
-	if (zip->ppmd7_valid) {
-		__archive_ppmd7_functions.Ppmd7_Free(
-			&zip->ppmd7_context);
-		zip->ppmd7_valid = 0;
-	}
-	return (r);
-}
-
-static int
-parse_7zip_uint64(struct archive_read *a, uint64_t *val)
-{
-	const unsigned char *p;
-	unsigned char avail, mask;
-	int i;
-
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	avail = *p;
-	mask = 0x80;
-	*val = 0;
-	for (i = 0; i < 8; i++) {
-		if (avail & mask) {
-			if ((p = header_bytes(a, 1)) == NULL)
-				return (-1);
-			*val |= ((uint64_t)*p) << (8 * i);
-			mask >>= 1;
-			continue;
-		}
-		*val += ((uint64_t)(avail & (mask -1))) << (8 * i);
-		break;
-	}
-	return (0);
-}
-
-static int
-read_Bools(struct archive_read *a, unsigned char *data, size_t num)
-{
-	const unsigned char *p;
-	unsigned i, mask = 0, avail = 0;
-
-	for (i = 0; i < num; i++) {
-		if (mask == 0) {
-			if ((p = header_bytes(a, 1)) == NULL)
-				return (-1);
-			avail = *p;
-			mask = 0x80;
-		}
-		data[i] = (avail & mask)?1:0;
-		mask >>= 1;
-	}
-	return (0);
-}
-
-static void
-free_Digest(struct _7z_digests *d)
-{
-	free(d->defineds);
-	free(d->digests);
-}
-
-static int
-read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num)
-{
-	const unsigned char *p;
-	unsigned i;
-
-	if (num == 0)
-		return (-1);
-	memset(d, 0, sizeof(*d));
-
-	d->defineds = malloc(num);
-	if (d->defineds == NULL)
-		return (-1);
-	/*
-	 * Read Bools.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p == 0) {
-		if (read_Bools(a, d->defineds, num) < 0)
-			return (-1);
-	} else
-		/* All are defined */
-		memset(d->defineds, 1, num);
-
-	d->digests = calloc(num, sizeof(*d->digests));
-	if (d->digests == NULL)
-		return (-1);
-	for (i = 0; i < num; i++) {
-		if (d->defineds[i]) {
-			if ((p = header_bytes(a, 4)) == NULL)
-				return (-1);
-			d->digests[i] = archive_le32dec(p);
-		}
-	}
-
-	return (0);
-}
-
-static void
-free_PackInfo(struct _7z_pack_info *pi)
-{
-	free(pi->sizes);
-	free(pi->positions);
-	free_Digest(&(pi->digest));
-}
-
-static int
-read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
-{
-	const unsigned char *p;
-	unsigned i;
-
-	memset(pi, 0, sizeof(*pi));
-
-	/*
-	 * Read PackPos.
-	 */
-	if (parse_7zip_uint64(a, &(pi->pos)) < 0)
-		return (-1);
-
-	/*
-	 * Read NumPackStreams.
-	 */
-	if (parse_7zip_uint64(a, &(pi->numPackStreams)) < 0)
-		return (-1);
-	if (pi->numPackStreams == 0)
-		return (-1);
-	if (UMAX_ENTRY < pi->numPackStreams)
-		return (-1);
-
-	/*
-	 * Read PackSizes[num]
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p == kEnd)
-		/* PackSizes[num] are not present. */
-		return (0);
-	if (*p != kSize)
-		return (-1);
-	pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
-	pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
-	if (pi->sizes == NULL || pi->positions == NULL)
-		return (-1);
-
-	for (i = 0; i < pi->numPackStreams; i++) {
-		if (parse_7zip_uint64(a, &(pi->sizes[i])) < 0)
-			return (-1);
-	}
-
-	/*
-	 * Read PackStreamDigests[num]
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p == kEnd) {
-		/* PackStreamDigests[num] are not present. */
-		pi->digest.defineds =
-		    calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds));
-		pi->digest.digests =
-		    calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests));
-		if (pi->digest.defineds == NULL || pi->digest.digests == NULL)
-			return (-1);
-		return (0);
-	}
-
-	if (*p != kCRC)
-		return (-1);
-
-	if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0)
-		return (-1);
-
-	/*
-	 *  Must be marked by kEnd.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p != kEnd)
-		return (-1);
-	return (0);
-}
-
-static void
-free_Folder(struct _7z_folder *f)
-{
-	unsigned i;
-
-	if (f->coders) {
-		for (i = 0; i< f->numCoders; i++) {
-			free(f->coders[i].properties);
-		}
-		free(f->coders);
-	}
-	free(f->bindPairs);
-	free(f->packedStreams);
-	free(f->unPackSize);
-}
-
-static int
-read_Folder(struct archive_read *a, struct _7z_folder *f)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const unsigned char *p;
-	uint64_t numInStreamsTotal = 0;
-	uint64_t numOutStreamsTotal = 0;
-	unsigned i;
-
-	memset(f, 0, sizeof(*f));
-
-	/*
-	 * Read NumCoders.
-	 */
-	if (parse_7zip_uint64(a, &(f->numCoders)) < 0)
-		return (-1);
-	if (f->numCoders > 4)
-		/* Too many coders. */
-		return (-1);
-
-	f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders));
-	if (f->coders == NULL)
-		return (-1);
-	for (i = 0; i< f->numCoders; i++) {
-		size_t codec_size;
-		int simple, attr;
-
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		/*
-		 * 0:3 CodecIdSize
-		 * 4:  0 - IsSimple
-		 *     1 - Is not Simple
-		 * 5:  0 - No Attributes
-		 *     1 - There are Attributes;
-		 * 7:  Must be zero.
-		 */
-		codec_size = *p & 0xf;
-		simple = (*p & 0x10)?0:1;
-		attr = *p & 0x20;
-		if (*p & 0x80)
-			return (-1);/* Not supported. */
-
-		/*
-		 * Read Decompression Method IDs.
-		 */
-		if ((p = header_bytes(a, codec_size)) == NULL)
-			return (-1);
-
-		f->coders[i].codec = decode_codec_id(p, codec_size);
-
-		if (simple) {
-			f->coders[i].numInStreams = 1;
-			f->coders[i].numOutStreams = 1;
-		} else {
-			if (parse_7zip_uint64(
-			    a, &(f->coders[i].numInStreams)) < 0)
-				return (-1);
-			if (UMAX_ENTRY < f->coders[i].numInStreams)
-				return (-1);
-			if (parse_7zip_uint64(
-			    a, &(f->coders[i].numOutStreams)) < 0)
-				return (-1);
-			if (UMAX_ENTRY < f->coders[i].numOutStreams)
-				return (-1);
-		}
-
-		if (attr) {
-			if (parse_7zip_uint64(
-			    a, &(f->coders[i].propertiesSize)) < 0)
-				return (-1);
-			if ((p = header_bytes(
-			    a, (size_t)f->coders[i].propertiesSize)) == NULL)
-				return (-1);
-			f->coders[i].properties =
-			    malloc((size_t)f->coders[i].propertiesSize);
-			if (f->coders[i].properties == NULL)
-				return (-1);
-			memcpy(f->coders[i].properties, p,
-			    (size_t)f->coders[i].propertiesSize);
-		}
-
-		numInStreamsTotal += f->coders[i].numInStreams;
-		numOutStreamsTotal += f->coders[i].numOutStreams;
-	}
-
-	if (numOutStreamsTotal == 0 ||
-	    numInStreamsTotal < numOutStreamsTotal-1)
-		return (-1);
-
-	f->numBindPairs = numOutStreamsTotal - 1;
-	if (zip->header_bytes_remaining < f->numBindPairs)
-			return (-1);
-	if (f->numBindPairs > 0) {
-		f->bindPairs =
-			calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs));
-		if (f->bindPairs == NULL)
-			return (-1);
-	} else
-		f->bindPairs = NULL;
-	for (i = 0; i < f->numBindPairs; i++) {
-		if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0)
-			return (-1);
-		if (UMAX_ENTRY < f->bindPairs[i].inIndex)
-			return (-1);
-		if (parse_7zip_uint64(a, &(f->bindPairs[i].outIndex)) < 0)
-			return (-1);
-		if (UMAX_ENTRY < f->bindPairs[i].outIndex)
-			return (-1);
-	}
-
-	f->numPackedStreams = numInStreamsTotal - f->numBindPairs;
-	f->packedStreams =
-	    calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams));
-	if (f->packedStreams == NULL)
-		return (-1);
-	if (f->numPackedStreams == 1) {
-		for (i = 0; i < numInStreamsTotal; i++) {
-			unsigned j;
-			for (j = 0; j < f->numBindPairs; j++) {
-				if (f->bindPairs[j].inIndex == i)
-					break;
-			}
-			if (j == f->numBindPairs)
-				break;
-		}
-		if (i == numInStreamsTotal)
-			return (-1);
-		f->packedStreams[0] = i;
-	} else {
-		for (i = 0; i < f->numPackedStreams; i++) {
-			if (parse_7zip_uint64(a, &(f->packedStreams[i])) < 0)
-				return (-1);
-			if (UMAX_ENTRY < f->packedStreams[i])
-				return (-1);
-		}
-	}
-	f->numInStreams = numInStreamsTotal;
-	f->numOutStreams = numOutStreamsTotal;
-
-	return (0);
-}
-
-static void
-free_CodersInfo(struct _7z_coders_info *ci)
-{
-	unsigned i;
-
-	if (ci->folders) {
-		for (i = 0; i < ci->numFolders; i++)
-			free_Folder(&(ci->folders[i]));
-		free(ci->folders);
-	}
-}
-
-static int
-read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
-{
-	const unsigned char *p;
-	struct _7z_digests digest;
-	unsigned i;
-
-	memset(ci, 0, sizeof(*ci));
-	memset(&digest, 0, sizeof(digest));
-
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	if (*p != kFolder)
-		goto failed;
-
-	/*
-	 * Read NumFolders.
-	 */
-	if (parse_7zip_uint64(a, &(ci->numFolders)) < 0)
-		goto failed;
-	if (UMAX_ENTRY < ci->numFolders)
-		return (-1);
-
-	/*
-	 * Read External.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	switch (*p) {
-	case 0:
-		ci->folders =
-			calloc((size_t)ci->numFolders, sizeof(*ci->folders));
-		if (ci->folders == NULL)
-			return (-1);
-		for (i = 0; i < ci->numFolders; i++) {
-			if (read_Folder(a, &(ci->folders[i])) < 0)
-				goto failed;
-		}
-		break;
-	case 1:
-		if (parse_7zip_uint64(a, &(ci->dataStreamIndex)) < 0)
-			return (-1);
-		if (UMAX_ENTRY < ci->dataStreamIndex)
-			return (-1);
-		if (ci->numFolders > 0) {
-			archive_set_error(&a->archive, -1,
-			    "Malformed 7-Zip archive");
-			goto failed;
-		}
-		break;
-	default:
-		archive_set_error(&a->archive, -1,
-		    "Malformed 7-Zip archive");
-		goto failed;
-	}
-
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	if (*p != kCodersUnPackSize)
-		goto failed;
-
-	for (i = 0; i < ci->numFolders; i++) {
-		struct _7z_folder *folder = &(ci->folders[i]);
-		unsigned j;
-
-		folder->unPackSize =
-		    calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize));
-		if (folder->unPackSize == NULL)
-			goto failed;
-		for (j = 0; j < folder->numOutStreams; j++) {
-			if (parse_7zip_uint64(a, &(folder->unPackSize[j])) < 0)
-				goto failed;
-		}
-	}
-
-	/*
-	 * Read CRCs.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	if (*p == kEnd)
-		return (0);
-	if (*p != kCRC)
-		goto failed;
-	if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0)
-		goto failed;
-	for (i = 0; i < ci->numFolders; i++) {
-		ci->folders[i].digest_defined = digest.defineds[i];
-		ci->folders[i].digest = digest.digests[i];
-	}
-
-	/*
-	 *  Must be kEnd.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	if (*p != kEnd)
-		goto failed;
-	free_Digest(&digest);
-	return (0);
-failed:
-	free_Digest(&digest);
-	return (-1);
-}
-
-static uint64_t
-folder_uncompressed_size(struct _7z_folder *f)
-{
-	int n = (int)f->numOutStreams;
-	unsigned pairs = (unsigned)f->numBindPairs;
-
-	while (--n >= 0) {
-		unsigned i;
-		for (i = 0; i < pairs; i++) {
-			if (f->bindPairs[i].outIndex == (uint64_t)n)
-				break;
-		}
-		if (i >= pairs)
-			return (f->unPackSize[n]);
-	}
-	return (0);
-}
-
-static void
-free_SubStreamsInfo(struct _7z_substream_info *ss)
-{
-	free(ss->unpackSizes);
-	free(ss->digestsDefined);
-	free(ss->digests);
-}
-
-static int
-read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss,
-    struct _7z_folder *f, size_t numFolders)
-{
-	const unsigned char *p;
-	uint64_t *usizes;
-	size_t unpack_streams;
-	int type;
-	unsigned i;
-	uint32_t numDigests;
-
-	memset(ss, 0, sizeof(*ss));
-
-	for (i = 0; i < numFolders; i++)
-		f[i].numUnpackStreams = 1;
-
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	type = *p;
-
-	if (type == kNumUnPackStream) {
-		unpack_streams = 0;
-		for (i = 0; i < numFolders; i++) {
-			if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0)
-				return (-1);
-			if (UMAX_ENTRY < f[i].numUnpackStreams)
-				return (-1);
-			if (unpack_streams > SIZE_MAX - UMAX_ENTRY) {
-				return (-1);
-			}
-			unpack_streams += (size_t)f[i].numUnpackStreams;
-		}
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		type = *p;
-	} else
-		unpack_streams = numFolders;
-
-	ss->unpack_streams = unpack_streams;
-	if (unpack_streams) {
-		ss->unpackSizes = calloc(unpack_streams,
-		    sizeof(*ss->unpackSizes));
-		ss->digestsDefined = calloc(unpack_streams,
-		    sizeof(*ss->digestsDefined));
-		ss->digests = calloc(unpack_streams,
-		    sizeof(*ss->digests));
-		if (ss->unpackSizes == NULL || ss->digestsDefined == NULL ||
-		    ss->digests == NULL)
-			return (-1);
-	}
-
-	usizes = ss->unpackSizes;
-	for (i = 0; i < numFolders; i++) {
-		unsigned pack;
-		uint64_t sum;
-
-		if (f[i].numUnpackStreams == 0)
-			continue;
-
-		sum = 0;
-		if (type == kSize) {
-			for (pack = 1; pack < f[i].numUnpackStreams; pack++) {
-				if (parse_7zip_uint64(a, usizes) < 0)
-					return (-1);
-				sum += *usizes++;
-			}
-		}
-		*usizes++ = folder_uncompressed_size(&f[i]) - sum;
-	}
-
-	if (type == kSize) {
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		type = *p;
-	}
-
-	for (i = 0; i < unpack_streams; i++) {
-		ss->digestsDefined[i] = 0;
-		ss->digests[i] = 0;
-	}
-
-	numDigests = 0;
-	for (i = 0; i < numFolders; i++) {
-		if (f[i].numUnpackStreams != 1 || !f[i].digest_defined)
-			numDigests += (uint32_t)f[i].numUnpackStreams;
-	}
-
-	if (type == kCRC) {
-		struct _7z_digests tmpDigests;
-		unsigned char *digestsDefined = ss->digestsDefined;
-		uint32_t * digests = ss->digests;
-		int di = 0;
-
-		memset(&tmpDigests, 0, sizeof(tmpDigests));
-		if (read_Digests(a, &(tmpDigests), numDigests) < 0) {
-			free_Digest(&tmpDigests);
-			return (-1);
-		}
-		for (i = 0; i < numFolders; i++) {
-			if (f[i].numUnpackStreams == 1 && f[i].digest_defined) {
-				*digestsDefined++ = 1;
-				*digests++ = f[i].digest;
-			} else {
-				unsigned j;
-
-				for (j = 0; j < f[i].numUnpackStreams;
-				    j++, di++) {
-					*digestsDefined++ =
-					    tmpDigests.defineds[di];
-					*digests++ =
-					    tmpDigests.digests[di];
-				}
-			}
-		}
-		free_Digest(&tmpDigests);
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		type = *p;
-	}
-
-	/*
-	 *  Must be kEnd.
-	 */
-	if (type != kEnd)
-		return (-1);
-	return (0);
-}
-
-static void
-free_StreamsInfo(struct _7z_stream_info *si)
-{
-	free_PackInfo(&(si->pi));
-	free_CodersInfo(&(si->ci));
-	free_SubStreamsInfo(&(si->ss));
-}
-
-static int
-read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const unsigned char *p;
-	unsigned i;
-
-	memset(si, 0, sizeof(*si));
-
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p == kPackInfo) {
-		uint64_t packPos;
-
-		if (read_PackInfo(a, &(si->pi)) < 0)
-			return (-1);
-
-		if (si->pi.positions == NULL || si->pi.sizes == NULL)
-			return (-1);
-		/*
-		 * Calculate packed stream positions.
-		 */
-		packPos = si->pi.pos;
-		for (i = 0; i < si->pi.numPackStreams; i++) {
-			si->pi.positions[i] = packPos;
-			packPos += si->pi.sizes[i];
-			if (packPos > zip->header_offset)
-				return (-1);
-		}
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-	}
-	if (*p == kUnPackInfo) {
-		uint32_t packIndex;
-		struct _7z_folder *f;
-
-		if (read_CodersInfo(a, &(si->ci)) < 0)
-			return (-1);
-
-		/*
-		 * Calculate packed stream indexes.
-		 */
-		packIndex = 0;
-		f = si->ci.folders;
-		for (i = 0; i < si->ci.numFolders; i++) {
-			f[i].packIndex = packIndex;
-			packIndex += (uint32_t)f[i].numPackedStreams;
-			if (packIndex > si->pi.numPackStreams)
-				return (-1);
-		}
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-	}
-
-	if (*p == kSubStreamsInfo) {
-		if (read_SubStreamsInfo(a, &(si->ss),
-		    si->ci.folders, (size_t)si->ci.numFolders) < 0)
-			return (-1);
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-	}
-
-	/*
-	 *  Must be kEnd.
-	 */
-	if (*p != kEnd)
-		return (-1);
-	return (0);
-}
-
-static void
-free_Header(struct _7z_header_info *h)
-{
-	free(h->emptyStreamBools);
-	free(h->emptyFileBools);
-	free(h->antiBools);
-	free(h->attrBools);
-}
-
-static int
-read_Header(struct archive_read *a, struct _7z_header_info *h,
-    int check_header_id)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const unsigned char *p;
-	struct _7z_folder *folders;
-	struct _7z_stream_info *si = &(zip->si);
-	struct _7zip_entry *entries;
-	uint32_t folderIndex, indexInFolder;
-	unsigned i;
-	int eindex, empty_streams, sindex;
-
-	if (check_header_id) {
-		/*
-		 * Read Header.
-		 */
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		if (*p != kHeader)
-			return (-1);
-	}
-
-	/*
-	 * Read ArchiveProperties.
-	 */
-	if ((p = header_bytes(a, 1)) == NULL)
-		return (-1);
-	if (*p == kArchiveProperties) {
-		for (;;) {
-			uint64_t size;
-			if ((p = header_bytes(a, 1)) == NULL)
-				return (-1);
-			if (*p == 0)
-				break;
-			if (parse_7zip_uint64(a, &size) < 0)
-				return (-1);
-		}
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-	}
-
-	/*
-	 * Read MainStreamsInfo.
-	 */
-	if (*p == kMainStreamsInfo) {
-		if (read_StreamsInfo(a, &(zip->si)) < 0)
-			return (-1);
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-	}
-	if (*p == kEnd)
-		return (0);
-
-	/*
-	 * Read FilesInfo.
-	 */
-	if (*p != kFilesInfo)
-		return (-1);
-
-	if (parse_7zip_uint64(a, &(zip->numFiles)) < 0)
-		return (-1);
-	if (UMAX_ENTRY < zip->numFiles)
-		return (-1);
-
-	zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries));
-	if (zip->entries == NULL)
-		return (-1);
-	entries = zip->entries;
-
-	empty_streams = 0;
-	for (;;) {
-		int type;
-		uint64_t size;
-		size_t ll;
-
-		if ((p = header_bytes(a, 1)) == NULL)
-			return (-1);
-		type = *p;
-		if (type == kEnd)
-			break;
-
-		if (parse_7zip_uint64(a, &size) < 0)
-			return (-1);
-		if (zip->header_bytes_remaining < size)
-			return (-1);
-		ll = (size_t)size;
-
-		switch (type) {
-		case kEmptyStream:
-			if (h->emptyStreamBools != NULL)
-				return (-1);
-			h->emptyStreamBools = calloc((size_t)zip->numFiles,
-			    sizeof(*h->emptyStreamBools));
-			if (h->emptyStreamBools == NULL)
-				return (-1);
-			if (read_Bools(
-			    a, h->emptyStreamBools, (size_t)zip->numFiles) < 0)
-				return (-1);
-			empty_streams = 0;
-			for (i = 0; i < zip->numFiles; i++) {
-				if (h->emptyStreamBools[i])
-					empty_streams++;
-			}
-			break;
-		case kEmptyFile:
-			if (empty_streams <= 0) {
-				/* Unexcepted sequence. Skip this. */
-				if (header_bytes(a, ll) == NULL)
-					return (-1);
-				break;
-			}
-			if (h->emptyFileBools != NULL)
-				return (-1);
-			h->emptyFileBools = calloc(empty_streams,
-			    sizeof(*h->emptyFileBools));
-			if (h->emptyFileBools == NULL)
-				return (-1);
-			if (read_Bools(a, h->emptyFileBools, empty_streams) < 0)
-				return (-1);
-			break;
-		case kAnti:
-			if (empty_streams <= 0) {
-				/* Unexcepted sequence. Skip this. */
-				if (header_bytes(a, ll) == NULL)
-					return (-1);
-				break;
-			}
-			if (h->antiBools != NULL)
-				return (-1);
-			h->antiBools = calloc(empty_streams,
-			    sizeof(*h->antiBools));
-			if (h->antiBools == NULL)
-				return (-1);
-			if (read_Bools(a, h->antiBools, empty_streams) < 0)
-				return (-1);
-			break;
-		case kCTime:
-		case kATime:
-		case kMTime:
-			if (read_Times(a, h, type) < 0)
-				return (-1);
-			break;
-		case kName:
-		{
-			unsigned char *np;
-			size_t nl, nb;
-
-			/* Skip one byte. */
-			if ((p = header_bytes(a, 1)) == NULL)
-				return (-1);
-			ll--;
-
-			if ((ll & 1) || ll < zip->numFiles * 4)
-				return (-1);
-
-			if (zip->entry_names != NULL)
-				return (-1);
-			zip->entry_names = malloc(ll);
-			if (zip->entry_names == NULL)
-				return (-1);
-			np = zip->entry_names;
-			nb = ll;
-			/*
-			 * Copy whole file names.
-			 * NOTE: This loop prevents from expanding
-			 * the uncompressed buffer in order not to
-			 * use extra memory resource.
-			 */
-			while (nb) {
-				size_t b;
-				if (nb > UBUFF_SIZE)
-					b = UBUFF_SIZE;
-				else
-					b = nb;
-				if ((p = header_bytes(a, b)) == NULL)
-					return (-1);
-				memcpy(np, p, b);
-				np += b;
-				nb -= b;
-			}
-			np = zip->entry_names;
-			nl = ll;
-
-			for (i = 0; i < zip->numFiles; i++) {
-				entries[i].utf16name = np;
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
-				entries[i].wname = (wchar_t *)np;
-#endif
-
-				/* Find a terminator. */
-				while (nl >= 2 && (np[0] || np[1])) {
-					np += 2;
-					nl -= 2;
-				}
-				if (nl < 2)
-					return (-1);/* Terminator not found */
-				entries[i].name_len = np - entries[i].utf16name;
-				np += 2;
-				nl -= 2;
-			}
-			break;
-		}
-		case kAttributes:
-		{
-			int allAreDefined;
-
-			if ((p = header_bytes(a, 2)) == NULL)
-				return (-1);
-			allAreDefined = *p;
-			if (h->attrBools != NULL)
-				return (-1);
-			h->attrBools = calloc((size_t)zip->numFiles,
-			    sizeof(*h->attrBools));
-			if (h->attrBools == NULL)
-				return (-1);
-			if (allAreDefined)
-				memset(h->attrBools, 1, (size_t)zip->numFiles);
-			else {
-				if (read_Bools(a, h->attrBools,
-				      (size_t)zip->numFiles) < 0)
-					return (-1);
-			}
-			for (i = 0; i < zip->numFiles; i++) {
-				if (h->attrBools[i]) {
-					if ((p = header_bytes(a, 4)) == NULL)
-						return (-1);
-					entries[i].attr = archive_le32dec(p);
-				}
-			}
-			break;
-		}
-		case kDummy:
-			if (ll == 0)
-				break;
-			__LA_FALLTHROUGH;
-		default:
-			if (header_bytes(a, ll) == NULL)
-				return (-1);
-			break;
-		}
-	}
-
-	/*
-	 * Set up entry's attributes.
-	 */
-	folders = si->ci.folders;
-	eindex = sindex = 0;
-	folderIndex = indexInFolder = 0;
-	for (i = 0; i < zip->numFiles; i++) {
-		if (h->emptyStreamBools == NULL || h->emptyStreamBools[i] == 0)
-			entries[i].flg |= HAS_STREAM;
-		/* The high 16 bits of attributes is a posix file mode. */
-		entries[i].mode = entries[i].attr >> 16;
-		if (entries[i].flg & HAS_STREAM) {
-			if ((size_t)sindex >= si->ss.unpack_streams)
-				return (-1);
-			if (entries[i].mode == 0)
-				entries[i].mode = AE_IFREG | 0666;
-			if (si->ss.digestsDefined[sindex])
-				entries[i].flg |= CRC32_IS_SET;
-			entries[i].ssIndex = sindex;
-			sindex++;
-		} else {
-			int dir;
-			if (h->emptyFileBools == NULL)
-				dir = 1;
-			else {
-				if (h->emptyFileBools[eindex])
-					dir = 0;
-				else
-					dir = 1;
-				eindex++;
-			}
-			if (entries[i].mode == 0) {
-				if (dir)
-					entries[i].mode = AE_IFDIR | 0777;
-				else
-					entries[i].mode = AE_IFREG | 0666;
-			} else if (dir &&
-			    (entries[i].mode & AE_IFMT) != AE_IFDIR) {
-				entries[i].mode &= ~AE_IFMT;
-				entries[i].mode |= AE_IFDIR;
-			}
-			if ((entries[i].mode & AE_IFMT) == AE_IFDIR &&
-			    entries[i].name_len >= 2 &&
-			    (entries[i].utf16name[entries[i].name_len-2] != '/' ||
-			     entries[i].utf16name[entries[i].name_len-1] != 0)) {
-				entries[i].utf16name[entries[i].name_len] = '/';
-				entries[i].utf16name[entries[i].name_len+1] = 0;
-				entries[i].name_len += 2;
-			}
-			entries[i].ssIndex = -1;
-		}
-		if (entries[i].attr & 0x01)
-			entries[i].mode &= ~0222;/* Read only. */
-
-		if ((entries[i].flg & HAS_STREAM) == 0 && indexInFolder == 0) {
-			/*
-			 * The entry is an empty file or a directory file,
-			 * those both have no contents.
-			 */
-			entries[i].folderIndex = -1;
-			continue;
-		}
-		if (indexInFolder == 0) {
-			for (;;) {
-				if (folderIndex >= si->ci.numFolders)
-					return (-1);
-				if (folders[folderIndex].numUnpackStreams)
-					break;
-				folderIndex++;
-			}
-		}
-		entries[i].folderIndex = folderIndex;
-		if ((entries[i].flg & HAS_STREAM) == 0)
-			continue;
-		indexInFolder++;
-		if (indexInFolder >= folders[folderIndex].numUnpackStreams) {
-			folderIndex++;
-			indexInFolder = 0;
-		}
-	}
-
-	return (0);
-}
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
-{
-
-	if (fileTime >= EPOC_TIME) {
-		fileTime -= EPOC_TIME;
-		/* milli seconds base */
-		*timep = (time_t)(fileTime / 10000000);
-		/* nano seconds base */
-		*ns = (long)(fileTime % 10000000) * 100;
-	} else {
-		*timep = 0;
-		*ns = 0;
-	}
-}
-
-static int
-read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const unsigned char *p;
-	struct _7zip_entry *entries = zip->entries;
-	unsigned char *timeBools;
-	int allAreDefined;
-	unsigned i;
-
-	timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools));
-	if (timeBools == NULL)
-		return (-1);
-
-	/* Read allAreDefined. */
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	allAreDefined = *p;
-	if (allAreDefined)
-		memset(timeBools, 1, (size_t)zip->numFiles);
-	else {
-		if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0)
-			goto failed;
-	}
-
-	/* Read external. */
-	if ((p = header_bytes(a, 1)) == NULL)
-		goto failed;
-	if (*p) {
-		if (parse_7zip_uint64(a, &(h->dataIndex)) < 0)
-			goto failed;
-		if (UMAX_ENTRY < h->dataIndex)
-			goto failed;
-	}
-
-	for (i = 0; i < zip->numFiles; i++) {
-		if (!timeBools[i])
-			continue;
-		if ((p = header_bytes(a, 8)) == NULL)
-			goto failed;
-		switch (type) {
-		case kCTime:
-			fileTimeToUtc(archive_le64dec(p),
-			    &(entries[i].ctime),
-			    &(entries[i].ctime_ns));
-			entries[i].flg |= CTIME_IS_SET;
-			break;
-		case kATime:
-			fileTimeToUtc(archive_le64dec(p),
-			    &(entries[i].atime),
-			    &(entries[i].atime_ns));
-			entries[i].flg |= ATIME_IS_SET;
-			break;
-		case kMTime:
-			fileTimeToUtc(archive_le64dec(p),
-			    &(entries[i].mtime),
-			    &(entries[i].mtime_ns));
-			entries[i].flg |= MTIME_IS_SET;
-			break;
-		}
-	}
-
-	free(timeBools);
-	return (0);
-failed:
-	free(timeBools);
-	return (-1);
-}
-
-static int
-decode_encoded_header_info(struct archive_read *a, struct _7z_stream_info *si)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-
-	errno = 0;
-	if (read_StreamsInfo(a, si) < 0) {
-		if (errno == ENOMEM)
-			archive_set_error(&a->archive, -1,
-			    "Couldn't allocate memory");
-		else
-			archive_set_error(&a->archive, -1,
-			    "Malformed 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (si->pi.numPackStreams == 0 || si->ci.numFolders == 0) {
-		archive_set_error(&a->archive, -1, "Malformed 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (zip->header_offset < si->pi.pos + si->pi.sizes[0] ||
-	    (int64_t)(si->pi.pos + si->pi.sizes[0]) < 0 ||
-	    si->pi.sizes[0] == 0 || (int64_t)si->pi.pos < 0) {
-		archive_set_error(&a->archive, -1, "Malformed Header offset");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static const unsigned char *
-header_bytes(struct archive_read *a, size_t rbytes)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const unsigned char *p;
-
-	if (zip->header_bytes_remaining < rbytes)
-		return (NULL);
-	if (zip->pack_stream_bytes_unconsumed)
-		read_consume(a);
-
-	if (zip->header_is_encoded == 0) {
-		p = __archive_read_ahead(a, rbytes, NULL);
-		if (p == NULL)
-			return (NULL);
-		zip->header_bytes_remaining -= rbytes;
-		zip->pack_stream_bytes_unconsumed = rbytes;
-	} else {
-		const void *buff;
-		ssize_t bytes;
-
-		bytes = read_stream(a, &buff, rbytes, rbytes);
-		if (bytes <= 0)
-			return (NULL);
-		zip->header_bytes_remaining -= bytes;
-		p = buff;
-	}
-
-	/* Update checksum */
-	zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
-	return (p);
-}
-
-static int
-slurp_central_directory(struct archive_read *a, struct _7zip *zip,
-    struct _7z_header_info *header)
-{
-	const unsigned char *p;
-	uint64_t next_header_offset;
-	uint64_t next_header_size;
-	uint32_t next_header_crc;
-	ssize_t bytes_avail;
-	int check_header_crc, r;
-
-	if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
-		return (ARCHIVE_FATAL);
-
-	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
-		/* This is an executable ? Must be self-extracting... */
-		r = skip_sfx(a, bytes_avail);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	zip->seek_base += 32;
-
-	if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) {
-		archive_set_error(&a->archive, -1, "Not 7-Zip archive file");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* CRC check. */
-	if (crc32(0, (const unsigned char *)p + 12, 20)
-	    != archive_le32dec(p + 8)) {
-#ifdef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&a->archive, -1, "Header CRC error");
-		return (ARCHIVE_FATAL);
-#endif
-	}
-
-	next_header_offset = archive_le64dec(p + 12);
-	next_header_size = archive_le64dec(p + 20);
-	next_header_crc = archive_le32dec(p + 28);
-
-	if (next_header_size == 0)
-		/* There is no entry in an archive file. */
-		return (ARCHIVE_EOF);
-
-	if (((int64_t)next_header_offset) < 0) {
-		archive_set_error(&a->archive, -1, "Malformed 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	}
-	__archive_read_consume(a, 32);
-	if (next_header_offset != 0) {
-		if (bytes_avail >= (ssize_t)next_header_offset)
-			__archive_read_consume(a, next_header_offset);
-		else if (__archive_read_seek(a,
-		    next_header_offset + zip->seek_base, SEEK_SET) < 0)
-			return (ARCHIVE_FATAL);
-	}
-	zip->stream_offset = next_header_offset;
-	zip->header_offset = next_header_offset;
-	zip->header_bytes_remaining = next_header_size;
-	zip->header_crc32 = 0;
-	zip->header_is_encoded = 0;
-	zip->header_is_being_read = 1;
-	zip->has_encrypted_entries = 0;
-	check_header_crc = 1;
-
-	if ((p = header_bytes(a, 1)) == NULL) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated 7-Zip file body");
-		return (ARCHIVE_FATAL);
-	}
-	/* Parse ArchiveProperties. */
-	switch (p[0]) {
-	case kEncodedHeader:
-		/*
-		 * The archive has an encoded header and we have to decode it
-		 * in order to parse the header correctly.
-		 */
-		r = decode_encoded_header_info(a, &(zip->si));
-
-		/* Check the EncodedHeader CRC.*/
-		if (r == 0 && zip->header_crc32 != next_header_crc) {
-			archive_set_error(&a->archive, -1,
-#ifndef DONT_FAIL_ON_CRC_ERROR
-			    "Damaged 7-Zip archive");
-			r = -1;
-#endif
-		}
-		if (r == 0) {
-			if (zip->si.ci.folders[0].digest_defined)
-				next_header_crc = zip->si.ci.folders[0].digest;
-			else
-				check_header_crc = 0;
-			if (zip->pack_stream_bytes_unconsumed)
-				read_consume(a);
-			r = setup_decode_folder(a, zip->si.ci.folders, 1);
-			if (r == 0) {
-				zip->header_bytes_remaining =
-					zip->folder_outbytes_remaining;
-				r = seek_pack(a);
-			}
-		}
-		/* Clean up StreamsInfo. */
-		free_StreamsInfo(&(zip->si));
-		memset(&(zip->si), 0, sizeof(zip->si));
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-		zip->header_is_encoded = 1;
-		zip->header_crc32 = 0;
-		/* FALL THROUGH */
-	case kHeader:
-		/*
-		 * Parse the header.
-		 */
-		errno = 0;
-		r = read_Header(a, header, zip->header_is_encoded);
-		if (r < 0) {
-			if (errno == ENOMEM)
-				archive_set_error(&a->archive, -1,
-				    "Couldn't allocate memory");
-			else
-				archive_set_error(&a->archive, -1,
-				    "Damaged 7-Zip archive");
-			return (ARCHIVE_FATAL);
-		}
-
-		/*
-		 *  Must be kEnd.
-		 */
-		if ((p = header_bytes(a, 1)) == NULL ||*p != kEnd) {
-			archive_set_error(&a->archive, -1,
-			    "Malformed 7-Zip archive");
-			return (ARCHIVE_FATAL);
-		}
-
-		/* Check the Header CRC.*/
-		if (check_header_crc && zip->header_crc32 != next_header_crc) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-			archive_set_error(&a->archive, -1,
-			    "Malformed 7-Zip archive");
-			return (ARCHIVE_FATAL);
-#endif
-		}
-		break;
-	default:
-		archive_set_error(&a->archive, -1,
-		    "Unexpected Property ID = %X", p[0]);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Clean up variables be used for decoding the archive header */
-	zip->pack_stream_remaining = 0;
-	zip->pack_stream_index = 0;
-	zip->folder_outbytes_remaining = 0;
-	zip->uncompressed_buffer_bytes_remaining = 0;
-	zip->pack_stream_bytes_unconsumed = 0;
-	zip->header_is_being_read = 0;
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-get_uncompressed_data(struct archive_read *a, const void **buff, size_t size,
-    size_t minimum)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	ssize_t bytes_avail;
-
-	if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
-		/* Copy mode. */
-
-		*buff = __archive_read_ahead(a, minimum, &bytes_avail);
-		if (bytes_avail <= 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated 7-Zip file data");
-			return (ARCHIVE_FATAL);
-		}
-		if ((size_t)bytes_avail >
-		    zip->uncompressed_buffer_bytes_remaining)
-			bytes_avail = (ssize_t)
-			    zip->uncompressed_buffer_bytes_remaining;
-		if ((size_t)bytes_avail > size)
-			bytes_avail = (ssize_t)size;
-
-		zip->pack_stream_bytes_unconsumed = bytes_avail;
-	} else if (zip->uncompressed_buffer_pointer == NULL) {
-		/* Decompression has failed. */
-		archive_set_error(&(a->archive),
-		    ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	} else {
-		/* Packed mode. */
-		if (minimum > zip->uncompressed_buffer_bytes_remaining) {
-			/*
-			 * If remaining uncompressed data size is less than
-			 * the minimum size, fill the buffer up to the
-			 * minimum size.
-			 */
-			if (extract_pack_stream(a, minimum) < 0)
-				return (ARCHIVE_FATAL);
-		}
-		if (size > zip->uncompressed_buffer_bytes_remaining)
-			bytes_avail = (ssize_t)
-			    zip->uncompressed_buffer_bytes_remaining;
-		else
-			bytes_avail = (ssize_t)size;
-		*buff = zip->uncompressed_buffer_pointer;
-		zip->uncompressed_buffer_pointer += bytes_avail;
-	}
-	zip->uncompressed_buffer_bytes_remaining -= bytes_avail;
-	return (bytes_avail);
-}
-
-static ssize_t
-extract_pack_stream(struct archive_read *a, size_t minimum)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	ssize_t bytes_avail;
-	int r;
-
-	if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
-		if (minimum == 0)
-			minimum = 1;
-		if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL
-		    || bytes_avail <= 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated 7-Zip file body");
-			return (ARCHIVE_FATAL);
-		}
-		if ((uint64_t)bytes_avail > zip->pack_stream_inbytes_remaining)
-			bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
-		zip->pack_stream_inbytes_remaining -= bytes_avail;
-		if ((uint64_t)bytes_avail > zip->folder_outbytes_remaining)
-			bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
-		zip->folder_outbytes_remaining -= bytes_avail;
-		zip->uncompressed_buffer_bytes_remaining = bytes_avail;
-		return (ARCHIVE_OK);
-	}
-
-	/* If the buffer hasn't been allocated, allocate it now. */
-	if (zip->uncompressed_buffer == NULL) {
-		zip->uncompressed_buffer_size = UBUFF_SIZE;
-		if (zip->uncompressed_buffer_size < minimum) {
-			zip->uncompressed_buffer_size = minimum + 1023;
-			zip->uncompressed_buffer_size &= ~0x3ff;
-		}
-		zip->uncompressed_buffer =
-		    malloc(zip->uncompressed_buffer_size);
-		if (zip->uncompressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for 7-Zip decompression");
-			return (ARCHIVE_FATAL);
-		}
-		zip->uncompressed_buffer_bytes_remaining = 0;
-	} else if (zip->uncompressed_buffer_size < minimum ||
-	    zip->uncompressed_buffer_bytes_remaining < minimum) {
-		/*
-		 * Make sure the uncompressed buffer can have bytes
-		 * at least `minimum' bytes.
-		 * NOTE: This case happen when reading the header.
-		 */
-		size_t used;
-		if (zip->uncompressed_buffer_pointer != 0)
-			used = zip->uncompressed_buffer_pointer -
-				zip->uncompressed_buffer;
-		else
-			used = 0;
-		if (zip->uncompressed_buffer_size < minimum) {
-			/*
-			 * Expand the uncompressed buffer up to
-			 * the minimum size.
-			 */
-			void *p;
-			size_t new_size;
-
-			new_size = minimum + 1023;
-			new_size &= ~0x3ff;
-			p = realloc(zip->uncompressed_buffer, new_size);
-			if (p == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for 7-Zip decompression");
-				return (ARCHIVE_FATAL);
-			}
-			zip->uncompressed_buffer = (unsigned char *)p;
-			zip->uncompressed_buffer_size = new_size;
-		}
-		/*
-		 * Move unconsumed bytes to the head.
-		 */
-		if (used) {
-			memmove(zip->uncompressed_buffer,
-				zip->uncompressed_buffer + used,
-				zip->uncompressed_buffer_bytes_remaining);
-		}
-	} else
-		zip->uncompressed_buffer_bytes_remaining = 0;
-	zip->uncompressed_buffer_pointer = NULL;
-	for (;;) {
-		size_t bytes_in, bytes_out;
-		const void *buff_in;
-		unsigned char *buff_out;
-		int end_of_data;
-
-		/*
-		 * Note: '1' here is a performance optimization.
-		 * Recall that the decompression layer returns a count of
-		 * available bytes; asking for more than that forces the
-		 * decompressor to combine reads by copying data.
-		 */
-		buff_in = __archive_read_ahead(a, 1, &bytes_avail);
-		if (bytes_avail <= 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated 7-Zip file body");
-			return (ARCHIVE_FATAL);
-		}
-
-		buff_out = zip->uncompressed_buffer
-			+ zip->uncompressed_buffer_bytes_remaining;
-		bytes_out = zip->uncompressed_buffer_size
-			- zip->uncompressed_buffer_bytes_remaining;
-		bytes_in = bytes_avail;
-		if (bytes_in > zip->pack_stream_inbytes_remaining)
-			bytes_in = (size_t)zip->pack_stream_inbytes_remaining;
-		/* Drive decompression. */
-		r = decompress(a, zip, buff_out, &bytes_out,
-			buff_in, &bytes_in);
-		switch (r) {
-		case ARCHIVE_OK:
-			end_of_data = 0;
-			break;
-		case ARCHIVE_EOF:
-			end_of_data = 1;
-			break;
-		default:
-			return (ARCHIVE_FATAL);
-		}
-		zip->pack_stream_inbytes_remaining -= bytes_in;
-		if (bytes_out > zip->folder_outbytes_remaining)
-			bytes_out = (size_t)zip->folder_outbytes_remaining;
-		zip->folder_outbytes_remaining -= bytes_out;
-		zip->uncompressed_buffer_bytes_remaining += bytes_out;
-		zip->pack_stream_bytes_unconsumed = bytes_in;
-
-		/*
-		 * Continue decompression until uncompressed_buffer is full.
-		 */
-		if (zip->uncompressed_buffer_bytes_remaining ==
-		    zip->uncompressed_buffer_size)
-			break;
-		if (zip->codec2 == _7Z_X86 && zip->odd_bcj_size &&
-		    zip->uncompressed_buffer_bytes_remaining + 5 >
-		    zip->uncompressed_buffer_size)
-			break;
-		if (zip->pack_stream_inbytes_remaining == 0 &&
-		    zip->folder_outbytes_remaining == 0)
-			break;
-		if (end_of_data || (bytes_in == 0 && bytes_out == 0)) {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
-			return (ARCHIVE_FATAL);
-		}
-		read_consume(a);
-	}
-	if (zip->uncompressed_buffer_bytes_remaining < minimum) {
-		archive_set_error(&(a->archive),
-		    ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	}
-	zip->uncompressed_buffer_pointer = zip->uncompressed_buffer;
-	return (ARCHIVE_OK);
-}
-
-static int
-seek_pack(struct archive_read *a)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	int64_t pack_offset;
-
-	if (zip->pack_stream_remaining <= 0) {
-		archive_set_error(&(a->archive),
-		    ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
-		return (ARCHIVE_FATAL);
-	}
-	zip->pack_stream_inbytes_remaining =
-	    zip->si.pi.sizes[zip->pack_stream_index];
-	pack_offset = zip->si.pi.positions[zip->pack_stream_index];
-	if (zip->stream_offset != pack_offset) {
-		if (0 > __archive_read_seek(a, pack_offset + zip->seek_base,
-		    SEEK_SET))
-			return (ARCHIVE_FATAL);
-		zip->stream_offset = pack_offset;
-	}
-	zip->pack_stream_index++;
-	zip->pack_stream_remaining--;
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-read_stream(struct archive_read *a, const void **buff, size_t size,
-    size_t minimum)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	uint64_t skip_bytes = 0;
-	ssize_t r;
-
-	if (zip->uncompressed_buffer_bytes_remaining == 0) {
-		if (zip->pack_stream_inbytes_remaining > 0) {
-			r = extract_pack_stream(a, 0);
-			if (r < 0)
-				return (r);
-			return (get_uncompressed_data(a, buff, size, minimum));
-		} else if (zip->folder_outbytes_remaining > 0) {
-			/* Extract a remaining pack stream. */
-			r = extract_pack_stream(a, 0);
-			if (r < 0)
-				return (r);
-			return (get_uncompressed_data(a, buff, size, minimum));
-		}
-	} else
-		return (get_uncompressed_data(a, buff, size, minimum));
-
-	/*
-	 * Current pack stream has been consumed.
-	 */
-	if (zip->pack_stream_remaining == 0) {
-		if (zip->header_is_being_read) {
-			/* Invalid sequence. This might happen when
-			 * reading a malformed archive. */
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC, "Malformed 7-Zip archive");
-			return (ARCHIVE_FATAL);
-		}
-
-		/*
-		 * All current folder's pack streams have been
-		 * consumed. Switch to next folder.
-		 */
-		if (zip->folder_index == 0 &&
-		    (zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
-		     || zip->folder_index != zip->entry->folderIndex)) {
-			zip->folder_index = zip->entry->folderIndex;
-			skip_bytes =
-			    zip->si.ci.folders[zip->folder_index].skipped_bytes;
-		}
-
-		if (zip->folder_index >= zip->si.ci.numFolders) {
-			/*
-			 * We have consumed all folders and its pack streams.
-			 */
-			*buff = NULL;
-			return (0);
-		}
-		r = setup_decode_folder(a,
-			&(zip->si.ci.folders[zip->folder_index]), 0);
-		if (r != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-
-		zip->folder_index++;
-	}
-
-	/*
-	 * Switch to next pack stream.
-	 */
-	r = seek_pack(a);
-	if (r < 0)
-		return (r);
-
-	/* Extract a new pack stream. */
-	r = extract_pack_stream(a, 0);
-	if (r < 0)
-		return (r);
-
-	/*
-	 * Skip the bytes we already has skipped in skip_stream().
-	 */
-	while (skip_bytes) {
-		ssize_t skipped;
-
-		if (zip->uncompressed_buffer_bytes_remaining == 0) {
-			if (zip->pack_stream_inbytes_remaining > 0) {
-				r = extract_pack_stream(a, 0);
-				if (r < 0)
-					return (r);
-			} else if (zip->folder_outbytes_remaining > 0) {
-				/* Extract a remaining pack stream. */
-				r = extract_pack_stream(a, 0);
-				if (r < 0)
-					return (r);
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Truncated 7-Zip file body");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		skipped = get_uncompressed_data(
-			a, buff, (size_t)skip_bytes, 0);
-		if (skipped < 0)
-			return (skipped);
-		skip_bytes -= skipped;
-		if (zip->pack_stream_bytes_unconsumed)
-			read_consume(a);
-	}
-
-	return (get_uncompressed_data(a, buff, size, minimum));
-}
-
-static int
-setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
-    int header)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const struct _7z_coder *coder1, *coder2;
-	const char *cname = (header)?"archive header":"file content";
-	unsigned i;
-	int r, found_bcj2 = 0;
-
-	/*
-	 * Release the memory which the previous folder used for BCJ2.
-	 */
-	for (i = 0; i < 3; i++) {
-		free(zip->sub_stream_buff[i]);
-		zip->sub_stream_buff[i] = NULL;
-	}
-
-	/*
-	 * Initialize a stream reader.
-	 */
-	zip->pack_stream_remaining = (unsigned)folder->numPackedStreams;
-	zip->pack_stream_index = (unsigned)folder->packIndex;
-	zip->folder_outbytes_remaining = folder_uncompressed_size(folder);
-	zip->uncompressed_buffer_bytes_remaining = 0;
-
-	/*
-	 * Check coder types.
-	 */
-	for (i = 0; i < folder->numCoders; i++) {
-		switch(folder->coders[i].codec) {
-			case _7Z_CRYPTO_MAIN_ZIP:
-			case _7Z_CRYPTO_RAR_29:
-			case _7Z_CRYPTO_AES_256_SHA_256: {
-				/* For entry that is associated with this folder, mark
-				   it as encrypted (data+metadata). */
-				zip->has_encrypted_entries = 1;
-				if (a->entry) {
-					archive_entry_set_is_data_encrypted(a->entry, 1);
-					archive_entry_set_is_metadata_encrypted(a->entry, 1);
-				}
-				archive_set_error(&(a->archive),
-					ARCHIVE_ERRNO_MISC,
-					"The %s is encrypted, "
-					"but currently not supported", cname);
-				return (ARCHIVE_FATAL);
-			}
-			case _7Z_X86_BCJ2: {
-				found_bcj2++;
-				break;
-			}
-		}
-	}
-	/* Now that we've checked for encryption, if there were still no
-	 * encrypted entries found we can say for sure that there are none.
-	 */
-	if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-		zip->has_encrypted_entries = 0;
-	}
-
-	if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) {
-		archive_set_error(&(a->archive),
-		    ARCHIVE_ERRNO_MISC,
-		    "The %s is encoded with many filters, "
-		    "but currently not supported", cname);
-		return (ARCHIVE_FATAL);
-	}
-	coder1 = &(folder->coders[0]);
-	if (folder->numCoders == 2)
-		coder2 = &(folder->coders[1]);
-	else
-		coder2 = NULL;
-
-	if (found_bcj2) {
-		/*
-		 * Preparation to decode BCJ2.
-		 * Decoding BCJ2 requires four sources. Those are at least,
-		 * as far as I know, two types of the storage form.
-		 */
-		const struct _7z_coder *fc = folder->coders;
-		static const struct _7z_coder coder_copy = {0, 1, 1, 0, NULL};
-		const struct _7z_coder *scoder[3] =
-			{&coder_copy, &coder_copy, &coder_copy};
-		const void *buff;
-		ssize_t bytes;
-		unsigned char *b[3] = {NULL, NULL, NULL};
-		uint64_t sunpack[3] ={-1, -1, -1};
-		size_t s[3] = {0, 0, 0};
-		int idx[3] = {0, 1, 2};
-
-		if (folder->numCoders == 4 && fc[3].codec == _7Z_X86_BCJ2 &&
-		    folder->numInStreams == 7 && folder->numOutStreams == 4 &&
-		    zip->pack_stream_remaining == 4) {
-			/* Source type 1 made by 7zr or 7z with -m options. */
-			if (folder->bindPairs[0].inIndex == 5) {
-				/* The form made by 7zr */
-				idx[0] = 1; idx[1] = 2; idx[2] = 0;
-				scoder[1] = &(fc[1]);
-				scoder[2] = &(fc[0]);
-				sunpack[1] = folder->unPackSize[1];
-				sunpack[2] = folder->unPackSize[0];
-				coder1 = &(fc[2]);
-			} else {
-				/*
-				 * NOTE: Some patterns do not work.
-				 * work:
-				 *  7z a -m0=BCJ2 -m1=COPY -m2=COPY
-				 *       -m3=(any)
-				 *  7z a -m0=BCJ2 -m1=COPY -m2=(any)
-				 *       -m3=COPY
-				 *  7z a -m0=BCJ2 -m1=(any) -m2=COPY
-				 *       -m3=COPY
-				 * not work:
-				 *  other patterns.
-				 *
-				 * We have to handle this like `pipe' or
-				 * our libarchive7s filter frame work,
-				 * decoding the BCJ2 main stream sequentially,
-				 * m3 -> m2 -> m1 -> BCJ2.
-				 *
-				 */
-				if (fc[0].codec == _7Z_COPY &&
-				    fc[1].codec == _7Z_COPY)
-					coder1 = &(folder->coders[2]);
-				else if (fc[0].codec == _7Z_COPY &&
-				    fc[2].codec == _7Z_COPY)
-					coder1 = &(folder->coders[1]);
-				else if (fc[1].codec == _7Z_COPY &&
-				    fc[2].codec == _7Z_COPY)
-					coder1 = &(folder->coders[0]);
-				else {
-					archive_set_error(&(a->archive),
-					    ARCHIVE_ERRNO_MISC,
-					    "Unsupported form of "
-					    "BCJ2 streams");
-					return (ARCHIVE_FATAL);
-				}
-			}
-			coder2 = &(fc[3]);
-			zip->main_stream_bytes_remaining =
-				(size_t)folder->unPackSize[2];
-		} else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 &&
-		    zip->pack_stream_remaining == 4 &&
-		    folder->numInStreams == 5 && folder->numOutStreams == 2) {
-			/* Source type 0 made by 7z */
-			zip->main_stream_bytes_remaining =
-				(size_t)folder->unPackSize[0];
-		} else {
-			/* We got an unexpected form. */
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Unsupported form of BCJ2 streams");
-			return (ARCHIVE_FATAL);
-		}
-
-		/* Skip the main stream at this time. */
-		if ((r = seek_pack(a)) < 0)
-			return (r);
-		zip->pack_stream_bytes_unconsumed =
-		    (size_t)zip->pack_stream_inbytes_remaining;
-		read_consume(a);
-
-		/* Read following three sub streams. */
-		for (i = 0; i < 3; i++) {
-			const struct _7z_coder *coder = scoder[i];
-
-			if ((r = seek_pack(a)) < 0) {
-				free(b[0]); free(b[1]); free(b[2]);
-				return (r);
-			}
-
-			if (sunpack[i] == (uint64_t)-1)
-				zip->folder_outbytes_remaining =
-				    zip->pack_stream_inbytes_remaining;
-			else
-				zip->folder_outbytes_remaining = sunpack[i];
-
-			r = init_decompression(a, zip, coder, NULL);
-			if (r != ARCHIVE_OK) {
-				free(b[0]); free(b[1]); free(b[2]);
-				return (ARCHIVE_FATAL);
-			}
-
-			/* Allocate memory for the decoded data of a sub
-			 * stream. */
-			b[i] = malloc((size_t)zip->folder_outbytes_remaining);
-			if (b[i] == NULL) {
-				free(b[0]); free(b[1]); free(b[2]);
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for 7-Zip decompression");
-				return (ARCHIVE_FATAL);
-			}
-
-			/* Extract a sub stream. */
-			while (zip->pack_stream_inbytes_remaining > 0) {
-				r = (int)extract_pack_stream(a, 0);
-				if (r < 0) {
-					free(b[0]); free(b[1]); free(b[2]);
-					return (r);
-				}
-				bytes = get_uncompressed_data(a, &buff,
-				    zip->uncompressed_buffer_bytes_remaining,
-				    0);
-				if (bytes < 0) {
-					free(b[0]); free(b[1]); free(b[2]);
-					return ((int)bytes);
-				}
-				memcpy(b[i]+s[i], buff, bytes);
-				s[i] += bytes;
-				if (zip->pack_stream_bytes_unconsumed)
-					read_consume(a);
-			}
-		}
-
-		/* Set the sub streams to the right place. */
-		for (i = 0; i < 3; i++) {
-			zip->sub_stream_buff[i] = b[idx[i]];
-			zip->sub_stream_size[i] = s[idx[i]];
-			zip->sub_stream_bytes_remaining[i] = s[idx[i]];
-		}
-
-		/* Allocate memory used for decoded main stream bytes. */
-		if (zip->tmp_stream_buff == NULL) {
-			zip->tmp_stream_buff_size = 32 * 1024;
-			zip->tmp_stream_buff =
-			    malloc(zip->tmp_stream_buff_size);
-			if (zip->tmp_stream_buff == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for 7-Zip decompression");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		zip->tmp_stream_bytes_avail = 0;
-		zip->tmp_stream_bytes_remaining = 0;
-		zip->odd_bcj_size = 0;
-		zip->bcj2_outPos = 0;
-
-		/*
-		 * Reset a stream reader in order to read the main stream
-		 * of BCJ2.
-		 */
-		zip->pack_stream_remaining = 1;
-		zip->pack_stream_index = (unsigned)folder->packIndex;
-		zip->folder_outbytes_remaining =
-		    folder_uncompressed_size(folder);
-		zip->uncompressed_buffer_bytes_remaining = 0;
-	}
-
-	/*
-	 * Initialize the decompressor for the new folder's pack streams.
-	 */
-	r = init_decompression(a, zip, coder1, coder2);
-	if (r != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	return (ARCHIVE_OK);
-}
-
-static int64_t
-skip_stream(struct archive_read *a, size_t skip_bytes)
-{
-	struct _7zip *zip = (struct _7zip *)a->format->data;
-	const void *p;
-	int64_t skipped_bytes;
-	size_t bytes = skip_bytes;
-
-	if (zip->folder_index == 0) {
-		/*
-		 * Optimization for a list mode.
-		 * Avoid unnecessary decoding operations.
-		 */
-		zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
-		    += skip_bytes;
-		return (skip_bytes);
-	}
-
-	while (bytes) {
-		skipped_bytes = read_stream(a, &p, bytes, 0);
-		if (skipped_bytes < 0)
-			return (skipped_bytes);
-		if (skipped_bytes == 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated 7-Zip file body");
-			return (ARCHIVE_FATAL);
-		}
-		bytes -= (size_t)skipped_bytes;
-		if (zip->pack_stream_bytes_unconsumed)
-			read_consume(a);
-	}
-	return (skip_bytes);
-}
-
-/*
- * Brought from LZMA SDK.
- *
- * Bra86.c -- Converter for x86 code (BCJ)
- * 2008-10-04 : Igor Pavlov : Public domain
- *
- */
-
-#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
-
-static void
-x86_Init(struct _7zip *zip)
-{
-	zip->bcj_state = 0;
-	zip->bcj_prevPosT = (size_t)0 - 1;
-	zip->bcj_prevMask = 0;
-	zip->bcj_ip = 5;
-}
-
-static size_t
-x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
-{
-	static const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
-	static const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
-	size_t bufferPos, prevPosT;
-	uint32_t ip, prevMask;
-
-	if (size < 5)
-		return 0;
-
-	bufferPos = 0;
-	prevPosT = zip->bcj_prevPosT;
-	prevMask = zip->bcj_prevMask;
-	ip = zip->bcj_ip;
-
-	for (;;) {
-		uint8_t *p = data + bufferPos;
-		uint8_t *limit = data + size - 4;
-
-		for (; p < limit; p++)
-			if ((*p & 0xFE) == 0xE8)
-				break;
-		bufferPos = (size_t)(p - data);
-		if (p >= limit)
-			break;
-		prevPosT = bufferPos - prevPosT;
-		if (prevPosT > 3)
-			prevMask = 0;
-		else {
-			prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
-			if (prevMask != 0) {
-				unsigned char b =
-					p[4 - kMaskToBitNumber[prevMask]];
-				if (!kMaskToAllowedStatus[prevMask] ||
-				    Test86MSByte(b)) {
-					prevPosT = bufferPos;
-					prevMask = ((prevMask << 1) & 0x7) | 1;
-					bufferPos++;
-					continue;
-				}
-			}
-		}
-		prevPosT = bufferPos;
-
-		if (Test86MSByte(p[4])) {
-			uint32_t src = ((uint32_t)p[4] << 24) |
-				((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) |
-				((uint32_t)p[1]);
-			uint32_t dest;
-			for (;;) {
-				uint8_t b;
-				int b_index;
-
-				dest = src - (ip + (uint32_t)bufferPos);
-				if (prevMask == 0)
-					break;
-				b_index = kMaskToBitNumber[prevMask] * 8;
-				b = (uint8_t)(dest >> (24 - b_index));
-				if (!Test86MSByte(b))
-					break;
-				src = dest ^ ((1 << (32 - b_index)) - 1);
-			}
-			p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1));
-			p[3] = (uint8_t)(dest >> 16);
-			p[2] = (uint8_t)(dest >> 8);
-			p[1] = (uint8_t)dest;
-			bufferPos += 5;
-		} else {
-			prevMask = ((prevMask << 1) & 0x7) | 1;
-			bufferPos++;
-		}
-	}
-	zip->bcj_prevPosT = prevPosT;
-	zip->bcj_prevMask = prevMask;
-	zip->bcj_ip += (uint32_t)bufferPos;
-	return (bufferPos);
-}
-
-static void
-arm_Init(struct _7zip *zip)
-{
-	zip->bcj_ip = 8;
-}
-
-static size_t
-arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
-{
-	// This function was adapted from
-	// static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
-	// in https://git.tukaani.org/xz-embedded.git
-
-	/*
-	 * Branch/Call/Jump (BCJ) filter decoders
-	 *
-	 * Authors: Lasse Collin <lasse.collin@tukaani.org>
-	 *          Igor Pavlov <https://7-zip.org/>
-	 *
-	 * This file has been put into the public domain.
-	 * You can do whatever you want with this file.
-	 */
-
-	size_t i;
-	uint32_t addr;
-
-	for (i = 0; i + 4 <= size; i += 4) {
-		if (buf[i + 3] == 0xEB) {
-			// Calculate the transformed addr.
-			addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
-				| ((uint32_t)buf[i + 2] << 16);
-			addr <<= 2;
-			addr -= zip->bcj_ip + (uint32_t)i;
-			addr >>= 2;
-
-			// Store the transformed addr in buf.
-			buf[i] = (uint8_t)addr;
-			buf[i + 1] = (uint8_t)(addr >> 8);
-			buf[i + 2] = (uint8_t)(addr >> 16);
-		}
-	}
-
-	zip->bcj_ip += (uint32_t)i;
-
-	return i;
-}
-
-static size_t
-arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
-{
-	// This function was adapted from
-	// static size_t bcj_arm64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
-	// in https://git.tukaani.org/xz-embedded.git
-
-	/*
-	 * Branch/Call/Jump (BCJ) filter decoders
-	 *
-	 * Authors: Lasse Collin <lasse.collin@tukaani.org>
-	 *          Igor Pavlov <https://7-zip.org/>
-	 *
-	 * This file has been put into the public domain.
-	 * You can do whatever you want with this file.
-	 */
-
-	size_t i;
-	uint32_t instr;
-	uint32_t addr;
-
-	for (i = 0; i + 4 <= size; i += 4) {
-		instr = (uint32_t)buf[i]
-			| ((uint32_t)buf[i+1] << 8)
-			| ((uint32_t)buf[i+2] << 16)
-			| ((uint32_t)buf[i+3] << 24);
-
-		if ((instr >> 26) == 0x25) {
-			/* BL instruction */
-			addr = instr - ((zip->bcj_ip + (uint32_t)i) >> 2);
-			instr = 0x94000000 | (addr & 0x03FFFFFF);
-
-			buf[i]   = (uint8_t)instr;
-			buf[i+1] = (uint8_t)(instr >> 8);
-			buf[i+2] = (uint8_t)(instr >> 16);
-			buf[i+3] = (uint8_t)(instr >> 24);
-		} else if ((instr & 0x9F000000) == 0x90000000) {
-			/* ADRP instruction */
-			addr = ((instr >> 29) & 3) | ((instr >> 3) & 0x1FFFFC);
-
-			/* Only convert values in the range +/-512 MiB. */
-			if ((addr + 0x020000) & 0x1C0000)
-				continue;
-
-			addr -= (zip->bcj_ip + (uint32_t)i) >> 12;
-
-			instr &= 0x9000001F;
-			instr |= (addr & 3) << 29;
-			instr |= (addr & 0x03FFFC) << 3;
-			instr |= (0U - (addr & 0x020000)) & 0xE00000;
-
-			buf[i]   = (uint8_t)instr;
-			buf[i+1] = (uint8_t)(instr >> 8);
-			buf[i+2] = (uint8_t)(instr >> 16);
-			buf[i+3] = (uint8_t)(instr >> 24);
-		}
-	}
-
-	zip->bcj_ip += (uint32_t)i;
-
-	return i;
-}
-
-/*
- * Brought from LZMA SDK.
- *
- * Bcj2.c -- Converter for x86 code (BCJ2)
- * 2008-10-04 : Igor Pavlov : Public domain
- *
- */
-
-#define SZ_ERROR_DATA	 ARCHIVE_FAILED
-
-#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
-#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
-
-#define kNumTopBits 24
-#define kTopValue ((uint32_t)1 << kNumTopBits)
-
-#define kNumBitModelTotalBits 11
-#define kBitModelTotal (1 << kNumBitModelTotalBits)
-#define kNumMoveBits 5
-
-#define RC_READ_BYTE (*buffer++)
-#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
-#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
-  { int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
-
-#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
-
-#define IF_BIT_0(p) ttt = *(p); bound = (zip->bcj2_range >> kNumBitModelTotalBits) * ttt; if (zip->bcj2_code < bound)
-#define UPDATE_0(p) zip->bcj2_range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
-#define UPDATE_1(p) zip->bcj2_range -= bound; zip->bcj2_code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
-
-static ssize_t
-Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
-{
-	size_t inPos = 0, outPos = 0;
-	const uint8_t *buf0, *buf1, *buf2, *buf3;
-	size_t size0, size1, size2, size3;
-	const uint8_t *buffer, *bufferLim;
-	unsigned int i, j;
-
-	size0 = zip->tmp_stream_bytes_remaining;
-	buf0 = zip->tmp_stream_buff + zip->tmp_stream_bytes_avail - size0;
-	size1 = zip->sub_stream_bytes_remaining[0];
-	buf1 = zip->sub_stream_buff[0] + zip->sub_stream_size[0] - size1;
-	size2 = zip->sub_stream_bytes_remaining[1];
-	buf2 = zip->sub_stream_buff[1] + zip->sub_stream_size[1] - size2;
-	size3 = zip->sub_stream_bytes_remaining[2];
-	buf3 = zip->sub_stream_buff[2] + zip->sub_stream_size[2] - size3;
-
-	buffer = buf3;
-	bufferLim = buffer + size3;
-
-	if (zip->bcj_state == 0) {
-		/*
-		 * Initialize.
-		 */
-		zip->bcj2_prevByte = 0;
-		for (i = 0;
-		    i < sizeof(zip->bcj2_p) / sizeof(zip->bcj2_p[0]); i++)
-			zip->bcj2_p[i] = kBitModelTotal >> 1;
-		RC_INIT2;
-		zip->bcj_state = 1;
-	}
-
-	/*
-	 * Gather the odd bytes of a previous call.
-	 */
-	for (i = 0; zip->odd_bcj_size > 0 && outPos < outSize; i++) {
-		outBuf[outPos++] = zip->odd_bcj[i];
-		zip->odd_bcj_size--;
-	}
-
-	if (outSize == 0) {
-		zip->bcj2_outPos += outPos;
-		return (outPos);
-	}
-
-	for (;;) {
-		uint8_t b;
-		CProb *prob;
-		uint32_t bound;
-		uint32_t ttt;
-
-		size_t limit = size0 - inPos;
-		if (outSize - outPos < limit)
-			limit = outSize - outPos;
-
-		if (zip->bcj_state == 1) {
-			while (limit != 0) {
-				uint8_t bb = buf0[inPos];
-				outBuf[outPos++] = bb;
-				if (IsJ(zip->bcj2_prevByte, bb)) {
-					zip->bcj_state = 2;
-					break;
-				}
-				inPos++;
-				zip->bcj2_prevByte = bb;
-				limit--;
-			}
-		}
-
-		if (limit == 0 || outPos == outSize)
-			break;
-		zip->bcj_state = 1;
-
-		b = buf0[inPos++];
-
-		if (b == 0xE8)
-			prob = zip->bcj2_p + zip->bcj2_prevByte;
-		else if (b == 0xE9)
-			prob = zip->bcj2_p + 256;
-		else
-			prob = zip->bcj2_p + 257;
-
-		IF_BIT_0(prob) {
-			UPDATE_0(prob)
-			zip->bcj2_prevByte = b;
-		} else {
-			uint32_t dest;
-			const uint8_t *v;
-			uint8_t out[4];
-
-			UPDATE_1(prob)
-			if (b == 0xE8) {
-				v = buf1;
-				if (size1 < 4)
-					return SZ_ERROR_DATA;
-				buf1 += 4;
-				size1 -= 4;
-			} else {
-				v = buf2;
-				if (size2 < 4)
-					return SZ_ERROR_DATA;
-				buf2 += 4;
-				size2 -= 4;
-			}
-			dest = (((uint32_t)v[0] << 24) |
-			    ((uint32_t)v[1] << 16) |
-			    ((uint32_t)v[2] << 8) |
-			    ((uint32_t)v[3])) -
-			    ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4);
-			out[0] = (uint8_t)dest;
-			out[1] = (uint8_t)(dest >> 8);
-			out[2] = (uint8_t)(dest >> 16);
-			out[3] = zip->bcj2_prevByte = (uint8_t)(dest >> 24);
-
-			for (i = 0; i < 4 && outPos < outSize; i++)
-				outBuf[outPos++] = out[i];
-			if (i < 4) {
-				/*
-				 * Save odd bytes which we could not add into
-				 * the output buffer because of out of space.
-				 */
-				zip->odd_bcj_size = 4 -i;
-				for (; i < 4; i++) {
-					j = i - 4 + (unsigned)zip->odd_bcj_size;
-					zip->odd_bcj[j] = out[i];
-				}
-				break;
-			}
-		}
-	}
-	zip->tmp_stream_bytes_remaining -= inPos;
-	zip->sub_stream_bytes_remaining[0] = size1;
-	zip->sub_stream_bytes_remaining[1] = size2;
-	zip->sub_stream_bytes_remaining[2] = bufferLim - buffer;
-	zip->bcj2_outPos += outPos;
-
-	return ((ssize_t)outPos);
-}
-
diff --git a/c/archive_read_support_format_all.c b/c/archive_read_support_format_all.c
deleted file mode 100644
--- a/c/archive_read_support_format_all.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * Copyright (c) 2003-2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_all.c 174991 2007-12-30 04:58:22Z kientzle $");
-
-#include "archive.h"
-#include "archive_private.h"
-
-int
-archive_read_support_format_all(struct archive *a)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_all");
-
-	/* TODO: It would be nice to compute the ordering
-	 * here automatically so that people who enable just
-	 * a few formats can still get the benefits.  That
-	 * may just require the format registration to include
-	 * a "maximum read-ahead" value (anything that uses seek
-	 * would be essentially infinite read-ahead).  The core
-	 * bid management can then sort the bidders before calling
-	 * them.
-	 *
-	 * If you implement the above, please return the list below
-	 * to alphabetic order.
-	 */
-
-	/*
-	 * These bidders are all pretty cheap; they just examine a
-	 * small initial part of the archive.  If one of these bids
-	 * high, we can maybe avoid running any of the more expensive
-	 * bidders below.
-	 */
-	archive_read_support_format_ar(a);
-	archive_read_support_format_cpio(a);
-	archive_read_support_format_empty(a);
-	archive_read_support_format_lha(a);
-	archive_read_support_format_mtree(a);
-	archive_read_support_format_tar(a);
-	archive_read_support_format_xar(a);
-	archive_read_support_format_warc(a);
-
-	/*
-	 * Install expensive bidders last.  By doing them last, we
-	 * increase the chance that a high bid from someone else will
-	 * make it unnecessary for these to do anything at all.
-	 */
-	/* These three have potentially large look-ahead. */
-	archive_read_support_format_7zip(a);
-	archive_read_support_format_cab(a);
-	archive_read_support_format_rar(a);
-	archive_read_support_format_rar5(a);
-	archive_read_support_format_iso9660(a);
-	/* Seek is really bad, since it forces the read-ahead
-	 * logic to discard buffered data. */
-	archive_read_support_format_zip(a);
-
-	/* Note: We always return ARCHIVE_OK here, even if some of the
-	 * above return ARCHIVE_WARN.  The intent here is to enable
-	 * "as much as possible."  Clients who need specific
-	 * compression should enable those individually so they can
-	 * verify the level of support. */
-	/* Clear any warning messages set by the above functions. */
-	archive_clear_error(a);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_support_format_ar.c b/c/archive_read_support_format_ar.c
deleted file mode 100644
--- a/c/archive_read_support_format_ar.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*-
- * Copyright (c) 2007 Kai Wang
- * Copyright (c) 2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_ar.c 201101 2009-12-28 03:06:27Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-struct ar {
-	int64_t	 entry_bytes_remaining;
-	/* unconsumed is purely to track data we've gotten from readahead,
-	 * but haven't yet marked as consumed.  Must be paired with
-	 * entry_bytes_remaining usage/modification.
-	 */
-	size_t   entry_bytes_unconsumed;
-	int64_t	 entry_offset;
-	int64_t	 entry_padding;
-	char	*strtab;
-	size_t	 strtab_size;
-	char	 read_global_header;
-};
-
-/*
- * Define structure of the "ar" header.
- */
-#define AR_name_offset 0
-#define AR_name_size 16
-#define AR_date_offset 16
-#define AR_date_size 12
-#define AR_uid_offset 28
-#define AR_uid_size 6
-#define AR_gid_offset 34
-#define AR_gid_size 6
-#define AR_mode_offset 40
-#define AR_mode_size 8
-#define AR_size_offset 48
-#define AR_size_size 10
-#define AR_fmag_offset 58
-#define AR_fmag_size 2
-
-static int	archive_read_format_ar_bid(struct archive_read *a, int);
-static int	archive_read_format_ar_cleanup(struct archive_read *a);
-static int	archive_read_format_ar_read_data(struct archive_read *a,
-		    const void **buff, size_t *size, int64_t *offset);
-static int	archive_read_format_ar_skip(struct archive_read *a);
-static int	archive_read_format_ar_read_header(struct archive_read *a,
-		    struct archive_entry *e);
-static uint64_t	ar_atol8(const char *p, unsigned char_cnt);
-static uint64_t	ar_atol10(const char *p, unsigned char_cnt);
-static int	ar_parse_gnu_filename_table(struct archive_read *a);
-static int	ar_parse_common_header(struct ar *ar, struct archive_entry *,
-		    const char *h);
-
-int
-archive_read_support_format_ar(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct ar *ar;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
-
-	ar = (struct ar *)calloc(1, sizeof(*ar));
-	if (ar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ar data");
-		return (ARCHIVE_FATAL);
-	}
-	ar->strtab = NULL;
-
-	r = __archive_read_register_format(a,
-	    ar,
-	    "ar",
-	    archive_read_format_ar_bid,
-	    NULL,
-	    archive_read_format_ar_read_header,
-	    archive_read_format_ar_read_data,
-	    archive_read_format_ar_skip,
-	    NULL,
-	    archive_read_format_ar_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK) {
-		free(ar);
-		return (r);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_ar_cleanup(struct archive_read *a)
-{
-	struct ar *ar;
-
-	ar = (struct ar *)(a->format->data);
-	free(ar->strtab);
-	free(ar);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_ar_bid(struct archive_read *a, int best_bid)
-{
-	const void *h;
-
-	(void)best_bid; /* UNUSED */
-
-	/*
-	 * Verify the 8-byte file signature.
-	 * TODO: Do we need to check more than this?
-	 */
-	if ((h = __archive_read_ahead(a, 8, NULL)) == NULL)
-		return (-1);
-	if (memcmp(h, "!<arch>\n", 8) == 0) {
-		return (64);
-	}
-	return (-1);
-}
-
-static int
-_ar_read_header(struct archive_read *a, struct archive_entry *entry,
-	struct ar *ar, const char *h, size_t *unconsumed)
-{
-	char filename[AR_name_size + 1];
-	uint64_t number; /* Used to hold parsed numbers before validation. */
-	size_t bsd_name_length, entry_size;
-	char *p, *st;
-	const void *b;
-	int r;
-
-	/* Verify the magic signature on the file header. */
-	if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
-		archive_set_error(&a->archive, EINVAL,
-		    "Incorrect file header signature");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Copy filename into work buffer. */
-	strncpy(filename, h + AR_name_offset, AR_name_size);
-	filename[AR_name_size] = '\0';
-
-	/*
-	 * Guess the format variant based on the filename.
-	 */
-	if (a->archive.archive_format == ARCHIVE_FORMAT_AR) {
-		/* We don't already know the variant, so let's guess. */
-		/*
-		 * Biggest clue is presence of '/': GNU starts special
-		 * filenames with '/', appends '/' as terminator to
-		 * non-special names, so anything with '/' should be
-		 * GNU except for BSD long filenames.
-		 */
-		if (strncmp(filename, "#1/", 3) == 0)
-			a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
-		else if (strchr(filename, '/') != NULL)
-			a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
-		else if (strncmp(filename, "__.SYMDEF", 9) == 0)
-			a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
-		/*
-		 * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/'
-		 * if name exactly fills 16-byte field?  If so, we
-		 * can't assume entries without '/' are BSD. XXX
-		 */
-	}
-
-	/* Update format name from the code. */
-	if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU)
-		a->archive.archive_format_name = "ar (GNU/SVR4)";
-	else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD)
-		a->archive.archive_format_name = "ar (BSD)";
-	else
-		a->archive.archive_format_name = "ar";
-
-	/*
-	 * Remove trailing spaces from the filename.  GNU and BSD
-	 * variants both pad filename area out with spaces.
-	 * This will only be wrong if GNU/SVR4 'ar' implementations
-	 * omit trailing '/' for 16-char filenames and we have
-	 * a 16-char filename that ends in ' '.
-	 */
-	p = filename + AR_name_size - 1;
-	while (p >= filename && *p == ' ') {
-		*p = '\0';
-		p--;
-	}
-
-	/*
-	 * Remove trailing slash unless first character is '/'.
-	 * (BSD entries never end in '/', so this will only trim
-	 * GNU-format entries.  GNU special entries start with '/'
-	 * and are not terminated in '/', so we don't trim anything
-	 * that starts with '/'.)
-	 */
-	if (filename[0] != '/' && p > filename && *p == '/') {
-		*p = '\0';
-	}
-
-	if (p < filename) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Found entry with empty filename");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * '//' is the GNU filename table.
-	 * Later entries can refer to names in this table.
-	 */
-	if (strcmp(filename, "//") == 0) {
-		/* This must come before any call to _read_ahead. */
-		ar_parse_common_header(ar, entry, h);
-		archive_entry_copy_pathname(entry, filename);
-		archive_entry_set_filetype(entry, AE_IFREG);
-		/* Get the size of the filename table. */
-		number = ar_atol10(h + AR_size_offset, AR_size_size);
-		if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Filename table too large");
-			return (ARCHIVE_FATAL);
-		}
-		entry_size = (size_t)number;
-		if (entry_size == 0) {
-			archive_set_error(&a->archive, EINVAL,
-			    "Invalid string table");
-			return (ARCHIVE_FATAL);
-		}
-		if (ar->strtab != NULL) {
-			archive_set_error(&a->archive, EINVAL,
-			    "More than one string tables exist");
-			return (ARCHIVE_FATAL);
-		}
-
-		/* Read the filename table into memory. */
-		st = malloc(entry_size);
-		if (st == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate filename table buffer");
-			return (ARCHIVE_FATAL);
-		}
-		ar->strtab = st;
-		ar->strtab_size = entry_size;
-
-		if (*unconsumed) {
-			__archive_read_consume(a, *unconsumed);
-			*unconsumed = 0;
-		}
-
-		if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL)
-			return (ARCHIVE_FATAL);
-		memcpy(st, b, entry_size);
-		__archive_read_consume(a, entry_size);
-		/* All contents are consumed. */
-		ar->entry_bytes_remaining = 0;
-		archive_entry_set_size(entry, ar->entry_bytes_remaining);
-
-		/* Parse the filename table. */
-		return (ar_parse_gnu_filename_table(a));
-	}
-
-	/*
-	 * GNU variant handles long filenames by storing /<number>
-	 * to indicate a name stored in the filename table.
-	 * XXX TODO: Verify that it's all digits... Don't be fooled
-	 * by "/9xyz" XXX
-	 */
-	if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') {
-		number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1);
-		/*
-		 * If we can't look up the real name, warn and return
-		 * the entry with the wrong name.
-		 */
-		if (ar->strtab == NULL || number >= ar->strtab_size) {
-			archive_set_error(&a->archive, EINVAL,
-			    "Can't find long filename for GNU/SVR4 archive entry");
-			archive_entry_copy_pathname(entry, filename);
-			/* Parse the time, owner, mode, size fields. */
-			ar_parse_common_header(ar, entry, h);
-			return (ARCHIVE_FATAL);
-		}
-
-		archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
-		/* Parse the time, owner, mode, size fields. */
-		return (ar_parse_common_header(ar, entry, h));
-	}
-
-	/*
-	 * BSD handles long filenames by storing "#1/" followed by the
-	 * length of filename as a decimal number, then prepends the
-	 * the filename to the file contents.
-	 */
-	if (strncmp(filename, "#1/", 3) == 0) {
-		/* Parse the time, owner, mode, size fields. */
-		/* This must occur before _read_ahead is called again. */
-		ar_parse_common_header(ar, entry, h);
-
-		/* Parse the size of the name, adjust the file size. */
-		number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
-		/* Sanity check the filename length:
-		 *   = Must be <= SIZE_MAX - 1
-		 *   = Must be <= 1MB
-		 *   = Cannot be bigger than the entire entry
-		 */
-		if (number > SIZE_MAX - 1
-		    || number > 1024 * 1024
-		    || (int64_t)number > ar->entry_bytes_remaining) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Bad input file size");
-			return (ARCHIVE_FATAL);
-		}
-		bsd_name_length = (size_t)number;
-		ar->entry_bytes_remaining -= bsd_name_length;
-		/* Adjust file size reported to client. */
-		archive_entry_set_size(entry, ar->entry_bytes_remaining);
-
-		if (*unconsumed) {
-			__archive_read_consume(a, *unconsumed);
-			*unconsumed = 0;
-		}
-
-		/* Read the long name into memory. */
-		if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Truncated input file");
-			return (ARCHIVE_FATAL);
-		}
-		/* Store it in the entry. */
-		p = (char *)malloc(bsd_name_length + 1);
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate fname buffer");
-			return (ARCHIVE_FATAL);
-		}
-		strncpy(p, b, bsd_name_length);
-		p[bsd_name_length] = '\0';
-
-		__archive_read_consume(a, bsd_name_length);
-
-		archive_entry_copy_pathname(entry, p);
-		free(p);
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * "/" is the SVR4/GNU archive symbol table.
-	 * "/SYM64/" is the SVR4/GNU 64-bit variant archive symbol table.
-	 */
-	if (strcmp(filename, "/") == 0 || strcmp(filename, "/SYM64/") == 0) {
-		archive_entry_copy_pathname(entry, filename);
-		/* Parse the time, owner, mode, size fields. */
-		r = ar_parse_common_header(ar, entry, h);
-		/* Force the file type to a regular file. */
-		archive_entry_set_filetype(entry, AE_IFREG);
-		return (r);
-	}
-
-	/*
-	 * "__.SYMDEF" is a BSD archive symbol table.
-	 */
-	if (strcmp(filename, "__.SYMDEF") == 0) {
-		archive_entry_copy_pathname(entry, filename);
-		/* Parse the time, owner, mode, size fields. */
-		return (ar_parse_common_header(ar, entry, h));
-	}
-
-	/*
-	 * Otherwise, this is a standard entry.  The filename
-	 * has already been trimmed as much as possible, based
-	 * on our current knowledge of the format.
-	 */
-	archive_entry_copy_pathname(entry, filename);
-	return (ar_parse_common_header(ar, entry, h));
-}
-
-static int
-archive_read_format_ar_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct ar *ar = (struct ar*)(a->format->data);
-	size_t unconsumed;
-	const void *header_data;
-	int ret;
-
-	if (!ar->read_global_header) {
-		/*
-		 * We are now at the beginning of the archive,
-		 * so we need first consume the ar global header.
-		 */
-		__archive_read_consume(a, 8);
-		ar->read_global_header = 1;
-		/* Set a default format code for now. */
-		a->archive.archive_format = ARCHIVE_FORMAT_AR;
-	}
-
-	/* Read the header for the next file entry. */
-	if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL)
-		/* Broken header. */
-		return (ARCHIVE_EOF);
-	
-	unconsumed = 60;
-	
-	ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed);
-
-	if (unconsumed)
-		__archive_read_consume(a, unconsumed);
-
-	return ret;
-}
-
-
-static int
-ar_parse_common_header(struct ar *ar, struct archive_entry *entry,
-    const char *h)
-{
-	uint64_t n;
-
-	/* Copy remaining header */
-	archive_entry_set_filetype(entry, AE_IFREG);
-	archive_entry_set_mtime(entry,
-	    (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
-	archive_entry_set_uid(entry,
-	    (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size));
-	archive_entry_set_gid(entry,
-	    (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size));
-	archive_entry_set_mode(entry,
-	    (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size));
-	n = ar_atol10(h + AR_size_offset, AR_size_size);
-
-	ar->entry_offset = 0;
-	ar->entry_padding = n % 2;
-	archive_entry_set_size(entry, n);
-	ar->entry_bytes_remaining = n;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_ar_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	ssize_t bytes_read;
-	struct ar *ar;
-
-	ar = (struct ar *)(a->format->data);
-
-	if (ar->entry_bytes_unconsumed) {
-		__archive_read_consume(a, ar->entry_bytes_unconsumed);
-		ar->entry_bytes_unconsumed = 0;
-	}
-
-	if (ar->entry_bytes_remaining > 0) {
-		*buff = __archive_read_ahead(a, 1, &bytes_read);
-		if (bytes_read == 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Truncated ar archive");
-			return (ARCHIVE_FATAL);
-		}
-		if (bytes_read < 0)
-			return (ARCHIVE_FATAL);
-		if (bytes_read > ar->entry_bytes_remaining)
-			bytes_read = (ssize_t)ar->entry_bytes_remaining;
-		*size = bytes_read;
-		ar->entry_bytes_unconsumed = bytes_read;
-		*offset = ar->entry_offset;
-		ar->entry_offset += bytes_read;
-		ar->entry_bytes_remaining -= bytes_read;
-		return (ARCHIVE_OK);
-	} else {
-		int64_t skipped = __archive_read_consume(a, ar->entry_padding);
-		if (skipped >= 0) {
-			ar->entry_padding -= skipped;
-		}
-		if (ar->entry_padding) {
-			if (skipped >= 0) {
-				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-					"Truncated ar archive- failed consuming padding");
-			}
-			return (ARCHIVE_FATAL);
-		}
-		*buff = NULL;
-		*size = 0;
-		*offset = ar->entry_offset;
-		return (ARCHIVE_EOF);
-	}
-}
-
-static int
-archive_read_format_ar_skip(struct archive_read *a)
-{
-	int64_t bytes_skipped;
-	struct ar* ar;
-
-	ar = (struct ar *)(a->format->data);
-
-	bytes_skipped = __archive_read_consume(a,
-	    ar->entry_bytes_remaining + ar->entry_padding
-	    + ar->entry_bytes_unconsumed);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-
-	ar->entry_bytes_remaining = 0;
-	ar->entry_bytes_unconsumed = 0;
-	ar->entry_padding = 0;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-ar_parse_gnu_filename_table(struct archive_read *a)
-{
-	struct ar *ar;
-	char *p;
-	size_t size;
-
-	ar = (struct ar*)(a->format->data);
-	size = ar->strtab_size;
-
-	for (p = ar->strtab; p < ar->strtab + size - 1; ++p) {
-		if (*p == '/') {
-			*p++ = '\0';
-			if (*p != '\n')
-				goto bad_string_table;
-			*p = '\0';
-		}
-	}
-	/*
-	 * GNU ar always pads the table to an even size.
-	 * The pad character is either '\n' or '`'.
-	 */
-	if (p != ar->strtab + size && *p != '\n' && *p != '`')
-		goto bad_string_table;
-
-	/* Enforce zero termination. */
-	ar->strtab[size - 1] = '\0';
-
-	return (ARCHIVE_OK);
-
-bad_string_table:
-	archive_set_error(&a->archive, EINVAL,
-	    "Invalid string table");
-	free(ar->strtab);
-	ar->strtab = NULL;
-	return (ARCHIVE_FATAL);
-}
-
-static uint64_t
-ar_atol8(const char *p, unsigned char_cnt)
-{
-	uint64_t l, limit, last_digit_limit;
-	unsigned int digit, base;
-
-	base = 8;
-	limit = UINT64_MAX / base;
-	last_digit_limit = UINT64_MAX % base;
-
-	while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
-		p++;
-
-	l = 0;
-	digit = *p - '0';
-	while (*p >= '0' && digit < base  && char_cnt-- > 0) {
-		if (l>limit || (l == limit && digit > last_digit_limit)) {
-			l = UINT64_MAX; /* Truncate on overflow. */
-			break;
-		}
-		l = (l * base) + digit;
-		digit = *++p - '0';
-	}
-	return (l);
-}
-
-static uint64_t
-ar_atol10(const char *p, unsigned char_cnt)
-{
-	uint64_t l, limit, last_digit_limit;
-	unsigned int base, digit;
-
-	base = 10;
-	limit = UINT64_MAX / base;
-	last_digit_limit = UINT64_MAX % base;
-
-	while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
-		p++;
-	l = 0;
-	digit = *p - '0';
-	while (*p >= '0' && digit < base  && char_cnt-- > 0) {
-		if (l > limit || (l == limit && digit > last_digit_limit)) {
-			l = UINT64_MAX; /* Truncate on overflow. */
-			break;
-		}
-		l = (l * base) + digit;
-		digit = *++p - '0';
-	}
-	return (l);
-}
diff --git a/c/archive_read_support_format_by_code.c b/c/archive_read_support_format_by_code.c
deleted file mode 100644
--- a/c/archive_read_support_format_by_code.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * Copyright (c) 2003-2011 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-int
-archive_read_support_format_by_code(struct archive *a, int format_code)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_by_code");
-
-	switch (format_code & ARCHIVE_FORMAT_BASE_MASK) {
-	case ARCHIVE_FORMAT_7ZIP:
-		return archive_read_support_format_7zip(a);
-		break;
-	case ARCHIVE_FORMAT_AR:
-		return archive_read_support_format_ar(a);
-		break;
-	case ARCHIVE_FORMAT_CAB:
-		return archive_read_support_format_cab(a);
-		break;
-	case ARCHIVE_FORMAT_CPIO:
-		return archive_read_support_format_cpio(a);
-		break;
-	case ARCHIVE_FORMAT_EMPTY:
-		return archive_read_support_format_empty(a);
-		break;
-	case ARCHIVE_FORMAT_ISO9660:
-		return archive_read_support_format_iso9660(a);
-		break;
-	case ARCHIVE_FORMAT_LHA:
-		return archive_read_support_format_lha(a);
-		break;
-	case ARCHIVE_FORMAT_MTREE:
-		return archive_read_support_format_mtree(a);
-		break;
-	case ARCHIVE_FORMAT_RAR:
-		return archive_read_support_format_rar(a);
-		break;
-	case ARCHIVE_FORMAT_RAR_V5:
-		return archive_read_support_format_rar5(a);
-		break;
-	case ARCHIVE_FORMAT_RAW:
-		return archive_read_support_format_raw(a);
-		break;
-	case ARCHIVE_FORMAT_TAR:
-		return archive_read_support_format_tar(a);
-		break;
-	case ARCHIVE_FORMAT_WARC:
-		return archive_read_support_format_warc(a);
-		break;
-	case ARCHIVE_FORMAT_XAR:
-		return archive_read_support_format_xar(a);
-		break;
-	case ARCHIVE_FORMAT_ZIP:
-		return archive_read_support_format_zip(a);
-		break;
-	}
-	archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
-	    "Invalid format code specified");
-	return (ARCHIVE_FATAL);
-}
diff --git a/c/archive_read_support_format_cab.c b/c/archive_read_support_format_cab.c
deleted file mode 100644
--- a/c/archive_read_support_format_cab.c
+++ /dev/null
@@ -1,3228 +0,0 @@
-/*-
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_endian.h"
-
-
-struct lzx_dec {
-	/* Decoding status. */
-	int     		 state;
-
-	/*
-	 * Window to see last decoded data, from 32KBi to 2MBi.
-	 */
-	int			 w_size;
-	int			 w_mask;
-	/* Window buffer, which is a loop buffer. */
-	unsigned char		*w_buff;
-	/* The insert position to the window. */
-	int			 w_pos;
-	/* The position where we can copy decoded code from the window. */
-	int     		 copy_pos;
-	/* The length how many bytes we can copy decoded code from
-	 * the window. */
-	int     		 copy_len;
-	/* Translation reversal for x86 processor CALL byte sequence(E8).
-	 * This is used for LZX only. */
-	uint32_t		 translation_size;
-	char			 translation;
-	char			 block_type;
-#define VERBATIM_BLOCK		1
-#define ALIGNED_OFFSET_BLOCK	2
-#define UNCOMPRESSED_BLOCK	3
-	size_t			 block_size;
-	size_t			 block_bytes_avail;
-	/* Repeated offset. */
-	int			 r0, r1, r2;
-	unsigned char		 rbytes[4];
-	int			 rbytes_avail;
-	int			 length_header;
-	int			 position_slot;
-	int			 offset_bits;
-
-	struct lzx_pos_tbl {
-		int		 base;
-		int		 footer_bits;
-	}			*pos_tbl;
-	/*
-	 * Bit stream reader.
-	 */
-	struct lzx_br {
-#define CACHE_TYPE		uint64_t
-#define CACHE_BITS		(8 * sizeof(CACHE_TYPE))
-	 	/* Cache buffer. */
-		CACHE_TYPE	 cache_buffer;
-		/* Indicates how many bits avail in cache_buffer. */
-		int		 cache_avail;
-		unsigned char	 odd;
-		char		 have_odd;
-	} br;
-
-	/*
-	 * Huffman coding.
-	 */
-	struct huffman {
-		int		 len_size;
-		int		 freq[17];
-		unsigned char	*bitlen;
-
-		/*
-		 * Use a index table. It's faster than searching a huffman
-		 * coding tree, which is a binary tree. But a use of a large
-		 * index table causes L1 cache read miss many times.
-		 */
-		int		 max_bits;
-		int		 tbl_bits;
-		int		 tree_used;
-		/* Direct access table. */
-		uint16_t	*tbl;
-	}			 at, lt, mt, pt;
-
-	int			 loop;
-	int			 error;
-};
-
-static const int slots[] = {
-	30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
-};
-#define SLOT_BASE	15
-#define SLOT_MAX	21/*->25*/
-
-struct lzx_stream {
-	const unsigned char	*next_in;
-	int64_t			 avail_in;
-	int64_t			 total_in;
-	unsigned char		*next_out;
-	int64_t			 avail_out;
-	int64_t			 total_out;
-	struct lzx_dec		*ds;
-};
-
-/*
- * Cabinet file definitions.
- */
-/* CFHEADER offset */
-#define CFHEADER_signature	0
-#define CFHEADER_cbCabinet	8
-#define CFHEADER_coffFiles	16
-#define CFHEADER_versionMinor	24
-#define CFHEADER_versionMajor	25
-#define CFHEADER_cFolders	26
-#define CFHEADER_cFiles		28
-#define CFHEADER_flags		30
-#define CFHEADER_setID		32
-#define CFHEADER_iCabinet	34
-#define CFHEADER_cbCFHeader	36
-#define CFHEADER_cbCFFolder	38
-#define CFHEADER_cbCFData	39
-
-/* CFFOLDER offset */
-#define CFFOLDER_coffCabStart	0
-#define CFFOLDER_cCFData	4
-#define CFFOLDER_typeCompress	6
-#define CFFOLDER_abReserve	8
-
-/* CFFILE offset */
-#define CFFILE_cbFile		0
-#define CFFILE_uoffFolderStart	4
-#define CFFILE_iFolder		8
-#define CFFILE_date_time	10
-#define CFFILE_attribs		14
-
-/* CFDATA offset */
-#define CFDATA_csum		0
-#define CFDATA_cbData		4
-#define CFDATA_cbUncomp		6
-
-static const char * const compression_name[] = {
-	"NONE",
-	"MSZIP",
-	"Quantum",
-	"LZX",
-};
-
-struct cfdata {
-	/* Sum value of this CFDATA. */
-	uint32_t		 sum;
-	uint16_t		 compressed_size;
-	uint16_t		 compressed_bytes_remaining;
-	uint16_t		 uncompressed_size;
-	uint16_t		 uncompressed_bytes_remaining;
-	/* To know how many bytes we have decompressed. */
-	uint16_t		 uncompressed_avail;
-	/* Offset from the beginning of compressed data of this CFDATA */
-	uint16_t		 read_offset;
-	int64_t			 unconsumed;
-	/* To keep memory image of this CFDATA to compute the sum. */
-	size_t			 memimage_size;
-	unsigned char		*memimage;
-	/* Result of calculation of sum. */
-	uint32_t		 sum_calculated;
-	unsigned char		 sum_extra[4];
-	int			 sum_extra_avail;
-	const void		*sum_ptr;
-};
-
-struct cffolder {
-	uint32_t		 cfdata_offset_in_cab;
-	uint16_t		 cfdata_count;
-	uint16_t		 comptype;
-#define COMPTYPE_NONE		0x0000
-#define COMPTYPE_MSZIP		0x0001
-#define COMPTYPE_QUANTUM	0x0002
-#define COMPTYPE_LZX		0x0003
-	uint16_t		 compdata;
-	const char		*compname;
-	/* At the time reading CFDATA */
-	struct cfdata		 cfdata;
-	int			 cfdata_index;
-	/* Flags to mark progress of decompression. */
-	char			 decompress_init;
-};
-
-struct cffile {
-	uint32_t		 uncompressed_size;
-	uint32_t		 offset;
-	time_t			 mtime;
-	uint16_t	 	 folder;
-#define iFoldCONTINUED_FROM_PREV	0xFFFD
-#define iFoldCONTINUED_TO_NEXT		0xFFFE
-#define iFoldCONTINUED_PREV_AND_NEXT	0xFFFF
-	unsigned char		 attr;
-#define ATTR_RDONLY		0x01
-#define ATTR_NAME_IS_UTF	0x80
-	struct archive_string 	 pathname;
-};
-
-struct cfheader {
-	/* Total bytes of all file size in a Cabinet. */
-	uint32_t		 total_bytes;
-	uint32_t		 files_offset;
-	uint16_t		 folder_count;
-	uint16_t		 file_count;
-	uint16_t		 flags;
-#define PREV_CABINET	0x0001
-#define NEXT_CABINET	0x0002
-#define RESERVE_PRESENT	0x0004
-	uint16_t		 setid;
-	uint16_t		 cabinet;
-	/* Version number. */
-	unsigned char		 major;
-	unsigned char		 minor;
-	unsigned char		 cffolder;
-	unsigned char		 cfdata;
-	/* All folders in a cabinet. */
-	struct cffolder		*folder_array;
-	/* All files in a cabinet. */
-	struct cffile		*file_array;
-	int			 file_index;
-};
-
-struct cab {
-	/* entry_bytes_remaining is the number of bytes we expect.	    */
-	int64_t			 entry_offset;
-	int64_t			 entry_bytes_remaining;
-	int64_t			 entry_unconsumed;
-	int64_t			 entry_compressed_bytes_read;
-	int64_t			 entry_uncompressed_bytes_read;
-	struct cffolder		*entry_cffolder;
-	struct cffile		*entry_cffile;
-	struct cfdata		*entry_cfdata;
-
-	/* Offset from beginning of a cabinet file. */
-	int64_t			 cab_offset;
-	struct cfheader		 cfheader;
-	struct archive_wstring	 ws;
-
-	/* Flag to mark progress that an archive was read their first header.*/
-	char			 found_header;
-	char			 end_of_archive;
-	char			 end_of_entry;
-	char			 end_of_entry_cleanup;
-	char			 read_data_invoked;
-	int64_t			 bytes_skipped;
-
-	unsigned char		*uncompressed_buffer;
-	size_t			 uncompressed_buffer_size;
-
-	int			 init_default_conversion;
-	struct archive_string_conv *sconv;
-	struct archive_string_conv *sconv_default;
-	struct archive_string_conv *sconv_utf8;
-	char			 format_name[64];
-
-#ifdef HAVE_ZLIB_H
-	z_stream		 stream;
-	char			 stream_valid;
-#endif
-	struct lzx_stream	 xstrm;
-};
-
-static int	archive_read_format_cab_bid(struct archive_read *, int);
-static int	archive_read_format_cab_options(struct archive_read *,
-		    const char *, const char *);
-static int	archive_read_format_cab_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	archive_read_format_cab_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_cab_read_data_skip(struct archive_read *);
-static int	archive_read_format_cab_cleanup(struct archive_read *);
-
-static int	cab_skip_sfx(struct archive_read *);
-static time_t	cab_dos_time(const unsigned char *);
-static int	cab_read_data(struct archive_read *, const void **,
-		    size_t *, int64_t *);
-static int	cab_read_header(struct archive_read *);
-static uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t);
-static uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t);
-static void	cab_checksum_update(struct archive_read *, size_t);
-static int	cab_checksum_finish(struct archive_read *);
-static int	cab_next_cfdata(struct archive_read *);
-static const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *);
-static const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *);
-static const void *cab_read_ahead_cfdata_deflate(struct archive_read *,
-		    ssize_t *);
-static const void *cab_read_ahead_cfdata_lzx(struct archive_read *,
-		    ssize_t *);
-static int64_t	cab_consume_cfdata(struct archive_read *, int64_t);
-static int64_t	cab_minimum_consume_cfdata(struct archive_read *, int64_t);
-static int	lzx_decode_init(struct lzx_stream *, int);
-static int	lzx_read_blocks(struct lzx_stream *, int);
-static int	lzx_decode_blocks(struct lzx_stream *, int);
-static void	lzx_decode_free(struct lzx_stream *);
-static void	lzx_translation(struct lzx_stream *, void *, size_t, uint32_t);
-static void	lzx_cleanup_bitstream(struct lzx_stream *);
-static int	lzx_decode(struct lzx_stream *, int);
-static int	lzx_read_pre_tree(struct lzx_stream *);
-static int	lzx_read_bitlen(struct lzx_stream *, struct huffman *, int);
-static int	lzx_huffman_init(struct huffman *, size_t, int);
-static void	lzx_huffman_free(struct huffman *);
-static int	lzx_make_huffman_table(struct huffman *);
-static inline int lzx_decode_huffman(struct huffman *, unsigned);
-
-
-int
-archive_read_support_format_cab(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct cab *cab;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_cab");
-
-	cab = (struct cab *)calloc(1, sizeof(*cab));
-	if (cab == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate CAB data");
-		return (ARCHIVE_FATAL);
-	}
-	archive_string_init(&cab->ws);
-	archive_wstring_ensure(&cab->ws, 256);
-
-	r = __archive_read_register_format(a,
-	    cab,
-	    "cab",
-	    archive_read_format_cab_bid,
-	    archive_read_format_cab_options,
-	    archive_read_format_cab_read_header,
-	    archive_read_format_cab_read_data,
-	    archive_read_format_cab_read_data_skip,
-	    NULL,
-	    archive_read_format_cab_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK)
-		free(cab);
-	return (ARCHIVE_OK);
-}
-
-static int
-find_cab_magic(const char *p)
-{
-	switch (p[4]) {
-	case 0:
-		/*
-		 * Note: Self-Extraction program has 'MSCF' string in their
-		 * program. If we were finding 'MSCF' string only, we got
-		 * wrong place for Cabinet header, thus, we have to check
-		 * following four bytes which are reserved and must be set
-		 * to zero.
-		 */
-		if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
-			return 0;
-		return 5;
-	case 'F': return 1;
-	case 'C': return 2;
-	case 'S': return 3;
-	case 'M': return 4;
-	default:  return 5;
-	}
-}
-
-static int
-archive_read_format_cab_bid(struct archive_read *a, int best_bid)
-{
-	const char *p;
-	ssize_t bytes_avail, offset, window;
-
-	/* If there's already a better bid than we can ever
-	   make, don't bother testing. */
-	if (best_bid > 64)
-		return (-1);
-
-	if ((p = __archive_read_ahead(a, 8, NULL)) == NULL)
-		return (-1);
-
-	if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
-		return (64);
-
-	/*
-	 * Attempt to handle self-extracting archives
-	 * by noting a PE header and searching forward
-	 * up to 128k for a 'MSCF' marker.
-	 */
-	if (p[0] == 'M' && p[1] == 'Z') {
-		offset = 0;
-		window = 4096;
-		while (offset < (1024 * 128)) {
-			const char *h = __archive_read_ahead(a, offset + window,
-			    &bytes_avail);
-			if (h == NULL) {
-				/* Remaining bytes are less than window. */
-				window >>= 1;
-				if (window < 128)
-					return (0);
-				continue;
-			}
-			p = h + offset;
-			while (p + 8 < h + bytes_avail) {
-				int next;
-				if ((next = find_cab_magic(p)) == 0)
-					return (64);
-				p += next;
-			}
-			offset = p - h;
-		}
-	}
-	return (0);
-}
-
-static int
-archive_read_format_cab_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct cab *cab;
-	int ret = ARCHIVE_FAILED;
-
-	cab = (struct cab *)(a->format->data);
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "cab: hdrcharset option needs a character-set name");
-		else {
-			cab->sconv = archive_string_conversion_from_charset(
-			    &a->archive, val, 0);
-			if (cab->sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-cab_skip_sfx(struct archive_read *a)
-{
-	const char *p, *q;
-	size_t skip;
-	ssize_t bytes, window;
-
-	window = 4096;
-	for (;;) {
-		const char *h = __archive_read_ahead(a, window, &bytes);
-		if (h == NULL) {
-			/* Remaining size are less than window. */
-			window >>= 1;
-			if (window < 128) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Couldn't find out CAB header");
-				return (ARCHIVE_FATAL);
-			}
-			continue;
-		}
-		p = h;
-		q = p + bytes;
-
-		/*
-		 * Scan ahead until we find something that looks
-		 * like the cab header.
-		 */
-		while (p + 8 < q) {
-			int next;
-			if ((next = find_cab_magic(p)) == 0) {
-				skip = p - h;
-				__archive_read_consume(a, skip);
-				return (ARCHIVE_OK);
-			}
-			p += next;
-		}
-		skip = p - h;
-		__archive_read_consume(a, skip);
-	}
-}
-
-static int
-truncated_error(struct archive_read *a)
-{
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Truncated CAB header");
-	return (ARCHIVE_FATAL);
-}
-
-static ssize_t
-cab_strnlen(const unsigned char *p, size_t maxlen)
-{
-	size_t i;
-
-	for (i = 0; i <= maxlen; i++) {
-		if (p[i] == 0)
-			break;
-	}
-	if (i > maxlen)
-		return (-1);/* invalid */
-	return ((ssize_t)i);
-}
-
-/* Read bytes as much as remaining. */
-static const void *
-cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail)
-{
-	const void *p;
-
-	while (min > 0) {
-		p = __archive_read_ahead(a, min, avail);
-		if (p != NULL)
-			return (p);
-		min--;
-	}
-	return (NULL);
-}
-
-/* Convert a path separator '\' -> '/' */
-static int
-cab_convert_path_separator_1(struct archive_string *fn, unsigned char attr)
-{
-	size_t i;
-	int mb;
-
-	/* Easy check if we have '\' in multi-byte string. */
-	mb = 0;
-	for (i = 0; i < archive_strlen(fn); i++) {
-		if (fn->s[i] == '\\') {
-			if (mb) {
-				/* This may be second byte of multi-byte
-				 * character. */
-				break;
-			}
-			fn->s[i] = '/';
-			mb = 0;
-		} else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF))
-			mb = 1;
-		else
-			mb = 0;
-	}
-	if (i == archive_strlen(fn))
-		return (0);
-	return (-1);
-}
-
-/*
- * Replace a character '\' with '/' in wide character.
- */
-static void
-cab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry)
-{
-	const wchar_t *wp;
-	size_t i;
-
-	/* If a conversion to wide character failed, force the replacement. */
-	if ((wp = archive_entry_pathname_w(entry)) != NULL) {
-		archive_wstrcpy(&(cab->ws), wp);
-		for (i = 0; i < archive_strlen(&(cab->ws)); i++) {
-			if (cab->ws.s[i] == L'\\')
-				cab->ws.s[i] = L'/';
-		}
-		archive_entry_copy_pathname_w(entry, cab->ws.s);
-	}
-}
-
-/*
- * Read CFHEADER, CFFOLDER and CFFILE.
- */
-static int
-cab_read_header(struct archive_read *a)
-{
-	const unsigned char *p;
-	struct cab *cab;
-	struct cfheader *hd;
-	size_t bytes, used;
-	ssize_t len;
-	int64_t skip;
-	int err, i;
-	int cur_folder, prev_folder;
-	uint32_t offset32;
-	
-	a->archive.archive_format = ARCHIVE_FORMAT_CAB;
-	if (a->archive.archive_format_name == NULL)
-		a->archive.archive_format_name = "CAB";
-
-	if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
-		return (truncated_error(a));
-
-	cab = (struct cab *)(a->format->data);
-	if (cab->found_header == 0 &&
-	    p[0] == 'M' && p[1] == 'Z') {
-		/* This is an executable?  Must be self-extracting... */
-		err = cab_skip_sfx(a);
-		if (err < ARCHIVE_WARN)
-			return (err);
-
-		/* Re-read header after processing the SFX. */
-		if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
-			return (truncated_error(a));
-	}
-
-	cab->cab_offset = 0;
-	/*
-	 * Read CFHEADER.
-	 */
-	hd = &cab->cfheader;
-	if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' ||
-	    p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Couldn't find out CAB header");
-		return (ARCHIVE_FATAL);
-	}
-	hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet);
-	hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles);
-	hd->minor = p[CFHEADER_versionMinor];
-	hd->major = p[CFHEADER_versionMajor];
-	hd->folder_count = archive_le16dec(p + CFHEADER_cFolders);
-	if (hd->folder_count == 0)
-		goto invalid;
-	hd->file_count = archive_le16dec(p + CFHEADER_cFiles);
-	if (hd->file_count == 0)
-		goto invalid;
-	hd->flags = archive_le16dec(p + CFHEADER_flags);
-	hd->setid = archive_le16dec(p + CFHEADER_setID);
-	hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet);
-	used = CFHEADER_iCabinet + 2;
-	if (hd->flags & RESERVE_PRESENT) {
-		uint16_t cfheader;
-		cfheader = archive_le16dec(p + CFHEADER_cbCFHeader);
-		if (cfheader > 60000U)
-			goto invalid;
-		hd->cffolder = p[CFHEADER_cbCFFolder];
-		hd->cfdata = p[CFHEADER_cbCFData];
-		used += 4;/* cbCFHeader, cbCFFolder and cbCFData */
-		used += cfheader;/* abReserve */
-	} else
-		hd->cffolder = 0;/* Avoid compiling warning. */
-	if (hd->flags & PREV_CABINET) {
-		/* How many bytes are used for szCabinetPrev. */
-		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
-			return (truncated_error(a));
-		if ((len = cab_strnlen(p + used, 255)) <= 0)
-			goto invalid;
-		used += len + 1;
-		/* How many bytes are used for szDiskPrev. */
-		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
-			return (truncated_error(a));
-		if ((len = cab_strnlen(p + used, 255)) <= 0)
-			goto invalid;
-		used += len + 1;
-	}
-	if (hd->flags & NEXT_CABINET) {
-		/* How many bytes are used for szCabinetNext. */
-		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
-			return (truncated_error(a));
-		if ((len = cab_strnlen(p + used, 255)) <= 0)
-			goto invalid;
-		used += len + 1;
-		/* How many bytes are used for szDiskNext. */
-		if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
-			return (truncated_error(a));
-		if ((len = cab_strnlen(p + used, 255)) <= 0)
-			goto invalid;
-		used += len + 1;
-	}
-	__archive_read_consume(a, used);
-	cab->cab_offset += used;
-	used = 0;
-
-	/*
-	 * Read CFFOLDER.
-	 */
-	hd->folder_array = (struct cffolder *)calloc(
-	    hd->folder_count, sizeof(struct cffolder));
-	if (hd->folder_array == NULL)
-		goto nomem;
-	
-	bytes = 8;
-	if (hd->flags & RESERVE_PRESENT)
-		bytes += hd->cffolder;
-	bytes *= hd->folder_count;
-	if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL)
-		return (truncated_error(a));
-	offset32 = 0;
-	for (i = 0; i < hd->folder_count; i++) {
-		struct cffolder *folder = &(hd->folder_array[i]);
-		folder->cfdata_offset_in_cab =
-		    archive_le32dec(p + CFFOLDER_coffCabStart);
-		folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData);
-		folder->comptype =
-		    archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F;
-		folder->compdata =
-		    archive_le16dec(p+CFFOLDER_typeCompress) >> 8;
-		/* Get a compression name. */
-		if (folder->comptype <
-		    sizeof(compression_name) / sizeof(compression_name[0]))
-			folder->compname = compression_name[folder->comptype];
-		else
-			folder->compname = "UNKNOWN";
-		p += 8;
-		used += 8;
-		if (hd->flags & RESERVE_PRESENT) {
-			p += hd->cffolder;/* abReserve */
-			used += hd->cffolder;
-		}
-		/*
-		 * Sanity check if each data is acceptable.
-		 */
-		if (offset32 >= folder->cfdata_offset_in_cab)
-			goto invalid;
-		offset32 = folder->cfdata_offset_in_cab;
-
-		/* Set a request to initialize zlib for the CFDATA of
-		 * this folder. */
-		folder->decompress_init = 0;
-	}
-	__archive_read_consume(a, used);
-	cab->cab_offset += used;
-
-	/*
-	 * Read CFFILE.
-	 */
-	/* Seek read pointer to the offset of CFFILE if needed. */
-	skip = (int64_t)hd->files_offset - cab->cab_offset;
-	if (skip <  0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid offset of CFFILE %jd < %jd",
-		    (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset);
-		return (ARCHIVE_FATAL);
-	}
-	if (skip) {
-		__archive_read_consume(a, skip);
-		cab->cab_offset += skip;
-	}
-	/* Allocate memory for CFDATA */
-	hd->file_array = (struct cffile *)calloc(
-	    hd->file_count, sizeof(struct cffile));
-	if (hd->file_array == NULL)
-		goto nomem;
-
-	prev_folder = -1;
-	for (i = 0; i < hd->file_count; i++) {
-		struct cffile *file = &(hd->file_array[i]);
-		ssize_t avail;
-
-		if ((p = __archive_read_ahead(a, 16, NULL)) == NULL)
-			return (truncated_error(a));
-		file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile);
-		file->offset = archive_le32dec(p + CFFILE_uoffFolderStart);
-		file->folder = archive_le16dec(p + CFFILE_iFolder);
-		file->mtime = cab_dos_time(p + CFFILE_date_time);
-		file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs);
-		__archive_read_consume(a, 16);
-
-		cab->cab_offset += 16;
-		if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL)
-			return (truncated_error(a));
-		if ((len = cab_strnlen(p, avail-1)) <= 0)
-			goto invalid;
-
-		/* Copy a pathname.  */
-		archive_string_init(&(file->pathname));
-		archive_strncpy(&(file->pathname), p, len);
-		__archive_read_consume(a, len + 1);
-		cab->cab_offset += len + 1;
-
-		/*
-		 * Sanity check if each data is acceptable.
-		 */
-		if (file->uncompressed_size > 0x7FFF8000)
-			goto invalid;/* Too large */
-		if ((int64_t)file->offset + (int64_t)file->uncompressed_size
-		    > ARCHIVE_LITERAL_LL(0x7FFF8000))
-			goto invalid;/* Too large */
-		switch (file->folder) {
-		case iFoldCONTINUED_TO_NEXT:
-			/* This must be last file in a folder. */
-			if (i != hd->file_count -1)
-				goto invalid;
-			cur_folder = hd->folder_count -1;
-			break;
-		case iFoldCONTINUED_PREV_AND_NEXT:
-			/* This must be only one file in a folder. */
-			if (hd->file_count != 1)
-				goto invalid;
-			/* FALL THROUGH */
-		case iFoldCONTINUED_FROM_PREV:
-			/* This must be first file in a folder. */
-			if (i != 0)
-				goto invalid;
-			prev_folder = cur_folder = 0;
-			offset32 = file->offset;
-			break;
-		default:
-			if (file->folder >= hd->folder_count)
-				goto invalid;
-			cur_folder = file->folder;
-			break;
-		}
-		/* Dot not back track. */
-		if (cur_folder < prev_folder)
-			goto invalid;
-		if (cur_folder != prev_folder)
-			offset32 = 0;
-		prev_folder = cur_folder;
-
-		/* Make sure there are not any blanks from last file
-		 * contents. */
-		if (offset32 != file->offset)
-			goto invalid;
-		offset32 += file->uncompressed_size;
-
-		/* CFDATA is available for file contents. */
-		if (file->uncompressed_size > 0 &&
-		    hd->folder_array[cur_folder].cfdata_count == 0)
-			goto invalid;
-	}
-
-	if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Multivolume cabinet file is unsupported");
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-invalid:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Invalid CAB header");
-	return (ARCHIVE_FATAL);
-nomem:
-	archive_set_error(&a->archive, ENOMEM,
-	    "Can't allocate memory for CAB data");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-archive_read_format_cab_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct cab *cab;
-	struct cfheader *hd;
-	struct cffolder *prev_folder;
-	struct cffile *file;
-	struct archive_string_conv *sconv;
-	int err = ARCHIVE_OK, r;
-	
-	cab = (struct cab *)(a->format->data);
-	if (cab->found_header == 0) {
-		err = cab_read_header(a); 
-		if (err < ARCHIVE_WARN)
-			return (err);
-		/* We've found the header. */
-		cab->found_header = 1;
-	}
-	hd = &cab->cfheader;
-
-	if (hd->file_index >= hd->file_count) {
-		cab->end_of_archive = 1;
-		return (ARCHIVE_EOF);
-	}
-	file = &hd->file_array[hd->file_index++];
-
-	cab->end_of_entry = 0;
-	cab->end_of_entry_cleanup = 0;
-	cab->entry_compressed_bytes_read = 0;
-	cab->entry_uncompressed_bytes_read = 0;
-	cab->entry_unconsumed = 0;
-	cab->entry_cffile = file;
-
-	/*
-	 * Choose a proper folder.
-	 */
-	prev_folder = cab->entry_cffolder;
-	switch (file->folder) {
-	case iFoldCONTINUED_FROM_PREV:
-	case iFoldCONTINUED_PREV_AND_NEXT:
-		cab->entry_cffolder = &hd->folder_array[0];
-		break;
-	case iFoldCONTINUED_TO_NEXT:
-		cab->entry_cffolder = &hd->folder_array[hd->folder_count-1];
-		break;
-	default:
-		cab->entry_cffolder = &hd->folder_array[file->folder];
-		break;
-	}
-	/* If a cffolder of this file is changed, reset a cfdata to read
-	 * file contents from next cfdata. */
-	if (prev_folder != cab->entry_cffolder)
-		cab->entry_cfdata = NULL;
-
-	/* If a pathname is UTF-8, prepare a string conversion object
-	 * for UTF-8 and use it. */
-	if (file->attr & ATTR_NAME_IS_UTF) {
-		if (cab->sconv_utf8 == NULL) {
-			cab->sconv_utf8 =
-			    archive_string_conversion_from_charset(
-				&(a->archive), "UTF-8", 1);
-			if (cab->sconv_utf8 == NULL)
-				return (ARCHIVE_FATAL);
-		}
-		sconv = cab->sconv_utf8;
-	} else if (cab->sconv != NULL) {
-		/* Choose the conversion specified by the option. */
-		sconv = cab->sconv;
-	} else {
-		/* Choose the default conversion. */
-		if (!cab->init_default_conversion) {
-			cab->sconv_default =
-			    archive_string_default_conversion_for_read(
-			      &(a->archive));
-			cab->init_default_conversion = 1;
-		}
-		sconv = cab->sconv_default;
-	}
-
-	/*
-	 * Set a default value and common data
-	 */
-	r = cab_convert_path_separator_1(&(file->pathname), file->attr);
-	if (archive_entry_copy_pathname_l(entry, file->pathname.s,
-	    archive_strlen(&(file->pathname)), sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Pathname cannot be converted "
-		    "from %s to current locale.",
-		    archive_string_conversion_charset_name(sconv));
-		err = ARCHIVE_WARN;
-	}
-	if (r < 0) {
-		/* Convert a path separator '\' -> '/' */
-		cab_convert_path_separator_2(cab, entry);
-	}
-
-	archive_entry_set_size(entry, file->uncompressed_size);
-	if (file->attr & ATTR_RDONLY)
-		archive_entry_set_mode(entry, AE_IFREG | 0555);
-	else
-		archive_entry_set_mode(entry, AE_IFREG | 0666);
-	archive_entry_set_mtime(entry, file->mtime, 0);
-
-	cab->entry_bytes_remaining = file->uncompressed_size;
-	cab->entry_offset = 0;
-	/* We don't need compress data. */
-	if (file->uncompressed_size == 0)
-		cab->end_of_entry_cleanup = cab->end_of_entry = 1;
-
-	/* Set up a more descriptive format name. */
-	snprintf(cab->format_name, sizeof(cab->format_name), "CAB %d.%d (%s)",
-	    hd->major, hd->minor, cab->entry_cffolder->compname);
-	a->archive.archive_format_name = cab->format_name;
-
-	return (err);
-}
-
-static int
-archive_read_format_cab_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	int r;
-
-	switch (cab->entry_cffile->folder) {
-	case iFoldCONTINUED_FROM_PREV:
-	case iFoldCONTINUED_TO_NEXT:
-	case iFoldCONTINUED_PREV_AND_NEXT:
-		*buff = NULL;
-		*size = 0;
-		*offset = 0;
-		archive_clear_error(&a->archive);
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Cannot restore this file split in multivolume.");
-		return (ARCHIVE_FAILED);
-	default:
-		break;
-	}
-	if (cab->read_data_invoked == 0) {
-		if (cab->bytes_skipped) {
-			if (cab->entry_cfdata == NULL) {
-				r = cab_next_cfdata(a);
-				if (r < 0)
-					return (r);
-			}
-			if (cab_consume_cfdata(a, cab->bytes_skipped) < 0)
-				return (ARCHIVE_FATAL);
-			cab->bytes_skipped = 0;
-		}
-		cab->read_data_invoked = 1;
-	}
-	if (cab->entry_unconsumed) {
-		/* Consume as much as the compressor actually used. */
-		r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
-		cab->entry_unconsumed = 0;
-		if (r < 0)
-			return (r);
-	}
-	if (cab->end_of_archive || cab->end_of_entry) {
-		if (!cab->end_of_entry_cleanup) {
-			/* End-of-entry cleanup done. */
-			cab->end_of_entry_cleanup = 1;
-		}
-		*offset = cab->entry_offset;
-		*size = 0;
-		*buff = NULL;
-		return (ARCHIVE_EOF);
-	}
-
-	return (cab_read_data(a, buff, size, offset));
-}
-
-static uint32_t
-cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
-{
-	const unsigned char *b;
-	unsigned u32num;
-	uint32_t sum;
-
-	u32num = (unsigned)bytes / 4;
-	sum = seed;
-	b = p;
-	for (;u32num > 0; --u32num) {
-		sum ^= archive_le32dec(b);
-		b += 4;
-	}
-	return (sum);
-}
-
-static uint32_t
-cab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed)
-{
-	const unsigned char *b;
-	uint32_t sum;
-	uint32_t t;
-
-	sum = cab_checksum_cfdata_4(p, bytes, seed);
-	b = p;
-	b += bytes & ~3;
-	t = 0;
-	switch (bytes & 3) {
-	case 3:
-		t |= ((uint32_t)(*b++)) << 16;
-		/* FALL THROUGH */
-	case 2:
-		t |= ((uint32_t)(*b++)) << 8;
-		/* FALL THROUGH */
-	case 1:
-		t |= *b;
-		/* FALL THROUGH */
-	default:
-		break;
-	}
-	sum ^= t;
-
-	return (sum);
-}
-
-static void
-cab_checksum_update(struct archive_read *a, size_t bytes)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata = cab->entry_cfdata;
-	const unsigned char *p;
-	size_t sumbytes;
-
-	if (cfdata->sum == 0 || cfdata->sum_ptr == NULL)
-		return;
-	/*
-	 * Calculate the sum of this CFDATA.
-	 * Make sure CFDATA must be calculated in four bytes.
-	 */
-	p = cfdata->sum_ptr;
-	sumbytes = bytes;
-	if (cfdata->sum_extra_avail) {
-		while (cfdata->sum_extra_avail < 4 && sumbytes > 0) {
-			cfdata->sum_extra[
-			    cfdata->sum_extra_avail++] = *p++;
-			sumbytes--;
-		}
-		if (cfdata->sum_extra_avail == 4) {
-			cfdata->sum_calculated = cab_checksum_cfdata_4(
-			    cfdata->sum_extra, 4, cfdata->sum_calculated);
-			cfdata->sum_extra_avail = 0;
-		}
-	}
-	if (sumbytes) {
-		int odd = sumbytes & 3;
-		if ((int)(sumbytes - odd) > 0)
-			cfdata->sum_calculated = cab_checksum_cfdata_4(
-			    p, sumbytes - odd, cfdata->sum_calculated);
-		if (odd)
-			memcpy(cfdata->sum_extra, p + sumbytes - odd, odd);
-		cfdata->sum_extra_avail = odd;
-	}
-	cfdata->sum_ptr = NULL;
-}
-
-static int
-cab_checksum_finish(struct archive_read *a)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata = cab->entry_cfdata;
-	int l;
-
-	/* Do not need to compute a sum. */
-	if (cfdata->sum == 0)
-		return (ARCHIVE_OK);
-
-	/*
-	 * Calculate the sum of remaining CFDATA.
-	 */
-	if (cfdata->sum_extra_avail) {
-		cfdata->sum_calculated =
-		    cab_checksum_cfdata(cfdata->sum_extra,
-		       cfdata->sum_extra_avail, cfdata->sum_calculated);
-		cfdata->sum_extra_avail = 0;
-	}
-
-	l = 4;
-	if (cab->cfheader.flags & RESERVE_PRESENT)
-		l += cab->cfheader.cfdata;
-	cfdata->sum_calculated = cab_checksum_cfdata(
-	    cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
-	if (cfdata->sum_calculated != cfdata->sum) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes",
-		    cab->entry_cffolder->cfdata_index -1,
-		    cfdata->sum, cfdata->sum_calculated,
-		    cfdata->compressed_size);
-		return (ARCHIVE_FAILED);
-#endif
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Read CFDATA if needed.
- */
-static int
-cab_next_cfdata(struct archive_read *a)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata = cab->entry_cfdata;
-
-	/* There are remaining bytes in current CFDATA, use it first. */
-	if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0)
-		return (ARCHIVE_OK);
-
-	if (cfdata == NULL) {
-		int64_t skip;
-
-		cab->entry_cffolder->cfdata_index = 0;
-
-		/* Seek read pointer to the offset of CFDATA if needed. */
-		skip = cab->entry_cffolder->cfdata_offset_in_cab
-			- cab->cab_offset;
-		if (skip < 0) {
-			int folder_index;
-			switch (cab->entry_cffile->folder) {
-			case iFoldCONTINUED_FROM_PREV:
-			case iFoldCONTINUED_PREV_AND_NEXT:
-				folder_index = 0;
-				break;
-			case iFoldCONTINUED_TO_NEXT:
-				folder_index = cab->cfheader.folder_count-1;
-				break;
-			default:
-				folder_index = cab->entry_cffile->folder;
-				break;
-			}
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid offset of CFDATA in folder(%d) %jd < %jd",
-			    folder_index,
-			    (intmax_t)cab->entry_cffolder->cfdata_offset_in_cab,
-			    (intmax_t)cab->cab_offset);
-			return (ARCHIVE_FATAL);
-		}
-		if (skip > 0) {
-			if (__archive_read_consume(a, skip) < 0)
-				return (ARCHIVE_FATAL);
-			cab->cab_offset =
-			    cab->entry_cffolder->cfdata_offset_in_cab;
-		}
-	}
-
-	/*
-	 * Read a CFDATA.
-	 */
-	if (cab->entry_cffolder->cfdata_index <
-	    cab->entry_cffolder->cfdata_count) {
-		const unsigned char *p;
-		int l;
-
-		cfdata = &(cab->entry_cffolder->cfdata);
-		cab->entry_cffolder->cfdata_index++;
-		cab->entry_cfdata = cfdata;
-		cfdata->sum_calculated = 0;
-		cfdata->sum_extra_avail = 0;
-		cfdata->sum_ptr = NULL;
-		l = 8;
-		if (cab->cfheader.flags & RESERVE_PRESENT)
-			l += cab->cfheader.cfdata;
-		if ((p = __archive_read_ahead(a, l, NULL)) == NULL)
-			return (truncated_error(a));
-		cfdata->sum = archive_le32dec(p + CFDATA_csum);
-		cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData);
-		cfdata->compressed_bytes_remaining = cfdata->compressed_size;
-		cfdata->uncompressed_size =
-		    archive_le16dec(p + CFDATA_cbUncomp);
-		cfdata->uncompressed_bytes_remaining =
-		    cfdata->uncompressed_size;
-		cfdata->uncompressed_avail = 0;
-		cfdata->read_offset = 0;
-		cfdata->unconsumed = 0;
-
-		/*
-		 * Sanity check if data size is acceptable.
-		 */
-		if (cfdata->compressed_size == 0 ||
-		    cfdata->compressed_size > (0x8000+6144))
-			goto invalid;
-		if (cfdata->uncompressed_size > 0x8000)
-			goto invalid;
-		if (cfdata->uncompressed_size == 0) {
-			switch (cab->entry_cffile->folder) {
-			case iFoldCONTINUED_PREV_AND_NEXT:
-			case iFoldCONTINUED_TO_NEXT:
-				break;
-			case iFoldCONTINUED_FROM_PREV:
-			default:
-				goto invalid;
-			}
-		}
-		/* If CFDATA is not last in a folder, an uncompressed
-		 * size must be 0x8000(32KBi) */
-		if ((cab->entry_cffolder->cfdata_index <
-		     cab->entry_cffolder->cfdata_count) &&
-		       cfdata->uncompressed_size != 0x8000)
-			goto invalid;
-
-		/* A compressed data size and an uncompressed data size must
-		 * be the same in no compression mode. */
-		if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
-		    cfdata->compressed_size != cfdata->uncompressed_size)
-			goto invalid;
-
-		/*
-		 * Save CFDATA image for sum check.
-		 */
-		if (cfdata->memimage_size < (size_t)l) {
-			free(cfdata->memimage);
-			cfdata->memimage = malloc(l);
-			if (cfdata->memimage == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for CAB data");
-				return (ARCHIVE_FATAL);
-			}
-			cfdata->memimage_size = l;
-		}
-		memcpy(cfdata->memimage, p, l);
-
-		/* Consume bytes as much as we used. */
-		__archive_read_consume(a, l);
-		cab->cab_offset += l;
-	} else if (cab->entry_cffolder->cfdata_count > 0) {
-		/* Run out of all CFDATA in a folder. */
-		cfdata->compressed_size = 0;
-		cfdata->uncompressed_size = 0;
-		cfdata->compressed_bytes_remaining = 0;
-		cfdata->uncompressed_bytes_remaining = 0;
-	} else {
-		/* Current folder does not have any CFDATA. */
-		cfdata = &(cab->entry_cffolder->cfdata);
-		cab->entry_cfdata = cfdata;
-		memset(cfdata, 0, sizeof(*cfdata));
-	}
-	return (ARCHIVE_OK);
-invalid:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Invalid CFDATA");
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Read ahead CFDATA.
- */
-static const void *
-cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	int err;
-
-	err = cab_next_cfdata(a);
-	if (err < ARCHIVE_OK) {
-		*avail = err;
-		return (NULL);
-	}
-
-	switch (cab->entry_cffolder->comptype) {
-	case COMPTYPE_NONE:
-		return (cab_read_ahead_cfdata_none(a, avail));
-	case COMPTYPE_MSZIP:
-		return (cab_read_ahead_cfdata_deflate(a, avail));
-	case COMPTYPE_LZX:
-		return (cab_read_ahead_cfdata_lzx(a, avail));
-	default: /* Unsupported compression. */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported CAB compression : %s",
-		    cab->entry_cffolder->compname);
-		*avail = ARCHIVE_FAILED;
-		return (NULL);
-	}
-}
-
-/*
- * Read ahead CFDATA as uncompressed data.
- */
-static const void *
-cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata;
-	const void *d;
-
-	cfdata = cab->entry_cfdata;
-
-	/*
-	 * Note: '1' here is a performance optimization.
-	 * Recall that the decompression layer returns a count of
-	 * available bytes; asking for more than that forces the
-	 * decompressor to combine reads by copying data.
-	 */
-	d = __archive_read_ahead(a, 1, avail);
-	if (*avail <= 0) {
-		*avail = truncated_error(a);
-		return (NULL);
-	}
-	if (*avail > cfdata->uncompressed_bytes_remaining)
-		*avail = cfdata->uncompressed_bytes_remaining;
-	cfdata->uncompressed_avail = cfdata->uncompressed_size;
-	cfdata->unconsumed = *avail;
-	cfdata->sum_ptr = d;
-	return (d);
-}
-
-/*
- * Read ahead CFDATA as deflate data.
- */
-#ifdef HAVE_ZLIB_H
-static const void *
-cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata;
-	const void *d;
-	int r, mszip;
-	uint16_t uavail;
-	char eod = 0;
-
-	cfdata = cab->entry_cfdata;
-	/* If the buffer hasn't been allocated, allocate it now. */
-	if (cab->uncompressed_buffer == NULL) {
-		cab->uncompressed_buffer_size = 0x8000;
-		cab->uncompressed_buffer
-		    = (unsigned char *)malloc(cab->uncompressed_buffer_size);
-		if (cab->uncompressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for CAB reader");
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-
-	uavail = cfdata->uncompressed_avail;
-	if (uavail == cfdata->uncompressed_size) {
-		d = cab->uncompressed_buffer + cfdata->read_offset;
-		*avail = uavail - cfdata->read_offset;
-		return (d);
-	}
-
-	if (!cab->entry_cffolder->decompress_init) {
-		cab->stream.next_in = NULL;
-		cab->stream.avail_in = 0;
-		cab->stream.total_in = 0;
-		cab->stream.next_out = NULL;
-		cab->stream.avail_out = 0;
-		cab->stream.total_out = 0;
-		if (cab->stream_valid)
-			r = inflateReset(&cab->stream);
-		else
-			r = inflateInit2(&cab->stream,
-			    -15 /* Don't check for zlib header */);
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't initialize deflate decompression.");
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-		/* Stream structure has been set up. */
-		cab->stream_valid = 1;
-		/* We've initialized decompression for this stream. */
-		cab->entry_cffolder->decompress_init = 1;
-	}
-
-	if (cfdata->compressed_bytes_remaining == cfdata->compressed_size)
-		mszip = 2;
-	else
-		mszip = 0;
-	eod = 0;
-	cab->stream.total_out = uavail;
-	/*
-	 * We always uncompress all data in current CFDATA.
-	 */
-	while (!eod && cab->stream.total_out < cfdata->uncompressed_size) {
-		ssize_t bytes_avail;
-
-		cab->stream.next_out =
-		    cab->uncompressed_buffer + cab->stream.total_out;
-		cab->stream.avail_out =
-		    cfdata->uncompressed_size - cab->stream.total_out;
-
-		d = __archive_read_ahead(a, 1, &bytes_avail);
-		if (bytes_avail <= 0) {
-			*avail = truncated_error(a);
-			return (NULL);
-		}
-		if (bytes_avail > cfdata->compressed_bytes_remaining)
-			bytes_avail = cfdata->compressed_bytes_remaining;
-		/*
-		 * A bug in zlib.h: stream.next_in should be marked 'const'
-		 * but isn't (the library never alters data through the
-		 * next_in pointer, only reads it).  The result: this ugly
-		 * cast to remove 'const'.
-		 */
-		cab->stream.next_in = (Bytef *)(uintptr_t)d;
-		cab->stream.avail_in = (uInt)bytes_avail;
-		cab->stream.total_in = 0;
-
-		/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
-		if (mszip > 0) {
-			if (bytes_avail <= 0)
-				goto nomszip;
-			if (bytes_avail <= mszip) {
-				if (mszip == 2) {
-					if (cab->stream.next_in[0] != 0x43)
-						goto nomszip;
-					if (bytes_avail > 1 &&
-					    cab->stream.next_in[1] != 0x4b)
-						goto nomszip;
-				} else if (cab->stream.next_in[0] != 0x4b)
-					goto nomszip;
-				cfdata->unconsumed = bytes_avail;
-				cfdata->sum_ptr = d;
-				if (cab_minimum_consume_cfdata(
-				    a, cfdata->unconsumed) < 0) {
-					*avail = ARCHIVE_FATAL;
-					return (NULL);
-				}
-				mszip -= (int)bytes_avail;
-				continue;
-			}
-			if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
-				goto nomszip;
-			else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 ||
-			    cab->stream.next_in[1] != 0x4b))
-				goto nomszip;
-			cab->stream.next_in += mszip;
-			cab->stream.avail_in -= mszip;
-			cab->stream.total_in += mszip;
-			mszip = 0;
-		}
-
-		r = inflate(&cab->stream, 0);
-		switch (r) {
-		case Z_OK:
-			break;
-		case Z_STREAM_END:
-			eod = 1;
-			break;
-		default:
-			goto zlibfailed;
-		}
-		cfdata->unconsumed = cab->stream.total_in;
-		cfdata->sum_ptr = d;
-		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-	uavail = (uint16_t)cab->stream.total_out;
-
-	if (uavail < cfdata->uncompressed_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid uncompressed size (%d < %d)",
-		    uavail, cfdata->uncompressed_size);
-		*avail = ARCHIVE_FATAL;
-		return (NULL);
-	}
-
-	/*
-	 * Note: I suspect there is a bug in makecab.exe because, in rare
-	 * case, compressed bytes are still remaining regardless we have
-	 * gotten all uncompressed bytes, which size is recorded in CFDATA,
-	 * as much as we need, and we have to use the garbage so as to
-	 * correctly compute the sum of CFDATA accordingly.
-	 */
-	if (cfdata->compressed_bytes_remaining > 0) {
-		ssize_t bytes_avail;
-
-		d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
-		    &bytes_avail);
-		if (bytes_avail <= 0) {
-			*avail = truncated_error(a);
-			return (NULL);
-		}
-		cfdata->unconsumed = cfdata->compressed_bytes_remaining;
-		cfdata->sum_ptr = d;
-		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-
-	/*
-	 * Set dictionary data for decompressing of next CFDATA, which
-	 * in the same folder. This is why we always do decompress CFDATA
-	 * even if beginning CFDATA or some of CFDATA are not used in
-	 * skipping file data.
-	 */
-	if (cab->entry_cffolder->cfdata_index <
-	    cab->entry_cffolder->cfdata_count) {
-		r = inflateReset(&cab->stream);
-		if (r != Z_OK)
-			goto zlibfailed;
-		r = inflateSetDictionary(&cab->stream,
-		    cab->uncompressed_buffer, cfdata->uncompressed_size);
-		if (r != Z_OK)
-			goto zlibfailed;
-	}
-
-	d = cab->uncompressed_buffer + cfdata->read_offset;
-	*avail = uavail - cfdata->read_offset;
-	cfdata->uncompressed_avail = uavail;
-
-	return (d);
-
-zlibfailed:
-	switch (r) {
-	case Z_MEM_ERROR:
-		archive_set_error(&a->archive, ENOMEM,
-		    "Out of memory for deflate decompression");
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Deflate decompression failed (%d)", r);
-		break;
-	}
-	*avail = ARCHIVE_FATAL;
-	return (NULL);
-nomszip:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "CFDATA incorrect(no MSZIP signature)");
-	*avail = ARCHIVE_FATAL;
-	return (NULL);
-}
-
-#else /* HAVE_ZLIB_H */
-
-static const void *
-cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
-{
-	*avail = ARCHIVE_FATAL;
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "libarchive compiled without deflate support (no libz)");
-	return (NULL);
-}
-
-#endif /* HAVE_ZLIB_H */
-
-static const void *
-cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata;
-	const void *d;
-	int r;
-	uint16_t uavail;
-
-	cfdata = cab->entry_cfdata;
-	/* If the buffer hasn't been allocated, allocate it now. */
-	if (cab->uncompressed_buffer == NULL) {
-		cab->uncompressed_buffer_size = 0x8000;
-		cab->uncompressed_buffer
-		    = (unsigned char *)malloc(cab->uncompressed_buffer_size);
-		if (cab->uncompressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for CAB reader");
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-
-	uavail = cfdata->uncompressed_avail;
-	if (uavail == cfdata->uncompressed_size) {
-		d = cab->uncompressed_buffer + cfdata->read_offset;
-		*avail = uavail - cfdata->read_offset;
-		return (d);
-	}
-
-	if (!cab->entry_cffolder->decompress_init) {
-		r = lzx_decode_init(&cab->xstrm,
-		    cab->entry_cffolder->compdata);
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't initialize LZX decompression.");
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-		/* We've initialized decompression for this stream. */
-		cab->entry_cffolder->decompress_init = 1;
-	}
-
-	/* Clean up remaining bits of previous CFDATA. */
-	lzx_cleanup_bitstream(&cab->xstrm);
-	cab->xstrm.total_out = uavail;
-	while (cab->xstrm.total_out < cfdata->uncompressed_size) {
-		ssize_t bytes_avail;
-
-		cab->xstrm.next_out =
-		    cab->uncompressed_buffer + cab->xstrm.total_out;
-		cab->xstrm.avail_out =
-		    cfdata->uncompressed_size - cab->xstrm.total_out;
-
-		d = __archive_read_ahead(a, 1, &bytes_avail);
-		if (bytes_avail <= 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated CAB file data");
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-		if (bytes_avail > cfdata->compressed_bytes_remaining)
-			bytes_avail = cfdata->compressed_bytes_remaining;
-
-		cab->xstrm.next_in = d;
-		cab->xstrm.avail_in = bytes_avail;
-		cab->xstrm.total_in = 0;
-		r = lzx_decode(&cab->xstrm,
-		    cfdata->compressed_bytes_remaining == bytes_avail);
-		switch (r) {
-		case ARCHIVE_OK:
-		case ARCHIVE_EOF:
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "LZX decompression failed (%d)", r);
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-		cfdata->unconsumed = cab->xstrm.total_in;
-		cfdata->sum_ptr = d;
-		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-
-	uavail = (uint16_t)cab->xstrm.total_out;
-	/*
-	 * Make sure a read pointer advances to next CFDATA.
-	 */
-	if (cfdata->compressed_bytes_remaining > 0) {
-		ssize_t bytes_avail;
-
-		d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
-		    &bytes_avail);
-		if (bytes_avail <= 0) {
-			*avail = truncated_error(a);
-			return (NULL);
-		}
-		cfdata->unconsumed = cfdata->compressed_bytes_remaining;
-		cfdata->sum_ptr = d;
-		if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
-			*avail = ARCHIVE_FATAL;
-			return (NULL);
-		}
-	}
-
-	/*
-	 * Translation reversal of x86 processor CALL byte sequence(E8).
-	 */
-	lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
-	    cfdata->uncompressed_size,
-	    (cab->entry_cffolder->cfdata_index-1) * 0x8000);
-
-	d = cab->uncompressed_buffer + cfdata->read_offset;
-	*avail = uavail - cfdata->read_offset;
-	cfdata->uncompressed_avail = uavail;
-
-	return (d);
-}
-
-/*
- * Consume CFDATA.
- * We always decompress CFDATA to consume CFDATA as much as we need
- * in uncompressed bytes because all CFDATA in a folder are related
- * so we do not skip any CFDATA without decompressing.
- * Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or
- * iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for
- * the CFFILE is remaining bytes of previous Multivolume CAB file.
- */
-static int64_t
-cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata;
-	int64_t cbytes, rbytes;
-	int err;
-
-	rbytes = cab_minimum_consume_cfdata(a, consumed_bytes);
-	if (rbytes < 0)
-		return (ARCHIVE_FATAL);
-
-	cfdata = cab->entry_cfdata;
-	while (rbytes > 0) {
-		ssize_t avail;
-
-		if (cfdata->compressed_size == 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Invalid CFDATA");
-			return (ARCHIVE_FATAL);
-		}
-		cbytes = cfdata->uncompressed_bytes_remaining;
-		if (cbytes > rbytes)
-			cbytes = rbytes;
-		rbytes -= cbytes;
-
-		if (cfdata->uncompressed_avail == 0 &&
-		   (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
-		    cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
-			/* We have not read any data yet. */
-			if (cbytes == cfdata->uncompressed_bytes_remaining) {
-				/* Skip whole current CFDATA. */
-				__archive_read_consume(a,
-				    cfdata->compressed_size);
-				cab->cab_offset += cfdata->compressed_size;
-				cfdata->compressed_bytes_remaining = 0;
-				cfdata->uncompressed_bytes_remaining = 0;
-				err = cab_next_cfdata(a);
-				if (err < 0)
-					return (err);
-				cfdata = cab->entry_cfdata;
-				if (cfdata->uncompressed_size == 0) {
-					switch (cab->entry_cffile->folder) {
-					case iFoldCONTINUED_PREV_AND_NEXT:
-					case iFoldCONTINUED_TO_NEXT:
-					case iFoldCONTINUED_FROM_PREV:
-						rbytes = 0;
-						break;
-					default:
-						break;
-					}
-				}
-				continue;
-			}
-			cfdata->read_offset += (uint16_t)cbytes;
-			cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
-			break;
-		} else if (cbytes == 0) {
-			err = cab_next_cfdata(a);
-			if (err < 0)
-				return (err);
-			cfdata = cab->entry_cfdata;
-			if (cfdata->uncompressed_size == 0) {
-				switch (cab->entry_cffile->folder) {
-				case iFoldCONTINUED_PREV_AND_NEXT:
-				case iFoldCONTINUED_TO_NEXT:
-				case iFoldCONTINUED_FROM_PREV:
-					return (ARCHIVE_FATAL);
-				default:
-					break;
-				}
-			}
-			continue;
-		}
-		while (cbytes > 0) {
-			(void)cab_read_ahead_cfdata(a, &avail);
-			if (avail <= 0)
-				return (ARCHIVE_FATAL);
-			if (avail > cbytes)
-				avail = (ssize_t)cbytes;
-			if (cab_minimum_consume_cfdata(a, avail) < 0)
-				return (ARCHIVE_FATAL);
-			cbytes -= avail;
-		}
-	}
-	return (consumed_bytes);
-}
-
-/*
- * Consume CFDATA as much as we have already gotten and
- * compute the sum of CFDATA.
- */
-static int64_t
-cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfdata *cfdata;
-	int64_t cbytes, rbytes;
-	int err;
-
-	cfdata = cab->entry_cfdata;
-	rbytes = consumed_bytes;
-	if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
-		if (consumed_bytes < cfdata->unconsumed)
-			cbytes = consumed_bytes;
-		else
-			cbytes = cfdata->unconsumed;
-		rbytes -= cbytes; 
-		cfdata->read_offset += (uint16_t)cbytes;
-		cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
-		cfdata->unconsumed -= cbytes;
-	} else {
-		cbytes = cfdata->uncompressed_avail - cfdata->read_offset;
-		if (cbytes > 0) {
-			if (consumed_bytes < cbytes)
-				cbytes = consumed_bytes;
-			rbytes -= cbytes;
-			cfdata->read_offset += (uint16_t)cbytes;
-			cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
-		}
-
-		if (cfdata->unconsumed) {
-			cbytes = cfdata->unconsumed;
-			cfdata->unconsumed = 0;
-		} else
-			cbytes = 0;
-	}
-	if (cbytes) {
-		/* Compute the sum. */
-		cab_checksum_update(a, (size_t)cbytes);
-
-		/* Consume as much as the compressor actually used. */
-		__archive_read_consume(a, cbytes);
-		cab->cab_offset += cbytes;
-		cfdata->compressed_bytes_remaining -= (uint16_t)cbytes;
-		if (cfdata->compressed_bytes_remaining == 0) {
-			err = cab_checksum_finish(a);
-			if (err < 0)
-				return (err);
-		}
-	}
-	return (rbytes);
-}
-
-/*
- * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
- * cab->end_of_entry if it consumes all of the data.
- */
-static int
-cab_read_data(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	ssize_t bytes_avail;
-
-	if (cab->entry_bytes_remaining == 0) {
-		*buff = NULL;
-		*size = 0;
-		*offset = cab->entry_offset;
-		cab->end_of_entry = 1;
-		return (ARCHIVE_OK);
-	}
-
-	*buff = cab_read_ahead_cfdata(a, &bytes_avail);
-	if (bytes_avail <= 0) {
-		*buff = NULL;
-		*size = 0;
-		*offset = 0;
-		if (bytes_avail == 0 &&
-		    cab->entry_cfdata->uncompressed_size == 0) {
-			/* All of CFDATA in a folder has been handled. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
-			return (ARCHIVE_FATAL);
-		} else
-			return ((int)bytes_avail);
-	}
-	if (bytes_avail > cab->entry_bytes_remaining)
-		bytes_avail = (ssize_t)cab->entry_bytes_remaining;
-
-	*size = bytes_avail;
-	*offset = cab->entry_offset;
-	cab->entry_offset += bytes_avail;
-	cab->entry_bytes_remaining -= bytes_avail;
-	if (cab->entry_bytes_remaining == 0)
-		cab->end_of_entry = 1;
-	cab->entry_unconsumed = bytes_avail;
-	if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
-		/* Don't consume more than current entry used. */
-		if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed)
-			cab->entry_cfdata->unconsumed = cab->entry_unconsumed;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_cab_read_data_skip(struct archive_read *a)
-{
-	struct cab *cab;
-	int64_t bytes_skipped;
-	int r;
-
-	cab = (struct cab *)(a->format->data);
-
-	if (cab->end_of_archive)
-		return (ARCHIVE_EOF);
-
-	if (!cab->read_data_invoked) {
-		cab->bytes_skipped += cab->entry_bytes_remaining;
-		cab->entry_bytes_remaining = 0;
-		/* This entry is finished and done. */
-		cab->end_of_entry_cleanup = cab->end_of_entry = 1;
-		return (ARCHIVE_OK);
-	}
-
-	if (cab->entry_unconsumed) {
-		/* Consume as much as the compressor actually used. */
-		r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
-		cab->entry_unconsumed = 0;
-		if (r < 0)
-			return (r);
-	} else if (cab->entry_cfdata == NULL) {
-		r = cab_next_cfdata(a);
-		if (r < 0)
-			return (r);
-	}
-
-	/* if we've already read to end of data, we're done. */
-	if (cab->end_of_entry_cleanup)
-		return (ARCHIVE_OK);
-
-	/*
-	 * If the length is at the beginning, we can skip the
-	 * compressed data much more quickly.
-	 */
-	bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-
-	/* If the compression type is none(uncompressed), we've already
-	 * consumed data as much as the current entry size. */
-	if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
-	    cab->entry_cfdata != NULL)
-		cab->entry_cfdata->unconsumed = 0;
-
-	/* This entry is finished and done. */
-	cab->end_of_entry_cleanup = cab->end_of_entry = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_cab_cleanup(struct archive_read *a)
-{
-	struct cab *cab = (struct cab *)(a->format->data);
-	struct cfheader *hd = &cab->cfheader;
-	int i;
-
-	if (hd->folder_array != NULL) {
-		for (i = 0; i < hd->folder_count; i++)
-			free(hd->folder_array[i].cfdata.memimage);
-		free(hd->folder_array);
-	}
-	if (hd->file_array != NULL) {
-		for (i = 0; i < cab->cfheader.file_count; i++)
-			archive_string_free(&(hd->file_array[i].pathname));
-		free(hd->file_array);
-	}
-#ifdef HAVE_ZLIB_H
-	if (cab->stream_valid)
-		inflateEnd(&cab->stream);
-#endif
-	lzx_decode_free(&cab->xstrm);
-	archive_wstring_free(&cab->ws);
-	free(cab->uncompressed_buffer);
-	free(cab);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-cab_dos_time(const unsigned char *p)
-{
-	int msTime, msDate;
-	struct tm ts;
-
-	msDate = archive_le16dec(p);
-	msTime = archive_le16dec(p+2);
-
-	memset(&ts, 0, sizeof(ts));
-	ts.tm_year = ((msDate >> 9) & 0x7f) + 80;   /* Years since 1900. */
-	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1;     /* Month number.     */
-	ts.tm_mday = msDate & 0x1f;		    /* Day of month.     */
-	ts.tm_hour = (msTime >> 11) & 0x1f;
-	ts.tm_min = (msTime >> 5) & 0x3f;
-	ts.tm_sec = (msTime << 1) & 0x3e;
-	ts.tm_isdst = -1;
-	return (mktime(&ts));
-}
-
-/*****************************************************************
- *
- * LZX decompression code.
- *
- *****************************************************************/
-
-/*
- * Initialize LZX decoder.
- *
- * Returns ARCHIVE_OK if initialization was successful.
- * Returns ARCHIVE_FAILED if w_bits has unsupported value.
- * Returns ARCHIVE_FATAL if initialization failed; memory allocation
- * error occurred.
- */
-static int
-lzx_decode_init(struct lzx_stream *strm, int w_bits)
-{
-	struct lzx_dec *ds;
-	int slot, w_size, w_slot;
-	int base, footer;
-	int base_inc[18];
-
-	if (strm->ds == NULL) {
-		strm->ds = calloc(1, sizeof(*strm->ds));
-		if (strm->ds == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	ds = strm->ds;
-	ds->error = ARCHIVE_FAILED;
-
-	/* Allow bits from 15(32KBi) up to 21(2MBi) */
-	if (w_bits < SLOT_BASE || w_bits > SLOT_MAX)
-		return (ARCHIVE_FAILED);
-
-	ds->error = ARCHIVE_FATAL;
-
-	/*
-	 * Alloc window
-	 */
-	w_size = ds->w_size;
-	w_slot = slots[w_bits - SLOT_BASE];
-	ds->w_size = 1U << w_bits;
-	ds->w_mask = ds->w_size -1;
-	if (ds->w_buff == NULL || w_size != ds->w_size) {
-		free(ds->w_buff);
-		ds->w_buff = malloc(ds->w_size);
-		if (ds->w_buff == NULL)
-			return (ARCHIVE_FATAL);
-		free(ds->pos_tbl);
-		ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
-		if (ds->pos_tbl == NULL)
-			return (ARCHIVE_FATAL);
-	}
-
-	for (footer = 0; footer < 18; footer++)
-		base_inc[footer] = 1 << footer;
-	base = footer = 0;
-	for (slot = 0; slot < w_slot; slot++) {
-		int n;
-		if (footer == 0)
-			base = slot;
-		else
-			base += base_inc[footer];
-		if (footer < 17) {
-			footer = -2;
-			for (n = base; n; n >>= 1)
-				footer++;
-			if (footer <= 0)
-				footer = 0;
-		}
-		ds->pos_tbl[slot].base = base;
-		ds->pos_tbl[slot].footer_bits = footer;
-	}
-
-	ds->w_pos = 0;
-	ds->state = 0;
-	ds->br.cache_buffer = 0;
-	ds->br.cache_avail = 0;
-	ds->r0 = ds->r1 = ds->r2 = 1;
-
-	/* Initialize aligned offset tree. */
-	if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Initialize pre-tree. */
-	if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Initialize Main tree. */
-	if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16)
-	    != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Initialize Length tree. */
-	if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	ds->error = 0;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Release LZX decoder.
- */
-static void
-lzx_decode_free(struct lzx_stream *strm)
-{
-
-	if (strm->ds == NULL)
-		return;
-	free(strm->ds->w_buff);
-	free(strm->ds->pos_tbl);
-	lzx_huffman_free(&(strm->ds->at));
-	lzx_huffman_free(&(strm->ds->pt));
-	lzx_huffman_free(&(strm->ds->mt));
-	lzx_huffman_free(&(strm->ds->lt));
-	free(strm->ds);
-	strm->ds = NULL;
-}
-
-/*
- * E8 Call Translation reversal.
- */
-static void
-lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
-{
-	struct lzx_dec *ds = strm->ds;
-	unsigned char *b, *end;
-
-	if (!ds->translation || size <= 10)
-		return;
-	b = p;
-	end = b + size - 10;
-	while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) {
-		size_t i = b - (unsigned char *)p;
-		int32_t cp, displacement, value;
-
-		cp = (int32_t)(offset + (uint32_t)i);
-		value = archive_le32dec(&b[1]);
-		if (value >= -cp && value < (int32_t)ds->translation_size) {
-			if (value >= 0)
-				displacement = value - cp;
-			else
-				displacement = value + ds->translation_size;
-			archive_le32enc(&b[1], (uint32_t)displacement);
-		}
-		b += 5;
-	}
-}
-
-/*
- * Bit stream reader.
- */
-/* Check that the cache buffer has enough bits. */
-#define lzx_br_has(br, n)	((br)->cache_avail >= n)
-/* Get compressed data by bit. */
-#define lzx_br_bits(br, n)				\
-	(((uint32_t)((br)->cache_buffer >>		\
-		((br)->cache_avail - (n)))) & cache_masks[n])
-#define lzx_br_bits_forced(br, n)			\
-	(((uint32_t)((br)->cache_buffer <<		\
-		((n) - (br)->cache_avail))) & cache_masks[n])
-/* Read ahead to make sure the cache buffer has enough compressed data we
- * will use.
- *  True  : completed, there is enough data in the cache buffer.
- *  False : we met that strm->next_in is empty, we have to get following
- *          bytes. */
-#define lzx_br_read_ahead_0(strm, br, n)	\
-	(lzx_br_has((br), (n)) || lzx_br_fillup(strm, br))
-/*  True  : the cache buffer has some bits as much as we need.
- *  False : there are no enough bits in the cache buffer to be used,
- *          we have to get following bytes if we could. */
-#define lzx_br_read_ahead(strm, br, n)	\
-	(lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n)))
-
-/* Notify how many bits we consumed. */
-#define lzx_br_consume(br, n)	((br)->cache_avail -= (n))
-#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f)
-
-#define lzx_br_is_unaligned(br)	((br)->cache_avail & 0x0f)
-
-static const uint32_t cache_masks[] = {
-	0x00000000, 0x00000001, 0x00000003, 0x00000007,
-	0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
-	0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
-	0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
-	0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
-	0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
-	0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
-	0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
-	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
-};
-
-/*
- * Shift away used bits in the cache data and fill it up with following bits.
- * Call this when cache buffer does not have enough bits you need.
- *
- * Returns 1 if the cache buffer is full.
- * Returns 0 if the cache buffer is not full; input buffer is empty.
- */
-static int
-lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
-{
-/*
- * x86 processor family can read misaligned data without an access error.
- */
-	int n = CACHE_BITS - br->cache_avail;
-
-	for (;;) {
-		switch (n >> 4) {
-		case 4:
-			if (strm->avail_in >= 8) {
-				br->cache_buffer =
-				    ((uint64_t)strm->next_in[1]) << 56 |
-				    ((uint64_t)strm->next_in[0]) << 48 |
-				    ((uint64_t)strm->next_in[3]) << 40 |
-				    ((uint64_t)strm->next_in[2]) << 32 |
-				    ((uint32_t)strm->next_in[5]) << 24 |
-				    ((uint32_t)strm->next_in[4]) << 16 |
-				    ((uint32_t)strm->next_in[7]) << 8 |
-				     (uint32_t)strm->next_in[6];
-				strm->next_in += 8;
-				strm->avail_in -= 8;
-				br->cache_avail += 8 * 8;
-				return (1);
-			}
-			break;
-		case 3:
-			if (strm->avail_in >= 6) {
-				br->cache_buffer =
-		 		   (br->cache_buffer << 48) |
-				    ((uint64_t)strm->next_in[1]) << 40 |
-				    ((uint64_t)strm->next_in[0]) << 32 |
-				    ((uint64_t)strm->next_in[3]) << 24 |
-				    ((uint64_t)strm->next_in[2]) << 16 |
-				    ((uint64_t)strm->next_in[5]) << 8 |
-				     (uint64_t)strm->next_in[4];
-				strm->next_in += 6;
-				strm->avail_in -= 6;
-				br->cache_avail += 6 * 8;
-				return (1);
-			}
-			break;
-		case 0:
-			/* We have enough compressed data in
-			 * the cache buffer.*/
-			return (1);
-		default:
-			break;
-		}
-		if (strm->avail_in < 2) {
-			/* There is not enough compressed data to
-			 * fill up the cache buffer. */
-			if (strm->avail_in == 1) {
-				br->odd = *strm->next_in++;
-				strm->avail_in--;
-				br->have_odd = 1;
-			}
-			return (0);
-		}
-		br->cache_buffer =
-		   (br->cache_buffer << 16) |
-		    archive_le16dec(strm->next_in);
-		strm->next_in += 2;
-		strm->avail_in -= 2;
-		br->cache_avail += 16;
-		n -= 16;
-	}
-}
-
-static void
-lzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br)
-{
-	int n = CACHE_BITS - br->cache_avail;
-
-	if (br->have_odd && n >= 16 && strm->avail_in > 0) {
-		br->cache_buffer =
-		   (br->cache_buffer << 16) |
-		   ((uint16_t)(*strm->next_in)) << 8 | br->odd;
-		strm->next_in++;
-		strm->avail_in--;
-		br->cache_avail += 16;
-		br->have_odd = 0;
-	}
-}
-
-static void
-lzx_cleanup_bitstream(struct lzx_stream *strm)
-{
-	strm->ds->br.cache_avail = 0;
-	strm->ds->br.have_odd = 0;
-}
-
-/*
- * Decode LZX.
- *
- * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty.
- *    Please set available buffer and call this function again.
- * 2. Returns ARCHIVE_EOF if decompression has been completed.
- * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data
- *    is broken or you do not set 'last' flag properly.
- */
-#define ST_RD_TRANSLATION	0
-#define ST_RD_TRANSLATION_SIZE	1
-#define ST_RD_BLOCK_TYPE	2
-#define ST_RD_BLOCK_SIZE	3
-#define ST_RD_ALIGNMENT		4
-#define ST_RD_R0		5
-#define ST_RD_R1		6
-#define ST_RD_R2		7
-#define ST_COPY_UNCOMP1		8
-#define ST_COPY_UNCOMP2		9
-#define ST_RD_ALIGNED_OFFSET	10
-#define ST_RD_VERBATIM		11
-#define ST_RD_PRE_MAIN_TREE_256	12
-#define ST_MAIN_TREE_256	13
-#define ST_RD_PRE_MAIN_TREE_REM	14
-#define ST_MAIN_TREE_REM	15
-#define ST_RD_PRE_LENGTH_TREE	16
-#define ST_LENGTH_TREE		17
-#define ST_MAIN			18
-#define ST_LENGTH		19
-#define ST_OFFSET		20
-#define ST_REAL_POS		21
-#define ST_COPY			22
-
-static int
-lzx_decode(struct lzx_stream *strm, int last)
-{
-	struct lzx_dec *ds = strm->ds;
-	int64_t avail_in;
-	int r;
-
-	if (ds->error)
-		return (ds->error);
-
-	avail_in = strm->avail_in;
-	lzx_br_fixup(strm, &(ds->br));
-	do {
-		if (ds->state < ST_MAIN)
-			r = lzx_read_blocks(strm, last);
-		else {
-			int64_t bytes_written = strm->avail_out;
-			r = lzx_decode_blocks(strm, last);
-			bytes_written -= strm->avail_out;
-			strm->next_out += bytes_written;
-			strm->total_out += bytes_written;
-		}
-	} while (r == 100);
-	strm->total_in += avail_in - strm->avail_in;
-	return (r);
-}
-
-static int
-lzx_read_blocks(struct lzx_stream *strm, int last)
-{
-	struct lzx_dec *ds = strm->ds;
-	struct lzx_br *br = &(ds->br);
-	int i, r;
-
-	for (;;) {
-		switch (ds->state) {
-		case ST_RD_TRANSLATION:
-			if (!lzx_br_read_ahead(strm, br, 1)) {
-				ds->state = ST_RD_TRANSLATION;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			ds->translation = lzx_br_bits(br, 1);
-			lzx_br_consume(br, 1);
-			/* FALL THROUGH */
-		case ST_RD_TRANSLATION_SIZE:
-			if (ds->translation) {
-				if (!lzx_br_read_ahead(strm, br, 32)) {
-					ds->state = ST_RD_TRANSLATION_SIZE;
-					if (last)
-						goto failed;
-					return (ARCHIVE_OK);
-				}
-				ds->translation_size = lzx_br_bits(br, 16);
-				lzx_br_consume(br, 16);
-				ds->translation_size <<= 16;
-				ds->translation_size |= lzx_br_bits(br, 16);
-				lzx_br_consume(br, 16);
-			}
-			/* FALL THROUGH */
-		case ST_RD_BLOCK_TYPE:
-			if (!lzx_br_read_ahead(strm, br, 3)) {
-				ds->state = ST_RD_BLOCK_TYPE;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			ds->block_type = lzx_br_bits(br, 3);
-			lzx_br_consume(br, 3);
-			/* Check a block type. */
-			switch (ds->block_type) {
-			case VERBATIM_BLOCK:
-			case ALIGNED_OFFSET_BLOCK:
-			case UNCOMPRESSED_BLOCK:
-				break;
-			default:
-				goto failed;/* Invalid */
-			}
-			/* FALL THROUGH */
-		case ST_RD_BLOCK_SIZE:
-			if (!lzx_br_read_ahead(strm, br, 24)) {
-				ds->state = ST_RD_BLOCK_SIZE;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			ds->block_size = lzx_br_bits(br, 8);
-			lzx_br_consume(br, 8);
-			ds->block_size <<= 16;
-			ds->block_size |= lzx_br_bits(br, 16);
-			lzx_br_consume(br, 16);
-			if (ds->block_size == 0)
-				goto failed;
-			ds->block_bytes_avail = ds->block_size;
-			if (ds->block_type != UNCOMPRESSED_BLOCK) {
-				if (ds->block_type == VERBATIM_BLOCK)
-					ds->state = ST_RD_VERBATIM;
-				else
-					ds->state = ST_RD_ALIGNED_OFFSET;
-				break;
-			}
-			/* FALL THROUGH */
-		case ST_RD_ALIGNMENT:
-			/*
-			 * Handle an Uncompressed Block.
-			 */
-			/* Skip padding to align following field on
-			 * 16-bit boundary. */
-			if (lzx_br_is_unaligned(br))
-				lzx_br_consume_unaligned_bits(br);
-			else {
-				if (lzx_br_read_ahead(strm, br, 16))
-					lzx_br_consume(br, 16);
-				else {
-					ds->state = ST_RD_ALIGNMENT;
-					if (last)
-						goto failed;
-					return (ARCHIVE_OK);
-				}
-			}
-			/* Preparation to read repeated offsets R0,R1 and R2. */
-			ds->rbytes_avail = 0;
-			ds->state = ST_RD_R0;
-			/* FALL THROUGH */
-		case ST_RD_R0:
-		case ST_RD_R1:
-		case ST_RD_R2:
-			do {
-				uint16_t u16;
-				/* Drain bits in the cache buffer of
-				 * bit-stream. */
-				if (lzx_br_has(br, 32)) {
-					u16 = lzx_br_bits(br, 16);
-					lzx_br_consume(br, 16);
-					archive_le16enc(ds->rbytes, u16);
-					u16 = lzx_br_bits(br, 16);
-					lzx_br_consume(br, 16);
-					archive_le16enc(ds->rbytes+2, u16);
-					ds->rbytes_avail = 4;
-				} else if (lzx_br_has(br, 16)) {
-					u16 = lzx_br_bits(br, 16);
-					lzx_br_consume(br, 16);
-					archive_le16enc(ds->rbytes, u16);
-					ds->rbytes_avail = 2;
-				}
-				if (ds->rbytes_avail < 4 && ds->br.have_odd) {
-					ds->rbytes[ds->rbytes_avail++] =
-					    ds->br.odd;
-					ds->br.have_odd = 0;
-				}
-				while (ds->rbytes_avail < 4) {
-					if (strm->avail_in <= 0) {
-						if (last)
-							goto failed;
-						return (ARCHIVE_OK);
-					}
-					ds->rbytes[ds->rbytes_avail++] =
-					    *strm->next_in++;
-					strm->avail_in--;
-				}
-				ds->rbytes_avail = 0;
-				if (ds->state == ST_RD_R0) {
-					ds->r0 = archive_le32dec(ds->rbytes);
-					if (ds->r0 < 0)
-						goto failed;
-					ds->state = ST_RD_R1;
-				} else if (ds->state == ST_RD_R1) {
-					ds->r1 = archive_le32dec(ds->rbytes);
-					if (ds->r1 < 0)
-						goto failed;
-					ds->state = ST_RD_R2;
-				} else if (ds->state == ST_RD_R2) {
-					ds->r2 = archive_le32dec(ds->rbytes);
-					if (ds->r2 < 0)
-						goto failed;
-					/* We've gotten all repeated offsets. */
-					ds->state = ST_COPY_UNCOMP1;
-				}
-			} while (ds->state != ST_COPY_UNCOMP1);
-			/* FALL THROUGH */
-		case ST_COPY_UNCOMP1:
-			/*
-			 * Copy bytes form next_in to next_out directly.
-			 */
-			while (ds->block_bytes_avail) {
-				int l;
-
-				if (strm->avail_out <= 0)
-					/* Output buffer is empty. */
-					return (ARCHIVE_OK);
-				if (strm->avail_in <= 0) {
-					/* Input buffer is empty. */
-					if (last)
-						goto failed;
-					return (ARCHIVE_OK);
-				}
-				l = (int)ds->block_bytes_avail;
-				if (l > ds->w_size - ds->w_pos)
-					l = ds->w_size - ds->w_pos;
-				if (l > strm->avail_out)
-					l = (int)strm->avail_out;
-				if (l > strm->avail_in)
-					l = (int)strm->avail_in;
-				memcpy(strm->next_out, strm->next_in, l);
-				memcpy(&(ds->w_buff[ds->w_pos]),
-				    strm->next_in, l);
-				strm->next_in += l;
-				strm->avail_in -= l;
-				strm->next_out += l;
-				strm->avail_out -= l;
-				strm->total_out += l;
-				ds->w_pos = (ds->w_pos + l) & ds->w_mask;
-				ds->block_bytes_avail -= l;
-			}
-			/* FALL THROUGH */
-		case ST_COPY_UNCOMP2:
-			/* Re-align; skip padding byte. */
-			if (ds->block_size & 1) {
-				if (strm->avail_in <= 0) {
-					/* Input buffer is empty. */
-					ds->state = ST_COPY_UNCOMP2;
-					if (last)
-						goto failed;
-					return (ARCHIVE_OK);
-				}
-				strm->next_in++;
-				strm->avail_in --;
-			}
-			/* This block ended. */
-			ds->state = ST_RD_BLOCK_TYPE;
-			return (ARCHIVE_EOF);
-			/********************/
-		case ST_RD_ALIGNED_OFFSET:
-			/*
-			 * Read Aligned offset tree.
-			 */
-			if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) {
-				ds->state = ST_RD_ALIGNED_OFFSET;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			memset(ds->at.freq, 0, sizeof(ds->at.freq));
-			for (i = 0; i < ds->at.len_size; i++) {
-				ds->at.bitlen[i] = lzx_br_bits(br, 3);
-				ds->at.freq[ds->at.bitlen[i]]++;
-				lzx_br_consume(br, 3);
-			}
-			if (!lzx_make_huffman_table(&ds->at))
-				goto failed;
-			/* FALL THROUGH */
-		case ST_RD_VERBATIM:
-			ds->loop = 0;
-			/* FALL THROUGH */
-		case ST_RD_PRE_MAIN_TREE_256:
-			/*
-			 * Read Pre-tree for first 256 elements of main tree.
-			 */
-			if (!lzx_read_pre_tree(strm)) {
-				ds->state = ST_RD_PRE_MAIN_TREE_256;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			if (!lzx_make_huffman_table(&ds->pt))
-				goto failed;
-			ds->loop = 0;
-			/* FALL THROUGH */
-		case ST_MAIN_TREE_256:
-			/*
-			 * Get path lengths of first 256 elements of main tree.
-			 */
-			r = lzx_read_bitlen(strm, &ds->mt, 256);
-			if (r < 0)
-				goto failed;
-			else if (!r) {
-				ds->state = ST_MAIN_TREE_256;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			ds->loop = 0;
-			/* FALL THROUGH */
-		case ST_RD_PRE_MAIN_TREE_REM:
-			/*
-			 * Read Pre-tree for remaining elements of main tree.
-			 */
-			if (!lzx_read_pre_tree(strm)) {
-				ds->state = ST_RD_PRE_MAIN_TREE_REM;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			if (!lzx_make_huffman_table(&ds->pt))
-				goto failed;
-			ds->loop = 256;
-			/* FALL THROUGH */
-		case ST_MAIN_TREE_REM:
-			/*
-			 * Get path lengths of remaining elements of main tree.
-			 */
-			r = lzx_read_bitlen(strm, &ds->mt, -1);
-			if (r < 0)
-				goto failed;
-			else if (!r) {
-				ds->state = ST_MAIN_TREE_REM;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			if (!lzx_make_huffman_table(&ds->mt))
-				goto failed;
-			ds->loop = 0;
-			/* FALL THROUGH */
-		case ST_RD_PRE_LENGTH_TREE:
-			/*
-			 * Read Pre-tree for remaining elements of main tree.
-			 */
-			if (!lzx_read_pre_tree(strm)) {
-				ds->state = ST_RD_PRE_LENGTH_TREE;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			if (!lzx_make_huffman_table(&ds->pt))
-				goto failed;
-			ds->loop = 0;
-			/* FALL THROUGH */
-		case ST_LENGTH_TREE:
-			/*
-			 * Get path lengths of remaining elements of main tree.
-			 */
-			r = lzx_read_bitlen(strm, &ds->lt, -1);
-			if (r < 0)
-				goto failed;
-			else if (!r) {
-				ds->state = ST_LENGTH_TREE;
-				if (last)
-					goto failed;
-				return (ARCHIVE_OK);
-			}
-			if (!lzx_make_huffman_table(&ds->lt))
-				goto failed;
-			ds->state = ST_MAIN;
-			return (100);
-		}
-	}
-failed:
-	return (ds->error = ARCHIVE_FAILED);
-}
-
-static int
-lzx_decode_blocks(struct lzx_stream *strm, int last)
-{
-	struct lzx_dec *ds = strm->ds;
-	struct lzx_br bre = ds->br;
-	struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
-	const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
-	unsigned char *noutp = strm->next_out;
-	unsigned char *endp = noutp + strm->avail_out;
-	unsigned char *w_buff = ds->w_buff;
-	unsigned char *at_bitlen = at->bitlen;
-	unsigned char *lt_bitlen = lt->bitlen;
-	unsigned char *mt_bitlen = mt->bitlen;
-	size_t block_bytes_avail = ds->block_bytes_avail;
-	int at_max_bits = at->max_bits;
-	int lt_max_bits = lt->max_bits;
-	int mt_max_bits = mt->max_bits;
-	int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos;
-	int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size;
-	int length_header = ds->length_header;
-	int offset_bits = ds->offset_bits;
-	int position_slot = ds->position_slot;
-	int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2;
-	int state = ds->state;
-	char block_type = ds->block_type;
-
-	for (;;) {
-		switch (state) {
-		case ST_MAIN:
-			for (;;) {
-				if (block_bytes_avail == 0) {
-					/* This block ended. */
-					ds->state = ST_RD_BLOCK_TYPE;
-					ds->br = bre;
-					ds->block_bytes_avail =
-					    block_bytes_avail;
-					ds->copy_len = copy_len;
-					ds->copy_pos = copy_pos;
-					ds->length_header = length_header;
-					ds->position_slot = position_slot;
-					ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
-					ds->w_pos = w_pos;
-					strm->avail_out = endp - noutp;
-					return (ARCHIVE_EOF);
-				}
-				if (noutp >= endp)
-					/* Output buffer is empty. */
-					goto next_data;
-
-				if (!lzx_br_read_ahead(strm, &bre,
-				    mt_max_bits)) {
-					if (!last)
-						goto next_data;
-					/* Remaining bits are less than
-					 * maximum bits(mt.max_bits) but maybe
-					 * it still remains as much as we need,
-					 * so we should try to use it with
-					 * dummy bits. */
-					c = lzx_decode_huffman(mt,
-					      lzx_br_bits_forced(
-				 	        &bre, mt_max_bits));
-					lzx_br_consume(&bre, mt_bitlen[c]);
-					if (!lzx_br_has(&bre, 0))
-						goto failed;/* Over read. */
-				} else {
-					c = lzx_decode_huffman(mt,
-					      lzx_br_bits(&bre, mt_max_bits));
-					lzx_br_consume(&bre, mt_bitlen[c]);
-				}
-				if (c > UCHAR_MAX)
-					break;
-				/*
-				 * 'c' is exactly literal code.
-				 */
-				/* Save a decoded code to reference it
-				 * afterward. */
-				w_buff[w_pos] = c;
-				w_pos = (w_pos + 1) & w_mask;
-				/* Store the decoded code to output buffer. */
-				*noutp++ = c;
-				block_bytes_avail--;
-			}
-			/*
-			 * Get a match code, its length and offset.
-			 */
-			c -= UCHAR_MAX + 1;
-			length_header = c & 7;
-			position_slot = c >> 3;
-			/* FALL THROUGH */
-		case ST_LENGTH:
-			/*
-			 * Get a length.
-			 */
-			if (length_header == 7) {
-				if (!lzx_br_read_ahead(strm, &bre,
-				    lt_max_bits)) {
-					if (!last) {
-						state = ST_LENGTH;
-						goto next_data;
-					}
-					c = lzx_decode_huffman(lt,
-					      lzx_br_bits_forced(
-					        &bre, lt_max_bits));
-					lzx_br_consume(&bre, lt_bitlen[c]);
-					if (!lzx_br_has(&bre, 0))
-						goto failed;/* Over read. */
-				} else {
-					c = lzx_decode_huffman(lt,
-					    lzx_br_bits(&bre, lt_max_bits));
-					lzx_br_consume(&bre, lt_bitlen[c]);
-				}
-				copy_len = c + 7 + 2;
-			} else
-				copy_len = length_header + 2;
-			if ((size_t)copy_len > block_bytes_avail)
-				goto failed;
-			/*
-			 * Get an offset.
-			 */
-			switch (position_slot) {
-			case 0: /* Use repeated offset 0. */
-				copy_pos = r0;
-				state = ST_REAL_POS;
-				continue;
-			case 1: /* Use repeated offset 1. */
-				copy_pos = r1;
-				/* Swap repeated offset. */
-				r1 = r0;
-				r0 = copy_pos;
-				state = ST_REAL_POS;
-				continue;
-			case 2: /* Use repeated offset 2. */
-				copy_pos = r2;
-				/* Swap repeated offset. */
-				r2 = r0;
-				r0 = copy_pos;
-				state = ST_REAL_POS;
-				continue;
-			default:
-				offset_bits =
-				    pos_tbl[position_slot].footer_bits;
-				break;
-			}
-			/* FALL THROUGH */
-		case ST_OFFSET:
-			/*
-			 * Get the offset, which is a distance from
-			 * current window position.
-			 */
-			if (block_type == ALIGNED_OFFSET_BLOCK &&
-			    offset_bits >= 3) {
-				int offbits = offset_bits - 3;
-
-				if (!lzx_br_read_ahead(strm, &bre, offbits)) {
-					state = ST_OFFSET;
-					if (last)
-						goto failed;
-					goto next_data;
-				}
-				copy_pos = lzx_br_bits(&bre, offbits) << 3;
-
-				/* Get an aligned number. */
-				if (!lzx_br_read_ahead(strm, &bre,
-				    offbits + at_max_bits)) {
-					if (!last) {
-						state = ST_OFFSET;
-						goto next_data;
-					}
-					lzx_br_consume(&bre, offbits);
-					c = lzx_decode_huffman(at,
-					      lzx_br_bits_forced(&bre,
-					        at_max_bits));
-					lzx_br_consume(&bre, at_bitlen[c]);
-					if (!lzx_br_has(&bre, 0))
-						goto failed;/* Over read. */
-				} else {
-					lzx_br_consume(&bre, offbits);
-					c = lzx_decode_huffman(at,
-					      lzx_br_bits(&bre, at_max_bits));
-					lzx_br_consume(&bre, at_bitlen[c]);
-				}
-				/* Add an aligned number. */
-				copy_pos += c;
-			} else {
-				if (!lzx_br_read_ahead(strm, &bre,
-				    offset_bits)) {
-					state = ST_OFFSET;
-					if (last)
-						goto failed;
-					goto next_data;
-				}
-				copy_pos = lzx_br_bits(&bre, offset_bits);
-				lzx_br_consume(&bre, offset_bits);
-			}
-			copy_pos += pos_tbl[position_slot].base -2;
-
-			/* Update repeated offset LRU queue. */
-			r2 = r1;
-			r1 = r0;
-			r0 = copy_pos;
-			/* FALL THROUGH */
-		case ST_REAL_POS:
-			/*
-			 * Compute a real position in window.
-			 */
-			copy_pos = (w_pos - copy_pos) & w_mask;
-			/* FALL THROUGH */
-		case ST_COPY:
-			/*
-			 * Copy several bytes as extracted data from the window
-			 * into the output buffer.
-			 */
-			for (;;) {
-				const unsigned char *s;
-				int l;
-
-				l = copy_len;
-				if (copy_pos > w_pos) {
-					if (l > w_size - copy_pos)
-						l = w_size - copy_pos;
-				} else {
-					if (l > w_size - w_pos)
-						l = w_size - w_pos;
-				}
-				if (noutp + l >= endp)
-					l = (int)(endp - noutp);
-				s = w_buff + copy_pos;
-				if (l >= 8 && ((copy_pos + l < w_pos)
-				  || (w_pos + l < copy_pos))) {
-					memcpy(w_buff + w_pos, s, l);
-					memcpy(noutp, s, l);
-				} else {
-					unsigned char *d;
-					int li;
-
-					d = w_buff + w_pos;
-					for (li = 0; li < l; li++)
-						noutp[li] = d[li] = s[li];
-				}
-				noutp += l;
-				copy_pos = (copy_pos + l) & w_mask;
-				w_pos = (w_pos + l) & w_mask;
-				block_bytes_avail -= l;
-				if (copy_len <= l)
-					/* A copy of current pattern ended. */
-					break;
-				copy_len -= l;
-				if (noutp >= endp) {
-					/* Output buffer is empty. */
-					state = ST_COPY;
-					goto next_data;
-				}
-			}
-			state = ST_MAIN;
-			break;
-		}
-	}
-failed:
-	return (ds->error = ARCHIVE_FAILED);
-next_data:
-	ds->br = bre;
-	ds->block_bytes_avail = block_bytes_avail;
-	ds->copy_len = copy_len;
-	ds->copy_pos = copy_pos;
-	ds->length_header = length_header;
-	ds->offset_bits = offset_bits;
-	ds->position_slot = position_slot;
-	ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
-	ds->state = state;
-	ds->w_pos = w_pos;
-	strm->avail_out = endp - noutp;
-	return (ARCHIVE_OK);
-}
-
-static int
-lzx_read_pre_tree(struct lzx_stream *strm)
-{
-	struct lzx_dec *ds = strm->ds;
-	struct lzx_br *br = &(ds->br);
-	int i;
-
-	if (ds->loop == 0)
-		memset(ds->pt.freq, 0, sizeof(ds->pt.freq));
-	for (i = ds->loop; i < ds->pt.len_size; i++) {
-		if (!lzx_br_read_ahead(strm, br, 4)) {
-			ds->loop = i;
-			return (0);
-		}
-		ds->pt.bitlen[i] = lzx_br_bits(br, 4);
-		ds->pt.freq[ds->pt.bitlen[i]]++;
-		lzx_br_consume(br, 4);
-	}
-	ds->loop = i;
-	return (1);
-}
-
-/*
- * Read a bunch of bit-lengths from pre-tree.
- */
-static int
-lzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end)
-{
-	struct lzx_dec *ds = strm->ds;
-	struct lzx_br *br = &(ds->br);
-	int c, i, j, ret, same;
-	unsigned rbits;
-
-	i = ds->loop;
-	if (i == 0)
-		memset(d->freq, 0, sizeof(d->freq));
-	ret = 0;
-	if (end < 0)
-		end = d->len_size;
-	while (i < end) {
-		ds->loop = i;
-		if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits))
-			goto getdata;
-		rbits = lzx_br_bits(br, ds->pt.max_bits);
-		c = lzx_decode_huffman(&(ds->pt), rbits);
-		switch (c) {
-		case 17:/* several zero lengths, from 4 to 19. */
-			if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4))
-				goto getdata;
-			lzx_br_consume(br, ds->pt.bitlen[c]);
-			same = lzx_br_bits(br, 4) + 4;
-			if (i + same > end)
-				return (-1);/* Invalid */
-			lzx_br_consume(br, 4);
-			for (j = 0; j < same; j++)
-				d->bitlen[i++] = 0;
-			break;
-		case 18:/* many zero lengths, from 20 to 51. */
-			if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5))
-				goto getdata;
-			lzx_br_consume(br, ds->pt.bitlen[c]);
-			same = lzx_br_bits(br, 5) + 20;
-			if (i + same > end)
-				return (-1);/* Invalid */
-			lzx_br_consume(br, 5);
-			memset(d->bitlen + i, 0, same);
-			i += same;
-			break;
-		case 19:/* a few same lengths. */
-			if (!lzx_br_read_ahead(strm, br,
-			    ds->pt.bitlen[c]+1+ds->pt.max_bits))
-				goto getdata;
-			lzx_br_consume(br, ds->pt.bitlen[c]);
-			same = lzx_br_bits(br, 1) + 4;
-			if (i + same > end)
-				return (-1);
-			lzx_br_consume(br, 1);
-			rbits = lzx_br_bits(br, ds->pt.max_bits);
-			c = lzx_decode_huffman(&(ds->pt), rbits);
-			lzx_br_consume(br, ds->pt.bitlen[c]);
-			c = (d->bitlen[i] - c + 17) % 17;
-			if (c < 0)
-				return (-1);/* Invalid */
-			for (j = 0; j < same; j++)
-				d->bitlen[i++] = c;
-			d->freq[c] += same;
-			break;
-		default:
-			lzx_br_consume(br, ds->pt.bitlen[c]);
-			c = (d->bitlen[i] - c + 17) % 17;
-			if (c < 0)
-				return (-1);/* Invalid */
-			d->freq[c]++;
-			d->bitlen[i++] = c;
-			break;
-		}
-	}
-	ret = 1;
-getdata:
-	ds->loop = i;
-	return (ret);
-}
-
-static int
-lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
-{
-
-	if (hf->bitlen == NULL || hf->len_size != (int)len_size) {
-		free(hf->bitlen);
-		hf->bitlen = calloc(len_size,  sizeof(hf->bitlen[0]));
-		if (hf->bitlen == NULL)
-			return (ARCHIVE_FATAL);
-		hf->len_size = (int)len_size;
-	} else
-		memset(hf->bitlen, 0, len_size *  sizeof(hf->bitlen[0]));
-	if (hf->tbl == NULL) {
-		hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0]));
-		if (hf->tbl == NULL)
-			return (ARCHIVE_FATAL);
-		hf->tbl_bits = tbl_bits;
-	}
-	return (ARCHIVE_OK);
-}
-
-static void
-lzx_huffman_free(struct huffman *hf)
-{
-	free(hf->bitlen);
-	free(hf->tbl);
-}
-
-/*
- * Make a huffman coding table.
- */
-static int
-lzx_make_huffman_table(struct huffman *hf)
-{
-	uint16_t *tbl;
-	const unsigned char *bitlen;
-	int bitptn[17], weight[17];
-	int i, maxbits = 0, ptn, tbl_size, w;
-	int len_avail;
-
-	/*
-	 * Initialize bit patterns.
-	 */
-	ptn = 0;
-	for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) {
-		bitptn[i] = ptn;
-		weight[i] = w;
-		if (hf->freq[i]) {
-			ptn += hf->freq[i] * w;
-			maxbits = i;
-		}
-	}
-	if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits)
-		return (0);/* Invalid */
-
-	hf->max_bits = maxbits;
-
-	/*
-	 * Cut out extra bits which we won't house in the table.
-	 * This preparation reduces the same calculation in the for-loop
-	 * making the table.
-	 */
-	if (maxbits < 16) {
-		int ebits = 16 - maxbits;
-		for (i = 1; i <= maxbits; i++) {
-			bitptn[i] >>= ebits;
-			weight[i] >>= ebits;
-		}
-	}
-
-	/*
-	 * Make the table.
-	 */
-	tbl_size = 1 << hf->tbl_bits;
-	tbl = hf->tbl;
-	bitlen = hf->bitlen;
-	len_avail = hf->len_size;
-	hf->tree_used = 0;
-	for (i = 0; i < len_avail; i++) {
-		uint16_t *p;
-		int len, cnt;
-
-		if (bitlen[i] == 0)
-			continue;
-		/* Get a bit pattern */
-		len = bitlen[i];
-		if (len > tbl_size)
-			return (0);
-		ptn = bitptn[len];
-		cnt = weight[len];
-		/* Calculate next bit pattern */
-		if ((bitptn[len] = ptn + cnt) > tbl_size)
-			return (0);/* Invalid */
-		/* Update the table */
-		p = &(tbl[ptn]);
-		while (--cnt >= 0)
-			p[cnt] = (uint16_t)i;
-	}
-	return (1);
-}
-
-static inline int
-lzx_decode_huffman(struct huffman *hf, unsigned rbits)
-{
-	int c;
-	c = hf->tbl[rbits];
-	if (c < hf->len_size)
-		return (c);
-	return (0);
-}
diff --git a/c/archive_read_support_format_cpio.c b/c/archive_read_support_format_cpio.c
deleted file mode 100644
--- a/c/archive_read_support_format_cpio.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 201163 2009-12-29 05:50:34Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-/* #include <stdint.h> */ /* See archive_platform.h */
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#define	bin_magic_offset 0
-#define	bin_magic_size 2
-#define	bin_dev_offset 2
-#define	bin_dev_size 2
-#define	bin_ino_offset 4
-#define	bin_ino_size 2
-#define	bin_mode_offset 6
-#define	bin_mode_size 2
-#define	bin_uid_offset 8
-#define	bin_uid_size 2
-#define	bin_gid_offset 10
-#define	bin_gid_size 2
-#define	bin_nlink_offset 12
-#define	bin_nlink_size 2
-#define	bin_rdev_offset 14
-#define	bin_rdev_size 2
-#define	bin_mtime_offset 16
-#define	bin_mtime_size 4
-#define	bin_namesize_offset 20
-#define	bin_namesize_size 2
-#define	bin_filesize_offset 22
-#define	bin_filesize_size 4
-#define	bin_header_size 26
-
-#define	odc_magic_offset 0
-#define	odc_magic_size 6
-#define	odc_dev_offset 6
-#define	odc_dev_size 6
-#define	odc_ino_offset 12
-#define	odc_ino_size 6
-#define	odc_mode_offset 18
-#define	odc_mode_size 6
-#define	odc_uid_offset 24
-#define	odc_uid_size 6
-#define	odc_gid_offset 30
-#define	odc_gid_size 6
-#define	odc_nlink_offset 36
-#define	odc_nlink_size 6
-#define	odc_rdev_offset 42
-#define	odc_rdev_size 6
-#define	odc_mtime_offset 48
-#define	odc_mtime_size 11
-#define	odc_namesize_offset 59
-#define	odc_namesize_size 6
-#define	odc_filesize_offset 65
-#define	odc_filesize_size 11
-#define	odc_header_size 76
-
-#define	newc_magic_offset 0
-#define	newc_magic_size 6
-#define	newc_ino_offset 6
-#define	newc_ino_size 8
-#define	newc_mode_offset 14
-#define	newc_mode_size 8
-#define	newc_uid_offset 22
-#define	newc_uid_size 8
-#define	newc_gid_offset 30
-#define	newc_gid_size 8
-#define	newc_nlink_offset 38
-#define	newc_nlink_size 8
-#define	newc_mtime_offset 46
-#define	newc_mtime_size 8
-#define	newc_filesize_offset 54
-#define	newc_filesize_size 8
-#define	newc_devmajor_offset 62
-#define	newc_devmajor_size 8
-#define	newc_devminor_offset 70
-#define	newc_devminor_size 8
-#define	newc_rdevmajor_offset 78
-#define	newc_rdevmajor_size 8
-#define	newc_rdevminor_offset 86
-#define	newc_rdevminor_size 8
-#define	newc_namesize_offset 94
-#define	newc_namesize_size 8
-#define	newc_checksum_offset 102
-#define	newc_checksum_size 8
-#define	newc_header_size 110
-
-/*
- * An afio large ASCII header, which they named itself.
- * afio utility uses this header, if a file size is larger than 2G bytes
- * or inode/uid/gid is bigger than 65535(0xFFFF) or mtime is bigger than
- * 0x7fffffff, which we cannot record to odc header because of its limit.
- * If not, uses odc header.
- */
-#define	afiol_magic_offset 0
-#define	afiol_magic_size 6
-#define	afiol_dev_offset 6
-#define	afiol_dev_size 8	/* hex */
-#define	afiol_ino_offset 14
-#define	afiol_ino_size 16	/* hex */
-#define	afiol_ino_m_offset 30	/* 'm' */
-#define	afiol_mode_offset 31
-#define	afiol_mode_size 6	/* oct */
-#define	afiol_uid_offset 37
-#define	afiol_uid_size 8	/* hex */
-#define	afiol_gid_offset 45
-#define	afiol_gid_size 8	/* hex */
-#define	afiol_nlink_offset 53
-#define	afiol_nlink_size 8	/* hex */
-#define	afiol_rdev_offset 61
-#define	afiol_rdev_size 8	/* hex */
-#define	afiol_mtime_offset 69
-#define	afiol_mtime_size 16	/* hex */
-#define	afiol_mtime_n_offset 85	/* 'n' */
-#define	afiol_namesize_offset 86
-#define	afiol_namesize_size 4	/* hex */
-#define	afiol_flag_offset 90
-#define	afiol_flag_size 4	/* hex */
-#define	afiol_xsize_offset 94
-#define	afiol_xsize_size 4	/* hex */
-#define	afiol_xsize_s_offset 98	/* 's' */
-#define	afiol_filesize_offset 99
-#define	afiol_filesize_size 16	/* hex */
-#define	afiol_filesize_c_offset 115	/* ':' */
-#define afiol_header_size 116
-
-
-struct links_entry {
-        struct links_entry      *next;
-        struct links_entry      *previous;
-        unsigned int             links;
-        dev_t                    dev;
-        int64_t                  ino;
-        char                    *name;
-};
-
-#define	CPIO_MAGIC   0x13141516
-struct cpio {
-	int			  magic;
-	int			(*read_header)(struct archive_read *, struct cpio *,
-				     struct archive_entry *, size_t *, size_t *);
-	struct links_entry	 *links_head;
-	int64_t			  entry_bytes_remaining;
-	int64_t			  entry_bytes_unconsumed;
-	int64_t			  entry_offset;
-	int64_t			  entry_padding;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int			  init_default_conversion;
-
-	int			  option_pwb;
-};
-
-static int64_t	atol16(const char *, unsigned);
-static int64_t	atol8(const char *, unsigned);
-static int	archive_read_format_cpio_bid(struct archive_read *, int);
-static int	archive_read_format_cpio_options(struct archive_read *,
-		    const char *, const char *);
-static int	archive_read_format_cpio_cleanup(struct archive_read *);
-static int	archive_read_format_cpio_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_cpio_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	archive_read_format_cpio_skip(struct archive_read *);
-static int64_t	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 *,
-		    struct archive_entry *, size_t *, size_t *);
-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	header_afiol(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 int64_t	le4(const unsigned char *);
-static int	record_hardlink(struct archive_read *a,
-		    struct cpio *cpio, struct archive_entry *entry);
-
-int
-archive_read_support_format_cpio(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct cpio *cpio;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_cpio");
-
-	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
-	if (cpio == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
-		return (ARCHIVE_FATAL);
-	}
-	cpio->magic = CPIO_MAGIC;
-
-	r = __archive_read_register_format(a,
-	    cpio,
-	    "cpio",
-	    archive_read_format_cpio_bid,
-	    archive_read_format_cpio_options,
-	    archive_read_format_cpio_read_header,
-	    archive_read_format_cpio_read_data,
-	    archive_read_format_cpio_skip,
-	    NULL,
-	    archive_read_format_cpio_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK)
-		free(cpio);
-	return (ARCHIVE_OK);
-}
-
-
-static int
-archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
-{
-	const unsigned char *p;
-	struct cpio *cpio;
-	int bid;
-
-	(void)best_bid; /* UNUSED */
-
-	cpio = (struct cpio *)(a->format->data);
-
-	if ((p = __archive_read_ahead(a, 6, NULL)) == NULL)
-		return (-1);
-
-	bid = 0;
-	if (memcmp(p, "070707", 6) == 0) {
-		/* ASCII cpio archive (odc, POSIX.1) */
-		cpio->read_header = header_odc;
-		bid += 48;
-		/*
-		 * XXX TODO:  More verification; Could check that only octal
-		 * digits appear in appropriate header locations. XXX
-		 */
-	} else if (memcmp(p, "070727", 6) == 0) {
-		/* afio large ASCII cpio archive */
-		cpio->read_header = header_odc;
-		bid += 48;
-		/*
-		 * XXX TODO:  More verification; Could check that almost hex
-		 * digits appear in appropriate header locations. XXX
-		 */
-	} else if (memcmp(p, "070701", 6) == 0) {
-		/* ASCII cpio archive (SVR4 without CRC) */
-		cpio->read_header = header_newc;
-		bid += 48;
-		/*
-		 * XXX TODO:  More verification; Could check that only hex
-		 * digits appear in appropriate header locations. XXX
-		 */
-	} else if (memcmp(p, "070702", 6) == 0) {
-		/* ASCII cpio archive (SVR4 with CRC) */
-		/* XXX TODO: Flag that we should check the CRC. XXX */
-		cpio->read_header = header_newc;
-		bid += 48;
-		/*
-		 * XXX TODO:  More verification; Could check that only hex
-		 * digits appear in appropriate header locations. XXX
-		 */
-	} else if (p[0] * 256 + p[1] == 070707) {
-		/* big-endian binary cpio archives */
-		cpio->read_header = header_bin_be;
-		bid += 16;
-		/* Is more verification possible here? */
-	} else if (p[0] + p[1] * 256 == 070707) {
-		/* little-endian binary cpio archives */
-		cpio->read_header = header_bin_le;
-		bid += 16;
-		/* Is more verification possible here? */
-	} else
-		return (ARCHIVE_WARN);
-
-	return (bid);
-}
-
-static int
-archive_read_format_cpio_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct cpio *cpio;
-	int ret = ARCHIVE_FAILED;
-
-	cpio = (struct cpio *)(a->format->data);
-	if (strcmp(key, "compat-2x")  == 0) {
-		/* Handle filenames as libarchive 2.x */
-		cpio->init_default_conversion = (val != NULL)?1:0;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "cpio: hdrcharset option needs a character-set name");
-		else {
-			cpio->opt_sconv =
-			    archive_string_conversion_from_charset(
-				&a->archive, val, 0);
-			if (cpio->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	} else if (strcmp(key, "pwb")  == 0) {
-		if (val != NULL && val[0] != 0)
-			cpio->option_pwb = 1;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_read_format_cpio_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct cpio *cpio;
-	const void *h, *hl;
-	struct archive_string_conv *sconv;
-	size_t namelength;
-	size_t name_pad;
-	int r;
-
-	cpio = (struct cpio *)(a->format->data);
-	sconv = cpio->opt_sconv;
-	if (sconv == NULL) {
-		if (!cpio->init_default_conversion) {
-			cpio->sconv_default =
-			    archive_string_default_conversion_for_read(
-			      &(a->archive));
-			cpio->init_default_conversion = 1;
-		}
-		sconv = cpio->sconv_default;
-	}
-	
-	r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad));
-
-	if (r < ARCHIVE_WARN)
-		return (r);
-
-	/* Read name from buffer. */
-	h = __archive_read_ahead(a, namelength + name_pad, NULL);
-	if (h == NULL)
-	    return (ARCHIVE_FATAL);
-	if (archive_entry_copy_pathname_l(entry,
-	    (const char *)h, namelength, sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Pathname can't be converted from %s to current locale.",
-		    archive_string_conversion_charset_name(sconv));
-		r = ARCHIVE_WARN;
-	}
-	cpio->entry_offset = 0;
-
-	__archive_read_consume(a, namelength + name_pad);
-
-	/* If this is a symlink, read the link contents. */
-	if (archive_entry_filetype(entry) == AE_IFLNK) {
-		if (cpio->entry_bytes_remaining > 1024 * 1024) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
-			return (ARCHIVE_FATAL);
-		}
-		hl = __archive_read_ahead(a,
-			(size_t)cpio->entry_bytes_remaining, NULL);
-		if (hl == NULL)
-			return (ARCHIVE_FATAL);
-		if (archive_entry_copy_symlink_l(entry, (const char *)hl,
-		    (size_t)cpio->entry_bytes_remaining, sconv) != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Linkname can't be converted from %s to "
-			    "current locale.",
-			    archive_string_conversion_charset_name(sconv));
-			r = ARCHIVE_WARN;
-		}
-		__archive_read_consume(a, cpio->entry_bytes_remaining);
-		cpio->entry_bytes_remaining = 0;
-	}
-
-	/* XXX TODO: If the full mode is 0160200, then this is a Solaris
-	 * ACL description for the following entry.  Read this body
-	 * and parse it as a Solaris-style ACL, then read the next
-	 * header.  XXX */
-
-	/* Compare name to "TRAILER!!!" to test for end-of-archive. */
-	if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
-	    10) == 0) {
-		/* TODO: Store file location of start of block. */
-		archive_clear_error(&a->archive);
-		return (ARCHIVE_EOF);
-	}
-
-	/* Detect and record hardlinks to previously-extracted entries. */
-	if (record_hardlink(a, cpio, entry) != ARCHIVE_OK) {
-		return (ARCHIVE_FATAL);
-	}
-
-	return (r);
-}
-
-static int
-archive_read_format_cpio_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	ssize_t bytes_read;
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)(a->format->data);
-
-	if (cpio->entry_bytes_unconsumed) {
-		__archive_read_consume(a, cpio->entry_bytes_unconsumed);
-		cpio->entry_bytes_unconsumed = 0;
-	}
-
-	if (cpio->entry_bytes_remaining > 0) {
-		*buff = __archive_read_ahead(a, 1, &bytes_read);
-		if (bytes_read <= 0)
-			return (ARCHIVE_FATAL);
-		if (bytes_read > cpio->entry_bytes_remaining)
-			bytes_read = (ssize_t)cpio->entry_bytes_remaining;
-		*size = bytes_read;
-		cpio->entry_bytes_unconsumed = bytes_read;
-		*offset = cpio->entry_offset;
-		cpio->entry_offset += bytes_read;
-		cpio->entry_bytes_remaining -= bytes_read;
-		return (ARCHIVE_OK);
-	} else {
-		if (cpio->entry_padding !=
-			__archive_read_consume(a, cpio->entry_padding)) {
-			return (ARCHIVE_FATAL);
-		}
-		cpio->entry_padding = 0;
-		*buff = NULL;
-		*size = 0;
-		*offset = cpio->entry_offset;
-		return (ARCHIVE_EOF);
-	}
-}
-
-static int
-archive_read_format_cpio_skip(struct archive_read *a)
-{
-	struct cpio *cpio = (struct cpio *)(a->format->data);
-	int64_t to_skip = cpio->entry_bytes_remaining + cpio->entry_padding +
-		cpio->entry_bytes_unconsumed;
-
-	if (to_skip != __archive_read_consume(a, to_skip)) {
-		return (ARCHIVE_FATAL);
-	}
-	cpio->entry_bytes_remaining = 0;
-	cpio->entry_padding = 0;
-	cpio->entry_bytes_unconsumed = 0;
-	return (ARCHIVE_OK);
-}
-
-/*
- * 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, skipped = 0;
-	ssize_t bytes;
-
-	for (;;) {
-		h = __archive_read_ahead(a, newc_header_size, &bytes);
-		if (h == NULL)
-			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, newc_header_size))
-			return (ARCHIVE_OK);
-
-		/*
-		 * Scan ahead until we find something that looks
-		 * like a newc header.
-		 */
-		while (p + newc_header_size <= q) {
-			switch (p[5]) {
-			case '1':
-			case '2':
-				if (memcmp("07070", p, 5) == 0
-				    && is_hex(p, newc_header_size)) {
-					skip = p - (const char *)h;
-					__archive_read_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;
-		__archive_read_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)
-{
-	const void *h;
-	const char *header;
-	int r;
-
-	r = find_newc_header(a);
-	if (r < ARCHIVE_WARN)
-		return (r);
-
-	/* Read fixed-size portion of header. */
-	h = __archive_read_ahead(a, newc_header_size, NULL);
-	if (h == NULL)
-	    return (ARCHIVE_FATAL);
-
-	/* Parse out hex fields. */
-	header = (const char *)h;
-
-	if (memcmp(header + newc_magic_offset, "070701", 6) == 0) {
-		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
-		a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)";
-	} else if (memcmp(header + newc_magic_offset, "070702", 6) == 0) {
-		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
-		a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)";
-	} else {
-		/* TODO: Abort here? */
-	}
-
-	archive_entry_set_devmajor(entry,
-		(dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size));
-	archive_entry_set_devminor(entry, 
-		(dev_t)atol16(header + newc_devminor_offset, newc_devminor_size));
-	archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size));
-	archive_entry_set_mode(entry, 
-		(mode_t)atol16(header + newc_mode_offset, newc_mode_size));
-	archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size));
-	archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size));
-	archive_entry_set_nlink(entry,
-		(unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size));
-	archive_entry_set_rdevmajor(entry,
-		(dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
-	archive_entry_set_rdevminor(entry,
-		(dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
-	archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0);
-	*namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size);
-	/* Pad name to 2 more than a multiple of 4. */
-	*name_pad = (2 - *namelength) & 3;
-
-	/* Make sure that the padded name length fits into size_t. */
-	if (*name_pad > SIZE_MAX - *namelength) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "cpio archive has invalid namelength");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Note: entry_bytes_remaining is at least 64 bits and
-	 * therefore guaranteed to be big enough for a 33-bit file
-	 * size.
-	 */
-	cpio->entry_bytes_remaining =
-	    atol16(header + newc_filesize_offset, newc_filesize_size);
-	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;
-	__archive_read_consume(a, newc_header_size);
-	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
-is_afio_large(const char *h, size_t len)
-{
-	if (len < afiol_header_size)
-		return (0);
-	if (h[afiol_ino_m_offset] != 'm'
-	    || h[afiol_mtime_n_offset] != 'n'
-	    || h[afiol_xsize_s_offset] != 's'
-	    || h[afiol_filesize_c_offset] != ':')
-		return (0);
-	if (!is_hex(h + afiol_dev_offset, afiol_ino_m_offset - afiol_dev_offset))
-		return (0);
-	if (!is_hex(h + afiol_mode_offset, afiol_mtime_n_offset - afiol_mode_offset))
-		return (0);
-	if (!is_hex(h + afiol_namesize_offset, afiol_xsize_s_offset - afiol_namesize_offset))
-		return (0);
-	if (!is_hex(h + afiol_filesize_offset, afiol_filesize_size))
-		return (0);
-	return (1);
-}
-
-static int
-find_odc_header(struct archive_read *a)
-{
-	const void *h;
-	const char *p, *q;
-	size_t skip, skipped = 0;
-	ssize_t bytes;
-
-	for (;;) {
-		h = __archive_read_ahead(a, odc_header_size, &bytes);
-		if (h == NULL)
-			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, odc_header_size))
-			return (ARCHIVE_OK);
-		if (memcmp("070727", p, 6) == 0 && is_afio_large(p, bytes)) {
-			a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE;
-			return (ARCHIVE_OK);
-		}
-
-		/*
-		 * Scan ahead until we find something that looks
-		 * like an odc header.
-		 */
-		while (p + odc_header_size <= q) {
-			switch (p[5]) {
-			case '7':
-				if ((memcmp("070707", p, 6) == 0
-				    && is_octal(p, odc_header_size))
-				    || (memcmp("070727", p, 6) == 0
-				        && is_afio_large(p, q - p))) {
-					skip = p - (const char *)h;
-					__archive_read_consume(a, skip);
-					skipped += skip;
-					if (p[4] == '2')
-						a->archive.archive_format =
-						    ARCHIVE_FORMAT_CPIO_AFIO_LARGE;
-					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;
-		__archive_read_consume(a, skip);
-		skipped += skip;
-	}
-}
-
-static int
-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 char *header;
-
-	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);
-
-	if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_AFIO_LARGE) {
-		int r2 = (header_afiol(a, cpio, entry, namelength, name_pad));
-		if (r2 == ARCHIVE_OK)
-			return (r);
-		else
-			return (r2);
-	}
-
-	/* Read fixed-size portion of header. */
-	h = __archive_read_ahead(a, odc_header_size, NULL);
-	if (h == NULL)
-	    return (ARCHIVE_FATAL);
-
-	/* Parse out octal fields. */
-	header = (const char *)h;
-
-	archive_entry_set_dev(entry, 
-		(dev_t)atol8(header + odc_dev_offset, odc_dev_size));
-	archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size));
-	archive_entry_set_mode(entry, 
-		(mode_t)atol8(header + odc_mode_offset, odc_mode_size));
-	archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size));
-	archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size));
-	archive_entry_set_nlink(entry, 
-		(unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size));
-	archive_entry_set_rdev(entry,
-		(dev_t)atol8(header + odc_rdev_offset, odc_rdev_size));
-	archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0);
-	*namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size);
-	*name_pad = 0; /* No padding of filename. */
-
-	/*
-	 * Note: entry_bytes_remaining is at least 64 bits and
-	 * therefore guaranteed to be big enough for a 33-bit file
-	 * size.
-	 */
-	cpio->entry_bytes_remaining =
-	    atol8(header + odc_filesize_offset, odc_filesize_size);
-	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
-	cpio->entry_padding = 0;
-	__archive_read_consume(a, odc_header_size);
-	return (r);
-}
-
-/*
- * NOTE: if a filename suffix is ".z", it is the file gziped by afio.
- * it would be nice that we can show uncompressed file size and we can
- * uncompressed file contents automatically, unfortunately we have nothing
- * to get a uncompressed file size while reading each header. It means
- * we also cannot uncompress file contents under our framework.
- */
-static int
-header_afiol(struct archive_read *a, struct cpio *cpio,
-    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
-{
-	const void *h;
-	const char *header;
-
-	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE;
-	a->archive.archive_format_name = "afio large ASCII";
-
-	/* Read fixed-size portion of header. */
-	h = __archive_read_ahead(a, afiol_header_size, NULL);
-	if (h == NULL)
-	    return (ARCHIVE_FATAL);
-
-	/* Parse out octal fields. */
-	header = (const char *)h;
-
-	archive_entry_set_dev(entry, 
-		(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
-	archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size));
-	archive_entry_set_mode(entry,
-		(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
-	archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
-	archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size));
-	archive_entry_set_nlink(entry,
-		(unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size));
-	archive_entry_set_rdev(entry,
-		(dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size));
-	archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0);
-	*namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size);
-	*name_pad = 0; /* No padding of filename. */
-
-	cpio->entry_bytes_remaining =
-	    atol16(header + afiol_filesize_offset, afiol_filesize_size);
-	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
-	cpio->entry_padding = 0;
-	__archive_read_consume(a, afiol_header_size);
-	return (ARCHIVE_OK);
-}
-
-
-static int
-header_bin_le(struct archive_read *a, struct cpio *cpio,
-    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
-{
-	const void *h;
-	const unsigned char *header;
-
-	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE;
-	a->archive.archive_format_name = "cpio (little-endian binary)";
-
-	/* Read fixed-size portion of header. */
-	h = __archive_read_ahead(a, bin_header_size, NULL);
-	if (h == NULL) {
-	    archive_set_error(&a->archive, 0,
-		"End of file trying to read next cpio header");
-	    return (ARCHIVE_FATAL);
-	}
-
-	/* Parse out binary fields. */
-	header = (const unsigned char *)h;
-
-	archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
-	archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
-	archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
-	if (cpio->option_pwb) {
-		/* turn off random bits left over from V6 inode */
-		archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
-		if ((archive_entry_mode(entry) & AE_IFMT) == 0)
-			archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
-	}
-	archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
-	archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
-	archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
-	archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256);
-	archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0);
-	*namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256;
-	*name_pad = *namelength & 1; /* Pad to even. */
-
-	cpio->entry_bytes_remaining = le4(header + bin_filesize_offset);
-	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
-	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
-	__archive_read_consume(a, bin_header_size);
-	return (ARCHIVE_OK);
-}
-
-static int
-header_bin_be(struct archive_read *a, struct cpio *cpio,
-    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
-{
-	const void *h;
-	const unsigned char *header;
-
-	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
-	a->archive.archive_format_name = "cpio (big-endian binary)";
-
-	/* Read fixed-size portion of header. */
-	h = __archive_read_ahead(a, bin_header_size, NULL);
-	if (h == NULL) {
-	    archive_set_error(&a->archive, 0,
-		"End of file trying to read next cpio header");
-	    return (ARCHIVE_FATAL);
-	}
-
-	/* Parse out binary fields. */
-	header = (const unsigned char *)h;
-
-	archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
-	archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
-	archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
-	if (cpio->option_pwb) {
-		/* turn off random bits left over from V6 inode */
-		archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
-		if ((archive_entry_mode(entry) & AE_IFMT) == 0)
-			archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
-	}
-	archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
-	archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
-	archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
-	archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]);
-	archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0);
-	*namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1];
-	*name_pad = *namelength & 1; /* Pad to even. */
-
-	cpio->entry_bytes_remaining = be4(header + bin_filesize_offset);
-	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
-	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
-	    __archive_read_consume(a, bin_header_size);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_cpio_cleanup(struct archive_read *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)(a->format->data);
-        /* Free inode->name map */
-        while (cpio->links_head != NULL) {
-                struct links_entry *lp = cpio->links_head->next;
-
-                free(cpio->links_head->name);
-                free(cpio->links_head);
-                cpio->links_head = lp;
-        }
-	free(cpio);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int64_t
-le4(const unsigned char *p)
-{
-	return ((p[0] << 16) | (((int64_t)p[1]) << 24) | (p[2] << 0) | (p[3] << 8));
-}
-
-
-static int64_t
-be4(const unsigned char *p)
-{
-	return ((((int64_t)p[0]) << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
-}
-
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
-static int64_t
-atol8(const char *p, unsigned char_cnt)
-{
-	int64_t l;
-	int digit;
-
-	l = 0;
-	while (char_cnt-- > 0) {
-		if (*p >= '0' && *p <= '7')
-			digit = *p - '0';
-		else
-			return (l);
-		p++;
-		l <<= 3;
-		l |= digit;
-	}
-	return (l);
-}
-
-static int64_t
-atol16(const char *p, unsigned char_cnt)
-{
-	int64_t l;
-	int digit;
-
-	l = 0;
-	while (char_cnt-- > 0) {
-		if (*p >= 'a' && *p <= 'f')
-			digit = *p - 'a' + 10;
-		else if (*p >= 'A' && *p <= 'F')
-			digit = *p - 'A' + 10;
-		else if (*p >= '0' && *p <= '9')
-			digit = *p - '0';
-		else
-			return (l);
-		p++;
-		l <<= 4;
-		l |= digit;
-	}
-	return (l);
-}
-
-static int
-record_hardlink(struct archive_read *a,
-    struct cpio *cpio, struct archive_entry *entry)
-{
-	struct links_entry      *le;
-	dev_t dev;
-	int64_t ino;
-
-	if (archive_entry_nlink(entry) <= 1)
-		return (ARCHIVE_OK);
-
-	dev = archive_entry_dev(entry);
-	ino = archive_entry_ino64(entry);
-
-	/*
-	 * First look in the list of multiply-linked files.  If we've
-	 * already dumped it, convert this entry to a hard link entry.
-	 */
-	for (le = cpio->links_head; le; le = le->next) {
-		if (le->dev == dev && le->ino == ino) {
-			archive_entry_copy_hardlink(entry, le->name);
-
-			if (--le->links <= 0) {
-				if (le->previous != NULL)
-					le->previous->next = le->next;
-				if (le->next != NULL)
-					le->next->previous = le->previous;
-				if (cpio->links_head == le)
-					cpio->links_head = le->next;
-				free(le->name);
-				free(le);
-			}
-
-			return (ARCHIVE_OK);
-		}
-	}
-
-	le = (struct links_entry *)malloc(sizeof(struct links_entry));
-	if (le == NULL) {
-		archive_set_error(&a->archive,
-		    ENOMEM, "Out of memory adding file to list");
-		return (ARCHIVE_FATAL);
-	}
-	if (cpio->links_head != NULL)
-		cpio->links_head->previous = le;
-	le->next = cpio->links_head;
-	le->previous = NULL;
-	cpio->links_head = le;
-	le->dev = dev;
-	le->ino = ino;
-	le->links = archive_entry_nlink(entry) - 1;
-	le->name = strdup(archive_entry_pathname(entry));
-	if (le->name == NULL) {
-		archive_set_error(&a->archive,
-		    ENOMEM, "Out of memory adding file to list");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_support_format_empty.c b/c/archive_read_support_format_empty.c
deleted file mode 100644
--- a/c/archive_read_support_format_empty.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_empty.c 191524 2009-04-26 18:24:14Z kientzle $");
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-static int	archive_read_format_empty_bid(struct archive_read *, int);
-static int	archive_read_format_empty_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_empty_read_header(struct archive_read *,
-		    struct archive_entry *);
-int
-archive_read_support_format_empty(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_empty");
-
-	r = __archive_read_register_format(a,
-	    NULL,
-	    "empty",
-	    archive_read_format_empty_bid,
-	    NULL,
-	    archive_read_format_empty_read_header,
-	    archive_read_format_empty_read_data,
-	    NULL,
-	    NULL,
-	    NULL,
-	    NULL,
-	    NULL);
-
-	return (r);
-}
-
-
-static int
-archive_read_format_empty_bid(struct archive_read *a, int best_bid)
-{
-	if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) == NULL)
-		return (1);
-	return (-1);
-}
-
-static int
-archive_read_format_empty_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	(void)a; /* UNUSED */
-	(void)entry; /* UNUSED */
-
-	a->archive.archive_format = ARCHIVE_FORMAT_EMPTY;
-	a->archive.archive_format_name = "Empty file";
-
-	return (ARCHIVE_EOF);
-}
-
-static int
-archive_read_format_empty_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	(void)a; /* UNUSED */
-	(void)buff; /* UNUSED */
-	(void)size; /* UNUSED */
-	(void)offset; /* UNUSED */
-
-	return (ARCHIVE_EOF);
-}
diff --git a/c/archive_read_support_format_iso9660.c b/c/archive_read_support_format_iso9660.c
deleted file mode 100644
--- a/c/archive_read_support_format_iso9660.c
+++ /dev/null
@@ -1,3279 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
- * Copyright (c) 2009-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_iso9660.c 201246 2009-12-30 05:30:35Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-/* #include <stdint.h> */ /* See archive_platform.h */
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_string.h"
-
-/*
- * An overview of ISO 9660 format:
- *
- * Each disk is laid out as follows:
- *   * 32k reserved for private use
- *   * Volume descriptor table.  Each volume descriptor
- *     is 2k and specifies basic format information.
- *     The "Primary Volume Descriptor" (PVD) is defined by the
- *     standard and should always be present; other volume
- *     descriptors include various vendor-specific extensions.
- *   * Files and directories.  Each file/dir is specified by
- *     an "extent" (starting sector and length in bytes).
- *     Dirs are just files with directory records packed one
- *     after another.  The PVD contains a single dir entry
- *     specifying the location of the root directory.  Everything
- *     else follows from there.
- *
- * This module works by first reading the volume descriptors, then
- * building a list of directory entries, sorted by starting
- * sector.  At each step, I look for the earliest dir entry that
- * hasn't yet been read, seek forward to that location and read
- * that entry.  If it's a dir, I slurp in the new dir entries and
- * add them to the heap; if it's a regular file, I return the
- * corresponding archive_entry and wait for the client to request
- * the file body.  This strategy allows us to read most compliant
- * CDs with a single pass through the data, as required by libarchive.
- */
-#define	LOGICAL_BLOCK_SIZE	2048
-#define	SYSTEM_AREA_BLOCK	16
-
-/* Structure of on-disk primary volume descriptor. */
-#define PVD_type_offset 0
-#define PVD_type_size 1
-#define PVD_id_offset (PVD_type_offset + PVD_type_size)
-#define PVD_id_size 5
-#define PVD_version_offset (PVD_id_offset + PVD_id_size)
-#define PVD_version_size 1
-#define PVD_reserved1_offset (PVD_version_offset + PVD_version_size)
-#define PVD_reserved1_size 1
-#define PVD_system_id_offset (PVD_reserved1_offset + PVD_reserved1_size)
-#define PVD_system_id_size 32
-#define PVD_volume_id_offset (PVD_system_id_offset + PVD_system_id_size)
-#define PVD_volume_id_size 32
-#define PVD_reserved2_offset (PVD_volume_id_offset + PVD_volume_id_size)
-#define PVD_reserved2_size 8
-#define PVD_volume_space_size_offset (PVD_reserved2_offset + PVD_reserved2_size)
-#define PVD_volume_space_size_size 8
-#define PVD_reserved3_offset (PVD_volume_space_size_offset + PVD_volume_space_size_size)
-#define PVD_reserved3_size 32
-#define PVD_volume_set_size_offset (PVD_reserved3_offset + PVD_reserved3_size)
-#define PVD_volume_set_size_size 4
-#define PVD_volume_sequence_number_offset (PVD_volume_set_size_offset + PVD_volume_set_size_size)
-#define PVD_volume_sequence_number_size 4
-#define PVD_logical_block_size_offset (PVD_volume_sequence_number_offset + PVD_volume_sequence_number_size)
-#define PVD_logical_block_size_size 4
-#define PVD_path_table_size_offset (PVD_logical_block_size_offset + PVD_logical_block_size_size)
-#define PVD_path_table_size_size 8
-#define PVD_type_1_path_table_offset (PVD_path_table_size_offset + PVD_path_table_size_size)
-#define PVD_type_1_path_table_size 4
-#define PVD_opt_type_1_path_table_offset (PVD_type_1_path_table_offset + PVD_type_1_path_table_size)
-#define PVD_opt_type_1_path_table_size 4
-#define PVD_type_m_path_table_offset (PVD_opt_type_1_path_table_offset + PVD_opt_type_1_path_table_size)
-#define PVD_type_m_path_table_size 4
-#define PVD_opt_type_m_path_table_offset (PVD_type_m_path_table_offset + PVD_type_m_path_table_size)
-#define PVD_opt_type_m_path_table_size 4
-#define PVD_root_directory_record_offset (PVD_opt_type_m_path_table_offset + PVD_opt_type_m_path_table_size)
-#define PVD_root_directory_record_size 34
-#define PVD_volume_set_id_offset (PVD_root_directory_record_offset + PVD_root_directory_record_size)
-#define PVD_volume_set_id_size 128
-#define PVD_publisher_id_offset (PVD_volume_set_id_offset + PVD_volume_set_id_size)
-#define PVD_publisher_id_size 128
-#define PVD_preparer_id_offset (PVD_publisher_id_offset + PVD_publisher_id_size)
-#define PVD_preparer_id_size 128
-#define PVD_application_id_offset (PVD_preparer_id_offset + PVD_preparer_id_size)
-#define PVD_application_id_size 128
-#define PVD_copyright_file_id_offset (PVD_application_id_offset + PVD_application_id_size)
-#define PVD_copyright_file_id_size 37
-#define PVD_abstract_file_id_offset (PVD_copyright_file_id_offset + PVD_copyright_file_id_size)
-#define PVD_abstract_file_id_size 37
-#define PVD_bibliographic_file_id_offset (PVD_abstract_file_id_offset + PVD_abstract_file_id_size)
-#define PVD_bibliographic_file_id_size 37
-#define PVD_creation_date_offset (PVD_bibliographic_file_id_offset + PVD_bibliographic_file_id_size)
-#define PVD_creation_date_size 17
-#define PVD_modification_date_offset (PVD_creation_date_offset + PVD_creation_date_size)
-#define PVD_modification_date_size 17
-#define PVD_expiration_date_offset (PVD_modification_date_offset + PVD_modification_date_size)
-#define PVD_expiration_date_size 17
-#define PVD_effective_date_offset (PVD_expiration_date_offset + PVD_expiration_date_size)
-#define PVD_effective_date_size 17
-#define PVD_file_structure_version_offset (PVD_effective_date_offset + PVD_effective_date_size)
-#define PVD_file_structure_version_size 1
-#define PVD_reserved4_offset (PVD_file_structure_version_offset + PVD_file_structure_version_size)
-#define PVD_reserved4_size 1
-#define PVD_application_data_offset (PVD_reserved4_offset + PVD_reserved4_size)
-#define PVD_application_data_size 512
-#define PVD_reserved5_offset (PVD_application_data_offset + PVD_application_data_size)
-#define PVD_reserved5_size (2048 - PVD_reserved5_offset)
-
-/* TODO: It would make future maintenance easier to just hardcode the
- * above values.  In particular, ECMA119 states the offsets as part of
- * the standard.  That would eliminate the need for the following check.*/
-#if PVD_reserved5_offset != 1395
-#error PVD offset and size definitions are wrong.
-#endif
-
-
-/* Structure of optional on-disk supplementary volume descriptor. */
-#define SVD_type_offset 0
-#define SVD_type_size 1
-#define SVD_id_offset (SVD_type_offset + SVD_type_size)
-#define SVD_id_size 5
-#define SVD_version_offset (SVD_id_offset + SVD_id_size)
-#define SVD_version_size 1
-/* ... */
-#define SVD_reserved1_offset	72
-#define SVD_reserved1_size	8
-#define SVD_volume_space_size_offset 80
-#define SVD_volume_space_size_size 8
-#define SVD_escape_sequences_offset (SVD_volume_space_size_offset + SVD_volume_space_size_size)
-#define SVD_escape_sequences_size 32
-/* ... */
-#define SVD_logical_block_size_offset 128
-#define SVD_logical_block_size_size 4
-#define SVD_type_L_path_table_offset 140
-#define SVD_type_M_path_table_offset 148
-/* ... */
-#define SVD_root_directory_record_offset 156
-#define SVD_root_directory_record_size 34
-#define SVD_file_structure_version_offset 881
-#define SVD_reserved2_offset	882
-#define SVD_reserved2_size	1
-#define SVD_reserved3_offset	1395
-#define SVD_reserved3_size	653
-/* ... */
-/* FIXME: validate correctness of last SVD entry offset. */
-
-/* Structure of an on-disk directory record. */
-/* Note:  ISO9660 stores each multi-byte integer twice, once in
- * each byte order.  The sizes here are the size of just one
- * of the two integers.  (This is why the offset of a field isn't
- * the same as the offset+size of the previous field.) */
-#define DR_length_offset 0
-#define DR_length_size 1
-#define DR_ext_attr_length_offset 1
-#define DR_ext_attr_length_size 1
-#define DR_extent_offset 2
-#define DR_extent_size 4
-#define DR_size_offset 10
-#define DR_size_size 4
-#define DR_date_offset 18
-#define DR_date_size 7
-#define DR_flags_offset 25
-#define DR_flags_size 1
-#define DR_file_unit_size_offset 26
-#define DR_file_unit_size_size 1
-#define DR_interleave_offset 27
-#define DR_interleave_size 1
-#define DR_volume_sequence_number_offset 28
-#define DR_volume_sequence_number_size 2
-#define DR_name_len_offset 32
-#define DR_name_len_size 1
-#define DR_name_offset 33
-
-#ifdef HAVE_ZLIB_H
-static const unsigned char zisofs_magic[8] = {
-	0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
-};
-
-struct zisofs {
-	/* Set 1 if this file compressed by paged zlib */
-	int		 pz;
-	int		 pz_log2_bs; /* Log2 of block size */
-	uint64_t	 pz_uncompressed_size;
-
-	int		 initialized;
-	unsigned char	*uncompressed_buffer;
-	size_t		 uncompressed_buffer_size;
-
-	uint32_t	 pz_offset;
-	unsigned char	 header[16];
-	size_t		 header_avail;
-	int		 header_passed;
-	unsigned char	*block_pointers;
-	size_t		 block_pointers_alloc;
-	size_t		 block_pointers_size;
-	size_t		 block_pointers_avail;
-	size_t		 block_off;
-	uint32_t	 block_avail;
-
-	z_stream	 stream;
-	int		 stream_valid;
-};
-#else
-struct zisofs {
-	/* Set 1 if this file compressed by paged zlib */
-	int		 pz;
-};
-#endif
-
-struct content {
-	uint64_t	 offset;/* Offset on disk.		*/
-	uint64_t	 size;	/* File size in bytes.		*/
-	struct content	*next;
-};
-
-/* In-memory storage for a directory record. */
-struct file_info {
-	struct file_info	*use_next;
-	struct file_info	*parent;
-	struct file_info	*next;
-	struct file_info	*re_next;
-	int		 subdirs;
-	uint64_t	 key;		/* Heap Key.			*/
-	uint64_t	 offset;	/* Offset on disk.		*/
-	uint64_t	 size;		/* File size in bytes.		*/
-	uint32_t	 ce_offset;	/* Offset of CE.		*/
-	uint32_t	 ce_size;	/* Size of CE.			*/
-	char		 rr_moved;	/* Flag to rr_moved.		*/
-	char		 rr_moved_has_re_only;
-	char		 re;		/* Having RRIP "RE" extension.	*/
-	char		 re_descendant;
-	uint64_t	 cl_offset;	/* Having RRIP "CL" extension.	*/
-	int		 birthtime_is_set;
-	time_t		 birthtime;	/* File created time.		*/
-	time_t		 mtime;		/* File last modified time.	*/
-	time_t		 atime;		/* File last accessed time.	*/
-	time_t		 ctime;		/* File attribute change time.	*/
-	uint64_t	 rdev;		/* Device number.		*/
-	mode_t		 mode;
-	uid_t		 uid;
-	gid_t		 gid;
-	int64_t		 number;
-	int		 nlinks;
-	struct archive_string name; /* Pathname */
-	unsigned char	*utf16be_name;
-	size_t		 utf16be_bytes;
-	char		 name_continues; /* Non-zero if name continues */
-	struct archive_string symlink;
-	char		 symlink_continues; /* Non-zero if link continues */
-	/* Set 1 if this file compressed by paged zlib(zisofs) */
-	int		 pz;
-	int		 pz_log2_bs; /* Log2 of block size */
-	uint64_t	 pz_uncompressed_size;
-	/* Set 1 if this file is multi extent. */
-	int		 multi_extent;
-	struct {
-		struct content	*first;
-		struct content	**last;
-	} contents;
-	struct {
-		struct file_info	*first;
-		struct file_info	**last;
-	} rede_files;
-};
-
-struct heap_queue {
-	struct file_info **files;
-	int		 allocated;
-	int		 used;
-};
-
-struct iso9660 {
-	int	magic;
-#define ISO9660_MAGIC   0x96609660
-
-	int opt_support_joliet;
-	int opt_support_rockridge;
-
-	struct archive_string pathname;
-	char	seenRockridge;	/* Set true if RR extensions are used. */
-	char	seenSUSP;	/* Set true if SUSP is being used. */
-	char	seenJoliet;
-
-	unsigned char	suspOffset;
-	struct file_info *rr_moved;
-	struct read_ce_queue {
-		struct read_ce_req {
-			uint64_t	 offset;/* Offset of CE on disk. */
-			struct file_info *file;
-		}		*reqs;
-		int		 cnt;
-		int		 allocated;
-	}	read_ce_req;
-
-	int64_t		previous_number;
-	struct archive_string previous_pathname;
-
-	struct file_info		*use_files;
-	struct heap_queue		 pending_files;
-	struct {
-		struct file_info	*first;
-		struct file_info	**last;
-	}	cache_files;
-	struct {
-		struct file_info	*first;
-		struct file_info	**last;
-	}	re_files;
-
-	uint64_t current_position;
-	ssize_t	logical_block_size;
-	uint64_t volume_size; /* Total size of volume in bytes. */
-	int32_t  volume_block;/* Total size of volume in logical blocks. */
-
-	struct vd {
-		int		location;	/* Location of Extent.	*/
-		uint32_t	size;
-	} primary, joliet;
-
-	int64_t	entry_sparse_offset;
-	int64_t	entry_bytes_remaining;
-	size_t  entry_bytes_unconsumed;
-	struct zisofs	 entry_zisofs;
-	struct content	*entry_content;
-	struct archive_string_conv *sconv_utf16be;
-	/*
-	 * Buffers for a full pathname in UTF-16BE in Joliet extensions.
-	 */
-#define UTF16_NAME_MAX	1024
-	unsigned char *utf16be_path;
-	size_t		 utf16be_path_len;
-	unsigned char *utf16be_previous_path;
-	size_t		 utf16be_previous_path_len;
-	/* Null buffer used in bidder to improve its performance. */
-	unsigned char	 null[2048];
-};
-
-static int	archive_read_format_iso9660_bid(struct archive_read *, int);
-static int	archive_read_format_iso9660_options(struct archive_read *,
-		    const char *, const char *);
-static int	archive_read_format_iso9660_cleanup(struct archive_read *);
-static int	archive_read_format_iso9660_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_iso9660_read_data_skip(struct archive_read *);
-static int	archive_read_format_iso9660_read_header(struct archive_read *,
-		    struct archive_entry *);
-static const char *build_pathname(struct archive_string *, struct file_info *, int);
-static int	build_pathname_utf16be(unsigned char *, size_t, size_t *,
-		    struct file_info *);
-#if DEBUG
-static void	dump_isodirrec(FILE *, const unsigned char *isodirrec);
-#endif
-static time_t	time_from_tm(struct tm *);
-static time_t	isodate17(const unsigned char *);
-static time_t	isodate7(const unsigned char *);
-static int	isBootRecord(struct iso9660 *, const unsigned char *);
-static int	isVolumePartition(struct iso9660 *, const unsigned char *);
-static int	isVDSetTerminator(struct iso9660 *, const unsigned char *);
-static int	isJolietSVD(struct iso9660 *, const unsigned char *);
-static int	isSVD(struct iso9660 *, const unsigned char *);
-static int	isEVD(struct iso9660 *, const unsigned char *);
-static int	isPVD(struct iso9660 *, const unsigned char *);
-static int	next_cache_entry(struct archive_read *, struct iso9660 *,
-		    struct file_info **);
-static int	next_entry_seek(struct archive_read *, struct iso9660 *,
-		    struct file_info **);
-static struct file_info *
-		parse_file_info(struct archive_read *a,
-		    struct file_info *parent, const unsigned char *isodirrec,
-		    size_t reclen);
-static int	parse_rockridge(struct archive_read *a,
-		    struct file_info *file, const unsigned char *start,
-		    const unsigned char *end);
-static int	register_CE(struct archive_read *a, int32_t location,
-		    struct file_info *file);
-static int	read_CE(struct archive_read *a, struct iso9660 *iso9660);
-static void	parse_rockridge_NM1(struct file_info *,
-		    const unsigned char *, int);
-static void	parse_rockridge_SL1(struct file_info *,
-		    const unsigned char *, int);
-static void	parse_rockridge_TF1(struct file_info *,
-		    const unsigned char *, int);
-static void	parse_rockridge_ZF1(struct file_info *,
-		    const unsigned char *, int);
-static void	register_file(struct iso9660 *, struct file_info *);
-static void	release_files(struct iso9660 *);
-static unsigned	toi(const void *p, int n);
-static inline void re_add_entry(struct iso9660 *, struct file_info *);
-static inline struct file_info * re_get_entry(struct iso9660 *);
-static inline int rede_add_entry(struct file_info *);
-static inline struct file_info * rede_get_entry(struct file_info *);
-static inline void cache_add_entry(struct iso9660 *iso9660,
-		    struct file_info *file);
-static inline struct file_info *cache_get_entry(struct iso9660 *iso9660);
-static int	heap_add_entry(struct archive_read *a, struct heap_queue *heap,
-		    struct file_info *file, uint64_t key);
-static struct file_info *heap_get_entry(struct heap_queue *heap);
-
-#define add_entry(arch, iso9660, file)	\
-	heap_add_entry(arch, &((iso9660)->pending_files), file, file->offset)
-#define next_entry(iso9660)		\
-	heap_get_entry(&((iso9660)->pending_files))
-
-int
-archive_read_support_format_iso9660(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct iso9660 *iso9660;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_iso9660");
-
-	iso9660 = (struct iso9660 *)calloc(1, sizeof(*iso9660));
-	if (iso9660 == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate iso9660 data");
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->magic = ISO9660_MAGIC;
-	iso9660->cache_files.first = NULL;
-	iso9660->cache_files.last = &(iso9660->cache_files.first);
-	iso9660->re_files.first = NULL;
-	iso9660->re_files.last = &(iso9660->re_files.first);
-	/* Enable to support Joliet extensions by default.	*/
-	iso9660->opt_support_joliet = 1;
-	/* Enable to support Rock Ridge extensions by default.	*/
-	iso9660->opt_support_rockridge = 1;
-
-	r = __archive_read_register_format(a,
-	    iso9660,
-	    "iso9660",
-	    archive_read_format_iso9660_bid,
-	    archive_read_format_iso9660_options,
-	    archive_read_format_iso9660_read_header,
-	    archive_read_format_iso9660_read_data,
-	    archive_read_format_iso9660_read_data_skip,
-	    NULL,
-	    archive_read_format_iso9660_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK) {
-		free(iso9660);
-		return (r);
-	}
-	return (ARCHIVE_OK);
-}
-
-
-static int
-archive_read_format_iso9660_bid(struct archive_read *a, int best_bid)
-{
-	struct iso9660 *iso9660;
-	ssize_t bytes_read;
-	const unsigned char *p;
-	int seenTerminator;
-
-	/* If there's already a better bid than we can ever
-	   make, don't bother testing. */
-	if (best_bid > 48)
-		return (-1);
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	/*
-	 * Skip the first 32k (reserved area) and get the first
-	 * 8 sectors of the volume descriptor table.  Of course,
-	 * if the I/O layer gives us more, we'll take it.
-	 */
-#define RESERVED_AREA	(SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE)
-	p = __archive_read_ahead(a,
-	    RESERVED_AREA + 8 * LOGICAL_BLOCK_SIZE,
-	    &bytes_read);
-	if (p == NULL)
-	    return (-1);
-
-	/* Skip the reserved area. */
-	bytes_read -= RESERVED_AREA;
-	p += RESERVED_AREA;
-
-	/* Check each volume descriptor. */
-	seenTerminator = 0;
-	for (; bytes_read > LOGICAL_BLOCK_SIZE;
-	    bytes_read -= LOGICAL_BLOCK_SIZE, p += LOGICAL_BLOCK_SIZE) {
-		/* Do not handle undefined Volume Descriptor Type. */
-		if (p[0] >= 4 && p[0] <= 254)
-			return (0);
-		/* Standard Identifier must be "CD001" */
-		if (memcmp(p + 1, "CD001", 5) != 0)
-			return (0);
-		if (isPVD(iso9660, p))
-			continue;
-		if (!iso9660->joliet.location) {
-			if (isJolietSVD(iso9660, p))
-				continue;
-		}
-		if (isBootRecord(iso9660, p))
-			continue;
-		if (isEVD(iso9660, p))
-			continue;
-		if (isSVD(iso9660, p))
-			continue;
-		if (isVolumePartition(iso9660, p))
-			continue;
-		if (isVDSetTerminator(iso9660, p)) {
-			seenTerminator = 1;
-			break;
-		}
-		return (0);
-	}
-	/*
-	 * ISO 9660 format must have Primary Volume Descriptor and
-	 * Volume Descriptor Set Terminator.
-	 */
-	if (seenTerminator && iso9660->primary.location > 16)
-		return (48);
-
-	/* We didn't find a valid PVD; return a bid of zero. */
-	return (0);
-}
-
-static int
-archive_read_format_iso9660_options(struct archive_read *a,
-		const char *key, const char *val)
-{
-	struct iso9660 *iso9660;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	if (strcmp(key, "joliet") == 0) {
-		if (val == NULL || strcmp(val, "off") == 0 ||
-				strcmp(val, "ignore") == 0 ||
-				strcmp(val, "disable") == 0 ||
-				strcmp(val, "0") == 0)
-			iso9660->opt_support_joliet = 0;
-		else
-			iso9660->opt_support_joliet = 1;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "rockridge") == 0 ||
-	    strcmp(key, "Rockridge") == 0) {
-		iso9660->opt_support_rockridge = val != NULL;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset,
-unsigned bytes)
-{
-
-	while (bytes >= sizeof(iso9660->null)) {
-		if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null)))
-			return (0);
-		offset += sizeof(iso9660->null);
-		bytes -= sizeof(iso9660->null);
-	}
-	if (bytes)
-		return memcmp(iso9660->null, h + offset, bytes) == 0;
-	else
-		return (1);
-}
-
-static int
-isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
-{
-	(void)iso9660; /* UNUSED */
-
-	/* Type of the Volume Descriptor Boot Record must be 0. */
-	if (h[0] != 0)
-		return (0);
-
-	/* Volume Descriptor Version must be 1. */
-	if (h[6] != 1)
-		return (0);
-
-	return (1);
-}
-
-static int
-isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
-{
-	int32_t location;
-
-	/* Type of the Volume Partition Descriptor must be 3. */
-	if (h[0] != 3)
-		return (0);
-
-	/* Volume Descriptor Version must be 1. */
-	if (h[6] != 1)
-		return (0);
-	/* Unused Field */
-	if (h[7] != 0)
-		return (0);
-
-	location = archive_le32dec(h + 72);
-	if (location <= SYSTEM_AREA_BLOCK ||
-	    location >= iso9660->volume_block)
-		return (0);
-	if ((uint32_t)location != archive_be32dec(h + 76))
-		return (0);
-
-	return (1);
-}
-
-static int
-isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
-{
-	(void)iso9660; /* UNUSED */
-
-	/* Type of the Volume Descriptor Set Terminator must be 255. */
-	if (h[0] != 255)
-		return (0);
-
-	/* Volume Descriptor Version must be 1. */
-	if (h[6] != 1)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, 7, 2048-7))
-		return (0);
-
-	return (1);
-}
-
-static int
-isJolietSVD(struct iso9660 *iso9660, const unsigned char *h)
-{
-	const unsigned char *p;
-	ssize_t logical_block_size;
-	int32_t volume_block;
-
-	/* Check if current sector is a kind of Supplementary Volume
-	 * Descriptor. */
-	if (!isSVD(iso9660, h))
-		return (0);
-
-	/* FIXME: do more validations according to joliet spec. */
-
-	/* check if this SVD contains joliet extension! */
-	p = h + SVD_escape_sequences_offset;
-	/* N.B. Joliet spec says p[1] == '\\', but.... */
-	if (p[0] == '%' && p[1] == '/') {
-		int level = 0;
-
-		if (p[2] == '@')
-			level = 1;
-		else if (p[2] == 'C')
-			level = 2;
-		else if (p[2] == 'E')
-			level = 3;
-		else /* not joliet */
-			return (0);
-
-		iso9660->seenJoliet = level;
-
-	} else /* not joliet */
-		return (0);
-
-	logical_block_size =
-	    archive_le16dec(h + SVD_logical_block_size_offset);
-	volume_block = archive_le32dec(h + SVD_volume_space_size_offset);
-
-	iso9660->logical_block_size = logical_block_size;
-	iso9660->volume_block = volume_block;
-	iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
-	/* Read Root Directory Record in Volume Descriptor. */
-	p = h + SVD_root_directory_record_offset;
-	iso9660->joliet.location = archive_le32dec(p + DR_extent_offset);
-	iso9660->joliet.size = archive_le32dec(p + DR_size_offset);
-
-	return (48);
-}
-
-static int
-isSVD(struct iso9660 *iso9660, const unsigned char *h)
-{
-	const unsigned char *p;
-	ssize_t logical_block_size;
-	int32_t volume_block;
-	int32_t location;
-
-	(void)iso9660; /* UNUSED */
-
-	/* Type 2 means it's a SVD. */
-	if (h[SVD_type_offset] != 2)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size))
-		return (0);
-	if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size))
-		return (0);
-	if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size))
-		return (0);
-
-	/* File structure version must be 1 for ISO9660/ECMA119. */
-	if (h[SVD_file_structure_version_offset] != 1)
-		return (0);
-
-	logical_block_size =
-	    archive_le16dec(h + SVD_logical_block_size_offset);
-	if (logical_block_size <= 0)
-		return (0);
-
-	volume_block = archive_le32dec(h + SVD_volume_space_size_offset);
-	if (volume_block <= SYSTEM_AREA_BLOCK+4)
-		return (0);
-
-	/* Location of Occurrence of Type L Path Table must be
-	 * available location,
-	 * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_le32dec(h+SVD_type_L_path_table_offset);
-	if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
-		return (0);
-
-	/* The Type M Path Table must be at a valid location (WinISO
-	 * and probably other programs omit this, so we allow zero)
-	 *
-	 * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_be32dec(h+SVD_type_M_path_table_offset);
-	if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
-	    || location >= volume_block)
-		return (0);
-
-	/* Read Root Directory Record in Volume Descriptor. */
-	p = h + SVD_root_directory_record_offset;
-	if (p[DR_length_offset] != 34)
-		return (0);
-
-	return (48);
-}
-
-static int
-isEVD(struct iso9660 *iso9660, const unsigned char *h)
-{
-	const unsigned char *p;
-	ssize_t logical_block_size;
-	int32_t volume_block;
-	int32_t location;
-
-	(void)iso9660; /* UNUSED */
-
-	/* Type of the Enhanced Volume Descriptor must be 2. */
-	if (h[PVD_type_offset] != 2)
-		return (0);
-
-	/* EVD version must be 2. */
-	if (h[PVD_version_offset] != 2)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (h[PVD_reserved1_offset] != 0)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
-		return (0);
-
-	/* Logical block size must be > 0. */
-	/* I've looked at Ecma 119 and can't find any stronger
-	 * restriction on this field. */
-	logical_block_size =
-	    archive_le16dec(h + PVD_logical_block_size_offset);
-	if (logical_block_size <= 0)
-		return (0);
-
-	volume_block =
-	    archive_le32dec(h + PVD_volume_space_size_offset);
-	if (volume_block <= SYSTEM_AREA_BLOCK+4)
-		return (0);
-
-	/* File structure version must be 2 for ISO9660:1999. */
-	if (h[PVD_file_structure_version_offset] != 2)
-		return (0);
-
-	/* Location of Occurrence of Type L Path Table must be
-	 * available location,
-	 * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_le32dec(h+PVD_type_1_path_table_offset);
-	if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
-		return (0);
-
-	/* Location of Occurrence of Type M Path Table must be
-	 * available location,
-	 * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_be32dec(h+PVD_type_m_path_table_offset);
-	if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
-	    || location >= volume_block)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size))
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
-		return (0);
-
-	/* Read Root Directory Record in Volume Descriptor. */
-	p = h + PVD_root_directory_record_offset;
-	if (p[DR_length_offset] != 34)
-		return (0);
-
-	return (48);
-}
-
-static int
-isPVD(struct iso9660 *iso9660, const unsigned char *h)
-{
-	const unsigned char *p;
-	ssize_t logical_block_size;
-	int32_t volume_block;
-	int32_t location;
-	int i;
-
-	/* Type of the Primary Volume Descriptor must be 1. */
-	if (h[PVD_type_offset] != 1)
-		return (0);
-
-	/* PVD version must be 1. */
-	if (h[PVD_version_offset] != 1)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (h[PVD_reserved1_offset] != 0)
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
-		return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
-		return (0);
-
-	/* Logical block size must be > 0. */
-	/* I've looked at Ecma 119 and can't find any stronger
-	 * restriction on this field. */
-	logical_block_size =
-	    archive_le16dec(h + PVD_logical_block_size_offset);
-	if (logical_block_size <= 0)
-		return (0);
-
-	volume_block = archive_le32dec(h + PVD_volume_space_size_offset);
-	if (volume_block <= SYSTEM_AREA_BLOCK+4)
-		return (0);
-
-	/* File structure version must be 1 for ISO9660/ECMA119. */
-	if (h[PVD_file_structure_version_offset] != 1)
-		return (0);
-
-	/* Location of Occurrence of Type L Path Table must be
-	 * available location,
-	 * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_le32dec(h+PVD_type_1_path_table_offset);
-	if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
-		return (0);
-
-	/* The Type M Path Table must also be at a valid location
-	 * (although ECMA 119 requires a Type M Path Table, WinISO and
-	 * probably other programs omit it, so we permit a zero here)
-	 *
-	 * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
-	location = archive_be32dec(h+PVD_type_m_path_table_offset);
-	if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
-	    || location >= volume_block)
-		return (0);
-
-	/* Reserved field must be 0. */
-	/* But accept NetBSD/FreeBSD "makefs" images with 0x20 here. */
-	for (i = 0; i < PVD_reserved4_size; ++i)
-		if (h[PVD_reserved4_offset + i] != 0
-		    && h[PVD_reserved4_offset + i] != 0x20)
-			return (0);
-
-	/* Reserved field must be 0. */
-	if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
-		return (0);
-
-	/* XXX TODO: Check other values for sanity; reject more
-	 * malformed PVDs. XXX */
-
-	/* Read Root Directory Record in Volume Descriptor. */
-	p = h + PVD_root_directory_record_offset;
-	if (p[DR_length_offset] != 34)
-		return (0);
-
-	if (!iso9660->primary.location) {
-		iso9660->logical_block_size = logical_block_size;
-		iso9660->volume_block = volume_block;
-		iso9660->volume_size =
-		    logical_block_size * (uint64_t)volume_block;
-		iso9660->primary.location =
-		    archive_le32dec(p + DR_extent_offset);
-		iso9660->primary.size = archive_le32dec(p + DR_size_offset);
-	}
-
-	return (48);
-}
-
-static int
-read_children(struct archive_read *a, struct file_info *parent)
-{
-	struct iso9660 *iso9660;
-	const unsigned char *b, *p;
-	struct file_info *multi;
-	size_t step, skip_size;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-	/* flush any remaining bytes from the last round to ensure
-	 * we're positioned */
-	if (iso9660->entry_bytes_unconsumed) {
-		__archive_read_consume(a, iso9660->entry_bytes_unconsumed);
-		iso9660->entry_bytes_unconsumed = 0;
-	}
-	if (iso9660->current_position > parent->offset) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Ignoring out-of-order directory (%s) %jd > %jd",
-		    parent->name.s,
-		    (intmax_t)iso9660->current_position,
-		    (intmax_t)parent->offset);
-		return (ARCHIVE_WARN);
-	}
-	if (parent->offset + parent->size > iso9660->volume_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Directory is beyond end-of-media: %s",
-		    parent->name.s);
-		return (ARCHIVE_WARN);
-	}
-	if (iso9660->current_position < parent->offset) {
-		int64_t skipsize;
-
-		skipsize = parent->offset - iso9660->current_position;
-		skipsize = __archive_read_consume(a, skipsize);
-		if (skipsize < 0)
-			return ((int)skipsize);
-		iso9660->current_position = parent->offset;
-	}
-
-	step = (size_t)(((parent->size + iso9660->logical_block_size -1) /
-	    iso9660->logical_block_size) * iso9660->logical_block_size);
-	b = __archive_read_ahead(a, step, NULL);
-	if (b == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to read full block when scanning "
-		    "ISO9660 directory list");
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->current_position += step;
-	multi = NULL;
-	skip_size = step;
-	while (step) {
-		p = b;
-		b += iso9660->logical_block_size;
-		step -= iso9660->logical_block_size;
-		for (; *p != 0 && p + DR_name_offset < b && p + *p <= b;
-			p += *p) {
-			struct file_info *child;
-
-			/* N.B.: these special directory identifiers
-			 * are 8 bit "values" even on a
-			 * Joliet CD with UCS-2 (16bit) encoding.
-			 */
-
-			/* Skip '.' entry. */
-			if (*(p + DR_name_len_offset) == 1
-			    && *(p + DR_name_offset) == '\0')
-				continue;
-			/* Skip '..' entry. */
-			if (*(p + DR_name_len_offset) == 1
-			    && *(p + DR_name_offset) == '\001')
-				continue;
-			child = parse_file_info(a, parent, p, b - p);
-			if (child == NULL) {
-				__archive_read_consume(a, skip_size);
-				return (ARCHIVE_FATAL);
-			}
-			if (child->cl_offset == 0 &&
-			    (child->multi_extent || multi != NULL)) {
-				struct content *con;
-
-				if (multi == NULL) {
-					multi = child;
-					multi->contents.first = NULL;
-					multi->contents.last =
-					    &(multi->contents.first);
-				}
-				con = malloc(sizeof(struct content));
-				if (con == NULL) {
-					archive_set_error(
-					    &a->archive, ENOMEM,
-					    "No memory for multi extent");
-					__archive_read_consume(a, skip_size);
-					return (ARCHIVE_FATAL);
-				}
-				con->offset = child->offset;
-				con->size = child->size;
-				con->next = NULL;
-				*multi->contents.last = con;
-				multi->contents.last = &(con->next);
-				if (multi == child) {
-					if (add_entry(a, iso9660, child)
-					    != ARCHIVE_OK)
-						return (ARCHIVE_FATAL);
-				} else {
-					multi->size += child->size;
-					if (!child->multi_extent)
-						multi = NULL;
-				}
-			} else
-				if (add_entry(a, iso9660, child) != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-		}
-	}
-
-	__archive_read_consume(a, skip_size);
-
-	/* Read data which recorded by RRIP "CE" extension. */
-	if (read_CE(a, iso9660) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-choose_volume(struct archive_read *a, struct iso9660 *iso9660)
-{
-	struct file_info *file;
-	int64_t skipsize;
-	struct vd *vd;
-	const void *block;
-	char seenJoliet;
-
-	vd = &(iso9660->primary);
-	if (!iso9660->opt_support_joliet)
-		iso9660->seenJoliet = 0;
-	if (iso9660->seenJoliet &&
-		vd->location > iso9660->joliet.location)
-		/* This condition is unlikely; by way of caution. */
-		vd = &(iso9660->joliet);
-
-	skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location;
-	skipsize = __archive_read_consume(a, skipsize);
-	if (skipsize < 0)
-		return ((int)skipsize);
-	iso9660->current_position = skipsize;
-
-	block = __archive_read_ahead(a, vd->size, NULL);
-	if (block == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to read full block when scanning "
-		    "ISO9660 directory list");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * While reading Root Directory, flag seenJoliet must be zero to
-	 * avoid converting special name 0x00(Current Directory) and
-	 * next byte to UCS2.
-	 */
-	seenJoliet = iso9660->seenJoliet;/* Save flag. */
-	iso9660->seenJoliet = 0;
-	file = parse_file_info(a, NULL, block, vd->size);
-	if (file == NULL)
-		return (ARCHIVE_FATAL);
-	iso9660->seenJoliet = seenJoliet;
-
-	/*
-	 * If the iso image has both RockRidge and Joliet, we preferentially
-	 * use RockRidge Extensions rather than Joliet ones.
-	 */
-	if (vd == &(iso9660->primary) && iso9660->seenRockridge
-	    && iso9660->seenJoliet)
-		iso9660->seenJoliet = 0;
-
-	if (vd == &(iso9660->primary) && !iso9660->seenRockridge
-	    && iso9660->seenJoliet) {
-		/* Switch reading data from primary to joliet. */
-		vd = &(iso9660->joliet);
-		skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location;
-		skipsize -= iso9660->current_position;
-		skipsize = __archive_read_consume(a, skipsize);
-		if (skipsize < 0)
-			return ((int)skipsize);
-		iso9660->current_position += skipsize;
-
-		block = __archive_read_ahead(a, vd->size, NULL);
-		if (block == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Failed to read full block when scanning "
-			    "ISO9660 directory list");
-			return (ARCHIVE_FATAL);
-		}
-		iso9660->seenJoliet = 0;
-		file = parse_file_info(a, NULL, block, vd->size);
-		if (file == NULL)
-			return (ARCHIVE_FATAL);
-		iso9660->seenJoliet = seenJoliet;
-	}
-
-	/* Store the root directory in the pending list. */
-	if (add_entry(a, iso9660, file) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	if (iso9660->seenRockridge) {
-		a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
-		a->archive.archive_format_name =
-		    "ISO9660 with Rockridge extensions";
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_iso9660_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct iso9660 *iso9660;
-	struct file_info *file;
-	int r, rd_r = ARCHIVE_OK;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	if (!a->archive.archive_format) {
-		a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
-		a->archive.archive_format_name = "ISO9660";
-	}
-
-	if (iso9660->current_position == 0) {
-		r = choose_volume(a, iso9660);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	file = NULL;/* Eliminate a warning. */
-	/* Get the next entry that appears after the current offset. */
-	r = next_entry_seek(a, iso9660, &file);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	if (iso9660->seenJoliet) {
-		/*
-		 * Convert UTF-16BE of a filename to local locale MBS
-		 * and store the result into a filename field.
-		 */
-		if (iso9660->sconv_utf16be == NULL) {
-			iso9660->sconv_utf16be =
-			    archive_string_conversion_from_charset(
-				&(a->archive), "UTF-16BE", 1);
-			if (iso9660->sconv_utf16be == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FATAL);
-		}
-		if (iso9660->utf16be_path == NULL) {
-			iso9660->utf16be_path = malloc(UTF16_NAME_MAX);
-			if (iso9660->utf16be_path == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		if (iso9660->utf16be_previous_path == NULL) {
-			iso9660->utf16be_previous_path = malloc(UTF16_NAME_MAX);
-			if (iso9660->utf16be_previous_path == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory");
-				return (ARCHIVE_FATAL);
-			}
-		}
-
-		iso9660->utf16be_path_len = 0;
-		if (build_pathname_utf16be(iso9660->utf16be_path,
-		    UTF16_NAME_MAX, &(iso9660->utf16be_path_len), file) != 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Pathname is too long");
-			return (ARCHIVE_FATAL);
-		}
-
-		r = archive_entry_copy_pathname_l(entry,
-		    (const char *)iso9660->utf16be_path,
-		    iso9660->utf16be_path_len,
-		    iso9660->sconv_utf16be);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for Pathname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Pathname cannot be converted "
-			    "from %s to current locale.",
-			    archive_string_conversion_charset_name(
-			      iso9660->sconv_utf16be));
-
-			rd_r = ARCHIVE_WARN;
-		}
-	} else {
-		const char *path = build_pathname(&iso9660->pathname, file, 0);
-		if (path == NULL) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Pathname is too long");
-			return (ARCHIVE_FATAL);
-		} else {
-			archive_string_empty(&iso9660->pathname);
-			archive_entry_set_pathname(entry, path);
-		}
-	}
-
-	iso9660->entry_bytes_remaining = file->size;
-	/* Offset for sparse-file-aware clients. */
-	iso9660->entry_sparse_offset = 0;
-
-	if (file->offset + file->size > iso9660->volume_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "File is beyond end-of-media: %s",
-		    archive_entry_pathname(entry));
-		iso9660->entry_bytes_remaining = 0;
-		return (ARCHIVE_WARN);
-	}
-
-	/* Set up the entry structure with information about this entry. */
-	archive_entry_set_mode(entry, file->mode);
-	archive_entry_set_uid(entry, file->uid);
-	archive_entry_set_gid(entry, file->gid);
-	archive_entry_set_nlink(entry, file->nlinks);
-	if (file->birthtime_is_set)
-		archive_entry_set_birthtime(entry, file->birthtime, 0);
-	else
-		archive_entry_unset_birthtime(entry);
-	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);
-	if (file->symlink.s != NULL)
-		archive_entry_copy_symlink(entry, file->symlink.s);
-
-	/* Note: If the input isn't seekable, we can't rewind to
-	 * return the same body again, so if the next entry refers to
-	 * the same data, we have to return it as a hardlink to the
-	 * original entry. */
-	if (file->number != -1 &&
-	    file->number == iso9660->previous_number) {
-		if (iso9660->seenJoliet) {
-			r = archive_entry_copy_hardlink_l(entry,
-			    (const char *)iso9660->utf16be_previous_path,
-			    iso9660->utf16be_previous_path_len,
-			    iso9660->sconv_utf16be);
-			if (r != 0) {
-				if (errno == ENOMEM) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "No memory for Linkname");
-					return (ARCHIVE_FATAL);
-				}
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Linkname cannot be converted "
-				    "from %s to current locale.",
-				    archive_string_conversion_charset_name(
-				      iso9660->sconv_utf16be));
-				rd_r = ARCHIVE_WARN;
-			}
-		} else
-			archive_entry_set_hardlink(entry,
-			    iso9660->previous_pathname.s);
-		archive_entry_unset_size(entry);
-		iso9660->entry_bytes_remaining = 0;
-		return (rd_r);
-	}
-
-	if ((file->mode & AE_IFMT) != AE_IFDIR &&
-	    file->offset < iso9660->current_position) {
-		int64_t r64;
-
-		r64 = __archive_read_seek(a, file->offset, SEEK_SET);
-		if (r64 != (int64_t)file->offset) {
-			/* We can't seek backwards to extract it, so issue
-			 * a warning.  Note that this can only happen if
-			 * this entry was added to the heap after we passed
-			 * this offset, that is, only if the directory
-			 * mentioning this entry is later than the body of
-			 * the entry. Such layouts are very unusual; most
-			 * ISO9660 writers lay out and record all directory
-			 * information first, then store all file bodies. */
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Ignoring out-of-order file @%jx (%s) %jd < %jd",
-			    (intmax_t)file->number,
-			    iso9660->pathname.s,
-			    (intmax_t)file->offset,
-			    (intmax_t)iso9660->current_position);
-			iso9660->entry_bytes_remaining = 0;
-			return (ARCHIVE_WARN);
-		}
-		iso9660->current_position = (uint64_t)r64;
-	}
-
-	/* Initialize zisofs variables. */
-	iso9660->entry_zisofs.pz = file->pz;
-	if (file->pz) {
-#ifdef HAVE_ZLIB_H
-		struct zisofs  *zisofs;
-
-		zisofs = &iso9660->entry_zisofs;
-		zisofs->initialized = 0;
-		zisofs->pz_log2_bs = file->pz_log2_bs;
-		zisofs->pz_uncompressed_size = file->pz_uncompressed_size;
-		zisofs->pz_offset = 0;
-		zisofs->header_avail = 0;
-		zisofs->header_passed = 0;
-		zisofs->block_pointers_avail = 0;
-#endif
-		archive_entry_set_size(entry, file->pz_uncompressed_size);
-	}
-
-	iso9660->previous_number = file->number;
-	if (iso9660->seenJoliet) {
-		memcpy(iso9660->utf16be_previous_path, iso9660->utf16be_path,
-		    iso9660->utf16be_path_len);
-		iso9660->utf16be_previous_path_len = iso9660->utf16be_path_len;
-	} else
-		archive_strcpy(
-		    &iso9660->previous_pathname, iso9660->pathname.s);
-
-	/* Reset entry_bytes_remaining if the file is multi extent. */
-	iso9660->entry_content = file->contents.first;
-	if (iso9660->entry_content != NULL)
-		iso9660->entry_bytes_remaining = iso9660->entry_content->size;
-
-	if (archive_entry_filetype(entry) == AE_IFDIR) {
-		/* Overwrite nlinks by proper link number which is
-		 * calculated from number of sub directories. */
-		archive_entry_set_nlink(entry, 2 + file->subdirs);
-		/* Directory data has been read completely. */
-		iso9660->entry_bytes_remaining = 0;
-	}
-
-	if (rd_r != ARCHIVE_OK)
-		return (rd_r);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_iso9660_read_data_skip(struct archive_read *a)
-{
-	/* Because read_next_header always does an explicit skip
-	 * to the next entry, we don't need to do anything here. */
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-#ifdef HAVE_ZLIB_H
-
-static int
-zisofs_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct iso9660 *iso9660;
-	struct zisofs  *zisofs;
-	const unsigned char *p;
-	size_t avail;
-	ssize_t bytes_read;
-	size_t uncompressed_size;
-	int r;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-	zisofs = &iso9660->entry_zisofs;
-
-	p = __archive_read_ahead(a, 1, &bytes_read);
-	if (bytes_read <= 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated zisofs file body");
-		return (ARCHIVE_FATAL);
-	}
-	if (bytes_read > iso9660->entry_bytes_remaining)
-		bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
-	avail = bytes_read;
-	uncompressed_size = 0;
-
-	if (!zisofs->initialized) {
-		size_t ceil, xsize;
-
-		/* Allocate block pointers buffer. */
-		ceil = (size_t)((zisofs->pz_uncompressed_size +
-			(((int64_t)1) << zisofs->pz_log2_bs) - 1)
-			>> zisofs->pz_log2_bs);
-		xsize = (ceil + 1) * 4;
-		if (zisofs->block_pointers_alloc < xsize) {
-			size_t alloc;
-
-			if (zisofs->block_pointers != NULL)
-				free(zisofs->block_pointers);
-			alloc = ((xsize >> 10) + 1) << 10;
-			zisofs->block_pointers = malloc(alloc);
-			if (zisofs->block_pointers == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for zisofs decompression");
-				return (ARCHIVE_FATAL);
-			}
-			zisofs->block_pointers_alloc = alloc;
-		}
-		zisofs->block_pointers_size = xsize;
-
-		/* Allocate uncompressed data buffer. */
-		xsize = (size_t)1UL << zisofs->pz_log2_bs;
-		if (zisofs->uncompressed_buffer_size < xsize) {
-			if (zisofs->uncompressed_buffer != NULL)
-				free(zisofs->uncompressed_buffer);
-			zisofs->uncompressed_buffer = malloc(xsize);
-			if (zisofs->uncompressed_buffer == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "No memory for zisofs decompression");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		zisofs->uncompressed_buffer_size = xsize;
-
-		/*
-		 * Read the file header, and check the magic code of zisofs.
-		 */
-		if (zisofs->header_avail < sizeof(zisofs->header)) {
-			xsize = sizeof(zisofs->header) - zisofs->header_avail;
-			if (avail < xsize)
-				xsize = avail;
-			memcpy(zisofs->header + zisofs->header_avail, p, xsize);
-			zisofs->header_avail += xsize;
-			avail -= xsize;
-			p += xsize;
-		}
-		if (!zisofs->header_passed &&
-		    zisofs->header_avail == sizeof(zisofs->header)) {
-			int err = 0;
-
-			if (memcmp(zisofs->header, zisofs_magic,
-			    sizeof(zisofs_magic)) != 0)
-				err = 1;
-			if (archive_le32dec(zisofs->header + 8)
-			    != zisofs->pz_uncompressed_size)
-				err = 1;
-			if (zisofs->header[12] != 4)
-				err = 1;
-			if (zisofs->header[13] != zisofs->pz_log2_bs)
-				err = 1;
-			if (err) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Illegal zisofs file body");
-				return (ARCHIVE_FATAL);
-			}
-			zisofs->header_passed = 1;
-		}
-		/*
-		 * Read block pointers.
-		 */
-		if (zisofs->header_passed &&
-		    zisofs->block_pointers_avail < zisofs->block_pointers_size) {
-			xsize = zisofs->block_pointers_size
-			    - zisofs->block_pointers_avail;
-			if (avail < xsize)
-				xsize = avail;
-			memcpy(zisofs->block_pointers
-			    + zisofs->block_pointers_avail, p, xsize);
-			zisofs->block_pointers_avail += xsize;
-			avail -= xsize;
-			p += xsize;
-		    	if (zisofs->block_pointers_avail
-			    == zisofs->block_pointers_size) {
-				/* We've got all block pointers and initialize
-				 * related variables.	*/
-				zisofs->block_off = 0;
-				zisofs->block_avail = 0;
-				/* Complete a initialization */
-				zisofs->initialized = 1;
-			}
-		}
-
-		if (!zisofs->initialized)
-			goto next_data; /* We need more data. */
-	}
-
-	/*
-	 * Get block offsets from block pointers.
-	 */
-	if (zisofs->block_avail == 0) {
-		uint32_t bst, bed;
-
-		if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
-			/* There isn't a pair of offsets. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers");
-			return (ARCHIVE_FATAL);
-		}
-		bst = archive_le32dec(
-		    zisofs->block_pointers + zisofs->block_off);
-		if (bst != zisofs->pz_offset + (bytes_read - avail)) {
-			/* TODO: Should we seek offset of current file
-			 * by bst ? */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers(cannot seek)");
-			return (ARCHIVE_FATAL);
-		}
-		bed = archive_le32dec(
-		    zisofs->block_pointers + zisofs->block_off + 4);
-		if (bed < bst) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers");
-			return (ARCHIVE_FATAL);
-		}
-		zisofs->block_avail = bed - bst;
-		zisofs->block_off += 4;
-
-		/* Initialize compression library for new block. */
-		if (zisofs->stream_valid)
-			r = inflateReset(&zisofs->stream);
-		else
-			r = inflateInit(&zisofs->stream);
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't initialize zisofs decompression.");
-			return (ARCHIVE_FATAL);
-		}
-		zisofs->stream_valid = 1;
-		zisofs->stream.total_in = 0;
-		zisofs->stream.total_out = 0;
-	}
-
-	/*
-	 * Make uncompressed data.
-	 */
-	if (zisofs->block_avail == 0) {
-		memset(zisofs->uncompressed_buffer, 0,
-		    zisofs->uncompressed_buffer_size);
-		uncompressed_size = zisofs->uncompressed_buffer_size;
-	} else {
-		zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
-		if (avail > zisofs->block_avail)
-			zisofs->stream.avail_in = zisofs->block_avail;
-		else
-			zisofs->stream.avail_in = (uInt)avail;
-		zisofs->stream.next_out = zisofs->uncompressed_buffer;
-		zisofs->stream.avail_out =
-		    (uInt)zisofs->uncompressed_buffer_size;
-
-		r = inflate(&zisofs->stream, 0);
-		switch (r) {
-		case Z_OK: /* Decompressor made some progress.*/
-		case Z_STREAM_END: /* Found end of stream. */
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "zisofs decompression failed (%d)", r);
-			return (ARCHIVE_FATAL);
-		}
-		uncompressed_size =
-		    zisofs->uncompressed_buffer_size - zisofs->stream.avail_out;
-		avail -= zisofs->stream.next_in - p;
-		zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
-	}
-next_data:
-	bytes_read -= avail;
-	*buff = zisofs->uncompressed_buffer;
-	*size = uncompressed_size;
-	*offset = iso9660->entry_sparse_offset;
-	iso9660->entry_sparse_offset += uncompressed_size;
-	iso9660->entry_bytes_remaining -= bytes_read;
-	iso9660->current_position += bytes_read;
-	zisofs->pz_offset += (uint32_t)bytes_read;
-	iso9660->entry_bytes_unconsumed += bytes_read;
-
-	return (ARCHIVE_OK);
-}
-
-#else /* HAVE_ZLIB_H */
-
-static int
-zisofs_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-
-	(void)buff;/* UNUSED */
-	(void)size;/* UNUSED */
-	(void)offset;/* UNUSED */
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "zisofs is not supported on this platform.");
-	return (ARCHIVE_FAILED);
-}
-
-#endif /* HAVE_ZLIB_H */
-
-static int
-archive_read_format_iso9660_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	ssize_t bytes_read;
-	struct iso9660 *iso9660;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	if (iso9660->entry_bytes_unconsumed) {
-		__archive_read_consume(a, iso9660->entry_bytes_unconsumed);
-		iso9660->entry_bytes_unconsumed = 0;
-	}
-
-	if (iso9660->entry_bytes_remaining <= 0) {
-		if (iso9660->entry_content != NULL)
-			iso9660->entry_content = iso9660->entry_content->next;
-		if (iso9660->entry_content == NULL) {
-			*buff = NULL;
-			*size = 0;
-			*offset = iso9660->entry_sparse_offset;
-			return (ARCHIVE_EOF);
-		}
-		/* Seek forward to the start of the entry. */
-		if (iso9660->current_position < iso9660->entry_content->offset) {
-			int64_t step;
-
-			step = iso9660->entry_content->offset -
-			    iso9660->current_position;
-			step = __archive_read_consume(a, step);
-			if (step < 0)
-				return ((int)step);
-			iso9660->current_position =
-			    iso9660->entry_content->offset;
-		}
-		if (iso9660->entry_content->offset < iso9660->current_position) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Ignoring out-of-order file (%s) %jd < %jd",
-			    iso9660->pathname.s,
-			    (intmax_t)iso9660->entry_content->offset,
-			    (intmax_t)iso9660->current_position);
-			*buff = NULL;
-			*size = 0;
-			*offset = iso9660->entry_sparse_offset;
-			return (ARCHIVE_WARN);
-		}
-		iso9660->entry_bytes_remaining = iso9660->entry_content->size;
-	}
-	if (iso9660->entry_zisofs.pz)
-		return (zisofs_read_data(a, buff, size, offset));
-
-	*buff = __archive_read_ahead(a, 1, &bytes_read);
-	if (bytes_read == 0)
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Truncated input file");
-	if (*buff == NULL)
-		return (ARCHIVE_FATAL);
-	if (bytes_read > iso9660->entry_bytes_remaining)
-		bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
-	*size = bytes_read;
-	*offset = iso9660->entry_sparse_offset;
-	iso9660->entry_sparse_offset += bytes_read;
-	iso9660->entry_bytes_remaining -= bytes_read;
-	iso9660->entry_bytes_unconsumed = bytes_read;
-	iso9660->current_position += bytes_read;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_iso9660_cleanup(struct archive_read *a)
-{
-	struct iso9660 *iso9660;
-	int r = ARCHIVE_OK;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-	release_files(iso9660);
-	free(iso9660->read_ce_req.reqs);
-	archive_string_free(&iso9660->pathname);
-	archive_string_free(&iso9660->previous_pathname);
-	free(iso9660->pending_files.files);
-#ifdef HAVE_ZLIB_H
-	free(iso9660->entry_zisofs.uncompressed_buffer);
-	free(iso9660->entry_zisofs.block_pointers);
-	if (iso9660->entry_zisofs.stream_valid) {
-		if (inflateEnd(&iso9660->entry_zisofs.stream) != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up zlib decompressor");
-			r = ARCHIVE_FATAL;
-		}
-	}
-#endif
-	free(iso9660->utf16be_path);
-	free(iso9660->utf16be_previous_path);
-	free(iso9660);
-	(a->format->data) = NULL;
-	return (r);
-}
-
-/*
- * This routine parses a single ISO directory record, makes sense
- * of any extensions, and stores the result in memory.
- */
-static struct file_info *
-parse_file_info(struct archive_read *a, struct file_info *parent,
-    const unsigned char *isodirrec, size_t reclen)
-{
-	struct iso9660 *iso9660;
-	struct file_info *file, *filep;
-	size_t name_len;
-	const unsigned char *rr_start, *rr_end;
-	const unsigned char *p;
-	size_t dr_len = 0;
-	uint64_t fsize, offset;
-	int32_t location;
-	int flags;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	if (reclen != 0)
-		dr_len = (size_t)isodirrec[DR_length_offset];
-	/*
-	 * Sanity check that reclen is not zero and dr_len is greater than
-	 * reclen but at least 34
-	 */
-	if (reclen == 0 || reclen < dr_len || dr_len < 34) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"Invalid length of directory record");
-		return (NULL);
-	}
-	name_len = (size_t)isodirrec[DR_name_len_offset];
-	location = archive_le32dec(isodirrec + DR_extent_offset);
-	fsize = toi(isodirrec + DR_size_offset, DR_size_size);
-	/* Sanity check that name_len doesn't exceed dr_len. */
-	if (dr_len - 33 < name_len || name_len == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid length of file identifier");
-		return (NULL);
-	}
-	/* Sanity check that location doesn't exceed volume block.
-	 * Don't check lower limit of location; it's possibility
-	 * the location has negative value when file type is symbolic
-	 * link or file size is zero. As far as I know latest mkisofs
-	 * do that.
-	 */
-	if (location > 0 &&
-	    (location + ((fsize + iso9660->logical_block_size -1)
-	       / iso9660->logical_block_size))
-			> (uint32_t)iso9660->volume_block) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid location of extent of file");
-		return (NULL);
-	}
-	/* Sanity check that location doesn't have a negative value
-	 * when the file is not empty. it's too large. */
-	if (fsize != 0 && location < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid location of extent of file");
-		return (NULL);
-	}
-
-	/* Sanity check that this entry does not create a cycle. */
-	offset = iso9660->logical_block_size * (uint64_t)location;
-	for (filep = parent; filep != NULL; filep = filep->parent) {
-		if (filep->offset == offset) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Directory structure contains loop");
-			return (NULL);
-		}
-	}
-
-	/* Create a new file entry and copy data from the ISO dir record. */
-	file = (struct file_info *)calloc(1, sizeof(*file));
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for file entry");
-		return (NULL);
-	}
-	file->parent = parent;
-	file->offset = offset;
-	file->size = fsize;
-	file->mtime = isodate7(isodirrec + DR_date_offset);
-	file->ctime = file->atime = file->mtime;
-	file->rede_files.first = NULL;
-	file->rede_files.last = &(file->rede_files.first);
-
-	p = isodirrec + DR_name_offset;
-	/* Rockridge extensions (if any) follow name.  Compute this
-	 * before fidgeting the name_len below. */
-	rr_start = p + name_len + (name_len & 1 ? 0 : 1);
-	rr_end = isodirrec + dr_len;
-
-	if (iso9660->seenJoliet) {
-		/* Joliet names are max 64 chars (128 bytes) according to spec,
-		 * but genisoimage/mkisofs allows recording longer Joliet
-		 * names which are 103 UCS2 characters(206 bytes) by their
-		 * option '-joliet-long'.
-		 */
-		if (name_len > 206)
-			name_len = 206;
-		name_len &= ~1;
-
-		/* trim trailing first version and dot from filename.
-		 *
-		 * Remember we were in UTF-16BE land!
-		 * SEPARATOR 1 (.) and SEPARATOR 2 (;) are both
-		 * 16 bits big endian characters on Joliet.
-		 *
-		 * TODO: sanitize filename?
-		 *       Joliet allows any UCS-2 char except:
-		 *       *, /, :, ;, ? and \.
-		 */
-		/* Chop off trailing ';1' from files. */
-		if (name_len > 4 && p[name_len-4] == 0 && p[name_len-3] == ';'
-		    && p[name_len-2] == 0 && p[name_len-1] == '1')
-			name_len -= 4;
-#if 0 /* XXX: this somehow manages to strip of single-character file extensions, like '.c'. */
-		/* Chop off trailing '.' from filenames. */
-		if (name_len > 2 && p[name_len-2] == 0 && p[name_len-1] == '.')
-			name_len -= 2;
-#endif
-		if ((file->utf16be_name = malloc(name_len)) == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for file name");
-			goto fail;
-		}
-		memcpy(file->utf16be_name, p, name_len);
-		file->utf16be_bytes = name_len;
-	} else {
-		/* Chop off trailing ';1' from files. */
-		if (name_len > 2 && p[name_len - 2] == ';' &&
-				p[name_len - 1] == '1')
-			name_len -= 2;
-		/* Chop off trailing '.' from filenames. */
-		if (name_len > 1 && p[name_len - 1] == '.')
-			--name_len;
-
-		archive_strncpy(&file->name, (const char *)p, name_len);
-	}
-
-	flags = isodirrec[DR_flags_offset];
-	if (flags & 0x02)
-		file->mode = AE_IFDIR | 0700;
-	else
-		file->mode = AE_IFREG | 0400;
-	if (flags & 0x80)
-		file->multi_extent = 1;
-	else
-		file->multi_extent = 0;
-	/*
-	 * Use a location for the file number, which is treated as an inode
-	 * number to find out hardlink target. If Rockridge extensions is
-	 * being used, the file number will be overwritten by FILE SERIAL
-	 * NUMBER of RRIP "PX" extension.
-	 * Note: Old mkisofs did not record that FILE SERIAL NUMBER
-	 * in ISO images.
-	 * Note2: xorriso set 0 to the location of a symlink file.
-	 */
-	if (file->size == 0 && location >= 0) {
-		/* If file->size is zero, its location points wrong place,
-		 * and so we should not use it for the file number.
-		 * When the location has negative value, it can be used
-		 * for the file number.
-		 */
-		file->number = -1;
-		/* Do not appear before any directory entries. */
-		file->offset = -1;
-	} else
-		file->number = (int64_t)(uint32_t)location;
-
-	/* Rockridge extensions overwrite information from above. */
-	if (iso9660->opt_support_rockridge) {
-		if (parent == NULL && rr_end - rr_start >= 7) {
-			p = rr_start;
-			if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) {
-				/*
-				 * SP extension stores the suspOffset
-				 * (Number of bytes to skip between
-				 * filename and SUSP records.)
-				 * It is mandatory by the SUSP standard
-				 * (IEEE 1281).
-				 *
-				 * It allows SUSP to coexist with
-				 * non-SUSP uses of the System
-				 * Use Area by placing non-SUSP data
-				 * before SUSP data.
-				 *
-				 * SP extension must be in the root
-				 * directory entry, disable all SUSP
-				 * processing if not found.
-				 */
-				iso9660->suspOffset = p[6];
-				iso9660->seenSUSP = 1;
-				rr_start += 7;
-			}
-		}
-		if (iso9660->seenSUSP) {
-			int r;
-
-			file->name_continues = 0;
-			file->symlink_continues = 0;
-			rr_start += iso9660->suspOffset;
-			r = parse_rockridge(a, file, rr_start, rr_end);
-			if (r != ARCHIVE_OK)
-				goto fail;
-			/*
-			 * A file size of symbolic link files in ISO images
-			 * made by makefs is not zero and its location is
-			 * the same as those of next regular file. That is
-			 * the same as hard like file and it causes unexpected
-			 * error.
-			 */
-			if (file->size > 0 &&
-			    (file->mode & AE_IFMT) == AE_IFLNK) {
-				file->size = 0;
-				file->number = -1;
-				file->offset = -1;
-			}
-		} else
-			/* If there isn't SUSP, disable parsing
-			 * rock ridge extensions. */
-			iso9660->opt_support_rockridge = 0;
-	}
-
-	file->nlinks = 1;/* Reset nlink. we'll calculate it later. */
-	/* Tell file's parent how many children that parent has. */
-	if (parent != NULL && (flags & 0x02))
-		parent->subdirs++;
-
-	if (iso9660->seenRockridge) {
-		if (parent != NULL && parent->parent == NULL &&
-		    (flags & 0x02) && iso9660->rr_moved == NULL &&
-		    file->name.s &&
-		    (strcmp(file->name.s, "rr_moved") == 0 ||
-		     strcmp(file->name.s, ".rr_moved") == 0)) {
-			iso9660->rr_moved = file;
-			file->rr_moved = 1;
-			file->rr_moved_has_re_only = 1;
-			file->re = 0;
-			parent->subdirs--;
-		} else if (file->re) {
-			/*
-			 * Sanity check: file's parent is rr_moved.
-			 */
-			if (parent == NULL || parent->rr_moved == 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge RE");
-				goto fail;
-			}
-			/*
-			 * Sanity check: file does not have "CL" extension.
-			 */
-			if (file->cl_offset) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge RE and CL");
-				goto fail;
-			}
-			/*
-			 * Sanity check: The file type must be a directory.
-			 */
-			if ((flags & 0x02) == 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge RE");
-				goto fail;
-			}
-		} else if (parent != NULL && parent->rr_moved)
-			file->rr_moved_has_re_only = 0;
-		else if (parent != NULL && (flags & 0x02) &&
-		    (parent->re || parent->re_descendant))
-			file->re_descendant = 1;
-		if (file->cl_offset) {
-			struct file_info *r;
-
-			if (parent == NULL || parent->parent == NULL) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge CL");
-				goto fail;
-			}
-			/*
-			 * Sanity check: The file type must be a regular file.
-			 */
-			if ((flags & 0x02) != 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge CL");
-				goto fail;
-			}
-			parent->subdirs++;
-			/* Overwrite an offset and a number of this "CL" entry
-			 * to appear before other dirs. "+1" to those is to
-			 * make sure to appear after "RE" entry which this
-			 * "CL" entry should be connected with. */
-			file->offset = file->number = file->cl_offset + 1;
-
-			/*
-			 * Sanity check: cl_offset does not point at its
-			 * the parents or itself.
-			 */
-			for (r = parent; r; r = r->parent) {
-				if (r->offset == file->cl_offset) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "Invalid Rockridge CL");
-					goto fail;
-				}
-			}
-			if (file->cl_offset == file->offset ||
-			    parent->rr_moved) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Invalid Rockridge CL");
-				goto fail;
-			}
-		}
-	}
-
-#if DEBUG
-	/* DEBUGGING: Warn about attributes I don't yet fully support. */
-	if ((flags & ~0x02) != 0) {
-		fprintf(stderr, "\n ** Unrecognized flag: ");
-		dump_isodirrec(stderr, isodirrec);
-		fprintf(stderr, "\n");
-	} else if (toi(isodirrec + DR_volume_sequence_number_offset, 2) != 1) {
-		fprintf(stderr, "\n ** Unrecognized sequence number: ");
-		dump_isodirrec(stderr, isodirrec);
-		fprintf(stderr, "\n");
-	} else if (*(isodirrec + DR_file_unit_size_offset) != 0) {
-		fprintf(stderr, "\n ** Unexpected file unit size: ");
-		dump_isodirrec(stderr, isodirrec);
-		fprintf(stderr, "\n");
-	} else if (*(isodirrec + DR_interleave_offset) != 0) {
-		fprintf(stderr, "\n ** Unexpected interleave: ");
-		dump_isodirrec(stderr, isodirrec);
-		fprintf(stderr, "\n");
-	} else if (*(isodirrec + DR_ext_attr_length_offset) != 0) {
-		fprintf(stderr, "\n ** Unexpected extended attribute length: ");
-		dump_isodirrec(stderr, isodirrec);
-		fprintf(stderr, "\n");
-	}
-#endif
-	register_file(iso9660, file);
-	return (file);
-fail:
-	archive_string_free(&file->name);
-	free(file);
-	return (NULL);
-}
-
-static int
-parse_rockridge(struct archive_read *a, struct file_info *file,
-    const unsigned char *p, const unsigned char *end)
-{
-	struct iso9660 *iso9660;
-	int entry_seen = 0;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-
-	while (p + 4 <= end  /* Enough space for another entry. */
-	    && p[0] >= 'A' && p[0] <= 'Z' /* Sanity-check 1st char of name. */
-	    && p[1] >= 'A' && p[1] <= 'Z' /* Sanity-check 2nd char of name. */
-	    && p[2] >= 4 /* Sanity-check length. */
-	    && p + p[2] <= end) { /* Sanity-check length. */
-		const unsigned char *data = p + 4;
-		int data_length = p[2] - 4;
-		int version = p[3];
-
-		switch(p[0]) {
-		case 'C':
-			if (p[1] == 'E') {
-				if (version == 1 && data_length == 24) {
-					/*
-					 * CE extension comprises:
-					 *   8 byte sector containing extension
-					 *   8 byte offset w/in above sector
-					 *   8 byte length of continuation
-					 */
-					int32_t location =
-					    archive_le32dec(data);
-					file->ce_offset =
-					    archive_le32dec(data+8);
-					file->ce_size =
-					    archive_le32dec(data+16);
-					if (register_CE(a, location, file)
-					    != ARCHIVE_OK)
-						return (ARCHIVE_FATAL);
-				}
-			}
-			else if (p[1] == 'L') {
-				if (version == 1 && data_length == 8) {
-					file->cl_offset = (uint64_t)
-					    iso9660->logical_block_size *
-					    (uint64_t)archive_le32dec(data);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			break;
-		case 'N':
-			if (p[1] == 'M') {
-				if (version == 1) {
-					parse_rockridge_NM1(file,
-					    data, data_length);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			break;
-		case 'P':
-			/*
-			 * PD extension is padding;
-			 * contents are always ignored.
-			 *
-			 * PL extension won't appear;
-			 * contents are always ignored.
-			 */
-			if (p[1] == 'N') {
-				if (version == 1 && data_length == 16) {
-					file->rdev = toi(data,4);
-					file->rdev <<= 32;
-					file->rdev |= toi(data + 8, 4);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			else if (p[1] == 'X') {
-				/*
-				 * PX extension comprises:
-				 *   8 bytes for mode,
-				 *   8 bytes for nlinks,
-				 *   8 bytes for uid,
-				 *   8 bytes for gid,
-				 *   8 bytes for inode.
-				 */
-				if (version == 1) {
-					if (data_length >= 8)
-						file->mode
-						    = toi(data, 4);
-					if (data_length >= 16)
-						file->nlinks
-						    = toi(data + 8, 4);
-					if (data_length >= 24)
-						file->uid
-						    = toi(data + 16, 4);
-					if (data_length >= 32)
-						file->gid
-						    = toi(data + 24, 4);
-					if (data_length >= 40)
-						file->number
-						    = toi(data + 32, 4);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			break;
-		case 'R':
-			if (p[1] == 'E' && version == 1) {
-				file->re = 1;
-				iso9660->seenRockridge = 1;
-			}
-			else if (p[1] == 'R' && version == 1) {
-				/*
-				 * RR extension comprises:
-				 *    one byte flag value
-				 * This extension is obsolete,
-				 * so contents are always ignored.
-				 */
-			}
-			break;
-		case 'S':
-			if (p[1] == 'L') {
-				if (version == 1) {
-					parse_rockridge_SL1(file,
-					    data, data_length);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			else if (p[1] == 'T'
-			    && data_length == 0 && version == 1) {
-				/*
-				 * ST extension marks end of this
-				 * block of SUSP entries.
-				 *
-				 * It allows SUSP to coexist with
-				 * non-SUSP uses of the System
-				 * Use Area by placing non-SUSP data
-				 * after SUSP data.
-				 */
-				iso9660->seenSUSP = 0;
-				iso9660->seenRockridge = 0;
-				return (ARCHIVE_OK);
-			}
-			break;
-		case 'T':
-			if (p[1] == 'F') {
-				if (version == 1) {
-					parse_rockridge_TF1(file,
-					    data, data_length);
-					iso9660->seenRockridge = 1;
-				}
-			}
-			break;
-		case 'Z':
-			if (p[1] == 'F') {
-				if (version == 1)
-					parse_rockridge_ZF1(file,
-					    data, data_length);
-			}
-			break;
-		default:
-			break;
-		}
-
-		p += p[2];
-		entry_seen = 1;
-	}
-
-	if (entry_seen)
-		return (ARCHIVE_OK);
-	else {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				  "Tried to parse Rockridge extensions, but none found");
-		return (ARCHIVE_WARN);
-	}
-}
-
-static int
-register_CE(struct archive_read *a, int32_t location,
-    struct file_info *file)
-{
-	struct iso9660 *iso9660;
-	struct read_ce_queue *heap;
-	struct read_ce_req *p;
-	uint64_t offset, parent_offset;
-	int hole, parent;
-
-	iso9660 = (struct iso9660 *)(a->format->data);
-	offset = ((uint64_t)location) * (uint64_t)iso9660->logical_block_size;
-	if (((file->mode & AE_IFMT) == AE_IFREG &&
-	    offset >= file->offset) ||
-	    offset < iso9660->current_position ||
-	    (((uint64_t)file->ce_offset) + file->ce_size)
-	      > (uint64_t)iso9660->logical_block_size ||
-	    offset + file->ce_offset + file->ce_size
-		  > iso9660->volume_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid parameter in SUSP \"CE\" extension");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Expand our CE list as necessary. */
-	heap = &(iso9660->read_ce_req);
-	if (heap->cnt >= heap->allocated) {
-		int new_size;
-
-		if (heap->allocated < 16)
-			new_size = 16;
-		else
-			new_size = heap->allocated * 2;
-		/* Overflow might keep us from growing the list. */
-		if (new_size <= heap->allocated) {
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		p = calloc(new_size, sizeof(p[0]));
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		if (heap->reqs != NULL) {
-			memcpy(p, heap->reqs, heap->cnt * sizeof(*p));
-			free(heap->reqs);
-		}
-		heap->reqs = p;
-		heap->allocated = new_size;
-	}
-
-	/*
-	 * Start with hole at end, walk it up tree to find insertion point.
-	 */
-	hole = heap->cnt++;
-	while (hole > 0) {
-		parent = (hole - 1)/2;
-		parent_offset = heap->reqs[parent].offset;
-		if (offset >= parent_offset) {
-			heap->reqs[hole].offset = offset;
-			heap->reqs[hole].file = file;
-			return (ARCHIVE_OK);
-		}
-		/* Move parent into hole <==> move hole up tree. */
-		heap->reqs[hole] = heap->reqs[parent];
-		hole = parent;
-	}
-	heap->reqs[0].offset = offset;
-	heap->reqs[0].file = file;
-	return (ARCHIVE_OK);
-}
-
-static void
-next_CE(struct read_ce_queue *heap)
-{
-	uint64_t a_offset, b_offset, c_offset;
-	int a, b, c;
-	struct read_ce_req tmp;
-
-	if (heap->cnt < 1)
-		return;
-
-	/*
-	 * Move the last item in the heap to the root of the tree
-	 */
-	heap->reqs[0] = heap->reqs[--(heap->cnt)];
-
-	/*
-	 * Rebalance the heap.
-	 */
-	a = 0; /* Starting element and its offset */
-	a_offset = heap->reqs[a].offset;
-	for (;;) {
-		b = a + a + 1; /* First child */
-		if (b >= heap->cnt)
-			return;
-		b_offset = heap->reqs[b].offset;
-		c = b + 1; /* Use second child if it is smaller. */
-		if (c < heap->cnt) {
-			c_offset = heap->reqs[c].offset;
-			if (c_offset < b_offset) {
-				b = c;
-				b_offset = c_offset;
-			}
-		}
-		if (a_offset <= b_offset)
-			return;
-		tmp = heap->reqs[a];
-		heap->reqs[a] = heap->reqs[b];
-		heap->reqs[b] = tmp;
-		a = b;
-	}
-}
-
-
-static int
-read_CE(struct archive_read *a, struct iso9660 *iso9660)
-{
-	struct read_ce_queue *heap;
-	const unsigned char *b, *p, *end;
-	struct file_info *file;
-	size_t step;
-	int r;
-
-	/* Read data which RRIP "CE" extension points. */
-	heap = &(iso9660->read_ce_req);
-	step = iso9660->logical_block_size;
-	while (heap->cnt &&
-	    heap->reqs[0].offset == iso9660->current_position) {
-		b = __archive_read_ahead(a, step, NULL);
-		if (b == NULL) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to read full block when scanning "
-			    "ISO9660 directory list");
-			return (ARCHIVE_FATAL);
-		}
-		do {
-			file = heap->reqs[0].file;
-			if (file->ce_offset + file->ce_size > step) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Malformed CE information");
-				return (ARCHIVE_FATAL);
-			}
-			p = b + file->ce_offset;
-			end = p + file->ce_size;
-			next_CE(heap);
-			r = parse_rockridge(a, file, p, end);
-			if (r != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		} while (heap->cnt &&
-		    heap->reqs[0].offset == iso9660->current_position);
-		/* NOTE: Do not move this consume's code to front of
-		 * do-while loop. Registration of nested CE extension
-		 * might cause error because of current position. */
-		__archive_read_consume(a, step);
-		iso9660->current_position += step;
-	}
-	return (ARCHIVE_OK);
-}
-
-static void
-parse_rockridge_NM1(struct file_info *file,
-		    const unsigned char *data, int data_length)
-{
-	if (!file->name_continues)
-		archive_string_empty(&file->name);
-	file->name_continues = 0;
-	if (data_length < 1)
-		return;
-	/*
-	 * NM version 1 extension comprises:
-	 *   1 byte flag, value is one of:
-	 *     = 0: remainder is name
-	 *     = 1: remainder is name, next NM entry continues name
-	 *     = 2: "."
-	 *     = 4: ".."
-	 *     = 32: Implementation specific
-	 *     All other values are reserved.
-	 */
-	switch(data[0]) {
-	case 0:
-		if (data_length < 2)
-			return;
-		archive_strncat(&file->name,
-		    (const char *)data + 1, data_length - 1);
-		break;
-	case 1:
-		if (data_length < 2)
-			return;
-		archive_strncat(&file->name,
-		    (const char *)data + 1, data_length - 1);
-		file->name_continues = 1;
-		break;
-	case 2:
-		archive_strcat(&file->name, ".");
-		break;
-	case 4:
-		archive_strcat(&file->name, "..");
-		break;
-	default:
-		return;
-	}
-
-}
-
-static void
-parse_rockridge_TF1(struct file_info *file, const unsigned char *data,
-    int data_length)
-{
-	char flag;
-	/*
-	 * TF extension comprises:
-	 *   one byte flag
-	 *   create time (optional)
-	 *   modify time (optional)
-	 *   access time (optional)
-	 *   attribute time (optional)
-	 *  Time format and presence of fields
-	 *  is controlled by flag bits.
-	 */
-	if (data_length < 1)
-		return;
-	flag = data[0];
-	++data;
-	--data_length;
-	if (flag & 0x80) {
-		/* Use 17-byte time format. */
-		if ((flag & 1) && data_length >= 17) {
-			/* Create time. */
-			file->birthtime_is_set = 1;
-			file->birthtime = isodate17(data);
-			data += 17;
-			data_length -= 17;
-		}
-		if ((flag & 2) && data_length >= 17) {
-			/* Modify time. */
-			file->mtime = isodate17(data);
-			data += 17;
-			data_length -= 17;
-		}
-		if ((flag & 4) && data_length >= 17) {
-			/* Access time. */
-			file->atime = isodate17(data);
-			data += 17;
-			data_length -= 17;
-		}
-		if ((flag & 8) && data_length >= 17) {
-			/* Attribute change time. */
-			file->ctime = isodate17(data);
-		}
-	} else {
-		/* Use 7-byte time format. */
-		if ((flag & 1) && data_length >= 7) {
-			/* Create time. */
-			file->birthtime_is_set = 1;
-			file->birthtime = isodate7(data);
-			data += 7;
-			data_length -= 7;
-		}
-		if ((flag & 2) && data_length >= 7) {
-			/* Modify time. */
-			file->mtime = isodate7(data);
-			data += 7;
-			data_length -= 7;
-		}
-		if ((flag & 4) && data_length >= 7) {
-			/* Access time. */
-			file->atime = isodate7(data);
-			data += 7;
-			data_length -= 7;
-		}
-		if ((flag & 8) && data_length >= 7) {
-			/* Attribute change time. */
-			file->ctime = isodate7(data);
-		}
-	}
-}
-
-static void
-parse_rockridge_SL1(struct file_info *file, const unsigned char *data,
-    int data_length)
-{
-	const char *separator = "";
-
-	if (!file->symlink_continues || file->symlink.length < 1)
-		archive_string_empty(&file->symlink);
-	file->symlink_continues = 0;
-
-	/*
-	 * Defined flag values:
-	 *  0: This is the last SL record for this symbolic link
-	 *  1: this symbolic link field continues in next SL entry
-	 *  All other values are reserved.
-	 */
-	if (data_length < 1)
-		return;
-	switch(*data) {
-	case 0:
-		break;
-	case 1:
-		file->symlink_continues = 1;
-		break;
-	default:
-		return;
-	}
-	++data;  /* Skip flag byte. */
-	--data_length;
-
-	/*
-	 * SL extension body stores "components".
-	 * Basically, this is a complicated way of storing
-	 * a POSIX path.  It also interferes with using
-	 * symlinks for storing non-path data. <sigh>
-	 *
-	 * Each component is 2 bytes (flag and length)
-	 * possibly followed by name data.
-	 */
-	while (data_length >= 2) {
-		unsigned char flag = *data++;
-		unsigned char nlen = *data++;
-		data_length -= 2;
-
-		archive_strcat(&file->symlink, separator);
-		separator = "/";
-
-		switch(flag) {
-		case 0: /* Usual case, this is text. */
-			if (data_length < nlen)
-				return;
-			archive_strncat(&file->symlink,
-			    (const char *)data, nlen);
-			break;
-		case 0x01: /* Text continues in next component. */
-			if (data_length < nlen)
-				return;
-			archive_strncat(&file->symlink,
-			    (const char *)data, nlen);
-			separator = "";
-			break;
-		case 0x02: /* Current dir. */
-			archive_strcat(&file->symlink, ".");
-			break;
-		case 0x04: /* Parent dir. */
-			archive_strcat(&file->symlink, "..");
-			break;
-		case 0x08: /* Root of filesystem. */
-			archive_strcat(&file->symlink, "/");
-			separator = "";
-			break;
-		case 0x10: /* Undefined (historically "volume root" */
-			archive_string_empty(&file->symlink);
-			archive_strcat(&file->symlink, "ROOT");
-			break;
-		case 0x20: /* Undefined (historically "hostname") */
-			archive_strcat(&file->symlink, "hostname");
-			break;
-		default:
-			/* TODO: issue a warning ? */
-			return;
-		}
-		data += nlen;
-		data_length -= nlen;
-	}
-}
-
-static void
-parse_rockridge_ZF1(struct file_info *file, const unsigned char *data,
-    int data_length)
-{
-
-	if (data[0] == 0x70 && data[1] == 0x7a && data_length == 12) {
-		/* paged zlib */
-		file->pz = 1;
-		file->pz_log2_bs = data[3];
-		file->pz_uncompressed_size = archive_le32dec(&data[4]);
-	}
-}
-
-static void
-register_file(struct iso9660 *iso9660, struct file_info *file)
-{
-
-	file->use_next = iso9660->use_files;
-	iso9660->use_files = file;
-}
-
-static void
-release_files(struct iso9660 *iso9660)
-{
-	struct content *con, *connext;
-	struct file_info *file;
-
-	file = iso9660->use_files;
-	while (file != NULL) {
-		struct file_info *next = file->use_next;
-
-		archive_string_free(&file->name);
-		archive_string_free(&file->symlink);
-		free(file->utf16be_name);
-		con = file->contents.first;
-		while (con != NULL) {
-			connext = con->next;
-			free(con);
-			con = connext;
-		}
-		free(file);
-		file = next;
-	}
-}
-
-static int
-next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
-    struct file_info **pfile)
-{
-	struct file_info *file;
-	int r;
-
-	r = next_cache_entry(a, iso9660, pfile);
-	if (r != ARCHIVE_OK)
-		return (r);
-	file = *pfile;
-
-	/* Don't waste time seeking for zero-length bodies. */
-	if (file->size == 0)
-		file->offset = iso9660->current_position;
-
-	/* flush any remaining bytes from the last round to ensure
-	 * we're positioned */
-	if (iso9660->entry_bytes_unconsumed) {
-		__archive_read_consume(a, iso9660->entry_bytes_unconsumed);
-		iso9660->entry_bytes_unconsumed = 0;
-	}
-
-	/* Seek forward to the start of the entry. */
-	if (iso9660->current_position < file->offset) {
-		int64_t step;
-
-		step = file->offset - iso9660->current_position;
-		step = __archive_read_consume(a, step);
-		if (step < 0)
-			return ((int)step);
-		iso9660->current_position = file->offset;
-	}
-
-	/* We found body of file; handle it now. */
-	return (ARCHIVE_OK);
-}
-
-static int
-next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
-    struct file_info **pfile)
-{
-	struct file_info *file;
-	struct {
-		struct file_info	*first;
-		struct file_info	**last;
-	}	empty_files;
-	int64_t number;
-	int count;
-
-	file = cache_get_entry(iso9660);
-	if (file != NULL) {
-		*pfile = file;
-		return (ARCHIVE_OK);
-	}
-
-	for (;;) {
-		struct file_info *re, *d;
-
-		*pfile = file = next_entry(iso9660);
-		if (file == NULL) {
-			/*
-			 * If directory entries all which are descendant of
-			 * rr_moved are still remaining, expose their.
-			 */
-			if (iso9660->re_files.first != NULL &&
-			    iso9660->rr_moved != NULL &&
-			    iso9660->rr_moved->rr_moved_has_re_only)
-				/* Expose "rr_moved" entry. */
-				cache_add_entry(iso9660, iso9660->rr_moved);
-			while ((re = re_get_entry(iso9660)) != NULL) {
-				/* Expose its descendant dirs. */
-				while ((d = rede_get_entry(re)) != NULL)
-					cache_add_entry(iso9660, d);
-			}
-			if (iso9660->cache_files.first != NULL)
-				return (next_cache_entry(a, iso9660, pfile));
-			return (ARCHIVE_EOF);
-		}
-
-		if (file->cl_offset) {
-			struct file_info *first_re = NULL;
-			int nexted_re = 0;
-
-			/*
-			 * Find "RE" dir for the current file, which
-			 * has "CL" flag.
-			 */
-			while ((re = re_get_entry(iso9660))
-			    != first_re) {
-				if (first_re == NULL)
-					first_re = re;
-				if (re->offset == file->cl_offset) {
-					re->parent->subdirs--;
-					re->parent = file->parent;
-					re->re = 0;
-					if (re->parent->re_descendant) {
-						nexted_re = 1;
-						re->re_descendant = 1;
-						if (rede_add_entry(re) < 0)
-							goto fatal_rr;
-						/* Move a list of descendants
-						 * to a new ancestor. */
-						while ((d = rede_get_entry(
-						    re)) != NULL)
-							if (rede_add_entry(d)
-							    < 0)
-								goto fatal_rr;
-						break;
-					}
-					/* Replace the current file
-					 * with "RE" dir */
-					*pfile = file = re;
-					/* Expose its descendant */
-					while ((d = rede_get_entry(
-					    file)) != NULL)
-						cache_add_entry(
-						    iso9660, d);
-					break;
-				} else
-					re_add_entry(iso9660, re);
-			}
-			if (nexted_re) {
-				/*
-				 * Do not expose this at this time
-				 * because we have not gotten its full-path
-				 * name yet.
-				 */
-				continue;
-			}
-		} else if ((file->mode & AE_IFMT) == AE_IFDIR) {
-			int r;
-
-			/* Read file entries in this dir. */
-			r = read_children(a, file);
-			if (r != ARCHIVE_OK)
-				return (r);
-
-			/*
-			 * Handle a special dir of Rockridge extensions,
-			 * "rr_moved".
-			 */
-			if (file->rr_moved) {
-				/*
-				 * If this has only the subdirectories which
-				 * have "RE" flags, do not expose at this time.
-				 */
-				if (file->rr_moved_has_re_only)
-					continue;
-				/* Otherwise expose "rr_moved" entry. */
-			} else if (file->re) {
-				/*
-				 * Do not expose this at this time
-				 * because we have not gotten its full-path
-				 * name yet.
-				 */
-				re_add_entry(iso9660, file);
-				continue;
-			} else if (file->re_descendant) {
-				/*
-				 * If the top level "RE" entry of this entry
-				 * is not exposed, we, accordingly, should not
-				 * expose this entry at this time because
-				 * we cannot make its proper full-path name.
-				 */
-				if (rede_add_entry(file) == 0)
-					continue;
-				/* Otherwise we can expose this entry because
-				 * it seems its top level "RE" has already been
-				 * exposed. */
-			}
-		}
-		break;
-	}
-
-	if ((file->mode & AE_IFMT) != AE_IFREG || file->number == -1)
-		return (ARCHIVE_OK);
-
-	count = 0;
-	number = file->number;
-	iso9660->cache_files.first = NULL;
-	iso9660->cache_files.last = &(iso9660->cache_files.first);
-	empty_files.first = NULL;
-	empty_files.last = &empty_files.first;
-	/* Collect files which has the same file serial number.
-	 * Peek pending_files so that file which number is different
-	 * is not put back. */
-	while (iso9660->pending_files.used > 0 &&
-	    (iso9660->pending_files.files[0]->number == -1 ||
-	     iso9660->pending_files.files[0]->number == number)) {
-		if (file->number == -1) {
-			/* This file has the same offset
-			 * but it's wrong offset which empty files
-			 * and symlink files have.
-			 * NOTE: This wrong offset was recorded by
-			 * old mkisofs utility. If ISO images is
-			 * created by latest mkisofs, this does not
-			 * happen.
-			 */
-			file->next = NULL;
-			*empty_files.last = file;
-			empty_files.last = &(file->next);
-		} else {
-			count++;
-			cache_add_entry(iso9660, file);
-		}
-		file = next_entry(iso9660);
-	}
-
-	if (count == 0) {
-		*pfile = file;
-		return ((file == NULL)?ARCHIVE_EOF:ARCHIVE_OK);
-	}
-	if (file->number == -1) {
-		file->next = NULL;
-		*empty_files.last = file;
-		empty_files.last = &(file->next);
-	} else {
-		count++;
-		cache_add_entry(iso9660, file);
-	}
-
-	if (count > 1) {
-		/* The count is the same as number of hardlink,
-		 * so much so that each nlinks of files in cache_file
-		 * is overwritten by value of the count.
-		 */
-		for (file = iso9660->cache_files.first;
-		    file != NULL; file = file->next)
-			file->nlinks = count;
-	}
-	/* If there are empty files, that files are added
-	 * to the tail of the cache_files. */
-	if (empty_files.first != NULL) {
-		*iso9660->cache_files.last = empty_files.first;
-		iso9660->cache_files.last = empty_files.last;
-	}
-	*pfile = cache_get_entry(iso9660);
-	return ((*pfile == NULL)?ARCHIVE_EOF:ARCHIVE_OK);
-
-fatal_rr:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of "
-	    "Rockridge extensions: current position = %jd, CL offset = %jd",
-	    (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset);
-	return (ARCHIVE_FATAL);
-}
-
-static inline void
-re_add_entry(struct iso9660 *iso9660, struct file_info *file)
-{
-	file->re_next = NULL;
-	*iso9660->re_files.last = file;
-	iso9660->re_files.last = &(file->re_next);
-}
-
-static inline struct file_info *
-re_get_entry(struct iso9660 *iso9660)
-{
-	struct file_info *file;
-
-	if ((file = iso9660->re_files.first) != NULL) {
-		iso9660->re_files.first = file->re_next;
-		if (iso9660->re_files.first == NULL)
-			iso9660->re_files.last =
-			    &(iso9660->re_files.first);
-	}
-	return (file);
-}
-
-static inline int
-rede_add_entry(struct file_info *file)
-{
-	struct file_info *re;
-
-	/*
-	 * Find "RE" entry.
-	 */
-	re = file->parent;
-	while (re != NULL && !re->re)
-		re = re->parent;
-	if (re == NULL)
-		return (-1);
-
-	file->re_next = NULL;
-	*re->rede_files.last = file;
-	re->rede_files.last = &(file->re_next);
-	return (0);
-}
-
-static inline struct file_info *
-rede_get_entry(struct file_info *re)
-{
-	struct file_info *file;
-
-	if ((file = re->rede_files.first) != NULL) {
-		re->rede_files.first = file->re_next;
-		if (re->rede_files.first == NULL)
-			re->rede_files.last =
-			    &(re->rede_files.first);
-	}
-	return (file);
-}
-
-static inline void
-cache_add_entry(struct iso9660 *iso9660, struct file_info *file)
-{
-	file->next = NULL;
-	*iso9660->cache_files.last = file;
-	iso9660->cache_files.last = &(file->next);
-}
-
-static inline struct file_info *
-cache_get_entry(struct iso9660 *iso9660)
-{
-	struct file_info *file;
-
-	if ((file = iso9660->cache_files.first) != NULL) {
-		iso9660->cache_files.first = file->next;
-		if (iso9660->cache_files.first == NULL)
-			iso9660->cache_files.last =
-			    &(iso9660->cache_files.first);
-	}
-	return (file);
-}
-
-static int
-heap_add_entry(struct archive_read *a, struct heap_queue *heap,
-    struct file_info *file, uint64_t key)
-{
-	uint64_t file_key, parent_key;
-	int hole, parent;
-
-	/* Expand our pending files list as necessary. */
-	if (heap->used >= heap->allocated) {
-		struct file_info **new_pending_files;
-		int new_size = heap->allocated * 2;
-
-		if (heap->allocated < 1024)
-			new_size = 1024;
-		/* Overflow might keep us from growing the list. */
-		if (new_size <= heap->allocated) {
-			archive_set_error(&a->archive,
-			    ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		new_pending_files = (struct file_info **)
-		    malloc(new_size * sizeof(new_pending_files[0]));
-		if (new_pending_files == NULL) {
-			archive_set_error(&a->archive,
-			    ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		if (heap->allocated)
-			memcpy(new_pending_files, heap->files,
-			    heap->allocated * sizeof(new_pending_files[0]));
-		free(heap->files);
-		heap->files = new_pending_files;
-		heap->allocated = new_size;
-	}
-
-	file_key = file->key = key;
-
-	/*
-	 * Start with hole at end, walk it up tree to find insertion point.
-	 */
-	hole = heap->used++;
-	while (hole > 0) {
-		parent = (hole - 1)/2;
-		parent_key = heap->files[parent]->key;
-		if (file_key >= parent_key) {
-			heap->files[hole] = file;
-			return (ARCHIVE_OK);
-		}
-		/* Move parent into hole <==> move hole up tree. */
-		heap->files[hole] = heap->files[parent];
-		hole = parent;
-	}
-	heap->files[0] = file;
-
-	return (ARCHIVE_OK);
-}
-
-static struct file_info *
-heap_get_entry(struct heap_queue *heap)
-{
-	uint64_t a_key, b_key, c_key;
-	int a, b, c;
-	struct file_info *r, *tmp;
-
-	if (heap->used < 1)
-		return (NULL);
-
-	/*
-	 * The first file in the list is the earliest; we'll return this.
-	 */
-	r = heap->files[0];
-
-	/*
-	 * Move the last item in the heap to the root of the tree
-	 */
-	heap->files[0] = heap->files[--(heap->used)];
-
-	/*
-	 * Rebalance the heap.
-	 */
-	a = 0; /* Starting element and its heap key */
-	a_key = heap->files[a]->key;
-	for (;;) {
-		b = a + a + 1; /* First child */
-		if (b >= heap->used)
-			return (r);
-		b_key = heap->files[b]->key;
-		c = b + 1; /* Use second child if it is smaller. */
-		if (c < heap->used) {
-			c_key = heap->files[c]->key;
-			if (c_key < b_key) {
-				b = c;
-				b_key = c_key;
-			}
-		}
-		if (a_key <= b_key)
-			return (r);
-		tmp = heap->files[a];
-		heap->files[a] = heap->files[b];
-		heap->files[b] = tmp;
-		a = b;
-	}
-}
-
-static unsigned int
-toi(const void *p, int n)
-{
-	const unsigned char *v = (const unsigned char *)p;
-	if (n > 1)
-		return v[0] + 256 * toi(v + 1, n - 1);
-	if (n == 1)
-		return v[0];
-	return (0);
-}
-
-static time_t
-isodate7(const unsigned char *v)
-{
-	struct tm tm;
-	int offset;
-	time_t t;
-
-	memset(&tm, 0, sizeof(tm));
-	tm.tm_year = v[0];
-	tm.tm_mon = v[1] - 1;
-	tm.tm_mday = v[2];
-	tm.tm_hour = v[3];
-	tm.tm_min = v[4];
-	tm.tm_sec = v[5];
-	/* v[6] is the signed timezone offset, in 1/4-hour increments. */
-	offset = ((const signed char *)v)[6];
-	if (offset > -48 && offset < 52) {
-		tm.tm_hour -= offset / 4;
-		tm.tm_min -= (offset % 4) * 15;
-	}
-	t = time_from_tm(&tm);
-	if (t == (time_t)-1)
-		return ((time_t)0);
-	return (t);
-}
-
-static time_t
-isodate17(const unsigned char *v)
-{
-	struct tm tm;
-	int offset;
-	time_t t;
-
-	memset(&tm, 0, sizeof(tm));
-	tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100
-	    + (v[2] - '0') * 10 + (v[3] - '0')
-	    - 1900;
-	tm.tm_mon = (v[4] - '0') * 10 + (v[5] - '0');
-	tm.tm_mday = (v[6] - '0') * 10 + (v[7] - '0');
-	tm.tm_hour = (v[8] - '0') * 10 + (v[9] - '0');
-	tm.tm_min = (v[10] - '0') * 10 + (v[11] - '0');
-	tm.tm_sec = (v[12] - '0') * 10 + (v[13] - '0');
-	/* v[16] is the signed timezone offset, in 1/4-hour increments. */
-	offset = ((const signed char *)v)[16];
-	if (offset > -48 && offset < 52) {
-		tm.tm_hour -= offset / 4;
-		tm.tm_min -= (offset % 4) * 15;
-	}
-	t = time_from_tm(&tm);
-	if (t == (time_t)-1)
-		return ((time_t)0);
-	return (t);
-}
-
-static time_t
-time_from_tm(struct tm *t)
-{
-#if HAVE__MKGMTIME
-        return _mkgmtime(t);
-#elif HAVE_TIMEGM
-        /* Use platform timegm() if available. */
-        return (timegm(t));
-#else
-        /* Else use direct calculation using POSIX assumptions. */
-        /* First, fix up tm_yday based on the year/month/day. */
-        if (mktime(t) == (time_t)-1)
-                return ((time_t)-1);
-        /* Then we can compute timegm() from first principles. */
-        return (t->tm_sec
-            + t->tm_min * 60
-            + t->tm_hour * 3600
-            + t->tm_yday * 86400
-            + (t->tm_year - 70) * 31536000
-            + ((t->tm_year - 69) / 4) * 86400
-            - ((t->tm_year - 1) / 100) * 86400
-            + ((t->tm_year + 299) / 400) * 86400);
-#endif
-}
-
-static const char *
-build_pathname(struct archive_string *as, struct file_info *file, int depth)
-{
-	// Plain ISO9660 only allows 8 dir levels; if we get
-	// to 1000, then something is very, very wrong.
-	if (depth > 1000) {
-		return NULL;
-	}
-	if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) {
-		if (build_pathname(as, file->parent, depth + 1) == NULL) {
-			return NULL;
-		}
-		archive_strcat(as, "/");
-	}
-	if (archive_strlen(&file->name) == 0)
-		archive_strcat(as, ".");
-	else
-		archive_string_concat(as, &file->name);
-	return (as->s);
-}
-
-static int
-build_pathname_utf16be(unsigned char *p, size_t max, size_t *len,
-    struct file_info *file)
-{
-	if (file->parent != NULL && file->parent->utf16be_bytes > 0) {
-		if (build_pathname_utf16be(p, max, len, file->parent) != 0)
-			return (-1);
-		p[*len] = 0;
-		p[*len + 1] = '/';
-		*len += 2;
-	}
-	if (file->utf16be_bytes == 0) {
-		if (*len + 2 > max)
-			return (-1);/* Path is too long! */
-		p[*len] = 0;
-		p[*len + 1] = '.';
-		*len += 2;
-	} else {
-		if (*len + file->utf16be_bytes > max)
-			return (-1);/* Path is too long! */
-		memcpy(p + *len, file->utf16be_name, file->utf16be_bytes);
-		*len += file->utf16be_bytes;
-	}
-	return (0);
-}
-
-#if DEBUG
-static void
-dump_isodirrec(FILE *out, const unsigned char *isodirrec)
-{
-	fprintf(out, " l %d,",
-	    toi(isodirrec + DR_length_offset, DR_length_size));
-	fprintf(out, " a %d,",
-	    toi(isodirrec + DR_ext_attr_length_offset, DR_ext_attr_length_size));
-	fprintf(out, " ext 0x%x,",
-	    toi(isodirrec + DR_extent_offset, DR_extent_size));
-	fprintf(out, " s %d,",
-	    toi(isodirrec + DR_size_offset, DR_extent_size));
-	fprintf(out, " f 0x%x,",
-	    toi(isodirrec + DR_flags_offset, DR_flags_size));
-	fprintf(out, " u %d,",
-	    toi(isodirrec + DR_file_unit_size_offset, DR_file_unit_size_size));
-	fprintf(out, " ilv %d,",
-	    toi(isodirrec + DR_interleave_offset, DR_interleave_size));
-	fprintf(out, " seq %d,",
-	    toi(isodirrec + DR_volume_sequence_number_offset,
-		DR_volume_sequence_number_size));
-	fprintf(out, " nl %d:",
-	    toi(isodirrec + DR_name_len_offset, DR_name_len_size));
-	fprintf(out, " `%.*s'",
-	    toi(isodirrec + DR_name_len_offset, DR_name_len_size),
-		isodirrec + DR_name_offset);
-}
-#endif
diff --git a/c/archive_read_support_format_lha.c b/c/archive_read_support_format_lha.c
deleted file mode 100644
--- a/c/archive_read_support_format_lha.c
+++ /dev/null
@@ -1,2919 +0,0 @@
-/*-
- * Copyright (c) 2008-2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_endian.h"
-
-
-#define MAXMATCH		256	/* Maximum match length. */
-#define MINMATCH		3	/* Minimum match length. */
-/*
- * Literal table format:
- * +0              +256                      +510
- * +---------------+-------------------------+
- * | literal code  |       match length      |
- * |   0 ... 255   |  MINMATCH ... MAXMATCH  |
- * +---------------+-------------------------+
- *  <---          LT_BITLEN_SIZE         --->
- */
-/* Literal table size. */
-#define LT_BITLEN_SIZE		(UCHAR_MAX + 1 + MAXMATCH - MINMATCH + 1)
-/* Position table size.
- * Note: this used for both position table and pre literal table.*/
-#define PT_BITLEN_SIZE		(3 + 16)
-
-struct lzh_dec {
-	/* Decoding status. */
-	int     		 state;
-
-	/*
-	 * Window to see last 8Ki(lh5),32Ki(lh6),64Ki(lh7) bytes of decoded
-	 * data.
-	 */
-	int			 w_size;
-	int			 w_mask;
-	/* Window buffer, which is a loop buffer. */
-	unsigned char		*w_buff;
-	/* The insert position to the window. */
-	int			 w_pos;
-	/* The position where we can copy decoded code from the window. */
-	int     		 copy_pos;
-	/* The length how many bytes we can copy decoded code from
-	 * the window. */
-	int     		 copy_len;
-
-	/*
-	 * Bit stream reader.
-	 */
-	struct lzh_br {
-#define CACHE_TYPE		uint64_t
-#define CACHE_BITS		(8 * sizeof(CACHE_TYPE))
-	 	/* Cache buffer. */
-		CACHE_TYPE	 cache_buffer;
-		/* Indicates how many bits avail in cache_buffer. */
-		int		 cache_avail;
-	} br;
-
-	/*
-	 * Huffman coding.
-	 */
-	struct huffman {
-		int		 len_size;
-		int		 len_avail;
-		int		 len_bits;
-		int		 freq[17];
-		unsigned char	*bitlen;
-
-		/*
-		 * Use a index table. It's faster than searching a huffman
-		 * coding tree, which is a binary tree. But a use of a large
-		 * index table causes L1 cache read miss many times.
-		 */
-#define HTBL_BITS	10
-		int		 max_bits;
-		int		 shift_bits;
-		int		 tbl_bits;
-		int		 tree_used;
-		int		 tree_avail;
-		/* Direct access table. */
-		uint16_t	*tbl;
-		/* Binary tree table for extra bits over the direct access. */
-		struct htree_t {
-			uint16_t left;
-			uint16_t right;
-		}		*tree;
-	}			 lt, pt;
-
-	int			 blocks_avail;
-	int			 pos_pt_len_size;
-	int			 pos_pt_len_bits;
-	int			 literal_pt_len_size;
-	int			 literal_pt_len_bits;
-	int			 reading_position;
-	int			 loop;
-	int			 error;
-};
-
-struct lzh_stream {
-	const unsigned char	*next_in;
-	int			 avail_in;
-	int64_t			 total_in;
-	const unsigned char	*ref_ptr;
-	int			 avail_out;
-	int64_t			 total_out;
-	struct lzh_dec		*ds;
-};
-
-struct lha {
-	/* entry_bytes_remaining is the number of bytes we expect.	    */
-	int64_t                  entry_offset;
-	int64_t                  entry_bytes_remaining;
-	int64_t			 entry_unconsumed;
-	uint16_t		 entry_crc_calculated;
- 
-	size_t			 header_size;	/* header size		    */
-	unsigned char		 level;		/* header level		    */
-	char			 method[3];	/* compress type	    */
-	int64_t			 compsize;	/* compressed data size	    */
-	int64_t			 origsize;	/* original file size	    */
-	int			 setflag;
-#define BIRTHTIME_IS_SET	1
-#define ATIME_IS_SET		2
-#define UNIX_MODE_IS_SET	4
-#define CRC_IS_SET		8
-	time_t			 birthtime;
-	long			 birthtime_tv_nsec;
-	time_t			 mtime;
-	long			 mtime_tv_nsec;
-	time_t			 atime;
-	long			 atime_tv_nsec;
-	mode_t			 mode;
-	int64_t			 uid;
-	int64_t			 gid;
-	struct archive_string 	 uname;
-	struct archive_string 	 gname;
-	uint16_t		 header_crc;
-	uint16_t		 crc;
-	/* dirname and filename could be in different codepages */
-	struct archive_string_conv *sconv_dir;
-	struct archive_string_conv *sconv_fname;
-	struct archive_string_conv *opt_sconv;
-
-	struct archive_string 	 dirname;
-	struct archive_string 	 filename;
-	struct archive_wstring	 ws;
-
-	unsigned char		 dos_attr;
-
-	/* Flag to mark progress that an archive was read their first header.*/
-	char			 found_first_header;
-	/* Flag to mark that indicates an empty directory. */
-	char			 directory;
-
-	/* Flags to mark progress of decompression. */
-	char			 decompress_init;
-	char			 end_of_entry;
-	char			 end_of_entry_cleanup;
-	char			 entry_is_compressed;
-
-	char			 format_name[64];
-
-	struct lzh_stream	 strm;
-};
-
-/*
- * LHA header common member offset.
- */
-#define H_METHOD_OFFSET	2	/* Compress type. */
-#define H_ATTR_OFFSET	19	/* DOS attribute. */
-#define H_LEVEL_OFFSET	20	/* Header Level.  */
-#define H_SIZE		22	/* Minimum header size. */
-
-static int      archive_read_format_lha_bid(struct archive_read *, int);
-static int      archive_read_format_lha_options(struct archive_read *,
-		    const char *, const char *);
-static int	archive_read_format_lha_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	archive_read_format_lha_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_lha_read_data_skip(struct archive_read *);
-static int	archive_read_format_lha_cleanup(struct archive_read *);
-
-static void	lha_replace_path_separator(struct lha *,
-		    struct archive_entry *);
-static int	lha_read_file_header_0(struct archive_read *, struct lha *);
-static int	lha_read_file_header_1(struct archive_read *, struct lha *);
-static int	lha_read_file_header_2(struct archive_read *, struct lha *);
-static int	lha_read_file_header_3(struct archive_read *, struct lha *);
-static int	lha_read_file_extended_header(struct archive_read *,
-		    struct lha *, uint16_t *, int, size_t, size_t *);
-static size_t	lha_check_header_format(const void *);
-static int	lha_skip_sfx(struct archive_read *);
-static time_t	lha_dos_time(const unsigned char *);
-static time_t	lha_win_time(uint64_t, long *);
-static unsigned char	lha_calcsum(unsigned char, const void *,
-		    int, size_t);
-static int	lha_parse_linkname(struct archive_wstring *,
-		    struct archive_wstring *);
-static int	lha_read_data_none(struct archive_read *, const void **,
-		    size_t *, int64_t *);
-static int	lha_read_data_lzh(struct archive_read *, const void **,
-		    size_t *, int64_t *);
-static void	lha_crc16_init(void);
-static uint16_t lha_crc16(uint16_t, const void *, size_t);
-static int	lzh_decode_init(struct lzh_stream *, const char *);
-static void	lzh_decode_free(struct lzh_stream *);
-static int	lzh_decode(struct lzh_stream *, int);
-static int	lzh_br_fillup(struct lzh_stream *, struct lzh_br *);
-static int	lzh_huffman_init(struct huffman *, size_t, int);
-static void	lzh_huffman_free(struct huffman *);
-static int	lzh_read_pt_bitlen(struct lzh_stream *, int start, int end);
-static int	lzh_make_fake_table(struct huffman *, uint16_t);
-static int	lzh_make_huffman_table(struct huffman *);
-static inline int lzh_decode_huffman(struct huffman *, unsigned);
-static int	lzh_decode_huffman_tree(struct huffman *, unsigned, int);
-
-
-int
-archive_read_support_format_lha(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct lha *lha;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_lha");
-
-	lha = (struct lha *)calloc(1, sizeof(*lha));
-	if (lha == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate lha data");
-		return (ARCHIVE_FATAL);
-	}
-	archive_string_init(&lha->ws);
-
-	r = __archive_read_register_format(a,
-	    lha,
-	    "lha",
-	    archive_read_format_lha_bid,
-	    archive_read_format_lha_options,
-	    archive_read_format_lha_read_header,
-	    archive_read_format_lha_read_data,
-	    archive_read_format_lha_read_data_skip,
-	    NULL,
-	    archive_read_format_lha_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK)
-		free(lha);
-	return (ARCHIVE_OK);
-}
-
-static size_t
-lha_check_header_format(const void *h)
-{
-	const unsigned char *p = h;
-	size_t next_skip_bytes;
-
-	switch (p[H_METHOD_OFFSET+3]) {
-	/*
-	 * "-lh0-" ... "-lh7-" "-lhd-"
-	 * "-lzs-" "-lz5-"
-	 */
-	case '0': case '1': case '2': case '3':
-	case '4': case '5': case '6': case '7':
-	case 'd':
-	case 's':
-		next_skip_bytes = 4;
-
-		/* b0 == 0 means the end of an LHa archive file.	*/
-		if (p[0] == 0)
-			break;
-		if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l'
-		    ||  p[H_METHOD_OFFSET+4] != '-')
-			break;
-
-		if (p[H_METHOD_OFFSET+2] == 'h') {
-			/* "-lh?-" */
-			if (p[H_METHOD_OFFSET+3] == 's')
-				break;
-			if (p[H_LEVEL_OFFSET] == 0)
-				return (0);
-			if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20)
-				return (0);
-		}
-		if (p[H_METHOD_OFFSET+2] == 'z') {
-			/* LArc extensions: -lzs-,-lz4- and -lz5- */
-			if (p[H_LEVEL_OFFSET] != 0)
-				break;
-			if (p[H_METHOD_OFFSET+3] == 's'
-			    || p[H_METHOD_OFFSET+3] == '4'
-			    || p[H_METHOD_OFFSET+3] == '5')
-				return (0);
-		}
-		break;
-	case 'h': next_skip_bytes = 1; break;
-	case 'z': next_skip_bytes = 1; break;
-	case 'l': next_skip_bytes = 2; break;
-	case '-': next_skip_bytes = 3; break;
-	default : next_skip_bytes = 4; break;
-	}
-
-	return (next_skip_bytes);
-}
-
-static int
-archive_read_format_lha_bid(struct archive_read *a, int best_bid)
-{
-	const char *p;
-	const void *buff;
-	ssize_t bytes_avail, offset, window;
-	size_t next;
-
-	/* If there's already a better bid than we can ever
-	   make, don't bother testing. */
-	if (best_bid > 30)
-		return (-1);
-
-	if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL)
-		return (-1);
-
-	if (lha_check_header_format(p) == 0)
-		return (30);
-
-	if (p[0] == 'M' && p[1] == 'Z') {
-		/* PE file */
-		offset = 0;
-		window = 4096;
-		while (offset < (1024 * 20)) {
-			buff = __archive_read_ahead(a, offset + window,
-			    &bytes_avail);
-			if (buff == NULL) {
-				/* Remaining bytes are less than window. */
-				window >>= 1;
-				if (window < (H_SIZE + 3))
-					return (0);
-				continue;
-			}
-			p = (const char *)buff + offset;
-			while (p + H_SIZE < (const char *)buff + bytes_avail) {
-				if ((next = lha_check_header_format(p)) == 0)
-					return (30);
-				p += next;
-			}
-			offset = p - (const char *)buff;
-		}
-	}
-	return (0);
-}
-
-static int
-archive_read_format_lha_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct lha *lha;
-	int ret = ARCHIVE_FAILED;
-
-	lha = (struct lha *)(a->format->data);
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "lha: hdrcharset option needs a character-set name");
-		else {
-			lha->opt_sconv =
-			    archive_string_conversion_from_charset(
-				&a->archive, val, 0);
-			if (lha->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-lha_skip_sfx(struct archive_read *a)
-{
-	const void *h;
-	const char *p, *q;
-	size_t next, skip;
-	ssize_t bytes, window;
-
-	window = 4096;
-	for (;;) {
-		h = __archive_read_ahead(a, window, &bytes);
-		if (h == NULL) {
-			/* Remaining bytes are less than window. */
-			window >>= 1;
-			if (window < (H_SIZE + 3))
-				goto fatal;
-			continue;
-		}
-		if (bytes < H_SIZE)
-			goto fatal;
-		p = h;
-		q = p + bytes;
-
-		/*
-		 * Scan ahead until we find something that looks
-		 * like the lha header.
-		 */
-		while (p + H_SIZE < q) {
-			if ((next = lha_check_header_format(p)) == 0) {
-				skip = p - (const char *)h;
-				__archive_read_consume(a, skip);
-				return (ARCHIVE_OK);
-			}
-			p += next;
-		}
-		skip = p - (const char *)h;
-		__archive_read_consume(a, skip);
-	}
-fatal:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Couldn't find out LHa header");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-truncated_error(struct archive_read *a)
-{
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Truncated LHa header");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-archive_read_format_lha_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct archive_wstring linkname;
-	struct archive_wstring pathname;
-	struct lha *lha;
-	const unsigned char *p;
-	const char *signature;
-	int err;
-	struct archive_mstring conv_buffer;
-	const wchar_t *conv_buffer_p;
-
-	lha_crc16_init();
-
-	a->archive.archive_format = ARCHIVE_FORMAT_LHA;
-	if (a->archive.archive_format_name == NULL)
-		a->archive.archive_format_name = "lha";
-
-	lha = (struct lha *)(a->format->data);
-	lha->decompress_init = 0;
-	lha->end_of_entry = 0;
-	lha->end_of_entry_cleanup = 0;
-	lha->entry_unconsumed = 0;
-
-	if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) {
-		/*
-		 * LHa archiver added 0 to the tail of its archive file as
-		 * the mark of the end of the archive.
-		 */
-		signature = __archive_read_ahead(a, sizeof(signature[0]), NULL);
-		if (signature == NULL || signature[0] == 0)
-			return (ARCHIVE_EOF);
-		return (truncated_error(a));
-	}
-
-	signature = (const char *)p;
-	if (lha->found_first_header == 0 &&
-	    signature[0] == 'M' && signature[1] == 'Z') {
-                /* This is an executable?  Must be self-extracting... 	*/
-		err = lha_skip_sfx(a);
-		if (err < ARCHIVE_WARN)
-			return (err);
-
-		if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
-			return (truncated_error(a));
-		signature = (const char *)p;
-	}
-	/* signature[0] == 0 means the end of an LHa archive file. */
-	if (signature[0] == 0)
-		return (ARCHIVE_EOF);
-
-	/*
-	 * Check the header format and method type.
-	 */
-	if (lha_check_header_format(p) != 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Bad LHa file");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* We've found the first header. */
-	lha->found_first_header = 1;
-	/* Set a default value and common data */
-	lha->header_size = 0;
-	lha->level = p[H_LEVEL_OFFSET];
-	lha->method[0] = p[H_METHOD_OFFSET+1];
-	lha->method[1] = p[H_METHOD_OFFSET+2];
-	lha->method[2] = p[H_METHOD_OFFSET+3];
-	if (memcmp(lha->method, "lhd", 3) == 0)
-		lha->directory = 1;
-	else
-		lha->directory = 0;
-	if (memcmp(lha->method, "lh0", 3) == 0 ||
-	    memcmp(lha->method, "lz4", 3) == 0)
-		lha->entry_is_compressed = 0;
-	else
-		lha->entry_is_compressed = 1;
-
-	lha->compsize = 0;
-	lha->origsize = 0;
-	lha->setflag = 0;
-	lha->birthtime = 0;
-	lha->birthtime_tv_nsec = 0;
-	lha->mtime = 0;
-	lha->mtime_tv_nsec = 0;
-	lha->atime = 0;
-	lha->atime_tv_nsec = 0;
-	lha->mode = (lha->directory)? 0777 : 0666;
-	lha->uid = 0;
-	lha->gid = 0;
-	archive_string_empty(&lha->dirname);
-	archive_string_empty(&lha->filename);
-	lha->dos_attr = 0;
-	if (lha->opt_sconv != NULL) {
-		lha->sconv_dir = lha->opt_sconv;
-		lha->sconv_fname = lha->opt_sconv;
-	} else {
-		lha->sconv_dir = NULL;
-		lha->sconv_fname = NULL;
-	}
-
-	switch (p[H_LEVEL_OFFSET]) {
-	case 0:
-		err = lha_read_file_header_0(a, lha);
-		break;
-	case 1:
-		err = lha_read_file_header_1(a, lha);
-		break;
-	case 2:
-		err = lha_read_file_header_2(a, lha);
-		break;
-	case 3:
-		err = lha_read_file_header_3(a, lha);
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]);
-		err = ARCHIVE_FATAL;
-		break;
-	}
-	if (err < ARCHIVE_WARN)
-		return (err);
-
-
-	if (!lha->directory && archive_strlen(&lha->filename) == 0)
-		/* The filename has not been set */
-		return (truncated_error(a));
-
-	/*
-	 * Make a pathname from a dirname and a filename, after converting to Unicode.
-	 * This is because codepages might differ between dirname and filename.
-	*/
-	archive_string_init(&pathname);
-	archive_string_init(&linkname);
-	archive_string_init(&conv_buffer.aes_mbs);
-	archive_string_init(&conv_buffer.aes_mbs_in_locale);
-	archive_string_init(&conv_buffer.aes_utf8);
-	archive_string_init(&conv_buffer.aes_wcs);
-	if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->dirname.s, lha->dirname.length, lha->sconv_dir)) {
-		archive_set_error(&a->archive,
-			ARCHIVE_ERRNO_FILE_FORMAT,
-			"Pathname cannot be converted "
-			"from %s to Unicode.",
-			archive_string_conversion_charset_name(lha->sconv_dir));
-		err = ARCHIVE_FATAL;
-	} else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p))
-		err = ARCHIVE_FATAL;
-	if (err == ARCHIVE_FATAL) {
-		archive_mstring_clean(&conv_buffer);
-		archive_wstring_free(&pathname);
-		archive_wstring_free(&linkname);
-		return (err);
-	}
-	archive_wstring_copy(&pathname, &conv_buffer.aes_wcs);
-
-	archive_string_empty(&conv_buffer.aes_mbs);
-	archive_string_empty(&conv_buffer.aes_mbs_in_locale);
-	archive_string_empty(&conv_buffer.aes_utf8);
-	archive_wstring_empty(&conv_buffer.aes_wcs);
-	if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->filename.s, lha->filename.length, lha->sconv_fname)) {
-		archive_set_error(&a->archive,
-			ARCHIVE_ERRNO_FILE_FORMAT,
-			"Pathname cannot be converted "
-			"from %s to Unicode.",
-			archive_string_conversion_charset_name(lha->sconv_fname));
-		err = ARCHIVE_FATAL;
-	}
-	else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p))
-		err = ARCHIVE_FATAL;
-	if (err == ARCHIVE_FATAL) {
-		archive_mstring_clean(&conv_buffer);
-		archive_wstring_free(&pathname);
-		archive_wstring_free(&linkname);
-		return (err);
-	}
-	archive_wstring_concat(&pathname, &conv_buffer.aes_wcs);
-	archive_mstring_clean(&conv_buffer);
-
-	if ((lha->mode & AE_IFMT) == AE_IFLNK) {
-		/*
-	 	 * Extract the symlink-name if it's included in the pathname.
-	 	 */
-		if (!lha_parse_linkname(&linkname, &pathname)) {
-			/* We couldn't get the symlink-name. */
-			archive_set_error(&a->archive,
-		    	    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unknown symlink-name");
-			archive_wstring_free(&pathname);
-			archive_wstring_free(&linkname);
-			return (ARCHIVE_FAILED);
-		}
-	} else {
-		/*
-		 * Make sure a file-type is set.
-		 * The mode has been overridden if it is in the extended data.
-		 */
-		lha->mode = (lha->mode & ~AE_IFMT) |
-		    ((lha->directory)? AE_IFDIR: AE_IFREG);
-	}
-	if ((lha->setflag & UNIX_MODE_IS_SET) == 0 &&
-	    (lha->dos_attr & 1) != 0)
-		lha->mode &= ~(0222);/* read only. */
-
-	/*
-	 * Set basic file parameters.
-	 */
-	archive_entry_copy_pathname_w(entry, pathname.s);
-	archive_wstring_free(&pathname);
-	if (archive_strlen(&linkname) > 0) {
-		archive_entry_copy_symlink_w(entry, linkname.s);
-	} else
-		archive_entry_set_symlink(entry, NULL);
-	archive_wstring_free(&linkname);
-	/*
-	 * When a header level is 0, there is a possibility that
-	 * a pathname and a symlink has '\' character, a directory
-	 * separator in DOS/Windows. So we should convert it to '/'.
-	 */
-	if (p[H_LEVEL_OFFSET] == 0)
-		lha_replace_path_separator(lha, entry);
-
-	archive_entry_set_mode(entry, lha->mode);
-	archive_entry_set_uid(entry, lha->uid);
-	archive_entry_set_gid(entry, lha->gid);
-	if (archive_strlen(&lha->uname) > 0)
-		archive_entry_set_uname(entry, lha->uname.s);
-	if (archive_strlen(&lha->gname) > 0)
-		archive_entry_set_gname(entry, lha->gname.s);
-	if (lha->setflag & BIRTHTIME_IS_SET) {
-		archive_entry_set_birthtime(entry, lha->birthtime,
-		    lha->birthtime_tv_nsec);
-		archive_entry_set_ctime(entry, lha->birthtime,
-		    lha->birthtime_tv_nsec);
-	} else {
-		archive_entry_unset_birthtime(entry);
-		archive_entry_unset_ctime(entry);
-	}
-	archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec);
-	if (lha->setflag & ATIME_IS_SET)
-		archive_entry_set_atime(entry, lha->atime,
-		    lha->atime_tv_nsec);
-	else
-		archive_entry_unset_atime(entry);
-	if (lha->directory || archive_entry_symlink(entry) != NULL)
-		archive_entry_unset_size(entry);
-	else
-		archive_entry_set_size(entry, lha->origsize);
-
-	/*
-	 * Prepare variables used to read a file content.
-	 */
-	lha->entry_bytes_remaining = lha->compsize;
-	if (lha->entry_bytes_remaining < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid LHa entry size");
-		return (ARCHIVE_FATAL);
-	}
-	lha->entry_offset = 0;
-	lha->entry_crc_calculated = 0;
-
-	/*
-	 * This file does not have a content.
-	 */
-	if (lha->directory || lha->compsize == 0)
-		lha->end_of_entry = 1;
-
-	snprintf(lha->format_name, sizeof(lha->format_name), "lha -%c%c%c-",
-	    lha->method[0], lha->method[1], lha->method[2]);
-	a->archive.archive_format_name = lha->format_name;
-
-	return (err);
-}
-
-/*
- * Replace a DOS path separator '\' by a character '/'.
- * Some multi-byte character set have  a character '\' in its second byte.
- */
-static void
-lha_replace_path_separator(struct lha *lha, struct archive_entry *entry)
-{
-	const wchar_t *wp;
-	size_t i;
-
-	if ((wp = archive_entry_pathname_w(entry)) != NULL) {
-		archive_wstrcpy(&(lha->ws), wp);
-		for (i = 0; i < archive_strlen(&(lha->ws)); i++) {
-			if (lha->ws.s[i] == L'\\')
-				lha->ws.s[i] = L'/';
-		}
-		archive_entry_copy_pathname_w(entry, lha->ws.s);
-	}
-
-	if ((wp = archive_entry_symlink_w(entry)) != NULL) {
-		archive_wstrcpy(&(lha->ws), wp);
-		for (i = 0; i < archive_strlen(&(lha->ws)); i++) {
-			if (lha->ws.s[i] == L'\\')
-				lha->ws.s[i] = L'/';
-		}
-		archive_entry_copy_symlink_w(entry, lha->ws.s);
-	}
-}
-
-/*
- * Header 0 format
- *
- * +0              +1         +2               +7                  +11
- * +---------------+----------+----------------+-------------------+
- * |header size(*1)|header sum|compression type|compressed size(*2)|
- * +---------------+----------+----------------+-------------------+
- *                             <---------------------(*1)----------*
- *
- * +11               +15       +17       +19            +20              +21
- * +-----------------+---------+---------+--------------+----------------+
- * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)|
- * +-----------------+---------+---------+--------------+----------------+
- * *--------------------------------(*1)---------------------------------*
- *
- * +21             +22       +22+(*3)   +22+(*3)+2       +22+(*3)+2+(*4)
- * +---------------+---------+----------+----------------+------------------+
- * |name length(*3)|file name|file CRC16|extra header(*4)|  compressed data |
- * +---------------+---------+----------+----------------+------------------+
- *                  <--(*3)->                             <------(*2)------>
- * *----------------------(*1)-------------------------->
- *
- */
-#define H0_HEADER_SIZE_OFFSET	0
-#define H0_HEADER_SUM_OFFSET	1
-#define H0_COMP_SIZE_OFFSET	7
-#define H0_ORIG_SIZE_OFFSET	11
-#define H0_DOS_TIME_OFFSET	15
-#define H0_NAME_LEN_OFFSET	21
-#define H0_FILE_NAME_OFFSET	22
-#define H0_FIXED_SIZE		24
-static int
-lha_read_file_header_0(struct archive_read *a, struct lha *lha)
-{
-	const unsigned char *p;
-	int extdsize, namelen;
-	unsigned char headersum, sum_calculated;
-
-	if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL)
-		return (truncated_error(a));
-	lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2;
-	headersum = p[H0_HEADER_SUM_OFFSET];
-	lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
-	lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
-	lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET);
-	namelen = p[H0_NAME_LEN_OFFSET];
-	extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
-	if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid LHa header");
-		return (ARCHIVE_FATAL);
-	}
-	if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL)
-		return (truncated_error(a));
-
-	archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen);
-	/* When extdsize == -2, A CRC16 value is not present in the header. */
-	if (extdsize >= 0) {
-		lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen);
-		lha->setflag |= CRC_IS_SET;
-	}
-	sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2);
-
-	/* Read an extended header */
-	if (extdsize > 0) {
-		/* This extended data is set by 'LHa for UNIX' only.
-		 * Maybe fixed size.
-		 */
-		p += H0_FILE_NAME_OFFSET + namelen + 2;
-		if (p[0] == 'U' && extdsize == 12) {
-			/* p[1] is a minor version. */
-			lha->mtime = archive_le32dec(&p[2]);
-			lha->mode = archive_le16dec(&p[6]);
-			lha->uid = archive_le16dec(&p[8]);
-			lha->gid = archive_le16dec(&p[10]);
-			lha->setflag |= UNIX_MODE_IS_SET;
-		}
-	}
-	__archive_read_consume(a, lha->header_size);
-
-	if (sum_calculated != headersum) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "LHa header sum error");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Header 1 format
- *
- * +0              +1         +2               +7            +11
- * +---------------+----------+----------------+-------------+
- * |header size(*1)|header sum|compression type|skip size(*2)|
- * +---------------+----------+----------------+-------------+
- *                             <---------------(*1)----------*
- *
- * +11               +15       +17       +19            +20              +21
- * +-----------------+---------+---------+--------------+----------------+
- * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)|
- * +-----------------+---------+---------+--------------+----------------+
- * *-------------------------------(*1)----------------------------------*
- *
- * +21             +22       +22+(*3)   +22+(*3)+2  +22+(*3)+3  +22+(*3)+3+(*4)
- * +---------------+---------+----------+-----------+-----------+
- * |name length(*3)|file name|file CRC16|  creator  |padding(*4)|
- * +---------------+---------+----------+-----------+-----------+
- *                  <--(*3)->
- * *----------------------------(*1)----------------------------*
- *
- * +22+(*3)+3+(*4)  +22+(*3)+3+(*4)+2     +22+(*3)+3+(*4)+2+(*5)
- * +----------------+---------------------+------------------------+
- * |next header size| extended header(*5) |     compressed data    |
- * +----------------+---------------------+------------------------+
- * *------(*1)-----> <--------------------(*2)-------------------->
- */
-#define H1_HEADER_SIZE_OFFSET	0
-#define H1_HEADER_SUM_OFFSET	1
-#define H1_COMP_SIZE_OFFSET	7
-#define H1_ORIG_SIZE_OFFSET	11
-#define H1_DOS_TIME_OFFSET	15
-#define H1_NAME_LEN_OFFSET	21
-#define H1_FILE_NAME_OFFSET	22
-#define H1_FIXED_SIZE		27
-static int
-lha_read_file_header_1(struct archive_read *a, struct lha *lha)
-{
-	const unsigned char *p;
-	size_t extdsize;
-	int i, err, err2;
-	int namelen, padding;
-	unsigned char headersum, sum_calculated;
-
-	err = ARCHIVE_OK;
-
-	if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL)
-		return (truncated_error(a));
-
-	lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2;
-	headersum = p[H1_HEADER_SUM_OFFSET];
-	/* Note: An extended header size is included in a compsize. */
-	lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
-	lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
-	lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
-	namelen = p[H1_NAME_LEN_OFFSET];
-	/* Calculate a padding size. The result will be normally 0 only(?) */
-	padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
-
-	if (namelen > 230 || padding < 0)
-		goto invalid;
-
-	if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL)
-		return (truncated_error(a));
-
-	for (i = 0; i < namelen; i++) {
-		if (p[i + H1_FILE_NAME_OFFSET] == 0xff)
-			goto invalid;/* Invalid filename. */
-	}
-	archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen);
-	lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen);
-	lha->setflag |= CRC_IS_SET;
-
-	sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2);
-	/* Consume used bytes but not include `next header size' data
-	 * since it will be consumed in lha_read_file_extended_header(). */
-	__archive_read_consume(a, lha->header_size - 2);
-
-	/* Read extended headers */
-	err2 = lha_read_file_extended_header(a, lha, NULL, 2,
-	    (size_t)(lha->compsize + 2), &extdsize);
-	if (err2 < ARCHIVE_WARN)
-		return (err2);
-	if (err2 < err)
-		err = err2;
-	/* Get a real compressed file size. */
-	lha->compsize -= extdsize - 2;
-
-	if (lha->compsize < 0)
-		goto invalid;	/* Invalid compressed file size */
-
-	if (sum_calculated != headersum) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "LHa header sum error");
-		return (ARCHIVE_FATAL);
-	}
-	return (err);
-invalid:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Invalid LHa header");
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Header 2 format
- *
- * +0              +2               +7                  +11               +15
- * +---------------+----------------+-------------------+-----------------+
- * |header size(*1)|compression type|compressed size(*2)|uncompressed size|
- * +---------------+----------------+-------------------+-----------------+
- *  <--------------------------------(*1)---------------------------------*
- *
- * +15               +19          +20              +21        +23         +24
- * +-----------------+------------+----------------+----------+-----------+
- * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16|  creator  |
- * +-----------------+------------+----------------+----------+-----------+
- * *---------------------------------(*1)---------------------------------*
- *
- * +24              +26                 +26+(*3)      +26+(*3)+(*4)
- * +----------------+-------------------+-------------+-------------------+
- * |next header size|extended header(*3)| padding(*4) |  compressed data  |
- * +----------------+-------------------+-------------+-------------------+
- * *--------------------------(*1)-------------------> <------(*2)------->
- *
- */
-#define H2_HEADER_SIZE_OFFSET	0
-#define H2_COMP_SIZE_OFFSET	7
-#define H2_ORIG_SIZE_OFFSET	11
-#define H2_TIME_OFFSET		15
-#define H2_CRC_OFFSET		21
-#define H2_FIXED_SIZE		24
-static int
-lha_read_file_header_2(struct archive_read *a, struct lha *lha)
-{
-	const unsigned char *p;
-	size_t extdsize;
-	int err, padding;
-	uint16_t header_crc;
-
-	if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL)
-		return (truncated_error(a));
-
-	lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET);
-	lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET);
-	lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET);
-	lha->mtime = archive_le32dec(p + H2_TIME_OFFSET);
-	lha->crc = archive_le16dec(p + H2_CRC_OFFSET);
-	lha->setflag |= CRC_IS_SET;
-
-	if (lha->header_size < H2_FIXED_SIZE) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid LHa header size");
-		return (ARCHIVE_FATAL);
-	}
-
-	header_crc = lha_crc16(0, p, H2_FIXED_SIZE);
-	__archive_read_consume(a, H2_FIXED_SIZE);
-
-	/* Read extended headers */
-	err = lha_read_file_extended_header(a, lha, &header_crc, 2,
-		  lha->header_size - H2_FIXED_SIZE, &extdsize);
-	if (err < ARCHIVE_WARN)
-		return (err);
-
-	/* Calculate a padding size. The result will be normally 0 or 1. */
-	padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize);
-	if (padding > 0) {
-		if ((p = __archive_read_ahead(a, padding, NULL)) == NULL)
-			return (truncated_error(a));
-		header_crc = lha_crc16(header_crc, p, padding);
-		__archive_read_consume(a, padding);
-	}
-
-	if (header_crc != lha->header_crc) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "LHa header CRC error");
-		return (ARCHIVE_FATAL);
-#endif
-	}
-	return (err);
-}
-
-/*
- * Header 3 format
- *
- * +0           +2               +7                  +11               +15
- * +------------+----------------+-------------------+-----------------+
- * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size|
- * +------------+----------------+-------------------+-----------------+
- *  <-------------------------------(*1)-------------------------------*
- *
- * +15               +19          +20              +21        +23         +24
- * +-----------------+------------+----------------+----------+-----------+
- * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16|  creator  |
- * +-----------------+------------+----------------+----------+-----------+
- * *--------------------------------(*1)----------------------------------*
- *
- * +24             +28              +32                 +32+(*3)
- * +---------------+----------------+-------------------+-----------------+
- * |header size(*1)|next header size|extended header(*3)| compressed data |
- * +---------------+----------------+-------------------+-----------------+
- * *------------------------(*1)-----------------------> <------(*2)----->
- *
- */
-#define H3_FIELD_LEN_OFFSET	0
-#define H3_COMP_SIZE_OFFSET	7
-#define H3_ORIG_SIZE_OFFSET	11
-#define H3_TIME_OFFSET		15
-#define H3_CRC_OFFSET		21
-#define H3_HEADER_SIZE_OFFSET	24
-#define H3_FIXED_SIZE		28
-static int
-lha_read_file_header_3(struct archive_read *a, struct lha *lha)
-{
-	const unsigned char *p;
-	size_t extdsize;
-	int err;
-	uint16_t header_crc;
-
-	if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL)
-		return (truncated_error(a));
-
-	if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
-		goto invalid;
-	lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
-	lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
-	lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
-	lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
-	lha->crc = archive_le16dec(p + H3_CRC_OFFSET);
-	lha->setflag |= CRC_IS_SET;
-
-	if (lha->header_size < H3_FIXED_SIZE + 4)
-		goto invalid;
-	header_crc = lha_crc16(0, p, H3_FIXED_SIZE);
-	__archive_read_consume(a, H3_FIXED_SIZE);
-
-	/* Read extended headers */
-	err = lha_read_file_extended_header(a, lha, &header_crc, 4,
-		  lha->header_size - H3_FIXED_SIZE, &extdsize);
-	if (err < ARCHIVE_WARN)
-		return (err);
-
-	if (header_crc != lha->header_crc) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "LHa header CRC error");
-		return (ARCHIVE_FATAL);
-#endif
-	}
-	return (err);
-invalid:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Invalid LHa header");
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Extended header format
- *
- * +0             +2        +3  -- used in header 1 and 2
- * +0             +4        +5  -- used in header 3
- * +--------------+---------+-------------------+--------------+--
- * |ex-header size|header id|        data       |ex-header size| .......
- * +--------------+---------+-------------------+--------------+--
- *  <-------------( ex-header size)------------> <-- next extended header --*
- *
- * If the ex-header size is zero, it is the make of the end of extended
- * headers.
- *
- */
-static int
-lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
-    uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size)
-{
-	const void *h;
-	const unsigned char *extdheader;
-	size_t	extdsize;
-	size_t	datasize;
-	unsigned int i;
-	unsigned char extdtype;
-
-#define EXT_HEADER_CRC		0x00		/* Header CRC and information*/
-#define EXT_FILENAME		0x01		/* Filename 		    */
-#define EXT_DIRECTORY		0x02		/* Directory name	    */
-#define EXT_DOS_ATTR		0x40		/* MS-DOS attribute	    */
-#define EXT_TIMESTAMP		0x41		/* Windows time stamp	    */
-#define EXT_FILESIZE		0x42		/* Large file size	    */
-#define EXT_TIMEZONE		0x43		/* Time zone		    */
-#define EXT_UTF16_FILENAME	0x44		/* UTF-16 filename 	    */
-#define EXT_UTF16_DIRECTORY	0x45		/* UTF-16 directory name    */
-#define EXT_CODEPAGE		0x46		/* Codepage		    */
-#define EXT_UNIX_MODE		0x50		/* File permission	    */
-#define EXT_UNIX_GID_UID	0x51		/* gid,uid		    */
-#define EXT_UNIX_GNAME		0x52		/* Group name		    */
-#define EXT_UNIX_UNAME		0x53		/* User name		    */
-#define EXT_UNIX_MTIME		0x54		/* Modified time	    */
-#define EXT_OS2_NEW_ATTR	0x7f		/* new attribute(OS/2 only) */
-#define EXT_NEW_ATTR		0xff		/* new attribute	    */
-
-	*total_size = sizefield_length;
-
-	for (;;) {
-		/* Read an extended header size. */
-		if ((h =
-		    __archive_read_ahead(a, sizefield_length, NULL)) == NULL)
-			return (truncated_error(a));
-		/* Check if the size is the zero indicates the end of the
-		 * extended header. */
-		if (sizefield_length == sizeof(uint16_t))
-			extdsize = archive_le16dec(h);
-		else
-			extdsize = archive_le32dec(h);
-		if (extdsize == 0) {
-			/* End of extended header */
-			if (crc != NULL)
-				*crc = lha_crc16(*crc, h, sizefield_length);
-			__archive_read_consume(a, sizefield_length);
-			return (ARCHIVE_OK);
-		}
-
-		/* Sanity check to the extended header size. */
-		if (((uint64_t)*total_size + extdsize) >
-				    (uint64_t)limitsize ||
-		    extdsize <= (size_t)sizefield_length)
-			goto invalid;
-
-		/* Read the extended header. */
-		if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL)
-			return (truncated_error(a));
-		*total_size += extdsize;
-
-		extdheader = (const unsigned char *)h;
-		/* Get the extended header type. */
-		extdtype = extdheader[sizefield_length];
-		/* Calculate an extended data size. */
-		datasize = extdsize - (1 + sizefield_length);
-		/* Skip an extended header size field and type field. */
-		extdheader += sizefield_length + 1;
-
-		if (crc != NULL && extdtype != EXT_HEADER_CRC)
-			*crc = lha_crc16(*crc, h, extdsize);
-		switch (extdtype) {
-		case EXT_HEADER_CRC:
-			/* We only use a header CRC. Following data will not
-			 * be used. */
-			if (datasize >= 2) {
-				lha->header_crc = archive_le16dec(extdheader);
-				if (crc != NULL) {
-					static const char zeros[2] = {0, 0};
-					*crc = lha_crc16(*crc, h,
-					    extdsize - datasize);
-					/* CRC value itself as zero */
-					*crc = lha_crc16(*crc, zeros, 2);
-					*crc = lha_crc16(*crc,
-					    extdheader+2, datasize - 2);
-				}
-			}
-			break;
-		case EXT_FILENAME:
-			if (datasize == 0) {
-				/* maybe directory header */
-				archive_string_empty(&lha->filename);
-				break;
-			}
-			if (extdheader[0] == '\0')
-				goto invalid;
-			archive_strncpy(&lha->filename,
-			    (const char *)extdheader, datasize);
-			break;
-		case EXT_UTF16_FILENAME:
-			if (datasize == 0) {
-				/* maybe directory header */
-				archive_string_empty(&lha->filename);
-				break;
-			} else if (datasize & 1) {
-				/* UTF-16 characters take always 2 or 4 bytes */
-				goto invalid;
-			}
-			if (extdheader[0] == '\0')
-				goto invalid;
-			archive_string_empty(&lha->filename);
-			archive_array_append(&lha->filename,
-				(const char *)extdheader, datasize);
-			/* Setup a string conversion for a filename. */
-			lha->sconv_fname =
-			    archive_string_conversion_from_charset(&a->archive,
-			        "UTF-16LE", 1);
-			if (lha->sconv_fname == NULL)
-				return (ARCHIVE_FATAL);
-			break;
-		case EXT_DIRECTORY:
-			if (datasize == 0 || extdheader[0] == '\0')
-				/* no directory name data. exit this case. */
-				goto invalid;
-
-			archive_strncpy(&lha->dirname,
-		  	    (const char *)extdheader, datasize);
-			/*
-			 * Convert directory delimiter from 0xFF
-			 * to '/' for local system.
-	 		 */
-			for (i = 0; i < lha->dirname.length; i++) {
-				if ((unsigned char)lha->dirname.s[i] == 0xFF)
-					lha->dirname.s[i] = '/';
-			}
-			/* Is last character directory separator? */
-			if (lha->dirname.s[lha->dirname.length-1] != '/')
-				/* invalid directory data */
-				goto invalid;
-			break;
-		case EXT_UTF16_DIRECTORY:
-			/* UTF-16 characters take always 2 or 4 bytes */
-			if (datasize == 0 || (datasize & 1) ||
-			    extdheader[0] == '\0') {
-				/* no directory name data. exit this case. */
-				goto invalid;
-			}
-
-			archive_string_empty(&lha->dirname);
-			archive_array_append(&lha->dirname,
-				(const char *)extdheader, datasize);
-			lha->sconv_dir =
-			    archive_string_conversion_from_charset(&a->archive,
-			        "UTF-16LE", 1);
-			if (lha->sconv_dir == NULL)
-				return (ARCHIVE_FATAL);
-			else {
-				/*
-				 * Convert directory delimiter from 0xFFFF
-				 * to '/' for local system.
-				 */
-				uint16_t dirSep;
-				uint16_t d = 1;
-				if (archive_be16dec(&d) == 1)
-					dirSep = 0x2F00;
-				else
-					dirSep = 0x002F;
-
-				/* UTF-16LE character */
-				uint16_t *utf16name =
-				    (uint16_t *)lha->dirname.s;
-				for (i = 0; i < lha->dirname.length / 2; i++) {
-					if (utf16name[i] == 0xFFFF) {
-						utf16name[i] = dirSep;
-					}
-				}
-				/* Is last character directory separator? */
-				if (utf16name[lha->dirname.length / 2 - 1] !=
-				    dirSep) {
-					/* invalid directory data */
-					goto invalid;
-				}
-			}
-			break;
-		case EXT_DOS_ATTR:
-			if (datasize == 2)
-				lha->dos_attr = (unsigned char)
-				    (archive_le16dec(extdheader) & 0xff);
-			break;
-		case EXT_TIMESTAMP:
-			if (datasize == (sizeof(uint64_t) * 3)) {
-				lha->birthtime = lha_win_time(
-				    archive_le64dec(extdheader),
-				    &lha->birthtime_tv_nsec);
-				extdheader += sizeof(uint64_t);
-				lha->mtime = lha_win_time(
-				    archive_le64dec(extdheader),
-				    &lha->mtime_tv_nsec);
-				extdheader += sizeof(uint64_t);
-				lha->atime = lha_win_time(
-				    archive_le64dec(extdheader),
-				    &lha->atime_tv_nsec);
-				lha->setflag |= BIRTHTIME_IS_SET |
-				    ATIME_IS_SET;
-			}
-			break;
-		case EXT_FILESIZE:
-			if (datasize == sizeof(uint64_t) * 2) {
-				lha->compsize = archive_le64dec(extdheader);
-				extdheader += sizeof(uint64_t);
-				lha->origsize = archive_le64dec(extdheader);
-			}
-			break;
-		case EXT_CODEPAGE:
-			/* Get an archived filename charset from codepage.
-			 * This overwrites the charset specified by
-			 * hdrcharset option. */
-			if (datasize == sizeof(uint32_t)) {
-				struct archive_string cp;
-				const char *charset;
-
-				archive_string_init(&cp);
-				switch (archive_le32dec(extdheader)) {
-				case 65001: /* UTF-8 */
-					charset = "UTF-8";
-					break;
-				default:
-					archive_string_sprintf(&cp, "CP%d",
-					    (int)archive_le32dec(extdheader));
-					charset = cp.s;
-					break;
-				}
-				lha->sconv_dir =
-				    archive_string_conversion_from_charset(
-					&(a->archive), charset, 1);
-				lha->sconv_fname =
-				    archive_string_conversion_from_charset(
-					&(a->archive), charset, 1);
-				archive_string_free(&cp);
-				if (lha->sconv_dir == NULL)
-					return (ARCHIVE_FATAL);
-				if (lha->sconv_fname == NULL)
-					return (ARCHIVE_FATAL);
-			}
-			break;
-		case EXT_UNIX_MODE:
-			if (datasize == sizeof(uint16_t)) {
-				lha->mode = archive_le16dec(extdheader);
-				lha->setflag |= UNIX_MODE_IS_SET;
-			}
-			break;
-		case EXT_UNIX_GID_UID:
-			if (datasize == (sizeof(uint16_t) * 2)) {
-				lha->gid = archive_le16dec(extdheader);
-				lha->uid = archive_le16dec(extdheader+2);
-			}
-			break;
-		case EXT_UNIX_GNAME:
-			if (datasize > 0)
-				archive_strncpy(&lha->gname,
-				    (const char *)extdheader, datasize);
-			break;
-		case EXT_UNIX_UNAME:
-			if (datasize > 0)
-				archive_strncpy(&lha->uname,
-				    (const char *)extdheader, datasize);
-			break;
-		case EXT_UNIX_MTIME:
-			if (datasize == sizeof(uint32_t))
-				lha->mtime = archive_le32dec(extdheader);
-			break;
-		case EXT_OS2_NEW_ATTR:
-			/* This extended header is OS/2 depend. */
-			if (datasize == 16) {
-				lha->dos_attr = (unsigned char)
-				    (archive_le16dec(extdheader) & 0xff);
-				lha->mode = archive_le16dec(extdheader+2);
-				lha->gid = archive_le16dec(extdheader+4);
-				lha->uid = archive_le16dec(extdheader+6);
-				lha->birthtime = archive_le32dec(extdheader+8);
-				lha->atime = archive_le32dec(extdheader+12);
-				lha->setflag |= UNIX_MODE_IS_SET
-				    | BIRTHTIME_IS_SET | ATIME_IS_SET;
-			}
-			break;
-		case EXT_NEW_ATTR:
-			if (datasize == 20) {
-				lha->mode = (mode_t)archive_le32dec(extdheader);
-				lha->gid = archive_le32dec(extdheader+4);
-				lha->uid = archive_le32dec(extdheader+8);
-				lha->birthtime = archive_le32dec(extdheader+12);
-				lha->atime = archive_le32dec(extdheader+16);
-				lha->setflag |= UNIX_MODE_IS_SET
-				    | BIRTHTIME_IS_SET | ATIME_IS_SET;
-			}
-			break;
-		case EXT_TIMEZONE:		/* Not supported */
-			break;
-		default:
-			break;
-		}
-
-		__archive_read_consume(a, extdsize);
-	}
-invalid:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Invalid extended LHa header");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-lha_end_of_entry(struct archive_read *a)
-{
-	struct lha *lha = (struct lha *)(a->format->data);
-	int r = ARCHIVE_EOF;
-
-	if (!lha->end_of_entry_cleanup) {
-		if ((lha->setflag & CRC_IS_SET) &&
-		    lha->crc != lha->entry_crc_calculated) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "LHa data CRC error");
-			r = ARCHIVE_WARN;
-		}
-
-		/* End-of-entry cleanup done. */
-		lha->end_of_entry_cleanup = 1;
-	}
-	return (r);
-}
-
-static int
-archive_read_format_lha_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct lha *lha = (struct lha *)(a->format->data);
-	int r;
-
-	if (lha->entry_unconsumed) {
-		/* Consume as much as the decompressor actually used. */
-		__archive_read_consume(a, lha->entry_unconsumed);
-		lha->entry_unconsumed = 0;
-	}
-	if (lha->end_of_entry) {
-		*offset = lha->entry_offset;
-		*size = 0;
-		*buff = NULL;
-		return (lha_end_of_entry(a));
-	}
-
-	if (lha->entry_is_compressed)
-		r =  lha_read_data_lzh(a, buff, size, offset);
-	else
-		/* No compression. */
-		r =  lha_read_data_none(a, buff, size, offset);
-	return (r);
-}
-
-/*
- * Read a file content in no compression.
- *
- * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
- * lha->end_of_entry if it consumes all of the data.
- */
-static int
-lha_read_data_none(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct lha *lha = (struct lha *)(a->format->data);
-	ssize_t bytes_avail;
-
-	if (lha->entry_bytes_remaining == 0) {
-		*buff = NULL;
-		*size = 0;
-		*offset = lha->entry_offset;
-		lha->end_of_entry = 1;
-		return (ARCHIVE_OK);
-	}
-	/*
-	 * Note: '1' here is a performance optimization.
-	 * Recall that the decompression layer returns a count of
-	 * available bytes; asking for more than that forces the
-	 * decompressor to combine reads by copying data.
-	 */
-	*buff = __archive_read_ahead(a, 1, &bytes_avail);
-	if (bytes_avail <= 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated LHa file data");
-		return (ARCHIVE_FATAL);
-	}
-	if (bytes_avail > lha->entry_bytes_remaining)
-		bytes_avail = (ssize_t)lha->entry_bytes_remaining;
-	lha->entry_crc_calculated =
-	    lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail);
-	*size = bytes_avail;
-	*offset = lha->entry_offset;
-	lha->entry_offset += bytes_avail;
-	lha->entry_bytes_remaining -= bytes_avail;
-	if (lha->entry_bytes_remaining == 0)
-		lha->end_of_entry = 1;
-	lha->entry_unconsumed = bytes_avail;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Read a file content in LZHUFF encoding.
- *
- * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is
- * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes
- * all of the data.
- */
-static int
-lha_read_data_lzh(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct lha *lha = (struct lha *)(a->format->data);
-	ssize_t bytes_avail;
-	int r;
-
-	/* If we haven't yet read any data, initialize the decompressor. */
-	if (!lha->decompress_init) {
-		r = lzh_decode_init(&(lha->strm), lha->method);
-		switch (r) {
-		case ARCHIVE_OK:
-			break;
-		case ARCHIVE_FAILED:
-        		/* Unsupported compression. */
-			*buff = NULL;
-			*size = 0;
-			*offset = 0;
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unsupported lzh compression method -%c%c%c-",
-			    lha->method[0], lha->method[1], lha->method[2]);
-			/* We know compressed size; just skip it. */
-			archive_read_format_lha_read_data_skip(a);
-			return (ARCHIVE_WARN);
-		default:
-			archive_set_error(&a->archive, ENOMEM,
-			    "Couldn't allocate memory "
-			    "for lzh decompression");
-			return (ARCHIVE_FATAL);
-		}
-		/* We've initialized decompression for this stream. */
-		lha->decompress_init = 1;
-		lha->strm.avail_out = 0;
-		lha->strm.total_out = 0;
-	}
-
-	/*
-	 * Note: '1' here is a performance optimization.
-	 * Recall that the decompression layer returns a count of
-	 * available bytes; asking for more than that forces the
-	 * decompressor to combine reads by copying data.
-	 */
-	lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail);
-	if (bytes_avail <= 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated LHa file body");
-		return (ARCHIVE_FATAL);
-	}
-	if (bytes_avail > lha->entry_bytes_remaining)
-		bytes_avail = (ssize_t)lha->entry_bytes_remaining;
-
-	lha->strm.avail_in = (int)bytes_avail;
-	lha->strm.total_in = 0;
-	lha->strm.avail_out = 0;
-
-	r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining);
-	switch (r) {
-	case ARCHIVE_OK:
-		break;
-	case ARCHIVE_EOF:
-		lha->end_of_entry = 1;
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Bad lzh data");
-		return (ARCHIVE_FAILED);
-	}
-	lha->entry_unconsumed = lha->strm.total_in;
-	lha->entry_bytes_remaining -= lha->strm.total_in;
-
-	if (lha->strm.avail_out) {
-		*offset = lha->entry_offset;
-		*size = lha->strm.avail_out;
-		*buff = lha->strm.ref_ptr;
-		lha->entry_crc_calculated =
-		    lha_crc16(lha->entry_crc_calculated, *buff, *size);
-		lha->entry_offset += *size;
-	} else {
-		*offset = lha->entry_offset;
-		*size = 0;
-		*buff = NULL;
-		if (lha->end_of_entry)
-			return (lha_end_of_entry(a));
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Skip a file content.
- */
-static int
-archive_read_format_lha_read_data_skip(struct archive_read *a)
-{
-	struct lha *lha;
-	int64_t bytes_skipped;
-
-	lha = (struct lha *)(a->format->data);
-
-	if (lha->entry_unconsumed) {
-		/* Consume as much as the decompressor actually used. */
-		__archive_read_consume(a, lha->entry_unconsumed);
-		lha->entry_unconsumed = 0;
-	}
-
-	/* if we've already read to end of data, we're done. */
-	if (lha->end_of_entry_cleanup)
-		return (ARCHIVE_OK);
-
-	/*
-	 * If the length is at the beginning, we can skip the
-	 * compressed data much more quickly.
-	 */
-	bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-
-	/* This entry is finished and done. */
-	lha->end_of_entry_cleanup = lha->end_of_entry = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_lha_cleanup(struct archive_read *a)
-{
-	struct lha *lha = (struct lha *)(a->format->data);
-
-	lzh_decode_free(&(lha->strm));
-	archive_string_free(&(lha->dirname));
-	archive_string_free(&(lha->filename));
-	archive_string_free(&(lha->uname));
-	archive_string_free(&(lha->gname));
-	archive_wstring_free(&(lha->ws));
-	free(lha);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-/*
- * 'LHa for UNIX' utility has archived a symbolic-link name after
- * a pathname with '|' character.
- * This function extracts the symbolic-link name from the pathname.
- *
- * example.
- *   1. a symbolic-name is 'aaa/bb/cc'
- *   2. a filename is 'xxx/bbb'
- *  then a archived pathname is 'xxx/bbb|aaa/bb/cc'
- */
-static int
-lha_parse_linkname(struct archive_wstring *linkname,
-    struct archive_wstring *pathname)
-{
-	wchar_t *	linkptr;
-	size_t 	symlen;
-
-	linkptr = wcschr(pathname->s, L'|');
-	if (linkptr != NULL) {
-		symlen = wcslen(linkptr + 1);
-		archive_wstrncpy(linkname, linkptr+1, symlen);
-
-		*linkptr = 0;
-		pathname->length = wcslen(pathname->s);
-
-		return (1);
-	}
-	return (0);
-}
-
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-lha_dos_time(const unsigned char *p)
-{
-	int msTime, msDate;
-	struct tm ts;
-
-	msTime = archive_le16dec(p);
-	msDate = archive_le16dec(p+2);
-
-	memset(&ts, 0, sizeof(ts));
-	ts.tm_year = ((msDate >> 9) & 0x7f) + 80;   /* Years since 1900. */
-	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1;     /* Month number.     */
-	ts.tm_mday = msDate & 0x1f;		    /* Day of month.     */
-	ts.tm_hour = (msTime >> 11) & 0x1f;
-	ts.tm_min = (msTime >> 5) & 0x3f;
-	ts.tm_sec = (msTime << 1) & 0x3e;
-	ts.tm_isdst = -1;
-	return (mktime(&ts));
-}
-
-/* Convert an MS-Windows-style date/time into Unix-style time. */
-static time_t
-lha_win_time(uint64_t wintime, long *ns)
-{
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-	if (wintime >= EPOC_TIME) {
-		wintime -= EPOC_TIME;	/* 1970-01-01 00:00:00 (UTC) */
-		if (ns != NULL)
-			*ns = (long)(wintime % 10000000) * 100;
-		return (wintime / 10000000);
-	} else {
-		if (ns != NULL)
-			*ns = 0;
-		return (0);
-	}
-}
-
-static unsigned char
-lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
-{
-	unsigned char const *p = (unsigned char const *)pp;
-
-	p += offset;
-	for (;size > 0; --size)
-		sum += *p++;
-	return (sum);
-}
-
-static uint16_t crc16tbl[2][256];
-static void
-lha_crc16_init(void)
-{
-	unsigned int i;
-	static int crc16init = 0;
-
-	if (crc16init)
-		return;
-	crc16init = 1;
-
-	for (i = 0; i < 256; i++) {
-		unsigned int j;
-		uint16_t crc = (uint16_t)i;
-		for (j = 8; j; j--)
-			crc = (crc >> 1) ^ ((crc & 1) * 0xA001);
-		crc16tbl[0][i] = crc;
-	}
-
-	for (i = 0; i < 256; i++) {
-		crc16tbl[1][i] = (crc16tbl[0][i] >> 8)
-			^ crc16tbl[0][crc16tbl[0][i] & 0xff];
-	}
-}
-
-static uint16_t
-lha_crc16(uint16_t crc, const void *pp, size_t len)
-{
-	const unsigned char *p = (const unsigned char *)pp;
-	const uint16_t *buff;
-	const union {
-		uint32_t i;
-		char c[4];
-	} u = { 0x01020304 };
-
-	if (len == 0)
-		return crc;
-
-	/* Process unaligned address. */
-	if (((uintptr_t)p) & (uintptr_t)0x1) {
-		crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff];
-		len--;
-	}
-	buff = (const uint16_t *)p;
-	/*
-	 * Modern C compiler such as GCC does not unroll automatically yet
-	 * without unrolling pragma, and Clang is so. So we should
-	 * unroll this loop for its performance.
-	 */
-	for (;len >= 8; len -= 8) {
-		/* This if statement expects compiler optimization will
-		 * remove the statement which will not be executed. */
-#undef bswap16
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1400  /* Visual Studio */
-#  define bswap16(x) _byteswap_ushort(x)
-#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
-/* GCC 4.8 and later has __builtin_bswap16() */
-#  define bswap16(x) __builtin_bswap16(x)
-#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
-/* Newer clang versions have __builtin_bswap16() */
-#  define bswap16(x) __builtin_bswap16(x)
-#else
-#  define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
-#endif
-#define CRC16W	do { 	\
-		if(u.c[0] == 1) { /* Big endian */		\
-			crc ^= bswap16(*buff); buff++;		\
-		} else						\
-			crc ^= *buff++;				\
-		crc = crc16tbl[1][crc & 0xff] ^ crc16tbl[0][crc >> 8];\
-} while (0)
-		CRC16W;
-		CRC16W;
-		CRC16W;
-		CRC16W;
-#undef CRC16W
-#undef bswap16
-	}
-
-	p = (const unsigned char *)buff;
-	for (;len; len--) {
-		crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff];
-	}
-	return crc;
-}
-
-/*
- * Initialize LZHUF decoder.
- *
- * Returns ARCHIVE_OK if initialization was successful.
- * Returns ARCHIVE_FAILED if method is unsupported.
- * Returns ARCHIVE_FATAL if initialization failed; memory allocation
- * error occurred.
- */
-static int
-lzh_decode_init(struct lzh_stream *strm, const char *method)
-{
-	struct lzh_dec *ds;
-	int w_bits, w_size;
-
-	if (strm->ds == NULL) {
-		strm->ds = calloc(1, sizeof(*strm->ds));
-		if (strm->ds == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	ds = strm->ds;
-	ds->error = ARCHIVE_FAILED;
-	if (method == NULL || method[0] != 'l' || method[1] != 'h')
-		return (ARCHIVE_FAILED);
-	switch (method[2]) {
-	case '5':
-		w_bits = 13;/* 8KiB for window */
-		break;
-	case '6':
-		w_bits = 15;/* 32KiB for window */
-		break;
-	case '7':
-		w_bits = 16;/* 64KiB for window */
-		break;
-	default:
-		return (ARCHIVE_FAILED);/* Not supported. */
-	}
-	ds->error = ARCHIVE_FATAL;
-	/* Expand a window size up to 128 KiB for decompressing process
-	 * performance whatever its original window size is. */
-	ds->w_size = 1U << 17;
-	ds->w_mask = ds->w_size -1;
-	if (ds->w_buff == NULL) {
-		ds->w_buff = malloc(ds->w_size);
-		if (ds->w_buff == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	w_size = 1U << w_bits;
-	memset(ds->w_buff + ds->w_size - w_size, 0x20, w_size);
-	ds->w_pos = 0;
-	ds->state = 0;
-	ds->pos_pt_len_size = w_bits + 1;
-	ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4;
-	ds->literal_pt_len_size = PT_BITLEN_SIZE;
-	ds->literal_pt_len_bits = 5;
-	ds->br.cache_buffer = 0;
-	ds->br.cache_avail = 0;
-
-	if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16)
-	    != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	ds->lt.len_bits = 9;
-	if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16)
-	    != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	ds->error = 0;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Release LZHUF decoder.
- */
-static void
-lzh_decode_free(struct lzh_stream *strm)
-{
-
-	if (strm->ds == NULL)
-		return;
-	free(strm->ds->w_buff);
-	lzh_huffman_free(&(strm->ds->lt));
-	lzh_huffman_free(&(strm->ds->pt));
-	free(strm->ds);
-	strm->ds = NULL;
-}
-
-/*
- * Bit stream reader.
- */
-/* Check that the cache buffer has enough bits. */
-#define lzh_br_has(br, n)	((br)->cache_avail >= n)
-/* Get compressed data by bit. */
-#define lzh_br_bits(br, n)				\
-	(((uint16_t)((br)->cache_buffer >>		\
-		((br)->cache_avail - (n)))) & cache_masks[n])
-#define lzh_br_bits_forced(br, n)			\
-	(((uint16_t)((br)->cache_buffer <<		\
-		((n) - (br)->cache_avail))) & cache_masks[n])
-/* Read ahead to make sure the cache buffer has enough compressed data we
- * will use.
- *  True  : completed, there is enough data in the cache buffer.
- *  False : we met that strm->next_in is empty, we have to get following
- *          bytes. */
-#define lzh_br_read_ahead_0(strm, br, n)	\
-	(lzh_br_has(br, (n)) || lzh_br_fillup(strm, br))
-/*  True  : the cache buffer has some bits as much as we need.
- *  False : there are no enough bits in the cache buffer to be used,
- *          we have to get following bytes if we could. */
-#define lzh_br_read_ahead(strm, br, n)	\
-	(lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n)))
-
-/* Notify how many bits we consumed. */
-#define lzh_br_consume(br, n)	((br)->cache_avail -= (n))
-#define lzh_br_unconsume(br, n)	((br)->cache_avail += (n))
-
-static const uint16_t cache_masks[] = {
-	0x0000, 0x0001, 0x0003, 0x0007,
-	0x000F, 0x001F, 0x003F, 0x007F,
-	0x00FF, 0x01FF, 0x03FF, 0x07FF,
-	0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
-};
-
-/*
- * Shift away used bits in the cache data and fill it up with following bits.
- * Call this when cache buffer does not have enough bits you need.
- *
- * Returns 1 if the cache buffer is full.
- * Returns 0 if the cache buffer is not full; input buffer is empty.
- */
-static int
-lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br)
-{
-	int n = CACHE_BITS - br->cache_avail;
-
-	for (;;) {
-		const int x = n >> 3;
-		if (strm->avail_in >= x) {
-			switch (x) {
-			case 8:
-				br->cache_buffer =
-				    ((uint64_t)strm->next_in[0]) << 56 |
-				    ((uint64_t)strm->next_in[1]) << 48 |
-				    ((uint64_t)strm->next_in[2]) << 40 |
-				    ((uint64_t)strm->next_in[3]) << 32 |
-				    ((uint32_t)strm->next_in[4]) << 24 |
-				    ((uint32_t)strm->next_in[5]) << 16 |
-				    ((uint32_t)strm->next_in[6]) << 8 |
-				     (uint32_t)strm->next_in[7];
-				strm->next_in += 8;
-				strm->avail_in -= 8;
-				br->cache_avail += 8 * 8;
-				return (1);
-			case 7:
-				br->cache_buffer =
-		 		   (br->cache_buffer << 56) |
-				    ((uint64_t)strm->next_in[0]) << 48 |
-				    ((uint64_t)strm->next_in[1]) << 40 |
-				    ((uint64_t)strm->next_in[2]) << 32 |
-				    ((uint64_t)strm->next_in[3]) << 24 |
-				    ((uint64_t)strm->next_in[4]) << 16 |
-				    ((uint64_t)strm->next_in[5]) << 8 |
-				     (uint64_t)strm->next_in[6];
-				strm->next_in += 7;
-				strm->avail_in -= 7;
-				br->cache_avail += 7 * 8;
-				return (1);
-			case 6:
-				br->cache_buffer =
-		 		   (br->cache_buffer << 48) |
-				    ((uint64_t)strm->next_in[0]) << 40 |
-				    ((uint64_t)strm->next_in[1]) << 32 |
-				    ((uint64_t)strm->next_in[2]) << 24 |
-				    ((uint64_t)strm->next_in[3]) << 16 |
-				    ((uint64_t)strm->next_in[4]) << 8 |
-				     (uint64_t)strm->next_in[5];
-				strm->next_in += 6;
-				strm->avail_in -= 6;
-				br->cache_avail += 6 * 8;
-				return (1);
-			case 0:
-				/* We have enough compressed data in
-				 * the cache buffer.*/
-				return (1);
-			default:
-				break;
-			}
-		}
-		if (strm->avail_in == 0) {
-			/* There is not enough compressed data to fill up the
-			 * cache buffer. */
-			return (0);
-		}
-		br->cache_buffer =
-		   (br->cache_buffer << 8) | *strm->next_in++;
-		strm->avail_in--;
-		br->cache_avail += 8;
-		n -= 8;
-	}
-}
-
-/*
- * Decode LZHUF.
- *
- * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty.
- *    Please set available buffer and call this function again.
- * 2. Returns ARCHIVE_EOF if decompression has been completed.
- * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data
- *    is broken or you do not set 'last' flag properly.
- * 4. 'last' flag is very important, you must set 1 to the flag if there
- *    is no input data. The lha compressed data format does not provide how
- *    to know the compressed data is really finished.
- *    Note: lha command utility check if the total size of output bytes is
- *    reached the uncompressed size recorded in its header. it does not mind
- *    that the decoding process is properly finished.
- *    GNU ZIP can decompress another compressed file made by SCO LZH compress.
- *    it handles EOF as null to fill read buffer with zero until the decoding
- *    process meet 2 bytes of zeros at reading a size of a next chunk, so the
- *    zeros are treated as the mark of the end of the data although the zeros
- *    is dummy, not the file data.
- */
-static int	lzh_read_blocks(struct lzh_stream *, int);
-static int	lzh_decode_blocks(struct lzh_stream *, int);
-#define ST_RD_BLOCK		0
-#define ST_RD_PT_1		1
-#define ST_RD_PT_2		2
-#define ST_RD_PT_3		3
-#define ST_RD_PT_4		4
-#define ST_RD_LITERAL_1		5
-#define ST_RD_LITERAL_2		6
-#define ST_RD_LITERAL_3		7
-#define ST_RD_POS_DATA_1	8
-#define ST_GET_LITERAL		9
-#define ST_GET_POS_1		10
-#define ST_GET_POS_2		11
-#define ST_COPY_DATA		12
-
-static int
-lzh_decode(struct lzh_stream *strm, int last)
-{
-	struct lzh_dec *ds = strm->ds;
-	int avail_in;
-	int r;
-
-	if (ds->error)
-		return (ds->error);
-
-	avail_in = strm->avail_in;
-	do {
-		if (ds->state < ST_GET_LITERAL)
-			r = lzh_read_blocks(strm, last);
-		else
-			r = lzh_decode_blocks(strm, last);
-	} while (r == 100);
-	strm->total_in += avail_in - strm->avail_in;
-	return (r);
-}
-
-static void
-lzh_emit_window(struct lzh_stream *strm, size_t s)
-{
-	strm->ref_ptr = strm->ds->w_buff;
-	strm->avail_out = (int)s;
-	strm->total_out += s;
-}
-
-static int
-lzh_read_blocks(struct lzh_stream *strm, int last)
-{
-	struct lzh_dec *ds = strm->ds;
-	struct lzh_br *br = &(ds->br);
-	int c = 0, i;
-	unsigned rbits;
-
-	for (;;) {
-		switch (ds->state) {
-		case ST_RD_BLOCK:
-			/*
-			 * Read a block number indicates how many blocks
-			 * we will handle. The block is composed of a
-			 * literal and a match, sometimes a literal only
-			 * in particular, there are no reference data at
-			 * the beginning of the decompression.
-			 */
-			if (!lzh_br_read_ahead_0(strm, br, 16)) {
-				if (!last)
-					/* We need following data. */
-					return (ARCHIVE_OK);
-				if (lzh_br_has(br, 8)) {
-					/*
-					 * It seems there are extra bits.
-					 *  1. Compressed data is broken.
-					 *  2. `last' flag does not properly
-					 *     set.
-					 */
-					goto failed;
-				}
-				if (ds->w_pos > 0) {
-					lzh_emit_window(strm, ds->w_pos);
-					ds->w_pos = 0;
-					return (ARCHIVE_OK);
-				}
-				/* End of compressed data; we have completely
-				 * handled all compressed data. */
-				return (ARCHIVE_EOF);
-			}
-			ds->blocks_avail = lzh_br_bits(br, 16);
-			if (ds->blocks_avail == 0)
-				goto failed;
-			lzh_br_consume(br, 16);
-			/*
-			 * Read a literal table compressed in huffman
-			 * coding.
-			 */
-			ds->pt.len_size = ds->literal_pt_len_size;
-			ds->pt.len_bits = ds->literal_pt_len_bits;
-			ds->reading_position = 0;
-			/* FALL THROUGH */
-		case ST_RD_PT_1:
-			/* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are
-			 * used in reading both a literal table and a
-			 * position table. */
-			if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) {
-				if (last)
-					goto failed;/* Truncated data. */
-				ds->state = ST_RD_PT_1;
-				return (ARCHIVE_OK);
-			}
-			ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits);
-			lzh_br_consume(br, ds->pt.len_bits);
-			/* FALL THROUGH */
-		case ST_RD_PT_2:
-			if (ds->pt.len_avail == 0) {
-				/* There is no bitlen. */
-				if (!lzh_br_read_ahead(strm, br,
-				    ds->pt.len_bits)) {
-					if (last)
-						goto failed;/* Truncated data.*/
-					ds->state = ST_RD_PT_2;
-					return (ARCHIVE_OK);
-				}
-				if (!lzh_make_fake_table(&(ds->pt),
-				    lzh_br_bits(br, ds->pt.len_bits)))
-					goto failed;/* Invalid data. */
-				lzh_br_consume(br, ds->pt.len_bits);
-				if (ds->reading_position)
-					ds->state = ST_GET_LITERAL;
-				else
-					ds->state = ST_RD_LITERAL_1;
-				break;
-			} else if (ds->pt.len_avail > ds->pt.len_size)
-				goto failed;/* Invalid data. */
-			ds->loop = 0;
-			memset(ds->pt.freq, 0, sizeof(ds->pt.freq));
-			if (ds->pt.len_avail < 3 ||
-			    ds->pt.len_size == ds->pos_pt_len_size) {
-				ds->state = ST_RD_PT_4;
-				break;
-			}
-			/* FALL THROUGH */
-		case ST_RD_PT_3:
-			ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3);
-			if (ds->loop < 3) {
-				if (ds->loop < 0 || last)
-					goto failed;/* Invalid data. */
-				/* Not completed, get following data. */
-				ds->state = ST_RD_PT_3;
-				return (ARCHIVE_OK);
-			}
-			/* There are some null in bitlen of the literal. */
-			if (!lzh_br_read_ahead(strm, br, 2)) {
-				if (last)
-					goto failed;/* Truncated data. */
-				ds->state = ST_RD_PT_3;
-				return (ARCHIVE_OK);
-			}
-			c = lzh_br_bits(br, 2);
-			lzh_br_consume(br, 2);
-			if (c > ds->pt.len_avail - 3)
-				goto failed;/* Invalid data. */
-			for (i = 3; c-- > 0 ;)
-				ds->pt.bitlen[i++] = 0;
-			ds->loop = i;
-			/* FALL THROUGH */
-		case ST_RD_PT_4:
-			ds->loop = lzh_read_pt_bitlen(strm, ds->loop,
-			    ds->pt.len_avail);
-			if (ds->loop < ds->pt.len_avail) {
-				if (ds->loop < 0 || last)
-					goto failed;/* Invalid data. */
-				/* Not completed, get following data. */
-				ds->state = ST_RD_PT_4;
-				return (ARCHIVE_OK);
-			}
-			if (!lzh_make_huffman_table(&(ds->pt)))
-				goto failed;/* Invalid data */
-			if (ds->reading_position) {
-				ds->state = ST_GET_LITERAL;
-				break;
-			}
-			/* FALL THROUGH */
-		case ST_RD_LITERAL_1:
-			if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) {
-				if (last)
-					goto failed;/* Truncated data. */
-				ds->state = ST_RD_LITERAL_1;
-				return (ARCHIVE_OK);
-			}
-			ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits);
-			lzh_br_consume(br, ds->lt.len_bits);
-			/* FALL THROUGH */
-		case ST_RD_LITERAL_2:
-			if (ds->lt.len_avail == 0) {
-				/* There is no bitlen. */
-				if (!lzh_br_read_ahead(strm, br,
-				    ds->lt.len_bits)) {
-					if (last)
-						goto failed;/* Truncated data.*/
-					ds->state = ST_RD_LITERAL_2;
-					return (ARCHIVE_OK);
-				}
-				if (!lzh_make_fake_table(&(ds->lt),
-				    lzh_br_bits(br, ds->lt.len_bits)))
-					goto failed;/* Invalid data */
-				lzh_br_consume(br, ds->lt.len_bits);
-				ds->state = ST_RD_POS_DATA_1;
-				break;
-			} else if (ds->lt.len_avail > ds->lt.len_size)
-				goto failed;/* Invalid data */
-			ds->loop = 0;
-			memset(ds->lt.freq, 0, sizeof(ds->lt.freq));
-			/* FALL THROUGH */
-		case ST_RD_LITERAL_3:
-			i = ds->loop;
-			while (i < ds->lt.len_avail) {
-				if (!lzh_br_read_ahead(strm, br,
-				    ds->pt.max_bits)) {
-					if (last)
-						goto failed;/* Truncated data.*/
-					ds->loop = i;
-					ds->state = ST_RD_LITERAL_3;
-					return (ARCHIVE_OK);
-				}
-				rbits = lzh_br_bits(br, ds->pt.max_bits);
-				c = lzh_decode_huffman(&(ds->pt), rbits);
-				if (c > 2) {
-					/* Note: 'c' will never be more than
-					 * eighteen since it's limited by
-					 * PT_BITLEN_SIZE, which is being set
-					 * to ds->pt.len_size through
-					 * ds->literal_pt_len_size. */
-					lzh_br_consume(br, ds->pt.bitlen[c]);
-					c -= 2;
-					ds->lt.freq[c]++;
-					ds->lt.bitlen[i++] = c;
-				} else if (c == 0) {
-					lzh_br_consume(br, ds->pt.bitlen[c]);
-					ds->lt.bitlen[i++] = 0;
-				} else {
-					/* c == 1 or c == 2 */
-					int n = (c == 1)?4:9;
-					if (!lzh_br_read_ahead(strm, br,
-					     ds->pt.bitlen[c] + n)) {
-						if (last) /* Truncated data. */
-							goto failed;
-						ds->loop = i;
-						ds->state = ST_RD_LITERAL_3;
-						return (ARCHIVE_OK);
-					}
-					lzh_br_consume(br, ds->pt.bitlen[c]);
-					c = lzh_br_bits(br, n);
-					lzh_br_consume(br, n);
-					c += (n == 4)?3:20;
-					if (i + c > ds->lt.len_avail)
-						goto failed;/* Invalid data */
-					memset(&(ds->lt.bitlen[i]), 0, c);
-					i += c;
-				}
-			}
-			if (i > ds->lt.len_avail ||
-			    !lzh_make_huffman_table(&(ds->lt)))
-				goto failed;/* Invalid data */
-			/* FALL THROUGH */
-		case ST_RD_POS_DATA_1:
-			/*
-			 * Read a position table compressed in huffman
-			 * coding.
-			 */
-			ds->pt.len_size = ds->pos_pt_len_size;
-			ds->pt.len_bits = ds->pos_pt_len_bits;
-			ds->reading_position = 1;
-			ds->state = ST_RD_PT_1;
-			break;
-		case ST_GET_LITERAL:
-			return (100);
-		}
-	}
-failed:
-	return (ds->error = ARCHIVE_FAILED);
-}
-
-static int
-lzh_decode_blocks(struct lzh_stream *strm, int last)
-{
-	struct lzh_dec *ds = strm->ds;
-	struct lzh_br bre = ds->br;
-	struct huffman *lt = &(ds->lt);
-	struct huffman *pt = &(ds->pt);
-	unsigned char *w_buff = ds->w_buff;
-	unsigned char *lt_bitlen = lt->bitlen;
-	unsigned char *pt_bitlen = pt->bitlen;
-	int blocks_avail = ds->blocks_avail, c = 0;
-	int copy_len = ds->copy_len, copy_pos = ds->copy_pos;
-	int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size;
-	int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits;
-	int state = ds->state;
-
-	for (;;) {
-		switch (state) {
-		case ST_GET_LITERAL:
-			for (;;) {
-				if (blocks_avail == 0) {
-					/* We have decoded all blocks.
-					 * Let's handle next blocks. */
-					ds->state = ST_RD_BLOCK;
-					ds->br = bre;
-					ds->blocks_avail = 0;
-					ds->w_pos = w_pos;
-					ds->copy_pos = 0;
-					return (100);
-				}
-
-				/* lzh_br_read_ahead() always try to fill the
-				 * cache buffer up. In specific situation we
-				 * are close to the end of the data, the cache
-				 * buffer will not be full and thus we have to
-				 * determine if the cache buffer has some bits
-				 * as much as we need after lzh_br_read_ahead()
-				 * failed. */
-				if (!lzh_br_read_ahead(strm, &bre,
-				    lt_max_bits)) {
-					if (!last)
-						goto next_data;
-					/* Remaining bits are less than
-					 * maximum bits(lt.max_bits) but maybe
-					 * it still remains as much as we need,
-					 * so we should try to use it with
-					 * dummy bits. */
-					c = lzh_decode_huffman(lt,
-					      lzh_br_bits_forced(&bre,
-					        lt_max_bits));
-					lzh_br_consume(&bre, lt_bitlen[c]);
-					if (!lzh_br_has(&bre, 0))
-						goto failed;/* Over read. */
-				} else {
-					c = lzh_decode_huffman(lt,
-					      lzh_br_bits(&bre, lt_max_bits));
-					lzh_br_consume(&bre, lt_bitlen[c]);
-				}
-				blocks_avail--;
-				if (c > UCHAR_MAX)
-					/* Current block is a match data. */
-					break;
-				/*
-				 * 'c' is exactly a literal code.
-				 */
-				/* Save a decoded code to reference it
-				 * afterward. */
-				w_buff[w_pos] = c;
-				if (++w_pos >= w_size) {
-					w_pos = 0;
-					lzh_emit_window(strm, w_size);
-					goto next_data;
-				}
-			}
-			/* 'c' is the length of a match pattern we have
-			 * already extracted, which has be stored in
-			 * window(ds->w_buff). */
-			copy_len = c - (UCHAR_MAX + 1) + MINMATCH;
-			/* FALL THROUGH */
-		case ST_GET_POS_1:
-			/*
-			 * Get a reference position. 
-			 */
-			if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) {
-				if (!last) {
-					state = ST_GET_POS_1;
-					ds->copy_len = copy_len;
-					goto next_data;
-				}
-				copy_pos = lzh_decode_huffman(pt,
-				    lzh_br_bits_forced(&bre, pt_max_bits));
-				lzh_br_consume(&bre, pt_bitlen[copy_pos]);
-				if (!lzh_br_has(&bre, 0))
-					goto failed;/* Over read. */
-			} else {
-				copy_pos = lzh_decode_huffman(pt,
-				    lzh_br_bits(&bre, pt_max_bits));
-				lzh_br_consume(&bre, pt_bitlen[copy_pos]);
-			}
-			/* FALL THROUGH */
-		case ST_GET_POS_2:
-			if (copy_pos > 1) {
-				/* We need an additional adjustment number to
-				 * the position. */
-				int p = copy_pos - 1;
-				if (!lzh_br_read_ahead(strm, &bre, p)) {
-					if (last)
-						goto failed;/* Truncated data.*/
-					state = ST_GET_POS_2;
-					ds->copy_len = copy_len;
-					ds->copy_pos = copy_pos;
-					goto next_data;
-				}
-				copy_pos = (1 << p) + lzh_br_bits(&bre, p);
-				lzh_br_consume(&bre, p);
-			}
-			/* The position is actually a distance from the last
-			 * code we had extracted and thus we have to convert
-			 * it to a position of the window. */
-			copy_pos = (w_pos - copy_pos - 1) & w_mask;
-			/* FALL THROUGH */
-		case ST_COPY_DATA:
-			/*
-			 * Copy `copy_len' bytes as extracted data from
-			 * the window into the output buffer.
-			 */
-			for (;;) {
-				int l;
-
-				l = copy_len;
-				if (copy_pos > w_pos) {
-					if (l > w_size - copy_pos)
-						l = w_size - copy_pos;
-				} else {
-					if (l > w_size - w_pos)
-						l = w_size - w_pos;
-				}
-				if ((copy_pos + l < w_pos)
-				    || (w_pos + l < copy_pos)) {
-					/* No overlap. */
-					memcpy(w_buff + w_pos,
-					    w_buff + copy_pos, l);
-				} else {
-					const unsigned char *s;
-					unsigned char *d;
-					int li;
-
-					d = w_buff + w_pos;
-					s = w_buff + copy_pos;
-					for (li = 0; li < l-1;) {
-						d[li] = s[li];li++;
-						d[li] = s[li];li++;
-					}
-					if (li < l)
-						d[li] = s[li];
-				}
-				w_pos += l;
-				if (w_pos == w_size) {
-					w_pos = 0;
-					lzh_emit_window(strm, w_size);
-					if (copy_len <= l)
-						state = ST_GET_LITERAL;
-					else {
-						state = ST_COPY_DATA;
-						ds->copy_len = copy_len - l;
-						ds->copy_pos =
-						    (copy_pos + l) & w_mask;
-					}
-					goto next_data;
-				}
-				if (copy_len <= l)
-					/* A copy of current pattern ended. */
-					break;
-				copy_len -= l;
-				copy_pos = (copy_pos + l) & w_mask;
-			}
-			state = ST_GET_LITERAL;
-			break;
-		}
-	}
-failed:
-	return (ds->error = ARCHIVE_FAILED);
-next_data:
-	ds->br = bre;
-	ds->blocks_avail = blocks_avail;
-	ds->state = state;
-	ds->w_pos = w_pos;
-	return (ARCHIVE_OK);
-}
-
-static int
-lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
-{
-	int bits;
-
-	if (hf->bitlen == NULL) {
-		hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0]));
-		if (hf->bitlen == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	if (hf->tbl == NULL) {
-		if (tbl_bits < HTBL_BITS)
-			bits = tbl_bits;
-		else
-			bits = HTBL_BITS;
-		hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
-		if (hf->tbl == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	if (hf->tree == NULL && tbl_bits > HTBL_BITS) {
-		hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4);
-		hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0]));
-		if (hf->tree == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	hf->len_size = (int)len_size;
-	hf->tbl_bits = tbl_bits;
-	return (ARCHIVE_OK);
-}
-
-static void
-lzh_huffman_free(struct huffman *hf)
-{
-	free(hf->bitlen);
-	free(hf->tbl);
-	free(hf->tree);
-}
-
-static const char bitlen_tbl[0x400] = {
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-	10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-	10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-	10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-	10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-	11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-	11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-	12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-	13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16,  0
-};
-static int
-lzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end)
-{
-	struct lzh_dec *ds = strm->ds;
-	struct lzh_br *br = &(ds->br);
-	int c, i;
-
-	for (i = start; i < end; ) {
-		/*
-		 *  bit pattern     the number we need
-		 *     000           ->  0
-		 *     001           ->  1
-		 *     010           ->  2
-		 *     ...
-		 *     110           ->  6
-		 *     1110          ->  7
-		 *     11110         ->  8
-		 *     ...
-		 *     1111111111110 ->  16
-		 */
-		if (!lzh_br_read_ahead(strm, br, 3))
-			return (i);
-		if ((c = lzh_br_bits(br, 3)) == 7) {
-			if (!lzh_br_read_ahead(strm, br, 13))
-				return (i);
-			c = bitlen_tbl[lzh_br_bits(br, 13) & 0x3FF];
-			if (c)
-				lzh_br_consume(br, c - 3);
-			else
-				return (-1);/* Invalid data. */
-		} else
-			lzh_br_consume(br, 3);
-		ds->pt.bitlen[i++] = c;
-		ds->pt.freq[c]++;
-	}
-	return (i);
-}
-
-static int
-lzh_make_fake_table(struct huffman *hf, uint16_t c)
-{
-	if (c >= hf->len_size)
-		return (0);
-	hf->tbl[0] = c;
-	hf->max_bits = 0;
-	hf->shift_bits = 0;
-	hf->bitlen[hf->tbl[0]] = 0;
-	return (1);
-}
-
-/*
- * Make a huffman coding table.
- */
-static int
-lzh_make_huffman_table(struct huffman *hf)
-{
-	uint16_t *tbl;
-	const unsigned char *bitlen;
-	int bitptn[17], weight[17];
-	int i, maxbits = 0, ptn, tbl_size, w;
-	int diffbits, len_avail;
-
-	/*
-	 * Initialize bit patterns.
-	 */
-	ptn = 0;
-	for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) {
-		bitptn[i] = ptn;
-		weight[i] = w;
-		if (hf->freq[i]) {
-			ptn += hf->freq[i] * w;
-			maxbits = i;
-		}
-	}
-	if (ptn != 0x10000 || maxbits > hf->tbl_bits)
-		return (0);/* Invalid */
-
-	hf->max_bits = maxbits;
-
-	/*
-	 * Cut out extra bits which we won't house in the table.
-	 * This preparation reduces the same calculation in the for-loop
-	 * making the table.
-	 */
-	if (maxbits < 16) {
-		int ebits = 16 - maxbits;
-		for (i = 1; i <= maxbits; i++) {
-			bitptn[i] >>= ebits;
-			weight[i] >>= ebits;
-		}
-	}
-	if (maxbits > HTBL_BITS) {
-		unsigned htbl_max;
-		uint16_t *p;
-
-		diffbits = maxbits - HTBL_BITS;
-		for (i = 1; i <= HTBL_BITS; i++) {
-			bitptn[i] >>= diffbits;
-			weight[i] >>= diffbits;
-		}
-		htbl_max = bitptn[HTBL_BITS] +
-		    weight[HTBL_BITS] * hf->freq[HTBL_BITS];
-		p = &(hf->tbl[htbl_max]);
-		while (p < &hf->tbl[1U<<HTBL_BITS])
-			*p++ = 0;
-	} else
-		diffbits = 0;
-	hf->shift_bits = diffbits;
-
-	/*
-	 * Make the table.
-	 */
-	tbl_size = 1 << HTBL_BITS;
-	tbl = hf->tbl;
-	bitlen = hf->bitlen;
-	len_avail = hf->len_avail;
-	hf->tree_used = 0;
-	for (i = 0; i < len_avail; i++) {
-		uint16_t *p;
-		int len, cnt;
-		uint16_t bit;
-		int extlen;
-		struct htree_t *ht;
-
-		if (bitlen[i] == 0)
-			continue;
-		/* Get a bit pattern */
-		len = bitlen[i];
-		ptn = bitptn[len];
-		cnt = weight[len];
-		if (len <= HTBL_BITS) {
-			/* Calculate next bit pattern */
-			if ((bitptn[len] = ptn + cnt) > tbl_size)
-				return (0);/* Invalid */
-			/* Update the table */
-			p = &(tbl[ptn]);
-			if (cnt > 7) {
-				uint16_t *pc;
-
-				cnt -= 8;
-				pc = &p[cnt];
-				pc[0] = (uint16_t)i;
-				pc[1] = (uint16_t)i;
-				pc[2] = (uint16_t)i;
-				pc[3] = (uint16_t)i;
-				pc[4] = (uint16_t)i;
-				pc[5] = (uint16_t)i;
-				pc[6] = (uint16_t)i;
-				pc[7] = (uint16_t)i;
-				if (cnt > 7) {
-					cnt -= 8;
-					memcpy(&p[cnt], pc,
-						8 * sizeof(uint16_t));
-					pc = &p[cnt];
-					while (cnt > 15) {
-						cnt -= 16;
-						memcpy(&p[cnt], pc,
-							16 * sizeof(uint16_t));
-					}
-				}
-				if (cnt)
-					memcpy(p, pc, cnt * sizeof(uint16_t));
-			} else {
-				while (cnt > 1) {
-					p[--cnt] = (uint16_t)i;
-					p[--cnt] = (uint16_t)i;
-				}
-				if (cnt)
-					p[--cnt] = (uint16_t)i;
-			}
-			continue;
-		}
-
-		/*
-		 * A bit length is too big to be housed to a direct table,
-		 * so we use a tree model for its extra bits.
-		 */
-		bitptn[len] = ptn + cnt;
-		bit = 1U << (diffbits -1);
-		extlen = len - HTBL_BITS;
-		
-		p = &(tbl[ptn >> diffbits]);
-		if (*p == 0) {
-			*p = len_avail + hf->tree_used;
-			ht = &(hf->tree[hf->tree_used++]);
-			if (hf->tree_used > hf->tree_avail)
-				return (0);/* Invalid */
-			ht->left = 0;
-			ht->right = 0;
-		} else {
-			if (*p < len_avail ||
-			    *p >= (len_avail + hf->tree_used))
-				return (0);/* Invalid */
-			ht = &(hf->tree[*p - len_avail]);
-		}
-		while (--extlen > 0) {
-			if (ptn & bit) {
-				if (ht->left < len_avail) {
-					ht->left = len_avail + hf->tree_used;
-					ht = &(hf->tree[hf->tree_used++]);
-					if (hf->tree_used > hf->tree_avail)
-						return (0);/* Invalid */
-					ht->left = 0;
-					ht->right = 0;
-				} else {
-					ht = &(hf->tree[ht->left - len_avail]);
-				}
-			} else {
-				if (ht->right < len_avail) {
-					ht->right = len_avail + hf->tree_used;
-					ht = &(hf->tree[hf->tree_used++]);
-					if (hf->tree_used > hf->tree_avail)
-						return (0);/* Invalid */
-					ht->left = 0;
-					ht->right = 0;
-				} else {
-					ht = &(hf->tree[ht->right - len_avail]);
-				}
-			}
-			bit >>= 1;
-		}
-		if (ptn & bit) {
-			if (ht->left != 0)
-				return (0);/* Invalid */
-			ht->left = (uint16_t)i;
-		} else {
-			if (ht->right != 0)
-				return (0);/* Invalid */
-			ht->right = (uint16_t)i;
-		}
-	}
-	return (1);
-}
-
-static int
-lzh_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c)
-{
-	struct htree_t *ht;
-	int extlen;
-
-	ht = hf->tree;
-	extlen = hf->shift_bits;
-	while (c >= hf->len_avail) {
-		c -= hf->len_avail;
-		if (extlen-- <= 0 || c >= hf->tree_used)
-			return (0);
-		if (rbits & (1U << extlen))
-			c = ht[c].left;
-		else
-			c = ht[c].right;
-	}
-	return (c);
-}
-
-static inline int
-lzh_decode_huffman(struct huffman *hf, unsigned rbits)
-{
-	int c;
-	/*
-	 * At first search an index table for a bit pattern.
-	 * If it fails, search a huffman tree for.
-	 */
-	c = hf->tbl[rbits >> hf->shift_bits];
-	if (c < hf->len_avail || hf->len_avail == 0)
-		return (c);
-	/* This bit pattern needs to be found out at a huffman tree. */
-	return (lzh_decode_huffman_tree(hf, rbits, c));
-}
-
diff --git a/c/archive_read_support_format_mtree.c b/c/archive_read_support_format_mtree.c
deleted file mode 100644
--- a/c/archive_read_support_format_mtree.c
+++ /dev/null
@@ -1,2156 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2008 Joerg Sonnenberger
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 201165 2009-12-29 05:52:13Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <stddef.h>
-/* #include <stdint.h> */ /* See archive_platform.h */
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_private.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_read_private.h"
-#include "archive_string.h"
-#include "archive_pack_dev.h"
-
-#ifndef O_BINARY
-#define	O_BINARY 0
-#endif
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-#define	MTREE_HAS_DEVICE	0x0001
-#define	MTREE_HAS_FFLAGS	0x0002
-#define	MTREE_HAS_GID		0x0004
-#define	MTREE_HAS_GNAME		0x0008
-#define	MTREE_HAS_MTIME		0x0010
-#define	MTREE_HAS_NLINK		0x0020
-#define	MTREE_HAS_PERM		0x0040
-#define	MTREE_HAS_SIZE		0x0080
-#define	MTREE_HAS_TYPE		0x0100
-#define	MTREE_HAS_UID		0x0200
-#define	MTREE_HAS_UNAME		0x0400
-
-#define	MTREE_HAS_OPTIONAL	0x0800
-#define	MTREE_HAS_NOCHANGE	0x1000 /* FreeBSD specific */
-
-#define	MAX_LINE_LEN		(1024 * 1024)
-
-struct mtree_option {
-	struct mtree_option *next;
-	char *value;
-};
-
-struct mtree_entry {
-	struct archive_rb_node rbnode;
-	struct mtree_entry *next_dup;
-	struct mtree_entry *next;
-	struct mtree_option *options;
-	char *name;
-	char full;
-	char used;
-};
-
-struct mtree {
-	struct archive_string	 line;
-	size_t			 buffsize;
-	char			*buff;
-	int64_t			 offset;
-	int			 fd;
-	int			 archive_format;
-	const char		*archive_format_name;
-	struct mtree_entry	*entries;
-	struct mtree_entry	*this_entry;
-	struct archive_rb_tree	 entry_rbtree;
-	struct archive_string	 current_dir;
-	struct archive_string	 contents_name;
-
-	struct archive_entry_linkresolver *resolver;
-	struct archive_rb_tree rbtree;
-
-	int64_t			 cur_size;
-	char checkfs;
-};
-
-static int	bid_keycmp(const char *, const char *, ssize_t);
-static int	cleanup(struct archive_read *);
-static int	detect_form(struct archive_read *, int *);
-static int	mtree_bid(struct archive_read *, int);
-static int	parse_file(struct archive_read *, struct archive_entry *,
-		    struct mtree *, struct mtree_entry *, int *);
-static void	parse_escapes(char *, struct mtree_entry *);
-static int	parse_line(struct archive_read *, struct archive_entry *,
-		    struct mtree *, struct mtree_entry *, int *);
-static int	parse_keyword(struct archive_read *, struct mtree *,
-		    struct archive_entry *, struct mtree_option *, int *);
-static int	read_data(struct archive_read *a,
-		    const void **buff, size_t *size, int64_t *offset);
-static ssize_t	readline(struct archive_read *, struct mtree *, char **, ssize_t);
-static int	skip(struct archive_read *a);
-static int	read_header(struct archive_read *,
-		    struct archive_entry *);
-static int64_t	mtree_atol(char **, int base);
-#ifndef HAVE_STRNLEN
-static size_t	mtree_strnlen(const char *, size_t);
-#endif
-
-/*
- * There's no standard for TIME_T_MAX/TIME_T_MIN.  So we compute them
- * here.  TODO: Move this to configure time, but be careful
- * about cross-compile environments.
- */
-static int64_t
-get_time_t_max(void)
-{
-#if defined(TIME_T_MAX)
-	return TIME_T_MAX;
-#else
-	/* ISO C allows time_t to be a floating-point type,
-	   but POSIX requires an integer type.  The following
-	   should work on any system that follows the POSIX
-	   conventions. */
-	if (((time_t)0) < ((time_t)-1)) {
-		/* Time_t is unsigned */
-		return (~(time_t)0);
-	} else {
-		/* Time_t is signed. */
-		/* Assume it's the same as int64_t or int32_t */
-		if (sizeof(time_t) == sizeof(int64_t)) {
-			return (time_t)INT64_MAX;
-		} else {
-			return (time_t)INT32_MAX;
-		}
-	}
-#endif
-}
-
-static int64_t
-get_time_t_min(void)
-{
-#if defined(TIME_T_MIN)
-	return TIME_T_MIN;
-#else
-	if (((time_t)0) < ((time_t)-1)) {
-		/* Time_t is unsigned */
-		return (time_t)0;
-	} else {
-		/* Time_t is signed. */
-		if (sizeof(time_t) == sizeof(int64_t)) {
-			return (time_t)INT64_MIN;
-		} else {
-			return (time_t)INT32_MIN;
-		}
-	}
-#endif
-}
-
-#ifdef HAVE_STRNLEN
-#define mtree_strnlen(a,b) strnlen(a,b)
-#else
-static size_t
-mtree_strnlen(const char *p, size_t maxlen)
-{
-	size_t i;
-
-	for (i = 0; i <= maxlen; i++) {
-		if (p[i] == 0)
-			break;
-	}
-	if (i > maxlen)
-		return (-1);/* invalid */
-	return (i);
-}
-#endif
-
-static int
-archive_read_format_mtree_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct mtree *mtree;
-
-	mtree = (struct mtree *)(a->format->data);
-	if (strcmp(key, "checkfs")  == 0) {
-		/* Allows to read information missing from the mtree from the file system */
-		if (val == NULL || val[0] == 0) {
-			mtree->checkfs = 0;
-		} else {
-			mtree->checkfs = 1;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static void
-free_options(struct mtree_option *head)
-{
-	struct mtree_option *next;
-
-	for (; head != NULL; head = next) {
-		next = head->next;
-		free(head->value);
-		free(head);
-	}
-}
-
-static int
-mtree_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
-	const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
-
-	return (strcmp(e1->name, e2->name));
-}
-
-static int
-mtree_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct mtree_entry *e = (const struct mtree_entry *)n;
-
-	return (strcmp(e->name, key));
-}
-
-int
-archive_read_support_format_mtree(struct archive *_a)
-{
-	static const struct archive_rb_tree_ops rb_ops = {
-		mtree_cmp_node, mtree_cmp_key,
-	};
-	struct archive_read *a = (struct archive_read *)_a;
-	struct mtree *mtree;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
-
-	mtree = (struct mtree *)calloc(1, sizeof(*mtree));
-	if (mtree == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate mtree data");
-		return (ARCHIVE_FATAL);
-	}
-	mtree->checkfs = 0;
-	mtree->fd = -1;
-
-	__archive_rb_tree_init(&mtree->rbtree, &rb_ops);
-
-	r = __archive_read_register_format(a, mtree, "mtree",
-           mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
-
-	if (r != ARCHIVE_OK)
-		free(mtree);
-	return (ARCHIVE_OK);
-}
-
-static int
-cleanup(struct archive_read *a)
-{
-	struct mtree *mtree;
-	struct mtree_entry *p, *q;
-
-	mtree = (struct mtree *)(a->format->data);
-
-	p = mtree->entries;
-	while (p != NULL) {
-		q = p->next;
-		free(p->name);
-		free_options(p->options);
-		free(p);
-		p = q;
-	}
-	archive_string_free(&mtree->line);
-	archive_string_free(&mtree->current_dir);
-	archive_string_free(&mtree->contents_name);
-	archive_entry_linkresolver_free(mtree->resolver);
-
-	free(mtree->buff);
-	free(mtree);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
-{
-	ssize_t len;
-
-	len = 0;
-	while (len < avail) {
-		switch (*b) {
-		case '\0':/* Non-ascii character or control character. */
-			if (nlsize != NULL)
-				*nlsize = 0;
-			return (-1);
-		case '\r':
-			if (avail-len > 1 && b[1] == '\n') {
-				if (nlsize != NULL)
-					*nlsize = 2;
-				return (len+2);
-			}
-			/* FALL THROUGH */
-		case '\n':
-			if (nlsize != NULL)
-				*nlsize = 1;
-			return (len+1);
-		default:
-			b++;
-			len++;
-			break;
-		}
-	}
-	if (nlsize != NULL)
-		*nlsize = 0;
-	return (avail);
-}
-
-/*
- *  <---------------- ravail --------------------->
- *  <-- diff ------> <---  avail ----------------->
- *                   <---- len ----------->
- * | Previous lines | line being parsed  nl extra |
- *                  ^
- *                  b
- *
- */
-static ssize_t
-next_line(struct archive_read *a,
-    const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
-{
-	ssize_t len;
-	int quit;
-	
-	quit = 0;
-	if (*avail == 0) {
-		*nl = 0;
-		len = 0;
-	} else
-		len = get_line_size(*b, *avail, nl);
-	/*
-	 * Read bytes more while it does not reach the end of line.
-	 */
-	while (*nl == 0 && len == *avail && !quit) {
-		ssize_t diff = *ravail - *avail;
-		size_t nbytes_req = (*ravail+1023) & ~1023U;
-		ssize_t tested;
-
-		/*
-		 * Place an arbitrary limit on the line length.
-		 * mtree is almost free-form input and without line length limits,
-		 * it can consume a lot of memory.
-		 */
-		if (len >= MAX_LINE_LEN)
-			return (-1);
-
-		/* Increase reading bytes if it is not enough to at least
-		 * new two lines. */
-		if (nbytes_req < (size_t)*ravail + 160)
-			nbytes_req <<= 1;
-
-		*b = __archive_read_ahead(a, nbytes_req, avail);
-		if (*b == NULL) {
-			if (*ravail >= *avail)
-				return (0);
-			/* Reading bytes reaches the end of file. */
-			*b = __archive_read_ahead(a, *avail, avail);
-			quit = 1;
-		}
-		*ravail = *avail;
-		*b += diff;
-		*avail -= diff;
-		tested = len;/* Skip some bytes we already determined. */
-		len = get_line_size(*b + len, *avail - len, nl);
-		if (len >= 0)
-			len += tested;
-	}
-	return (len);
-}
-
-/*
- * Compare characters with a mtree keyword.
- * Returns the length of a mtree keyword if matched.
- * Returns 0 if not matched.
- */
-static int
-bid_keycmp(const char *p, const char *key, ssize_t len)
-{
-	int match_len = 0;
-
-	while (len > 0 && *p && *key) {
-		if (*p == *key) {
-			--len;
-			++p;
-			++key;
-			++match_len;
-			continue;
-		}
-		return (0);/* Not match */
-	}
-	if (*key != '\0')
-		return (0);/* Not match */
-
-	/* A following character should be specified characters */
-	if (p[0] == '=' || p[0] == ' ' || p[0] == '\t' ||
-	    p[0] == '\n' || p[0] == '\r' ||
-	   (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r')))
-		return (match_len);
-	return (0);/* Not match */
-}
-
-/*
- * Test whether the characters 'p' has is mtree keyword.
- * Returns the length of a detected keyword.
- * Returns 0 if any keywords were not found.
- */
-static int
-bid_keyword(const char *p,  ssize_t len)
-{
-	static const char * const keys_c[] = {
-		"content", "contents", "cksum", NULL
-	};
-	static const char * const keys_df[] = {
-		"device", "flags", NULL
-	};
-	static const char * const keys_g[] = {
-		"gid", "gname", NULL
-	};
-	static const char * const keys_il[] = {
-		"ignore", "inode", "link", NULL
-	};
-	static const char * const keys_m[] = {
-		"md5", "md5digest", "mode", NULL
-	};
-	static const char * const keys_no[] = {
-		"nlink", "nochange", "optional", NULL
-	};
-	static const char * const keys_r[] = {
-		"resdevice", "rmd160", "rmd160digest", NULL
-	};
-	static const char * const keys_s[] = {
-		"sha1", "sha1digest",
-		"sha256", "sha256digest",
-		"sha384", "sha384digest",
-		"sha512", "sha512digest",
-		"size", NULL
-	};
-	static const char * const keys_t[] = {
-		"tags", "time", "type", NULL
-	};
-	static const char * const keys_u[] = {
-		"uid", "uname",	NULL
-	};
-	const char * const *keys;
-	int i;
-
-	switch (*p) {
-	case 'c': keys = keys_c; break;
-	case 'd': case 'f': keys = keys_df; break;
-	case 'g': keys = keys_g; break;
-	case 'i': case 'l': keys = keys_il; break;
-	case 'm': keys = keys_m; break;
-	case 'n': case 'o': keys = keys_no; break;
-	case 'r': keys = keys_r; break;
-	case 's': keys = keys_s; break;
-	case 't': keys = keys_t; break;
-	case 'u': keys = keys_u; break;
-	default: return (0);/* Unknown key */
-	}
-
-	for (i = 0; keys[i] != NULL; i++) {
-		int l = bid_keycmp(p, keys[i], len);
-		if (l > 0)
-			return (l);
-	}
-	return (0);/* Unknown key */
-}
-
-/*
- * Test whether there is a set of mtree keywords.
- * Returns the number of keyword.
- * Returns -1 if we got incorrect sequence.
- * This function expects a set of "<space characters>keyword=value".
- * When "unset" is specified, expects a set of "<space characters>keyword".
- */
-static int
-bid_keyword_list(const char *p,  ssize_t len, int unset, int last_is_path)
-{
-	int l;
-	int keycnt = 0;
-
-	while (len > 0 && *p) {
-		int blank = 0;
-
-		/* Test whether there are blank characters in the line. */
-		while (len >0 && (*p == ' ' || *p == '\t')) {
-			++p;
-			--len;
-			blank = 1;
-		}
-		if (*p == '\n' || *p == '\r')
-			break;
-		if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
-			break;
-		if (!blank && !last_is_path) /* No blank character. */
-			return (-1);
-		if (last_is_path && len == 0)
-				return (keycnt);
-
-		if (unset) {
-			l = bid_keycmp(p, "all", len);
-			if (l > 0)
-				return (1);
-		}
-		/* Test whether there is a correct key in the line. */
-		l = bid_keyword(p, len);
-		if (l == 0)
-			return (-1);/* Unknown keyword was found. */
-		p += l;
-		len -= l;
-		keycnt++;
-
-		/* Skip value */
-		if (*p == '=') {
-			int value = 0;
-			++p;
-			--len;
-			while (len > 0 && *p != ' ' && *p != '\t') {
-				++p;
-				--len;
-				value = 1;
-			}
-			/* A keyword should have a its value unless
-			 * "/unset" operation. */ 
-			if (!unset && value == 0)
-				return (-1);
-		}
-	}
-	return (keycnt);
-}
-
-static int
-bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
-{
-	int f = 0;
-	static const unsigned char safe_char[256] = {
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
-		/* !"$%&'()*+,-./  EXCLUSION:( )(#) */
-		0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
-		/* 0123456789:;<>?  EXCLUSION:(=) */
-		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
-		/* @ABCDEFGHIJKLMNO */
-		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
-		/* PQRSTUVWXYZ[\]^_  */
-		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
-		/* `abcdefghijklmno */
-		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
-		/* pqrstuvwxyz{|}~ */
-		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-	};
-	ssize_t ll;
-	const char *pp = p;
-	const char * const pp_end = pp + len;
-
-	*last_is_path = 0;
-	/*
-	 * Skip the path-name which is quoted.
-	 */
-	for (;pp < pp_end; ++pp) {
-		if (!safe_char[*(const unsigned char *)pp]) {
-			if (*pp != ' ' && *pp != '\t' && *pp != '\r'
-			    && *pp != '\n')
-				f = 0;
-			break;
-		}
-		f = 1;
-	}
-	ll = pp_end - pp;
-
-	/* If a path-name was not found at the first, try to check
-	 * a mtree format(a.k.a form D) ``NetBSD's mtree -D'' creates,
-	 * which places the path-name at the last. */
-	if (f == 0) {
-		const char *pb = p + len - nl;
-		int name_len = 0;
-		int slash;
-
-		/* The form D accepts only a single line for an entry. */
-		if (pb-2 >= p &&
-		    pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
-			return (-1);
-		if (pb-1 >= p && pb[-1] == '\\')
-			return (-1);
-
-		slash = 0;
-		while (p <= --pb && *pb != ' ' && *pb != '\t') {
-			if (!safe_char[*(const unsigned char *)pb])
-				return (-1);
-			name_len++;
-			/* The pathname should have a slash in this
-			 * format. */
-			if (*pb == '/')
-				slash = 1;
-		}
-		if (name_len == 0 || slash == 0)
-			return (-1);
-		/* If '/' is placed at the first in this field, this is not
-		 * a valid filename. */
-		if (pb[1] == '/')
-			return (-1);
-		ll = len - nl - name_len;
-		pp = p;
-		*last_is_path = 1;
-	}
-
-	return (bid_keyword_list(pp, ll, 0, *last_is_path));
-}
-
-#define MAX_BID_ENTRY	3
-
-static int
-mtree_bid(struct archive_read *a, int best_bid)
-{
-	const char *signature = "#mtree";
-	const char *p;
-
-	(void)best_bid; /* UNUSED */
-
-	/* Now let's look at the actual header and see if it matches. */
-	p = __archive_read_ahead(a, strlen(signature), NULL);
-	if (p == NULL)
-		return (-1);
-
-	if (memcmp(p, signature, strlen(signature)) == 0)
-		return (8 * (int)strlen(signature));
-
-	/*
-	 * There is not a mtree signature. Let's try to detect mtree format.
-	 */
-	return (detect_form(a, NULL));
-}
-
-static int
-detect_form(struct archive_read *a, int *is_form_d)
-{
-	const char *p;
-	ssize_t avail, ravail;
-	ssize_t len, nl;
-	int entry_cnt = 0, multiline = 0;
-	int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
-			* (In this source we call it `form D') . */
-
-	if (is_form_d != NULL)
-		*is_form_d = 0;
-	p = __archive_read_ahead(a, 1, &avail);
-	if (p == NULL)
-		return (-1);
-	ravail = avail;
-	for (;;) {
-		len = next_line(a, &p, &avail, &ravail, &nl);
-		/* The terminal character of the line should be
-		 * a new line character, '\r\n' or '\n'. */
-		if (len <= 0 || nl == 0)
-			break;
-		if (!multiline) {
-			/* Leading whitespace is never significant,
-			 * ignore it. */
-			while (len > 0 && (*p == ' ' || *p == '\t')) {
-				++p;
-				--avail;
-				--len;
-			}
-			/* Skip comment or empty line. */ 
-			if (p[0] == '#' || p[0] == '\n' || p[0] == '\r') {
-				p += len;
-				avail -= len;
-				continue;
-			}
-		} else {
-			/* A continuance line; the terminal
-			 * character of previous line was '\' character. */
-			if (bid_keyword_list(p, len, 0, 0) <= 0)
-				break;
-			if (p[len-nl-1] != '\\') {
-				if (multiline == 1 &&
-				    ++entry_cnt >= MAX_BID_ENTRY)
-					break;
-				multiline = 0;
-			}
-			p += len;
-			avail -= len;
-			continue;
-		}
-		if (p[0] != '/') {
-			int last_is_path, keywords;
-
-			keywords = bid_entry(p, len, nl, &last_is_path);
-			if (keywords >= 0) {
-				if (form_D == 0) {
-					if (last_is_path)
-						form_D = 1;
-					else if (keywords > 0)
-						/* This line is not `form D'. */
-						form_D = -1;
-				} else if (form_D == 1) {
-					if (!last_is_path && keywords > 0)
-						/* This this is not `form D'
-						 * and We cannot accept mixed
-						 * format. */
-						break;
-				}
-				if (!last_is_path && p[len-nl-1] == '\\')
-					/* This line continues. */
-					multiline = 1;
-				else {
-					/* We've got plenty of correct lines
-					 * to assume that this file is a mtree
-					 * format. */
-					if (++entry_cnt >= MAX_BID_ENTRY)
-						break;
-				}
-			} else
-				break;
-		} else if (len > 4 && strncmp(p, "/set", 4) == 0) {
-			if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
-				break;
-			/* This line continues. */
-			if (p[len-nl-1] == '\\')
-				multiline = 2;
-		} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
-			if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
-				break;
-			/* This line continues. */
-			if (p[len-nl-1] == '\\')
-				multiline = 2;
-		} else
-			break;
-
-		/* Test next line. */
-		p += len;
-		avail -= len;
-	}
-	if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
-		if (is_form_d != NULL) {
-			if (form_D == 1)
-				*is_form_d = 1;
-		}
-		return (32);
-	}
-
-	return (0);
-}
-
-/*
- * The extended mtree format permits multiple lines specifying
- * attributes for each file.  For those entries, only the last line
- * is actually used.  Practically speaking, that means we have
- * to read the entire mtree file into memory up front.
- *
- * The parsing is done in two steps.  First, it is decided if a line
- * changes the global defaults and if it is, processed accordingly.
- * Otherwise, the options of the line are merged with the current
- * global options.
- */
-static int
-add_option(struct archive_read *a, struct mtree_option **global,
-    const char *value, size_t len)
-{
-	struct mtree_option *opt;
-
-	if ((opt = malloc(sizeof(*opt))) == NULL) {
-		archive_set_error(&a->archive, errno, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	if ((opt->value = malloc(len + 1)) == NULL) {
-		free(opt);
-		archive_set_error(&a->archive, errno, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	memcpy(opt->value, value, len);
-	opt->value[len] = '\0';
-	opt->next = *global;
-	*global = opt;
-	return (ARCHIVE_OK);
-}
-
-static void
-remove_option(struct mtree_option **global, const char *value, size_t len)
-{
-	struct mtree_option *iter, *last;
-
-	last = NULL;
-	for (iter = *global; iter != NULL; last = iter, iter = iter->next) {
-		if (strncmp(iter->value, value, len) == 0 &&
-		    (iter->value[len] == '\0' ||
-		     iter->value[len] == '='))
-			break;
-	}
-	if (iter == NULL)
-		return;
-	if (last == NULL)
-		*global = iter->next;
-	else
-		last->next = iter->next;
-
-	free(iter->value);
-	free(iter);
-}
-
-static int
-process_global_set(struct archive_read *a,
-    struct mtree_option **global, const char *line)
-{
-	const char *next, *eq;
-	size_t len;
-	int r;
-
-	line += 4;
-	for (;;) {
-		next = line + strspn(line, " \t\r\n");
-		if (*next == '\0')
-			return (ARCHIVE_OK);
-		line = next;
-		next = line + strcspn(line, " \t\r\n");
-		eq = strchr(line, '=');
-		if (eq > next)
-			len = next - line;
-		else
-			len = eq - line;
-
-		remove_option(global, line, len);
-		r = add_option(a, global, line, next - line);
-		if (r != ARCHIVE_OK)
-			return (r);
-		line = next;
-	}
-}
-
-static int
-process_global_unset(struct archive_read *a,
-    struct mtree_option **global, const char *line)
-{
-	const char *next;
-	size_t len;
-
-	line += 6;
-	if (strchr(line, '=') != NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "/unset shall not contain `='");
-		return ARCHIVE_FATAL;
-	}
-
-	for (;;) {
-		next = line + strspn(line, " \t\r\n");
-		if (*next == '\0')
-			return (ARCHIVE_OK);
-		line = next;
-		len = strcspn(line, " \t\r\n");
-
-		if (len == 3 && strncmp(line, "all", 3) == 0) {
-			free_options(*global);
-			*global = NULL;
-		} else {
-			remove_option(global, line, len);
-		}
-
-		line += len;
-	}
-}
-
-static int
-process_add_entry(struct archive_read *a, struct mtree *mtree,
-    struct mtree_option **global, const char *line, ssize_t line_len,
-    struct mtree_entry **last_entry, int is_form_d)
-{
-	struct mtree_entry *entry;
-	struct mtree_option *iter;
-	const char *next, *eq, *name, *end;
-	size_t name_len, len;
-	int r, i;
-
-	if ((entry = malloc(sizeof(*entry))) == NULL) {
-		archive_set_error(&a->archive, errno, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	entry->next = NULL;
-	entry->options = NULL;
-	entry->name = NULL;
-	entry->used = 0;
-	entry->full = 0;
-
-	/* Add this entry to list. */
-	if (*last_entry == NULL)
-		mtree->entries = entry;
-	else
-		(*last_entry)->next = entry;
-	*last_entry = entry;
-
-	if (is_form_d) {
-		/* Filename is last item on line. */
-		/* Adjust line_len to trim trailing whitespace */
-		while (line_len > 0) {
-			char last_character = line[line_len - 1];
-			if (last_character == '\r'
-			    || last_character == '\n'
-			    || last_character == '\t'
-			    || last_character == ' ') {
-				line_len--;
-			} else {
-				break;
-			}
-		}
-		/* Name starts after the last whitespace separator */
-		name = line;
-		for (i = 0; i < line_len; i++) {
-			if (line[i] == '\r'
-			    || line[i] == '\n'
-			    || line[i] == '\t'
-			    || line[i] == ' ') {
-				name = line + i + 1;
-			}
-		}
-		name_len = line + line_len - name;
-		end = name;
-	} else {
-		/* Filename is first item on line */
-		name_len = strcspn(line, " \t\r\n");
-		name = line;
-		line += name_len;
-		end = line + line_len;
-	}
-	/* name/name_len is the name within the line. */
-	/* line..end brackets the entire line except the name */
-
-	if ((entry->name = malloc(name_len + 1)) == NULL) {
-		archive_set_error(&a->archive, errno, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	memcpy(entry->name, name, name_len);
-	entry->name[name_len] = '\0';
-	parse_escapes(entry->name, entry);
-
-	entry->next_dup = NULL;
-	if (entry->full) {
-		if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
-			struct mtree_entry *alt;
-			alt = (struct mtree_entry *)__archive_rb_tree_find_node(
-			    &mtree->rbtree, entry->name);
-			if (alt != NULL) {
-				while (alt->next_dup)
-					alt = alt->next_dup;
-				alt->next_dup = entry;
-			}
-		}
-	}
-
-	for (iter = *global; iter != NULL; iter = iter->next) {
-		r = add_option(a, &entry->options, iter->value,
-		    strlen(iter->value));
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	for (;;) {
-		next = line + strspn(line, " \t\r\n");
-		if (*next == '\0')
-			return (ARCHIVE_OK);
-		if (next >= end)
-			return (ARCHIVE_OK);
-		line = next;
-		next = line + strcspn(line, " \t\r\n");
-		eq = strchr(line, '=');
-		if (eq == NULL || eq > next)
-			len = next - line;
-		else
-			len = eq - line;
-
-		remove_option(&entry->options, line, len);
-		r = add_option(a, &entry->options, line, next - line);
-		if (r != ARCHIVE_OK)
-			return (r);
-		line = next;
-	}
-}
-
-static int
-read_mtree(struct archive_read *a, struct mtree *mtree)
-{
-	ssize_t len;
-	uintmax_t counter;
-	char *p, *s;
-	struct mtree_option *global;
-	struct mtree_entry *last_entry;
-	int r, is_form_d;
-
-	mtree->archive_format = ARCHIVE_FORMAT_MTREE;
-	mtree->archive_format_name = "mtree";
-
-	global = NULL;
-	last_entry = NULL;
-
-	(void)detect_form(a, &is_form_d);
-
-	for (counter = 1; ; ++counter) {
-		r = ARCHIVE_OK;
-		len = readline(a, mtree, &p, 65536);
-		if (len == 0) {
-			mtree->this_entry = mtree->entries;
-			free_options(global);
-			return (ARCHIVE_OK);
-		}
-		if (len < 0) {
-			free_options(global);
-			return ((int)len);
-		}
-		/* Leading whitespace is never significant, ignore it. */
-		while (*p == ' ' || *p == '\t') {
-			++p;
-			--len;
-		}
-		/* Skip content lines and blank lines. */
-		if (*p == '#')
-			continue;
-		if (*p == '\r' || *p == '\n' || *p == '\0')
-			continue;
-		/* Non-printable characters are not allowed */
-		for (s = p;s < p + len - 1; s++) {
-			if (!isprint((unsigned char)*s) && *s != '\t') {
-				r = ARCHIVE_FATAL;
-				break;
-			}
-		}
-		if (r != ARCHIVE_OK)
-			break;
-		if (*p != '/') {
-			r = process_add_entry(a, mtree, &global, p, len,
-			    &last_entry, is_form_d);
-		} else if (len > 4 && strncmp(p, "/set", 4) == 0) {
-			if (p[4] != ' ' && p[4] != '\t')
-				break;
-			r = process_global_set(a, &global, p);
-		} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
-			if (p[6] != ' ' && p[6] != '\t')
-				break;
-			r = process_global_unset(a, &global, p);
-		} else
-			break;
-
-		if (r != ARCHIVE_OK) {
-			free_options(global);
-			return r;
-		}
-	}
-
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Can't parse line %ju", counter);
-	free_options(global);
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Read in the entire mtree file into memory on the first request.
- * Then use the next unused file to satisfy each header request.
- */
-static int
-read_header(struct archive_read *a, struct archive_entry *entry)
-{
-	struct mtree *mtree;
-	char *p;
-	int r, use_next;
-
-	mtree = (struct mtree *)(a->format->data);
-
-	if (mtree->fd >= 0) {
-		close(mtree->fd);
-		mtree->fd = -1;
-	}
-
-	if (mtree->entries == NULL) {
-		mtree->resolver = archive_entry_linkresolver_new();
-		if (mtree->resolver == NULL)
-			return ARCHIVE_FATAL;
-		archive_entry_linkresolver_set_strategy(mtree->resolver,
-		    ARCHIVE_FORMAT_MTREE);
-		r = read_mtree(a, mtree);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	a->archive.archive_format = mtree->archive_format;
-	a->archive.archive_format_name = mtree->archive_format_name;
-
-	for (;;) {
-		if (mtree->this_entry == NULL)
-			return (ARCHIVE_EOF);
-		if (strcmp(mtree->this_entry->name, "..") == 0) {
-			mtree->this_entry->used = 1;
-			if (archive_strlen(&mtree->current_dir) > 0) {
-				/* Roll back current path. */
-				p = mtree->current_dir.s
-				    + mtree->current_dir.length - 1;
-				while (p >= mtree->current_dir.s && *p != '/')
-					--p;
-				if (p >= mtree->current_dir.s)
-					--p;
-				mtree->current_dir.length
-				    = p - mtree->current_dir.s + 1;
-			}
-		}
-		if (!mtree->this_entry->used) {
-			use_next = 0;
-			r = parse_file(a, entry, mtree, mtree->this_entry,
-				&use_next);
-			if (use_next == 0)
-				return (r);
-		}
-		mtree->this_entry = mtree->this_entry->next;
-	}
-}
-
-/*
- * A single file can have multiple lines contribute specifications.
- * Parse as many lines as necessary, then pull additional information
- * from a backing file on disk as necessary.
- */
-static int
-parse_file(struct archive_read *a, struct archive_entry *entry,
-    struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
-{
-	const char *path;
-	struct stat st_storage, *st;
-	struct mtree_entry *mp;
-	struct archive_entry *sparse_entry;
-	int r = ARCHIVE_OK, r1, parsed_kws;
-
-	mentry->used = 1;
-
-	/* Initialize reasonable defaults. */
-	archive_entry_set_filetype(entry, AE_IFREG);
-	archive_entry_set_size(entry, 0);
-	archive_string_empty(&mtree->contents_name);
-
-	/* Parse options from this line. */
-	parsed_kws = 0;
-	r = parse_line(a, entry, mtree, mentry, &parsed_kws);
-
-	if (mentry->full) {
-		archive_entry_copy_pathname(entry, mentry->name);
-		/*
-		 * "Full" entries are allowed to have multiple lines
-		 * and those lines aren't required to be adjacent.  We
-		 * don't support multiple lines for "relative" entries
-		 * nor do we make any attempt to merge data from
-		 * separate "relative" and "full" entries.  (Merging
-		 * "relative" and "full" entries would require dealing
-		 * with pathname canonicalization, which is a very
-		 * tricky subject.)
-		 */
-		mp = (struct mtree_entry *)__archive_rb_tree_find_node(
-		    &mtree->rbtree, mentry->name);
-		for (; mp; mp = mp->next_dup) {
-			if (mp->full && !mp->used) {
-				/* Later lines override earlier ones. */
-				mp->used = 1;
-				r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
-				if (r1 < r)
-					r = r1;
-			}
-		}
-	} else {
-		/*
-		 * Relative entries require us to construct
-		 * the full path and possibly update the
-		 * current directory.
-		 */
-		size_t n = archive_strlen(&mtree->current_dir);
-		if (n > 0)
-			archive_strcat(&mtree->current_dir, "/");
-		archive_strcat(&mtree->current_dir, mentry->name);
-		archive_entry_copy_pathname(entry, mtree->current_dir.s);
-		if (archive_entry_filetype(entry) != AE_IFDIR)
-			mtree->current_dir.length = n;
-	}
-
-	if (mtree->checkfs) {
-		/*
-		 * Try to open and stat the file to get the real size
-		 * and other file info.  It would be nice to avoid
-		 * this here so that getting a listing of an mtree
-		 * wouldn't require opening every referenced contents
-		 * file.  But then we wouldn't know the actual
-		 * contents size, so I don't see a really viable way
-		 * around this.  (Also, we may want to someday pull
-		 * other unspecified info from the contents file on
-		 * disk.)
-		 */
-		mtree->fd = -1;
-		if (archive_strlen(&mtree->contents_name) > 0)
-			path = mtree->contents_name.s;
-		else
-			path = archive_entry_pathname(entry);
-
-		if (archive_entry_filetype(entry) == AE_IFREG ||
-				archive_entry_filetype(entry) == AE_IFDIR) {
-			mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
-			__archive_ensure_cloexec_flag(mtree->fd);
-			if (mtree->fd == -1 && (
-#if defined(_WIN32) && !defined(__CYGWIN__)
-        /*
-         * On Windows, attempting to open a file with an
-         * invalid name result in EINVAL (Error 22)
-         */
-				(errno != ENOENT && errno != EINVAL)
-#else
-				errno != ENOENT
-#endif
-        || archive_strlen(&mtree->contents_name) > 0)) {
-				archive_set_error(&a->archive, errno,
-						"Can't open %s", path);
-				r = ARCHIVE_WARN;
-			}
-		}
-
-		st = &st_storage;
-		if (mtree->fd >= 0) {
-			if (fstat(mtree->fd, st) == -1) {
-				archive_set_error(&a->archive, errno,
-						"Could not fstat %s", path);
-				r = ARCHIVE_WARN;
-				/* If we can't stat it, don't keep it open. */
-				close(mtree->fd);
-				mtree->fd = -1;
-				st = NULL;
-			}
-		}
-#ifdef HAVE_LSTAT
-		else if (lstat(path, st) == -1)
-#else
-		else if (la_stat(path, st) == -1)
-#endif
-		{
-			st = NULL;
-		}
-
-		/*
-		 * Check for a mismatch between the type in the specification
-		 * and the type of the contents object on disk.
-		 */
-		if (st != NULL) {
-			if (((st->st_mode & S_IFMT) == S_IFREG &&
-			      archive_entry_filetype(entry) == AE_IFREG)
-#ifdef S_IFLNK
-			  ||((st->st_mode & S_IFMT) == S_IFLNK &&
-			      archive_entry_filetype(entry) == AE_IFLNK)
-#endif
-#ifdef S_IFSOCK
-			  ||((st->st_mode & S_IFSOCK) == S_IFSOCK &&
-			      archive_entry_filetype(entry) == AE_IFSOCK)
-#endif
-#ifdef S_IFCHR
-			  ||((st->st_mode & S_IFMT) == S_IFCHR &&
-			      archive_entry_filetype(entry) == AE_IFCHR)
-#endif
-#ifdef S_IFBLK
-			  ||((st->st_mode & S_IFMT) == S_IFBLK &&
-			      archive_entry_filetype(entry) == AE_IFBLK)
-#endif
-			  ||((st->st_mode & S_IFMT) == S_IFDIR &&
-			      archive_entry_filetype(entry) == AE_IFDIR)
-#ifdef S_IFIFO
-			  ||((st->st_mode & S_IFMT) == S_IFIFO &&
-			      archive_entry_filetype(entry) == AE_IFIFO)
-#endif
-			) {
-				/* Types match. */
-			} else {
-				/* Types don't match; bail out gracefully. */
-				if (mtree->fd >= 0)
-					close(mtree->fd);
-				mtree->fd = -1;
-				if (parsed_kws & MTREE_HAS_OPTIONAL) {
-					/* It's not an error for an optional
-					 * entry to not match disk. */
-					*use_next = 1;
-				} else if (r == ARCHIVE_OK) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "mtree specification has different"
-					    " type for %s",
-					    archive_entry_pathname(entry));
-					r = ARCHIVE_WARN;
-				}
-				return (r);
-			}
-		}
-
-		/*
-		 * If there is a contents file on disk, pick some of the
-		 * metadata from that file.  For most of these, we only
-		 * set it from the contents if it wasn't already parsed
-		 * from the specification.
-		 */
-		if (st != NULL) {
-			if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
-				(parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
-				(archive_entry_filetype(entry) == AE_IFCHR ||
-				 archive_entry_filetype(entry) == AE_IFBLK))
-				archive_entry_set_rdev(entry, st->st_rdev);
-			if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME))
-				== 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
-				archive_entry_set_gid(entry, st->st_gid);
-			if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME))
-				== 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
-				archive_entry_set_uid(entry, st->st_uid);
-			if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
-#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
-				archive_entry_set_mtime(entry, st->st_mtime,
-						st->st_mtimespec.tv_nsec);
-#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-				archive_entry_set_mtime(entry, st->st_mtime,
-						st->st_mtim.tv_nsec);
-#elif HAVE_STRUCT_STAT_ST_MTIME_N
-				archive_entry_set_mtime(entry, st->st_mtime,
-						st->st_mtime_n);
-#elif HAVE_STRUCT_STAT_ST_UMTIME
-				archive_entry_set_mtime(entry, st->st_mtime,
-						st->st_umtime*1000);
-#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
-				archive_entry_set_mtime(entry, st->st_mtime,
-						st->st_mtime_usec*1000);
-#else
-				archive_entry_set_mtime(entry, st->st_mtime, 0);
-#endif
-			}
-			if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
-				archive_entry_set_nlink(entry, st->st_nlink);
-			if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
-				archive_entry_set_perm(entry, st->st_mode);
-			if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
-			    (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
-				archive_entry_set_size(entry, st->st_size);
-			archive_entry_set_ino(entry, st->st_ino);
-			archive_entry_set_dev(entry, st->st_dev);
-
-			archive_entry_linkify(mtree->resolver, &entry,
-				&sparse_entry);
-		} else if (parsed_kws & MTREE_HAS_OPTIONAL) {
-			/*
-			 * Couldn't open the entry, stat it or the on-disk type
-			 * didn't match.  If this entry is optional, just
-			 * ignore it and read the next header entry.
-			 */
-			*use_next = 1;
-			return ARCHIVE_OK;
-		}
-	}
-
-	mtree->cur_size = archive_entry_size(entry);
-	mtree->offset = 0;
-
-	return r;
-}
-
-/*
- * Each line contains a sequence of keywords.
- */
-static int
-parse_line(struct archive_read *a, struct archive_entry *entry,
-    struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
-{
-	struct mtree_option *iter;
-	int r = ARCHIVE_OK, r1;
-
-	for (iter = mp->options; iter != NULL; iter = iter->next) {
-		r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
-		if (r1 < r)
-			r = r1;
-	}
-	if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Missing type keyword in mtree specification");
-		return (ARCHIVE_WARN);
-	}
-	return (r);
-}
-
-/*
- * Device entries have one of the following forms:
- *  - raw dev_t
- *  - format,major,minor[,subdevice]
- * When parsing succeeded, `pdev' will contain the appropriate dev_t value.
- */
-
-/* strsep() is not in C90, but strcspn() is. */
-/* Taken from http://unixpapa.com/incnote/string.html */
-static char *
-la_strsep(char **sp, const char *sep)
-{
-	char *p, *s;
-	if (sp == NULL || *sp == NULL || **sp == '\0')
-		return(NULL);
-	s = *sp;
-	p = s + strcspn(s, sep);
-	if (*p != '\0')
-		*p++ = '\0';
-	*sp = p;
-	return(s);
-}
-
-static int
-parse_device(dev_t *pdev, struct archive *a, char *val)
-{
-#define MAX_PACK_ARGS 3
-	unsigned long numbers[MAX_PACK_ARGS];
-	char *p, *dev;
-	int argc;
-	pack_t *pack;
-	dev_t result;
-	const char *error = NULL;
-
-	memset(pdev, 0, sizeof(*pdev));
-	if ((dev = strchr(val, ',')) != NULL) {
-		/*
-		 * Device's major/minor are given in a specified format.
-		 * Decode and pack it accordingly.
-		 */
-		*dev++ = '\0';
-		if ((pack = pack_find(val)) == NULL) {
-			archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unknown format `%s'", val);
-			return ARCHIVE_WARN;
-		}
-		argc = 0;
-		while ((p = la_strsep(&dev, ",")) != NULL) {
-			if (*p == '\0') {
-				archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Missing number");
-				return ARCHIVE_WARN;
-			}
-			if (argc >= MAX_PACK_ARGS) {
-				archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Too many arguments");
-				return ARCHIVE_WARN;
-			}
-			numbers[argc++] = (unsigned long)mtree_atol(&p, 0);
-		}
-		if (argc < 2) {
-			archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Not enough arguments");
-			return ARCHIVE_WARN;
-		}
-		result = (*pack)(argc, numbers, &error);
-		if (error != NULL) {
-			archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "%s", error);
-			return ARCHIVE_WARN;
-		}
-	} else {
-		/* file system raw value. */
-		result = (dev_t)mtree_atol(&val, 0);
-	}
-	*pdev = result;
-	return ARCHIVE_OK;
-#undef MAX_PACK_ARGS
-}
-
-static int
-parse_hex_nibble(char c)
-{
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return 10 + c - 'a';
-#if 0
-	/* XXX: Is uppercase something we should support? */
-	if (c >= 'A' && c <= 'F')
-		return 10 + c - 'A';
-#endif
-
-	return -1;
-}
-
-static int
-parse_digest(struct archive_read *a, struct archive_entry *entry,
-    const char *digest, int type)
-{
-	unsigned char digest_buf[64];
-	int high, low;
-	size_t i, j, len;
-
-	switch (type) {
-	case ARCHIVE_ENTRY_DIGEST_MD5:
-		len = sizeof(entry->digest.md5);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_RMD160:
-		len = sizeof(entry->digest.rmd160);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA1:
-		len = sizeof(entry->digest.sha1);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA256:
-		len = sizeof(entry->digest.sha256);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA384:
-		len = sizeof(entry->digest.sha384);
-		break;
-	case ARCHIVE_ENTRY_DIGEST_SHA512:
-		len = sizeof(entry->digest.sha512);
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-			"Internal error: Unknown digest type");
-		return ARCHIVE_FATAL;
-	}
-
-	if (len > sizeof(digest_buf)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-			"Internal error: Digest storage too large");
-		return ARCHIVE_FATAL;
-	}
-
-	len *= 2;
-
-	if (mtree_strnlen(digest, len+1) != len) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				  "incorrect digest length, ignoring");
-		return ARCHIVE_WARN;
-	}
-
-	for (i = 0, j = 0; i < len; i += 2, j++) {
-		high = parse_hex_nibble(digest[i]);
-		low = parse_hex_nibble(digest[i+1]);
-		if (high == -1 || low == -1) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-					  "invalid digest data, ignoring");
-			return ARCHIVE_WARN;
-		}
-
-		digest_buf[j] = high << 4 | low;
-	}
-
-	return archive_entry_set_digest(entry, type, digest_buf);
-}
-
-/*
- * Parse a single keyword and its value.
- */
-static int
-parse_keyword(struct archive_read *a, struct mtree *mtree,
-    struct archive_entry *entry, struct mtree_option *opt, int *parsed_kws)
-{
-	char *val, *key;
-
-	key = opt->value;
-
-	if (*key == '\0')
-		return (ARCHIVE_OK);
-
-	if (strcmp(key, "nochange") == 0) {
-		*parsed_kws |= MTREE_HAS_NOCHANGE;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "optional") == 0) {
-		*parsed_kws |= MTREE_HAS_OPTIONAL;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "ignore") == 0) {
-		/*
-		 * The mtree processing is not recursive, so
-		 * recursion will only happen for explicitly listed
-		 * entries.
-		 */
-		return (ARCHIVE_OK);
-	}
-
-	val = strchr(key, '=');
-	if (val == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Malformed attribute \"%s\" (%d)", key, key[0]);
-		return (ARCHIVE_WARN);
-	}
-
-	*val = '\0';
-	++val;
-
-	switch (key[0]) {
-	case 'c':
-		if (strcmp(key, "content") == 0
-		    || strcmp(key, "contents") == 0) {
-			parse_escapes(val, NULL);
-			archive_strcpy(&mtree->contents_name, val);
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "cksum") == 0)
-			return (ARCHIVE_OK);
-		break;
-	case 'd':
-		if (strcmp(key, "device") == 0) {
-			/* stat(2) st_rdev field, e.g. the major/minor IDs
-			 * of a char/block special file */
-			int r;
-			dev_t dev;
-
-			*parsed_kws |= MTREE_HAS_DEVICE;
-			r = parse_device(&dev, &a->archive, val);
-			if (r == ARCHIVE_OK)
-				archive_entry_set_rdev(entry, dev);
-			return r;
-		}
-		break;
-	case 'f':
-		if (strcmp(key, "flags") == 0) {
-			*parsed_kws |= MTREE_HAS_FFLAGS;
-			archive_entry_copy_fflags_text(entry, val);
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'g':
-		if (strcmp(key, "gid") == 0) {
-			*parsed_kws |= MTREE_HAS_GID;
-			archive_entry_set_gid(entry, mtree_atol(&val, 10));
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "gname") == 0) {
-			*parsed_kws |= MTREE_HAS_GNAME;
-			archive_entry_copy_gname(entry, val);
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'i':
-		if (strcmp(key, "inode") == 0) {
-			archive_entry_set_ino(entry, mtree_atol(&val, 10));
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'l':
-		if (strcmp(key, "link") == 0) {
-			parse_escapes(val, NULL);
-			archive_entry_copy_symlink(entry, val);
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'm':
-		if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_MD5);
-		}
-		if (strcmp(key, "mode") == 0) {
-			if (val[0] < '0' || val[0] > '7') {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Symbolic or non-octal mode \"%s\" unsupported", val);
-				return (ARCHIVE_WARN);
-			}
-			*parsed_kws |= MTREE_HAS_PERM;
-			archive_entry_set_perm(entry, (mode_t)mtree_atol(&val, 8));
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'n':
-		if (strcmp(key, "nlink") == 0) {
-			*parsed_kws |= MTREE_HAS_NLINK;
-			archive_entry_set_nlink(entry,
-				(unsigned int)mtree_atol(&val, 10));
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'r':
-		if (strcmp(key, "resdevice") == 0) {
-			/* stat(2) st_dev field, e.g. the device ID where the
-			 * inode resides */
-			int r;
-			dev_t dev;
-
-			r = parse_device(&dev, &a->archive, val);
-			if (r == ARCHIVE_OK)
-				archive_entry_set_dev(entry, dev);
-			return r;
-		}
-		if (strcmp(key, "rmd160") == 0 ||
-		    strcmp(key, "rmd160digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_RMD160);
-		}
-		break;
-	case 's':
-		if (strcmp(key, "sha1") == 0 ||
-		    strcmp(key, "sha1digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_SHA1);
-		}
-		if (strcmp(key, "sha256") == 0 ||
-		    strcmp(key, "sha256digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_SHA256);
-		}
-		if (strcmp(key, "sha384") == 0 ||
-		    strcmp(key, "sha384digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_SHA384);
-		}
-		if (strcmp(key, "sha512") == 0 ||
-		    strcmp(key, "sha512digest") == 0) {
-			return parse_digest(a, entry, val,
-			    ARCHIVE_ENTRY_DIGEST_SHA512);
-		}
-		if (strcmp(key, "size") == 0) {
-			archive_entry_set_size(entry, mtree_atol(&val, 10));
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 't':
-		if (strcmp(key, "tags") == 0) {
-			/*
-			 * Comma delimited list of tags.
-			 * Ignore the tags for now, but the interface
-			 * should be extended to allow inclusion/exclusion.
-			 */
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "time") == 0) {
-			int64_t m;
-			int64_t my_time_t_max = get_time_t_max();
-			int64_t my_time_t_min = get_time_t_min();
-			long ns = 0;
-
-			*parsed_kws |= MTREE_HAS_MTIME;
-			m = mtree_atol(&val, 10);
-			/* Replicate an old mtree bug:
-			 * 123456789.1 represents 123456789
-			 * seconds and 1 nanosecond. */
-			if (*val == '.') {
-				++val;
-				ns = (long)mtree_atol(&val, 10);
-				if (ns < 0)
-					ns = 0;
-				else if (ns > 999999999)
-					ns = 999999999;
-			}
-			if (m > my_time_t_max)
-				m = my_time_t_max;
-			else if (m < my_time_t_min)
-				m = my_time_t_min;
-			archive_entry_set_mtime(entry, (time_t)m, ns);
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "type") == 0) {
-			switch (val[0]) {
-			case 'b':
-				if (strcmp(val, "block") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFBLK);
-					return (ARCHIVE_OK);
-				}
-				break;
-			case 'c':
-				if (strcmp(val, "char") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFCHR);
-					return (ARCHIVE_OK);
-				}
-				break;
-			case 'd':
-				if (strcmp(val, "dir") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFDIR);
-					return (ARCHIVE_OK);
-				}
-				break;
-			case 'f':
-				if (strcmp(val, "fifo") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFIFO);
-					return (ARCHIVE_OK);
-				}
-				if (strcmp(val, "file") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFREG);
-					return (ARCHIVE_OK);
-				}
-				break;
-			case 'l':
-				if (strcmp(val, "link") == 0) {
-					*parsed_kws |= MTREE_HAS_TYPE;
-					archive_entry_set_filetype(entry,
-						AE_IFLNK);
-					return (ARCHIVE_OK);
-				}
-				break;
-			default:
-				break;
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unrecognized file type \"%s\"; "
-			    "assuming \"file\"", val);
-			archive_entry_set_filetype(entry, AE_IFREG);
-			return (ARCHIVE_WARN);
-		}
-		break;
-	case 'u':
-		if (strcmp(key, "uid") == 0) {
-			*parsed_kws |= MTREE_HAS_UID;
-			archive_entry_set_uid(entry, mtree_atol(&val, 10));
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "uname") == 0) {
-			*parsed_kws |= MTREE_HAS_UNAME;
-			archive_entry_copy_uname(entry, val);
-			return (ARCHIVE_OK);
-		}
-		break;
-	default:
-		break;
-	}
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Unrecognized key %s=%s", key, val);
-	return (ARCHIVE_WARN);
-}
-
-static int
-read_data(struct archive_read *a, const void **buff, size_t *size,
-    int64_t *offset)
-{
-	size_t bytes_to_read;
-	ssize_t bytes_read;
-	struct mtree *mtree;
-
-	mtree = (struct mtree *)(a->format->data);
-	if (mtree->fd < 0) {
-		*buff = NULL;
-		*offset = 0;
-		*size = 0;
-		return (ARCHIVE_EOF);
-	}
-	if (mtree->buff == NULL) {
-		mtree->buffsize = 64 * 1024;
-		mtree->buff = malloc(mtree->buffsize);
-		if (mtree->buff == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	*buff = mtree->buff;
-	*offset = mtree->offset;
-	if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
-		bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
-	else
-		bytes_to_read = mtree->buffsize;
-	bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
-	if (bytes_read < 0) {
-		archive_set_error(&a->archive, errno, "Can't read");
-		return (ARCHIVE_WARN);
-	}
-	if (bytes_read == 0) {
-		*size = 0;
-		return (ARCHIVE_EOF);
-	}
-	mtree->offset += bytes_read;
-	*size = bytes_read;
-	return (ARCHIVE_OK);
-}
-
-/* Skip does nothing except possibly close the contents file. */
-static int
-skip(struct archive_read *a)
-{
-	struct mtree *mtree;
-
-	mtree = (struct mtree *)(a->format->data);
-	if (mtree->fd >= 0) {
-		close(mtree->fd);
-		mtree->fd = -1;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Since parsing backslash sequences always makes strings shorter,
- * we can always do this conversion in-place.
- */
-static void
-parse_escapes(char *src, struct mtree_entry *mentry)
-{
-	char *dest = src;
-	char c;
-
-	if (mentry != NULL && strcmp(src, ".") == 0)
-		mentry->full = 1;
-
-	while (*src != '\0') {
-		c = *src++;
-		if (c == '/' && mentry != NULL)
-			mentry->full = 1;
-		if (c == '\\') {
-			switch (src[0]) {
-			case '0':
-				if (src[1] < '0' || src[1] > '7') {
-					c = 0;
-					++src;
-					break;
-				}
-				/* FALLTHROUGH */
-			case '1':
-			case '2':
-			case '3':
-				if (src[1] >= '0' && src[1] <= '7' &&
-				    src[2] >= '0' && src[2] <= '7') {
-					c = (src[0] - '0') << 6;
-					c |= (src[1] - '0') << 3;
-					c |= (src[2] - '0');
-					src += 3;
-				}
-				break;
-			case 'a':
-				c = '\a';
-				++src;
-				break;
-			case 'b':
-				c = '\b';
-				++src;
-				break;
-			case 'f':
-				c = '\f';
-				++src;
-				break;
-			case 'n':
-				c = '\n';
-				++src;
-				break;
-			case 'r':
-				c = '\r';
-				++src;
-				break;
-			case 's':
-				c = ' ';
-				++src;
-				break;
-			case 't':
-				c = '\t';
-				++src;
-				break;
-			case 'v':
-				c = '\v';
-				++src;
-				break;
-			case '\\':
-				c = '\\';
-				++src;
-				break;
-			}
-		}
-		*dest++ = c;
-	}
-	*dest = '\0';
-}
-
-/* Parse a hex digit. */
-static int
-parsedigit(char c)
-{
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	else if (c >= 'a' && c <= 'f')
-		return c - 'a';
-	else if (c >= 'A' && c <= 'F')
-		return c - 'A';
-	else
-		return -1;
-}
-
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
-static int64_t
-mtree_atol(char **p, int base)
-{
-	int64_t l, limit;
-	int digit, last_digit_limit;
-
-	if (base == 0) {
-		if (**p != '0')
-			base = 10;
-		else if ((*p)[1] == 'x' || (*p)[1] == 'X') {
-			*p += 2;
-			base = 16;
-		} else {
-			base = 8;
-		}
-	}
-
-	if (**p == '-') {
-		limit = INT64_MIN / base;
-		last_digit_limit = -(INT64_MIN % base);
-		++(*p);
-
-		l = 0;
-		digit = parsedigit(**p);
-		while (digit >= 0 && digit < base) {
-			if (l < limit || (l == limit && digit >= last_digit_limit))
-				return INT64_MIN;
-			l = (l * base) - digit;
-			digit = parsedigit(*++(*p));
-		}
-		return l;
-	} else {
-		limit = INT64_MAX / base;
-		last_digit_limit = INT64_MAX % base;
-
-		l = 0;
-		digit = parsedigit(**p);
-		while (digit >= 0 && digit < base) {
-			if (l > limit || (l == limit && digit > last_digit_limit))
-				return INT64_MAX;
-			l = (l * base) + digit;
-			digit = parsedigit(*++(*p));
-		}
-		return l;
-	}
-}
-
-/*
- * Returns length of line (including trailing newline)
- * or negative on error.  'start' argument is updated to
- * point to first character of line.
- */
-static ssize_t
-readline(struct archive_read *a, struct mtree *mtree, char **start,
-    ssize_t limit)
-{
-	ssize_t bytes_read;
-	ssize_t total_size = 0;
-	ssize_t find_off = 0;
-	const void *t;
-	void *nl;
-	char *u;
-
-	/* Accumulate line in a line buffer. */
-	for (;;) {
-		/* Read some more. */
-		t = __archive_read_ahead(a, 1, &bytes_read);
-		if (t == NULL)
-			return (0);
-		if (bytes_read < 0)
-			return (ARCHIVE_FATAL);
-		nl = memchr(t, '\n', bytes_read);
-		/* If we found '\n', trim the read to end exactly there. */
-		if (nl != NULL) {
-			bytes_read = ((const char *)nl) - ((const char *)t) + 1;
-		}
-		if (total_size + bytes_read + 1 > limit) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Line too long");
-			return (ARCHIVE_FATAL);
-		}
-		if (archive_string_ensure(&mtree->line,
-			total_size + bytes_read + 1) == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate working buffer");
-			return (ARCHIVE_FATAL);
-		}
-		/* Append new bytes to string. */
-		memcpy(mtree->line.s + total_size, t, bytes_read);
-		__archive_read_consume(a, bytes_read);
-		total_size += bytes_read;
-		mtree->line.s[total_size] = '\0';
-
-		for (u = mtree->line.s + find_off; *u; ++u) {
-			if (u[0] == '\n') {
-				/* Ends with unescaped newline. */
-				*start = mtree->line.s;
-				return total_size;
-			} else if (u[0] == '#') {
-				/* Ends with comment sequence #...\n */
-				if (nl == NULL) {
-					/* But we've not found the \n yet */
-					break;
-				}
-			} else if (u[0] == '\\') {
-				if (u[1] == '\n') {
-					/* Trim escaped newline. */
-					total_size -= 2;
-					mtree->line.s[total_size] = '\0';
-					break;
-				} else if (u[1] != '\0') {
-					/* Skip the two-char escape sequence */
-					++u;
-				}
-			}
-		}
-		find_off = u - mtree->line.s;
-	}
-}
diff --git a/c/archive_read_support_format_rar.c b/c/archive_read_support_format_rar.c
deleted file mode 100644
--- a/c/archive_read_support_format_rar.c
+++ /dev/null
@@ -1,3788 +0,0 @@
-/*-
-* Copyright (c) 2003-2007 Tim Kientzle
-* Copyright (c) 2011 Andres Mejia
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "archive_platform.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <time.h>
-#include <limits.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h> /* crc32 */
-#endif
-
-#include "archive.h"
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_ppmd7_private.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-/* RAR signature, also known as the mark header */
-#define RAR_SIGNATURE "\x52\x61\x72\x21\x1A\x07\x00"
-
-/* Header types */
-#define MARK_HEAD    0x72
-#define MAIN_HEAD    0x73
-#define FILE_HEAD    0x74
-#define COMM_HEAD    0x75
-#define AV_HEAD      0x76
-#define SUB_HEAD     0x77
-#define PROTECT_HEAD 0x78
-#define SIGN_HEAD    0x79
-#define NEWSUB_HEAD  0x7a
-#define ENDARC_HEAD  0x7b
-
-/* Main Header Flags */
-#define MHD_VOLUME       0x0001
-#define MHD_COMMENT      0x0002
-#define MHD_LOCK         0x0004
-#define MHD_SOLID        0x0008
-#define MHD_NEWNUMBERING 0x0010
-#define MHD_AV           0x0020
-#define MHD_PROTECT      0x0040
-#define MHD_PASSWORD     0x0080
-#define MHD_FIRSTVOLUME  0x0100
-#define MHD_ENCRYPTVER   0x0200
-
-/* Flags common to all headers */
-#define HD_MARKDELETION     0x4000
-#define HD_ADD_SIZE_PRESENT 0x8000
-
-/* File Header Flags */
-#define FHD_SPLIT_BEFORE 0x0001
-#define FHD_SPLIT_AFTER  0x0002
-#define FHD_PASSWORD     0x0004
-#define FHD_COMMENT      0x0008
-#define FHD_SOLID        0x0010
-#define FHD_LARGE        0x0100
-#define FHD_UNICODE      0x0200
-#define FHD_SALT         0x0400
-#define FHD_VERSION      0x0800
-#define FHD_EXTTIME      0x1000
-#define FHD_EXTFLAGS     0x2000
-
-/* File dictionary sizes */
-#define DICTIONARY_SIZE_64   0x00
-#define DICTIONARY_SIZE_128  0x20
-#define DICTIONARY_SIZE_256  0x40
-#define DICTIONARY_SIZE_512  0x60
-#define DICTIONARY_SIZE_1024 0x80
-#define DICTIONARY_SIZE_2048 0xA0
-#define DICTIONARY_SIZE_4096 0xC0
-#define FILE_IS_DIRECTORY    0xE0
-#define DICTIONARY_MASK      FILE_IS_DIRECTORY
-
-/* OS Flags */
-#define OS_MSDOS  0
-#define OS_OS2    1
-#define OS_WIN32  2
-#define OS_UNIX   3
-#define OS_MAC_OS 4
-#define OS_BEOS   5
-
-/* Compression Methods */
-#define COMPRESS_METHOD_STORE   0x30
-/* LZSS */
-#define COMPRESS_METHOD_FASTEST 0x31
-#define COMPRESS_METHOD_FAST    0x32
-#define COMPRESS_METHOD_NORMAL  0x33
-/* PPMd Variant H */
-#define COMPRESS_METHOD_GOOD    0x34
-#define COMPRESS_METHOD_BEST    0x35
-
-#define CRC_POLYNOMIAL 0xEDB88320
-
-#define NS_UNIT 10000000
-
-#define DICTIONARY_MAX_SIZE 0x400000
-
-#define MAINCODE_SIZE      299
-#define OFFSETCODE_SIZE    60
-#define LOWOFFSETCODE_SIZE 17
-#define LENGTHCODE_SIZE    28
-#define HUFFMAN_TABLE_SIZE \
-  MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE
-
-#define MAX_SYMBOL_LENGTH 0xF
-#define MAX_SYMBOLS       20
-
-/* Virtual Machine Properties */
-#define VM_MEMORY_SIZE 0x40000
-#define VM_MEMORY_MASK (VM_MEMORY_SIZE - 1)
-#define PROGRAM_WORK_SIZE 0x3C000
-#define PROGRAM_GLOBAL_SIZE 0x2000
-#define PROGRAM_SYSTEM_GLOBAL_ADDRESS PROGRAM_WORK_SIZE
-#define PROGRAM_SYSTEM_GLOBAL_SIZE 0x40
-#define PROGRAM_USER_GLOBAL_ADDRESS (PROGRAM_SYSTEM_GLOBAL_ADDRESS + PROGRAM_SYSTEM_GLOBAL_SIZE)
-#define PROGRAM_USER_GLOBAL_SIZE (PROGRAM_GLOBAL_SIZE - PROGRAM_SYSTEM_GLOBAL_SIZE)
-
-/*
- * Considering L1,L2 cache miss and a calling of write system-call,
- * the best size of the output buffer(uncompressed buffer) is 128K.
- * If the structure of extracting process is changed, this value
- * might be researched again.
- */
-#define UNP_BUFFER_SIZE   (128 * 1024)
-
-/* Define this here for non-Windows platforms */
-#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__))
-#define FILE_ATTRIBUTE_DIRECTORY 0x10
-#endif
-
-#undef minimum
-#define minimum(a, b)	((a)<(b)?(a):(b))
-
-/* Stack overflow check */
-#define MAX_COMPRESS_DEPTH 1024
-
-/* Fields common to all headers */
-struct rar_header
-{
-  char crc[2];
-  char type;
-  char flags[2];
-  char size[2];
-};
-
-/* Fields common to all file headers */
-struct rar_file_header
-{
-  char pack_size[4];
-  char unp_size[4];
-  char host_os;
-  char file_crc[4];
-  char file_time[4];
-  char unp_ver;
-  char method;
-  char name_size[2];
-  char file_attr[4];
-};
-
-struct huffman_tree_node
-{
-  int branches[2];
-};
-
-struct huffman_table_entry
-{
-  unsigned int length;
-  int value;
-};
-
-struct huffman_code
-{
-  struct huffman_tree_node *tree;
-  int numentries;
-  int numallocatedentries;
-  int minlength;
-  int maxlength;
-  int tablesize;
-  struct huffman_table_entry *table;
-};
-
-struct lzss
-{
-  unsigned char *window;
-  int mask;
-  int64_t position;
-};
-
-struct data_block_offsets
-{
-  int64_t header_size;
-  int64_t start_offset;
-  int64_t end_offset;
-};
-
-struct rar_program_code
-{
-  uint8_t *staticdata;
-  uint32_t staticdatalen;
-  uint8_t *globalbackup;
-  uint32_t globalbackuplen;
-  uint64_t fingerprint;
-  uint32_t usagecount;
-  uint32_t oldfilterlength;
-  struct rar_program_code *next;
-};
-
-struct rar_filter
-{
-  struct rar_program_code *prog;
-  uint32_t initialregisters[8];
-  uint8_t *globaldata;
-  uint32_t globaldatalen;
-  size_t blockstartpos;
-  uint32_t blocklength;
-  uint32_t filteredblockaddress;
-  uint32_t filteredblocklength;
-  struct rar_filter *next;
-};
-
-struct memory_bit_reader
-{
-  const uint8_t *bytes;
-  size_t length;
-  size_t offset;
-  uint64_t bits;
-  int available;
-  int at_eof;
-};
-
-struct rar_virtual_machine
-{
-  uint32_t registers[8];
-  uint8_t memory[VM_MEMORY_SIZE + sizeof(uint32_t)];
-};
-
-struct rar_filters
-{
-  struct rar_virtual_machine *vm;
-  struct rar_program_code *progs;
-  struct rar_filter *stack;
-  int64_t filterstart;
-  uint32_t lastfilternum;
-  int64_t lastend;
-  uint8_t *bytes;
-  size_t bytes_ready;
-};
-
-struct audio_state
-{
-  int8_t weight[5];
-  int16_t delta[4];
-  int8_t lastdelta;
-  int error[11];
-  int count;
-  uint8_t lastbyte;
-};
-
-struct rar
-{
-  /* Entries from main RAR header */
-  unsigned main_flags;
-  unsigned long file_crc;
-  char reserved1[2];
-  char reserved2[4];
-  char encryptver;
-
-  /* File header entries */
-  char compression_method;
-  unsigned file_flags;
-  int64_t packed_size;
-  int64_t unp_size;
-  time_t mtime;
-  long mnsec;
-  mode_t mode;
-  char *filename;
-  char *filename_save;
-  size_t filename_save_size;
-  size_t filename_allocated;
-
-  /* File header optional entries */
-  char salt[8];
-  time_t atime;
-  long ansec;
-  time_t ctime;
-  long cnsec;
-  time_t arctime;
-  long arcnsec;
-
-  /* Fields to help with tracking decompression of files. */
-  int64_t bytes_unconsumed;
-  int64_t bytes_remaining;
-  int64_t bytes_uncopied;
-  int64_t offset;
-  int64_t offset_outgoing;
-  int64_t offset_seek;
-  char valid;
-  unsigned int unp_offset;
-  unsigned int unp_buffer_size;
-  unsigned char *unp_buffer;
-  unsigned int dictionary_size;
-  char start_new_block;
-  char entry_eof;
-  unsigned long crc_calculated;
-  int found_first_header;
-  char has_endarc_header;
-  struct data_block_offsets *dbo;
-  unsigned int cursor;
-  unsigned int nodes;
-  char filename_must_match;
-
-  /* LZSS members */
-  struct huffman_code maincode;
-  struct huffman_code offsetcode;
-  struct huffman_code lowoffsetcode;
-  struct huffman_code lengthcode;
-  unsigned char lengthtable[HUFFMAN_TABLE_SIZE];
-  struct lzss lzss;
-  unsigned int lastlength;
-  unsigned int lastoffset;
-  unsigned int oldoffset[4];
-  unsigned int lastlowoffset;
-  unsigned int numlowoffsetrepeats;
-  char start_new_table;
-
-  /* Filters */
-  struct rar_filters filters;
-
-  /* PPMd Variant H members */
-  char ppmd_valid;
-  char ppmd_eod;
-  char is_ppmd_block;
-  int ppmd_escape;
-  CPpmd7 ppmd7_context;
-  CPpmd7z_RangeDec range_dec;
-  IByteIn bytein;
-
-  /*
-   * String conversion object.
-   */
-  int init_default_conversion;
-  struct archive_string_conv *sconv_default;
-  struct archive_string_conv *opt_sconv;
-  struct archive_string_conv *sconv_utf8;
-  struct archive_string_conv *sconv_utf16be;
-
-  /*
-   * Bit stream reader.
-   */
-  struct rar_br {
-#define CACHE_TYPE	uint64_t
-#define CACHE_BITS	(8 * sizeof(CACHE_TYPE))
-    /* Cache buffer. */
-    CACHE_TYPE		 cache_buffer;
-    /* Indicates how many bits avail in cache_buffer. */
-    int			 cache_avail;
-    ssize_t		 avail_in;
-    const unsigned char *next_in;
-  } br;
-
-  /*
-   * Custom field to denote that this archive contains encrypted entries
-   */
-  int has_encrypted_entries;
-};
-
-static int archive_read_support_format_rar_capabilities(struct archive_read *);
-static int archive_read_format_rar_has_encrypted_entries(struct archive_read *);
-static int archive_read_format_rar_bid(struct archive_read *, int);
-static int archive_read_format_rar_options(struct archive_read *,
-    const char *, const char *);
-static int archive_read_format_rar_read_header(struct archive_read *,
-    struct archive_entry *);
-static int archive_read_format_rar_read_data(struct archive_read *,
-    const void **, size_t *, int64_t *);
-static int archive_read_format_rar_read_data_skip(struct archive_read *a);
-static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
-    int);
-static int archive_read_format_rar_cleanup(struct archive_read *);
-
-/* Support functions */
-static int read_header(struct archive_read *, struct archive_entry *, char);
-static time_t get_time(int);
-static int read_exttime(const char *, struct rar *, const char *);
-static int read_symlink_stored(struct archive_read *, struct archive_entry *,
-                               struct archive_string_conv *);
-static int read_data_stored(struct archive_read *, const void **, size_t *,
-                            int64_t *);
-static int read_data_compressed(struct archive_read *, const void **, size_t *,
-                                int64_t *, size_t);
-static int rar_br_preparation(struct archive_read *, struct rar_br *);
-static int parse_codes(struct archive_read *);
-static void free_codes(struct archive_read *);
-static int read_next_symbol(struct archive_read *, struct huffman_code *);
-static int create_code(struct archive_read *, struct huffman_code *,
-                       unsigned char *, int, char);
-static int add_value(struct archive_read *, struct huffman_code *, int, int,
-                     int);
-static int new_node(struct huffman_code *);
-static int make_table(struct archive_read *, struct huffman_code *);
-static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
-                              struct huffman_table_entry *, int, int);
-static int expand(struct archive_read *, int64_t *);
-static int copy_from_lzss_window_to_unp(struct archive_read *, const void **,
-                                        int64_t, int);
-static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
-static int parse_filter(struct archive_read *, const uint8_t *, uint16_t,
-                        uint8_t);
-static int run_filters(struct archive_read *);
-static void clear_filters(struct rar_filters *);
-static struct rar_filter *create_filter(struct rar_program_code *,
-                                        const uint8_t *, uint32_t,
-                                        uint32_t[8], size_t, uint32_t);
-static void delete_filter(struct rar_filter *filter);
-static struct rar_program_code *compile_program(const uint8_t *, size_t);
-static void delete_program_code(struct rar_program_code *prog);
-static uint32_t membr_next_rarvm_number(struct memory_bit_reader *br);
-static inline uint32_t membr_bits(struct memory_bit_reader *br, int bits);
-static int membr_fill(struct memory_bit_reader *br, int bits);
-static int read_filter(struct archive_read *, int64_t *);
-static int rar_decode_byte(struct archive_read*, uint8_t *);
-static int execute_filter(struct archive_read*, struct rar_filter *,
-                          struct rar_virtual_machine *, size_t);
-static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
-static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
-static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
-
-/*
- * Bit stream reader.
- */
-/* Check that the cache buffer has enough bits. */
-#define rar_br_has(br, n) ((br)->cache_avail >= n)
-/* Get compressed data by bit. */
-#define rar_br_bits(br, n)        \
-  (((uint32_t)((br)->cache_buffer >>    \
-    ((br)->cache_avail - (n)))) & cache_masks[n])
-#define rar_br_bits_forced(br, n)     \
-  (((uint32_t)((br)->cache_buffer <<    \
-    ((n) - (br)->cache_avail))) & cache_masks[n])
-/* Read ahead to make sure the cache buffer has enough compressed data we
- * will use.
- *  True  : completed, there is enough data in the cache buffer.
- *  False : there is no data in the stream. */
-#define rar_br_read_ahead(a, br, n) \
-  ((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n)))
-/* Notify how many bits we consumed. */
-#define rar_br_consume(br, n) ((br)->cache_avail -= (n))
-#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7)
-
-static const uint32_t cache_masks[] = {
-  0x00000000, 0x00000001, 0x00000003, 0x00000007,
-  0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
-  0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
-  0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
-  0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
-  0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
-  0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
-  0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
-  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
-};
-
-/*
- * Shift away used bits in the cache data and fill it up with following bits.
- * Call this when cache buffer does not have enough bits you need.
- *
- * Returns 1 if the cache buffer is full.
- * Returns 0 if the cache buffer is not full; input buffer is empty.
- */
-static int
-rar_br_fillup(struct archive_read *a, struct rar_br *br)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  int n = CACHE_BITS - br->cache_avail;
-
-  for (;;) {
-    switch (n >> 3) {
-    case 8:
-      if (br->avail_in >= 8) {
-        br->cache_buffer =
-            ((uint64_t)br->next_in[0]) << 56 |
-            ((uint64_t)br->next_in[1]) << 48 |
-            ((uint64_t)br->next_in[2]) << 40 |
-            ((uint64_t)br->next_in[3]) << 32 |
-            ((uint32_t)br->next_in[4]) << 24 |
-            ((uint32_t)br->next_in[5]) << 16 |
-            ((uint32_t)br->next_in[6]) << 8 |
-             (uint32_t)br->next_in[7];
-        br->next_in += 8;
-        br->avail_in -= 8;
-        br->cache_avail += 8 * 8;
-        rar->bytes_unconsumed += 8;
-        rar->bytes_remaining -= 8;
-        return (1);
-      }
-      break;
-    case 7:
-      if (br->avail_in >= 7) {
-        br->cache_buffer =
-           (br->cache_buffer << 56) |
-            ((uint64_t)br->next_in[0]) << 48 |
-            ((uint64_t)br->next_in[1]) << 40 |
-            ((uint64_t)br->next_in[2]) << 32 |
-            ((uint32_t)br->next_in[3]) << 24 |
-            ((uint32_t)br->next_in[4]) << 16 |
-            ((uint32_t)br->next_in[5]) << 8 |
-             (uint32_t)br->next_in[6];
-        br->next_in += 7;
-        br->avail_in -= 7;
-        br->cache_avail += 7 * 8;
-        rar->bytes_unconsumed += 7;
-        rar->bytes_remaining -= 7;
-        return (1);
-      }
-      break;
-    case 6:
-      if (br->avail_in >= 6) {
-        br->cache_buffer =
-           (br->cache_buffer << 48) |
-            ((uint64_t)br->next_in[0]) << 40 |
-            ((uint64_t)br->next_in[1]) << 32 |
-            ((uint32_t)br->next_in[2]) << 24 |
-            ((uint32_t)br->next_in[3]) << 16 |
-            ((uint32_t)br->next_in[4]) << 8 |
-             (uint32_t)br->next_in[5];
-        br->next_in += 6;
-        br->avail_in -= 6;
-        br->cache_avail += 6 * 8;
-        rar->bytes_unconsumed += 6;
-        rar->bytes_remaining -= 6;
-        return (1);
-      }
-      break;
-    case 0:
-      /* We have enough compressed data in
-       * the cache buffer.*/
-      return (1);
-    default:
-      break;
-    }
-    if (br->avail_in <= 0) {
-
-      if (rar->bytes_unconsumed > 0) {
-        /* Consume as much as the decompressor
-         * actually used. */
-        __archive_read_consume(a, rar->bytes_unconsumed);
-        rar->bytes_unconsumed = 0;
-      }
-      br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
-      if (br->next_in == NULL)
-        return (0);
-      if (br->avail_in == 0)
-        return (0);
-    }
-    br->cache_buffer =
-       (br->cache_buffer << 8) | *br->next_in++;
-    br->avail_in--;
-    br->cache_avail += 8;
-    n -= 8;
-    rar->bytes_unconsumed++;
-    rar->bytes_remaining--;
-  }
-}
-
-static int
-rar_br_preparation(struct archive_read *a, struct rar_br *br)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-
-  if (rar->bytes_remaining > 0) {
-    br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
-    if (br->next_in == NULL) {
-      archive_set_error(&a->archive,
-          ARCHIVE_ERRNO_FILE_FORMAT,
-          "Truncated RAR file data");
-      return (ARCHIVE_FATAL);
-    }
-    if (br->cache_avail == 0)
-      (void)rar_br_fillup(a, br);
-  }
-  return (ARCHIVE_OK);
-}
-
-/* Find last bit set */
-static inline int
-rar_fls(unsigned int word)
-{
-  word |= (word >>  1);
-  word |= (word >>  2);
-  word |= (word >>  4);
-  word |= (word >>  8);
-  word |= (word >> 16);
-  return word - (word >> 1);
-}
-
-/* LZSS functions */
-static inline int64_t
-lzss_position(struct lzss *lzss)
-{
-  return lzss->position;
-}
-
-static inline int
-lzss_mask(struct lzss *lzss)
-{
-  return lzss->mask;
-}
-
-static inline int
-lzss_size(struct lzss *lzss)
-{
-  return lzss->mask + 1;
-}
-
-static inline int
-lzss_offset_for_position(struct lzss *lzss, int64_t pos)
-{
-  return (int)(pos & lzss->mask);
-}
-
-static inline unsigned char *
-lzss_pointer_for_position(struct lzss *lzss, int64_t pos)
-{
-  return &lzss->window[lzss_offset_for_position(lzss, pos)];
-}
-
-static inline int
-lzss_current_offset(struct lzss *lzss)
-{
-  return lzss_offset_for_position(lzss, lzss->position);
-}
-
-static inline uint8_t *
-lzss_current_pointer(struct lzss *lzss)
-{
-  return lzss_pointer_for_position(lzss, lzss->position);
-}
-
-static inline void
-lzss_emit_literal(struct rar *rar, uint8_t literal)
-{
-  *lzss_current_pointer(&rar->lzss) = literal;
-  rar->lzss.position++;
-}
-
-static inline void
-lzss_emit_match(struct rar *rar, int offset, int length)
-{
-  int dstoffs = lzss_current_offset(&rar->lzss);
-  int srcoffs = (dstoffs - offset) & lzss_mask(&rar->lzss);
-  int l, li, remaining;
-  unsigned char *d, *s;
-
-  remaining = length;
-  while (remaining > 0) {
-    l = remaining;
-    if (dstoffs > srcoffs) {
-      if (l > lzss_size(&rar->lzss) - dstoffs)
-        l = lzss_size(&rar->lzss) - dstoffs;
-    } else {
-      if (l > lzss_size(&rar->lzss) - srcoffs)
-        l = lzss_size(&rar->lzss) - srcoffs;
-    }
-    d = &(rar->lzss.window[dstoffs]);
-    s = &(rar->lzss.window[srcoffs]);
-    if ((dstoffs + l < srcoffs) || (srcoffs + l < dstoffs))
-      memcpy(d, s, l);
-    else {
-      for (li = 0; li < l; li++)
-        d[li] = s[li];
-    }
-    remaining -= l;
-    dstoffs = (dstoffs + l) & lzss_mask(&(rar->lzss));
-    srcoffs = (srcoffs + l) & lzss_mask(&(rar->lzss));
-  }
-  rar->lzss.position += length;
-}
-
-static Byte
-ppmd_read(void *p)
-{
-  struct archive_read *a = ((IByteIn*)p)->a;
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_br *br = &(rar->br);
-  Byte b;
-  if (!rar_br_read_ahead(a, br, 8))
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Truncated RAR file data");
-    rar->valid = 0;
-    return 0;
-  }
-  b = rar_br_bits(br, 8);
-  rar_br_consume(br, 8);
-  return b;
-}
-
-int
-archive_read_support_format_rar(struct archive *_a)
-{
-  struct archive_read *a = (struct archive_read *)_a;
-  struct rar *rar;
-  int r;
-
-  archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-                      "archive_read_support_format_rar");
-
-  rar = (struct rar *)calloc(sizeof(*rar), 1);
-  if (rar == NULL)
-  {
-    archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
-    return (ARCHIVE_FATAL);
-  }
-
-	/*
-	 * Until enough data has been read, we cannot tell about
-	 * any encrypted entries yet.
-	 */
-	rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-
-  r = __archive_read_register_format(a,
-                                     rar,
-                                     "rar",
-                                     archive_read_format_rar_bid,
-                                     archive_read_format_rar_options,
-                                     archive_read_format_rar_read_header,
-                                     archive_read_format_rar_read_data,
-                                     archive_read_format_rar_read_data_skip,
-                                     archive_read_format_rar_seek_data,
-                                     archive_read_format_rar_cleanup,
-                                     archive_read_support_format_rar_capabilities,
-                                     archive_read_format_rar_has_encrypted_entries);
-
-  if (r != ARCHIVE_OK)
-    free(rar);
-  return (r);
-}
-
-static int
-archive_read_support_format_rar_capabilities(struct archive_read * a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
-			| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
-}
-
-static int
-archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
-{
-	if (_a && _a->format) {
-		struct rar * rar = (struct rar *)_a->format->data;
-		if (rar) {
-			return rar->has_encrypted_entries;
-		}
-	}
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-}
-
-
-static int
-archive_read_format_rar_bid(struct archive_read *a, int best_bid)
-{
-  const char *p;
-
-  /* If there's already a bid > 30, we'll never win. */
-  if (best_bid > 30)
-	  return (-1);
-
-  if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
-    return (-1);
-
-  if (memcmp(p, RAR_SIGNATURE, 7) == 0)
-    return (30);
-
-  if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
-    /* This is a PE file */
-    ssize_t offset = 0x10000;
-    ssize_t window = 4096;
-    ssize_t bytes_avail;
-    while (offset + window <= (1024 * 128)) {
-      const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
-      if (buff == NULL) {
-        /* Remaining bytes are less than window. */
-        window >>= 1;
-        if (window < 0x40)
-          return (0);
-        continue;
-      }
-      p = buff + offset;
-      while (p + 7 < buff + bytes_avail) {
-        if (memcmp(p, RAR_SIGNATURE, 7) == 0)
-          return (30);
-        p += 0x10;
-      }
-      offset = p - buff;
-    }
-  }
-  return (0);
-}
-
-static int
-skip_sfx(struct archive_read *a)
-{
-  const void *h;
-  const char *p, *q;
-  size_t skip, total;
-  ssize_t bytes, window;
-
-  total = 0;
-  window = 4096;
-  while (total + window <= (1024 * 128)) {
-    h = __archive_read_ahead(a, window, &bytes);
-    if (h == NULL) {
-      /* Remaining bytes are less than window. */
-      window >>= 1;
-      if (window < 0x40)
-      	goto fatal;
-      continue;
-    }
-    if (bytes < 0x40)
-      goto fatal;
-    p = h;
-    q = p + bytes;
-
-    /*
-     * Scan ahead until we find something that looks
-     * like the RAR header.
-     */
-    while (p + 7 < q) {
-      if (memcmp(p, RAR_SIGNATURE, 7) == 0) {
-      	skip = p - (const char *)h;
-      	__archive_read_consume(a, skip);
-      	return (ARCHIVE_OK);
-      }
-      p += 0x10;
-    }
-    skip = p - (const char *)h;
-    __archive_read_consume(a, skip);
-	total += skip;
-  }
-fatal:
-  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-      "Couldn't find out RAR header");
-  return (ARCHIVE_FATAL);
-}
-
-static int
-archive_read_format_rar_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-  struct rar *rar;
-  int ret = ARCHIVE_FAILED;
-
-  rar = (struct rar *)(a->format->data);
-  if (strcmp(key, "hdrcharset")  == 0) {
-    if (val == NULL || val[0] == 0)
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-          "rar: hdrcharset option needs a character-set name");
-    else {
-      rar->opt_sconv =
-          archive_string_conversion_from_charset(
-              &a->archive, val, 0);
-      if (rar->opt_sconv != NULL)
-        ret = ARCHIVE_OK;
-      else
-        ret = ARCHIVE_FATAL;
-    }
-    return (ret);
-  }
-
-  /* Note: The "warn" return is just to inform the options
-   * supervisor that we didn't handle it.  It will generate
-   * a suitable error if no one used this option. */
-  return (ARCHIVE_WARN);
-}
-
-static int
-archive_read_format_rar_read_header(struct archive_read *a,
-                                    struct archive_entry *entry)
-{
-  const void *h;
-  const char *p;
-  struct rar *rar;
-  size_t skip;
-  char head_type;
-  int ret;
-  unsigned flags;
-  unsigned long crc32_expected;
-
-  a->archive.archive_format = ARCHIVE_FORMAT_RAR;
-  if (a->archive.archive_format_name == NULL)
-    a->archive.archive_format_name = "RAR";
-
-  rar = (struct rar *)(a->format->data);
-
-  /*
-   * It should be sufficient to call archive_read_next_header() for
-   * a reader to determine if an entry is encrypted or not. If the
-   * encryption of an entry is only detectable when calling
-   * archive_read_data(), so be it. We'll do the same check there
-   * as well.
-   */
-  if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-	  rar->has_encrypted_entries = 0;
-  }
-
-  /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
-  * this fails.
-  */
-  if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
-    return (ARCHIVE_EOF);
-
-  p = h;
-  if (rar->found_first_header == 0 &&
-     ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)) {
-    /* This is an executable ? Must be self-extracting... */
-    ret = skip_sfx(a);
-    if (ret < ARCHIVE_WARN)
-      return (ret);
-  }
-  rar->found_first_header = 1;
-
-  while (1)
-  {
-    unsigned long crc32_val;
-
-    if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
-      return (ARCHIVE_FATAL);
-    p = h;
-
-    head_type = p[2];
-    switch(head_type)
-    {
-    case MARK_HEAD:
-      if (memcmp(p, RAR_SIGNATURE, 7) != 0) {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Invalid marker header");
-        return (ARCHIVE_FATAL);
-      }
-      __archive_read_consume(a, 7);
-      break;
-
-    case MAIN_HEAD:
-      rar->main_flags = archive_le16dec(p + 3);
-      skip = archive_le16dec(p + 5);
-      if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Invalid header size");
-        return (ARCHIVE_FATAL);
-      }
-      if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
-        return (ARCHIVE_FATAL);
-      p = h;
-      memcpy(rar->reserved1, p + 7, sizeof(rar->reserved1));
-      memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
-             sizeof(rar->reserved2));
-      if (rar->main_flags & MHD_ENCRYPTVER) {
-        if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) {
-          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-            "Invalid header size");
-          return (ARCHIVE_FATAL);
-        }
-        rar->encryptver = *(p + 7 + sizeof(rar->reserved1) +
-                            sizeof(rar->reserved2));
-      }
-
-      /* Main header is password encrypted, so we cannot read any
-         file names or any other info about files from the header. */
-      if (rar->main_flags & MHD_PASSWORD)
-      {
-        archive_entry_set_is_metadata_encrypted(entry, 1);
-        archive_entry_set_is_data_encrypted(entry, 1);
-        rar->has_encrypted_entries = 1;
-         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "RAR encryption support unavailable.");
-        return (ARCHIVE_FATAL);
-      }
-
-      crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
-      if ((crc32_val & 0xffff) != archive_le16dec(p)) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Header CRC error");
-        return (ARCHIVE_FATAL);
-#endif
-      }
-      __archive_read_consume(a, skip);
-      break;
-
-    case FILE_HEAD:
-      return read_header(a, entry, head_type);
-
-    case COMM_HEAD:
-    case AV_HEAD:
-    case SUB_HEAD:
-    case PROTECT_HEAD:
-    case SIGN_HEAD:
-    case ENDARC_HEAD:
-      flags = archive_le16dec(p + 3);
-      skip = archive_le16dec(p + 5);
-      if (skip < 7) {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Invalid header size too small");
-        return (ARCHIVE_FATAL);
-      }
-      if (flags & HD_ADD_SIZE_PRESENT)
-      {
-        if (skip < 7 + 4) {
-          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-            "Invalid header size too small");
-          return (ARCHIVE_FATAL);
-        }
-        if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
-          return (ARCHIVE_FATAL);
-        p = h;
-        skip += archive_le32dec(p + 7);
-      }
-
-      /* Skip over the 2-byte CRC at the beginning of the header. */
-      crc32_expected = archive_le16dec(p);
-      __archive_read_consume(a, 2);
-      skip -= 2;
-
-      /* Skim the entire header and compute the CRC. */
-      crc32_val = 0;
-      while (skip > 0) {
-	      size_t to_read = skip;
-	      if (to_read > 32 * 1024)
-		      to_read = 32 * 1024;
-	      if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
-		      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
-			  "Bad RAR file");
-		      return (ARCHIVE_FATAL);
-	      }
-	      p = h;
-	      crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned int)to_read);
-	      __archive_read_consume(a, to_read);
-	      skip -= to_read;
-      }
-      if ((crc32_val & 0xffff) != crc32_expected) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		  "Header CRC error");
-	      return (ARCHIVE_FATAL);
-#endif
-      }
-      if (head_type == ENDARC_HEAD)
-	      return (ARCHIVE_EOF);
-      break;
-
-    case NEWSUB_HEAD:
-      if ((ret = read_header(a, entry, head_type)) < ARCHIVE_WARN)
-        return ret;
-      break;
-
-    default:
-      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Bad RAR file");
-      return (ARCHIVE_FATAL);
-    }
-  }
-}
-
-static int
-archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
-                                  size_t *size, int64_t *offset)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  int ret;
-
-  if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-	  rar->has_encrypted_entries = 0;
-  }
-
-  if (rar->bytes_unconsumed > 0) {
-      /* Consume as much as the decompressor actually used. */
-      __archive_read_consume(a, rar->bytes_unconsumed);
-      rar->bytes_unconsumed = 0;
-  }
-
-  *buff = NULL;
-  if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
-    *size = 0;
-    *offset = rar->offset;
-    if (*offset < rar->unp_size)
-      *offset = rar->unp_size;
-    return (ARCHIVE_EOF);
-  }
-
-  switch (rar->compression_method)
-  {
-  case COMPRESS_METHOD_STORE:
-    ret = read_data_stored(a, buff, size, offset);
-    break;
-
-  case COMPRESS_METHOD_FASTEST:
-  case COMPRESS_METHOD_FAST:
-  case COMPRESS_METHOD_NORMAL:
-  case COMPRESS_METHOD_GOOD:
-  case COMPRESS_METHOD_BEST:
-    ret = read_data_compressed(a, buff, size, offset, 0);
-    if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
-      __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
-      rar->start_new_table = 1;
-      rar->ppmd_valid = 0;
-    }
-    break;
-
-  default:
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Unsupported compression method for RAR file.");
-    ret = ARCHIVE_FATAL;
-    break;
-  }
-  return (ret);
-}
-
-static int
-archive_read_format_rar_read_data_skip(struct archive_read *a)
-{
-  struct rar *rar;
-  int64_t bytes_skipped;
-  int ret;
-
-  rar = (struct rar *)(a->format->data);
-
-  if (rar->bytes_unconsumed > 0) {
-      /* Consume as much as the decompressor actually used. */
-      __archive_read_consume(a, rar->bytes_unconsumed);
-      rar->bytes_unconsumed = 0;
-  }
-
-  if (rar->bytes_remaining > 0) {
-    bytes_skipped = __archive_read_consume(a, rar->bytes_remaining);
-    if (bytes_skipped < 0)
-      return (ARCHIVE_FATAL);
-  }
-
-  /* Compressed data to skip must be read from each header in a multivolume
-   * archive.
-   */
-  if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
-  {
-    ret = archive_read_format_rar_read_header(a, a->entry);
-    if (ret == (ARCHIVE_EOF))
-      ret = archive_read_format_rar_read_header(a, a->entry);
-    if (ret != (ARCHIVE_OK))
-      return ret;
-    return archive_read_format_rar_read_data_skip(a);
-  }
-
-  return (ARCHIVE_OK);
-}
-
-static int64_t
-archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
-    int whence)
-{
-  int64_t client_offset, ret;
-  unsigned int i;
-  struct rar *rar = (struct rar *)(a->format->data);
-
-  if (rar->compression_method == COMPRESS_METHOD_STORE)
-  {
-    /* Modify the offset for use with SEEK_SET */
-    switch (whence)
-    {
-      case SEEK_CUR:
-        client_offset = rar->offset_seek;
-        break;
-      case SEEK_END:
-        client_offset = rar->unp_size;
-        break;
-      case SEEK_SET:
-      default:
-        client_offset = 0;
-    }
-    client_offset += offset;
-    if (client_offset < 0)
-    {
-      /* Can't seek past beginning of data block */
-      return -1;
-    }
-    else if (client_offset > rar->unp_size)
-    {
-      /*
-       * Set the returned offset but only seek to the end of
-       * the data block.
-       */
-      rar->offset_seek = client_offset;
-      client_offset = rar->unp_size;
-    }
-
-    client_offset += rar->dbo[0].start_offset;
-    i = 0;
-    while (i < rar->cursor)
-    {
-      i++;
-      client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
-    }
-    if (rar->main_flags & MHD_VOLUME)
-    {
-      /* Find the appropriate offset among the multivolume archive */
-      while (1)
-      {
-        if (client_offset < rar->dbo[rar->cursor].start_offset &&
-          rar->file_flags & FHD_SPLIT_BEFORE)
-        {
-          /* Search backwards for the correct data block */
-          if (rar->cursor == 0)
-          {
-            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-              "Attempt to seek past beginning of RAR data block");
-            return (ARCHIVE_FAILED);
-          }
-          rar->cursor--;
-          client_offset -= rar->dbo[rar->cursor+1].start_offset -
-            rar->dbo[rar->cursor].end_offset;
-          if (client_offset < rar->dbo[rar->cursor].start_offset)
-            continue;
-          ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
-            rar->dbo[rar->cursor].header_size, SEEK_SET);
-          if (ret < (ARCHIVE_OK))
-            return ret;
-          ret = archive_read_format_rar_read_header(a, a->entry);
-          if (ret != (ARCHIVE_OK))
-          {
-            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-              "Error during seek of RAR file");
-            return (ARCHIVE_FAILED);
-          }
-          rar->cursor--;
-          break;
-        }
-        else if (client_offset > rar->dbo[rar->cursor].end_offset &&
-          rar->file_flags & FHD_SPLIT_AFTER)
-        {
-          /* Search forward for the correct data block */
-          rar->cursor++;
-          if (rar->cursor < rar->nodes &&
-            client_offset > rar->dbo[rar->cursor].end_offset)
-          {
-            client_offset += rar->dbo[rar->cursor].start_offset -
-              rar->dbo[rar->cursor-1].end_offset;
-            continue;
-          }
-          rar->cursor--;
-          ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
-                                    SEEK_SET);
-          if (ret < (ARCHIVE_OK))
-            return ret;
-          ret = archive_read_format_rar_read_header(a, a->entry);
-          if (ret == (ARCHIVE_EOF))
-          {
-            rar->has_endarc_header = 1;
-            ret = archive_read_format_rar_read_header(a, a->entry);
-          }
-          if (ret != (ARCHIVE_OK))
-          {
-            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-              "Error during seek of RAR file");
-            return (ARCHIVE_FAILED);
-          }
-          client_offset += rar->dbo[rar->cursor].start_offset -
-            rar->dbo[rar->cursor-1].end_offset;
-          continue;
-        }
-        break;
-      }
-    }
-
-    ret = __archive_read_seek(a, client_offset, SEEK_SET);
-    if (ret < (ARCHIVE_OK))
-      return ret;
-    rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
-    i = rar->cursor;
-    while (i > 0)
-    {
-      i--;
-      ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
-    }
-    ret -= rar->dbo[0].start_offset;
-
-    /* Always restart reading the file after a seek */
-    __archive_reset_read_data(&a->archive);
-
-    rar->bytes_unconsumed = 0;
-    rar->offset = 0;
-
-    /*
-     * If a seek past the end of file was requested, return the requested
-     * offset.
-     */
-    if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
-      return rar->offset_seek;
-
-    /* Return the new offset */
-    rar->offset_seek = ret;
-    return rar->offset_seek;
-  }
-  else
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-      "Seeking of compressed RAR files is unsupported");
-  }
-  return (ARCHIVE_FAILED);
-}
-
-static int
-archive_read_format_rar_cleanup(struct archive_read *a)
-{
-  struct rar *rar;
-
-  rar = (struct rar *)(a->format->data);
-  free_codes(a);
-  clear_filters(&rar->filters);
-  free(rar->filename);
-  free(rar->filename_save);
-  free(rar->dbo);
-  free(rar->unp_buffer);
-  free(rar->lzss.window);
-  __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
-  free(rar);
-  (a->format->data) = NULL;
-  return (ARCHIVE_OK);
-}
-
-static int
-read_header(struct archive_read *a, struct archive_entry *entry,
-            char head_type)
-{
-  const void *h;
-  const char *p, *endp;
-  struct rar *rar;
-  struct rar_header rar_header;
-  struct rar_file_header file_header;
-  int64_t header_size;
-  unsigned filename_size, end;
-  char *filename;
-  char *strp;
-  char packed_size[8];
-  char unp_size[8];
-  int ttime;
-  struct archive_string_conv *sconv, *fn_sconv;
-  unsigned long crc32_val;
-  int ret = (ARCHIVE_OK), ret2;
-
-  rar = (struct rar *)(a->format->data);
-
-  /* Setup a string conversion object for non-rar-unicode filenames. */
-  sconv = rar->opt_sconv;
-  if (sconv == NULL) {
-    if (!rar->init_default_conversion) {
-      rar->sconv_default =
-          archive_string_default_conversion_for_read(
-            &(a->archive));
-      rar->init_default_conversion = 1;
-    }
-    sconv = rar->sconv_default;
-  }
-
-
-  if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
-    return (ARCHIVE_FATAL);
-  p = h;
-  memcpy(&rar_header, p, sizeof(rar_header));
-  rar->file_flags = archive_le16dec(rar_header.flags);
-  header_size = archive_le16dec(rar_header.size);
-  if (header_size < (int64_t)sizeof(file_header) + 7) {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-      "Invalid header size");
-    return (ARCHIVE_FATAL);
-  }
-  crc32_val = crc32(0, (const unsigned char *)p + 2, 7 - 2);
-  __archive_read_consume(a, 7);
-
-  if (!(rar->file_flags & FHD_SOLID))
-  {
-    rar->compression_method = 0;
-    rar->packed_size = 0;
-    rar->unp_size = 0;
-    rar->mtime = 0;
-    rar->ctime = 0;
-    rar->atime = 0;
-    rar->arctime = 0;
-    rar->mode = 0;
-    memset(&rar->salt, 0, sizeof(rar->salt));
-    rar->atime = 0;
-    rar->ansec = 0;
-    rar->ctime = 0;
-    rar->cnsec = 0;
-    rar->mtime = 0;
-    rar->mnsec = 0;
-    rar->arctime = 0;
-    rar->arcnsec = 0;
-  }
-  else
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "RAR solid archive support unavailable.");
-    return (ARCHIVE_FATAL);
-  }
-
-  if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
-    return (ARCHIVE_FATAL);
-
-  /* File Header CRC check. */
-  crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
-  if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-      "Header CRC error");
-    return (ARCHIVE_FATAL);
-#endif
-  }
-  /* If no CRC error, Go on parsing File Header. */
-  p = h;
-  endp = p + header_size - 7;
-  memcpy(&file_header, p, sizeof(file_header));
-  p += sizeof(file_header);
-
-  rar->compression_method = file_header.method;
-
-  ttime = archive_le32dec(file_header.file_time);
-  rar->mtime = get_time(ttime);
-
-  rar->file_crc = archive_le32dec(file_header.file_crc);
-
-  if (rar->file_flags & FHD_PASSWORD)
-  {
-	archive_entry_set_is_data_encrypted(entry, 1);
-	rar->has_encrypted_entries = 1;
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "RAR encryption support unavailable.");
-    /* Since it is only the data part itself that is encrypted we can at least
-       extract information about the currently processed entry and don't need
-       to return ARCHIVE_FATAL here. */
-    /*return (ARCHIVE_FATAL);*/
-  }
-
-  if (rar->file_flags & FHD_LARGE)
-  {
-    memcpy(packed_size, file_header.pack_size, 4);
-    memcpy(packed_size + 4, p, 4); /* High pack size */
-    p += 4;
-    memcpy(unp_size, file_header.unp_size, 4);
-    memcpy(unp_size + 4, p, 4); /* High unpack size */
-    p += 4;
-    rar->packed_size = archive_le64dec(&packed_size);
-    rar->unp_size = archive_le64dec(&unp_size);
-  }
-  else
-  {
-    rar->packed_size = archive_le32dec(file_header.pack_size);
-    rar->unp_size = archive_le32dec(file_header.unp_size);
-  }
-
-  if (rar->packed_size < 0 || rar->unp_size < 0)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Invalid sizes specified.");
-    return (ARCHIVE_FATAL);
-  }
-
-  rar->bytes_remaining = rar->packed_size;
-
-  /* TODO: RARv3 subblocks contain comments. For now the complete block is
-   * consumed at the end.
-   */
-  if (head_type == NEWSUB_HEAD) {
-    size_t distance = p - (const char *)h;
-    header_size += rar->packed_size;
-    /* Make sure we have the extended data. */
-    if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
-        return (ARCHIVE_FATAL);
-    p = h;
-    endp = p + header_size - 7;
-    p += distance;
-  }
-
-  filename_size = archive_le16dec(file_header.name_size);
-  if (p + filename_size > endp) {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-      "Invalid filename size");
-    return (ARCHIVE_FATAL);
-  }
-  if (rar->filename_allocated < filename_size * 2 + 2) {
-    char *newptr;
-    size_t newsize = filename_size * 2 + 2;
-    newptr = realloc(rar->filename, newsize);
-    if (newptr == NULL) {
-      archive_set_error(&a->archive, ENOMEM,
-                        "Couldn't allocate memory.");
-      return (ARCHIVE_FATAL);
-    }
-    rar->filename = newptr;
-    rar->filename_allocated = newsize;
-  }
-  filename = rar->filename;
-  memcpy(filename, p, filename_size);
-  filename[filename_size] = '\0';
-  if (rar->file_flags & FHD_UNICODE)
-  {
-    if (filename_size != strlen(filename))
-    {
-      unsigned char highbyte, flagbits, flagbyte;
-      unsigned fn_end, offset;
-
-      end = filename_size;
-      fn_end = filename_size * 2;
-      filename_size = 0;
-      offset = (unsigned)strlen(filename) + 1;
-      highbyte = *(p + offset++);
-      flagbits = 0;
-      flagbyte = 0;
-      while (offset < end && filename_size < fn_end)
-      {
-        if (!flagbits)
-        {
-          flagbyte = *(p + offset++);
-          flagbits = 8;
-        }
-
-        flagbits -= 2;
-        switch((flagbyte >> flagbits) & 3)
-        {
-          case 0:
-            filename[filename_size++] = '\0';
-            filename[filename_size++] = *(p + offset++);
-            break;
-          case 1:
-            filename[filename_size++] = highbyte;
-            filename[filename_size++] = *(p + offset++);
-            break;
-          case 2:
-            filename[filename_size++] = *(p + offset + 1);
-            filename[filename_size++] = *(p + offset);
-            offset += 2;
-            break;
-          case 3:
-          {
-            char extra, high;
-            uint8_t length = *(p + offset++);
-
-            if (length & 0x80) {
-              extra = *(p + offset++);
-              high = (char)highbyte;
-            } else
-              extra = high = 0;
-            length = (length & 0x7f) + 2;
-            while (length && filename_size < fn_end) {
-              unsigned cp = filename_size >> 1;
-              filename[filename_size++] = high;
-              filename[filename_size++] = p[cp] + extra;
-              length--;
-            }
-          }
-          break;
-        }
-      }
-      if (filename_size > fn_end) {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Invalid filename");
-        return (ARCHIVE_FATAL);
-      }
-      filename[filename_size++] = '\0';
-      /*
-       * Do not increment filename_size here as the computations below
-       * add the space for the terminating NUL explicitly.
-       */
-      filename[filename_size] = '\0';
-
-      /* Decoded unicode form is UTF-16BE, so we have to update a string
-       * conversion object for it. */
-      if (rar->sconv_utf16be == NULL) {
-        rar->sconv_utf16be = archive_string_conversion_from_charset(
-           &a->archive, "UTF-16BE", 1);
-        if (rar->sconv_utf16be == NULL)
-          return (ARCHIVE_FATAL);
-      }
-      fn_sconv = rar->sconv_utf16be;
-
-      strp = filename;
-      while (memcmp(strp, "\x00\x00", 2))
-      {
-        if (!memcmp(strp, "\x00\\", 2))
-          *(strp + 1) = '/';
-        strp += 2;
-      }
-      p += offset;
-    } else {
-      /*
-       * If FHD_UNICODE is set but no unicode data, this file name form
-       * is UTF-8, so we have to update a string conversion object for
-       * it accordingly.
-       */
-      if (rar->sconv_utf8 == NULL) {
-        rar->sconv_utf8 = archive_string_conversion_from_charset(
-           &a->archive, "UTF-8", 1);
-        if (rar->sconv_utf8 == NULL)
-          return (ARCHIVE_FATAL);
-      }
-      fn_sconv = rar->sconv_utf8;
-      while ((strp = strchr(filename, '\\')) != NULL)
-        *strp = '/';
-      p += filename_size;
-    }
-  }
-  else
-  {
-    fn_sconv = sconv;
-    while ((strp = strchr(filename, '\\')) != NULL)
-      *strp = '/';
-    p += filename_size;
-  }
-
-  /* Split file in multivolume RAR. No more need to process header. */
-  if (rar->filename_save &&
-    filename_size == rar->filename_save_size &&
-    !memcmp(rar->filename, rar->filename_save, filename_size + 1))
-  {
-    __archive_read_consume(a, header_size - 7);
-    rar->cursor++;
-    if (rar->cursor >= rar->nodes)
-    {
-      rar->nodes++;
-      if ((rar->dbo =
-        realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
-      {
-        archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
-        return (ARCHIVE_FATAL);
-      }
-      rar->dbo[rar->cursor].header_size = header_size;
-      rar->dbo[rar->cursor].start_offset = -1;
-      rar->dbo[rar->cursor].end_offset = -1;
-    }
-    if (rar->dbo[rar->cursor].start_offset < 0)
-    {
-      rar->dbo[rar->cursor].start_offset = a->filter->position;
-      rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
-        rar->packed_size;
-    }
-    return ret;
-  }
-  else if (rar->filename_must_match)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-      "Mismatch of file parts split across multi-volume archive");
-    return (ARCHIVE_FATAL);
-  }
-
-  rar->filename_save = (char*)realloc(rar->filename_save,
-                                      filename_size + 1);
-  memcpy(rar->filename_save, rar->filename, filename_size + 1);
-  rar->filename_save_size = filename_size;
-
-  /* Set info for seeking */
-  free(rar->dbo);
-  if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
-  {
-    archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
-    return (ARCHIVE_FATAL);
-  }
-  rar->dbo[0].header_size = header_size;
-  rar->dbo[0].start_offset = -1;
-  rar->dbo[0].end_offset = -1;
-  rar->cursor = 0;
-  rar->nodes = 1;
-
-  if (rar->file_flags & FHD_SALT)
-  {
-    if (p + 8 > endp) {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-        "Invalid header size");
-      return (ARCHIVE_FATAL);
-    }
-    memcpy(rar->salt, p, 8);
-    p += 8;
-  }
-
-  if (rar->file_flags & FHD_EXTTIME) {
-    if (read_exttime(p, rar, endp) < 0) {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-        "Invalid header size");
-      return (ARCHIVE_FATAL);
-    }
-  }
-
-  __archive_read_consume(a, header_size - 7);
-  rar->dbo[0].start_offset = a->filter->position;
-  rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
-
-  switch(file_header.host_os)
-  {
-  case OS_MSDOS:
-  case OS_OS2:
-  case OS_WIN32:
-    rar->mode = archive_le32dec(file_header.file_attr);
-    if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
-      rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
-    else
-      rar->mode = AE_IFREG;
-    rar->mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-    break;
-
-  case OS_UNIX:
-  case OS_MAC_OS:
-  case OS_BEOS:
-    rar->mode = archive_le32dec(file_header.file_attr);
-    break;
-
-  default:
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Unknown file attributes from RAR file's host OS");
-    return (ARCHIVE_FATAL);
-  }
-
-  rar->bytes_uncopied = rar->bytes_unconsumed = 0;
-  rar->lzss.position = rar->offset = 0;
-  rar->offset_seek = 0;
-  rar->dictionary_size = 0;
-  rar->offset_outgoing = 0;
-  rar->br.cache_avail = 0;
-  rar->br.avail_in = 0;
-  rar->crc_calculated = 0;
-  rar->entry_eof = 0;
-  rar->valid = 1;
-  rar->is_ppmd_block = 0;
-  rar->start_new_table = 1;
-  free(rar->unp_buffer);
-  rar->unp_buffer = NULL;
-  rar->unp_offset = 0;
-  rar->unp_buffer_size = UNP_BUFFER_SIZE;
-  memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
-  __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
-  rar->ppmd_valid = rar->ppmd_eod = 0;
-  rar->filters.filterstart = INT64_MAX;
-
-  /* Don't set any archive entries for non-file header types */
-  if (head_type == NEWSUB_HEAD)
-    return ret;
-
-  archive_entry_set_mtime(entry, rar->mtime, rar->mnsec);
-  archive_entry_set_ctime(entry, rar->ctime, rar->cnsec);
-  archive_entry_set_atime(entry, rar->atime, rar->ansec);
-  archive_entry_set_size(entry, rar->unp_size);
-  archive_entry_set_mode(entry, rar->mode);
-
-  if (archive_entry_copy_pathname_l(entry, filename, filename_size, fn_sconv))
-  {
-    if (errno == ENOMEM)
-    {
-      archive_set_error(&a->archive, ENOMEM,
-                        "Can't allocate memory for Pathname");
-      return (ARCHIVE_FATAL);
-    }
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Pathname cannot be converted from %s to current locale.",
-                      archive_string_conversion_charset_name(fn_sconv));
-    ret = (ARCHIVE_WARN);
-  }
-
-  if (((rar->mode) & AE_IFMT) == AE_IFLNK)
-  {
-    /* Make sure a symbolic-link file does not have its body. */
-    rar->bytes_remaining = 0;
-    archive_entry_set_size(entry, 0);
-
-    /* Read a symbolic-link name. */
-    if ((ret2 = read_symlink_stored(a, entry, sconv)) < (ARCHIVE_WARN))
-      return ret2;
-    if (ret > ret2)
-      ret = ret2;
-  }
-
-  if (rar->bytes_remaining == 0)
-    rar->entry_eof = 1;
-
-  return ret;
-}
-
-static time_t
-get_time(int ttime)
-{
-  struct tm tm;
-  tm.tm_sec = 2 * (ttime & 0x1f);
-  tm.tm_min = (ttime >> 5) & 0x3f;
-  tm.tm_hour = (ttime >> 11) & 0x1f;
-  tm.tm_mday = (ttime >> 16) & 0x1f;
-  tm.tm_mon = ((ttime >> 21) & 0x0f) - 1;
-  tm.tm_year = ((ttime >> 25) & 0x7f) + 80;
-  tm.tm_isdst = -1;
-  return mktime(&tm);
-}
-
-static int
-read_exttime(const char *p, struct rar *rar, const char *endp)
-{
-  unsigned rmode, flags, rem, j, count;
-  int ttime, i;
-  struct tm *tm;
-  time_t t;
-  long nsec;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
-  struct tm tmbuf;
-#endif
-
-  if (p + 2 > endp)
-    return (-1);
-  flags = archive_le16dec(p);
-  p += 2;
-
-  for (i = 3; i >= 0; i--)
-  {
-    t = 0;
-    if (i == 3)
-      t = rar->mtime;
-    rmode = flags >> i * 4;
-    if (rmode & 8)
-    {
-      if (!t)
-      {
-        if (p + 4 > endp)
-          return (-1);
-        ttime = archive_le32dec(p);
-        t = get_time(ttime);
-        p += 4;
-      }
-      rem = 0;
-      count = rmode & 3;
-      if (p + count > endp)
-        return (-1);
-      for (j = 0; j < count; j++)
-      {
-        rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
-        p++;
-      }
-#if defined(HAVE_LOCALTIME_S)
-      tm = localtime_s(&tmbuf, &t) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-      tm = localtime_r(&t, &tmbuf);
-#else
-      tm = localtime(&t);
-#endif
-      nsec = tm->tm_sec + rem / NS_UNIT;
-      if (rmode & 4)
-      {
-        tm->tm_sec++;
-        t = mktime(tm);
-      }
-      if (i == 3)
-      {
-        rar->mtime = t;
-        rar->mnsec = nsec;
-      }
-      else if (i == 2)
-      {
-        rar->ctime = t;
-        rar->cnsec = nsec;
-      }
-      else if (i == 1)
-      {
-        rar->atime = t;
-        rar->ansec = nsec;
-      }
-      else
-      {
-        rar->arctime = t;
-        rar->arcnsec = nsec;
-      }
-    }
-  }
-  return (0);
-}
-
-static int
-read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
-                    struct archive_string_conv *sconv)
-{
-  const void *h;
-  const char *p;
-  struct rar *rar;
-  int ret = (ARCHIVE_OK);
-
-  rar = (struct rar *)(a->format->data);
-  if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
-    return (ARCHIVE_FATAL);
-  p = h;
-
-  if (archive_entry_copy_symlink_l(entry,
-      p, (size_t)rar->packed_size, sconv))
-  {
-    if (errno == ENOMEM)
-    {
-      archive_set_error(&a->archive, ENOMEM,
-                        "Can't allocate memory for link");
-      return (ARCHIVE_FATAL);
-    }
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "link cannot be converted from %s to current locale.",
-                      archive_string_conversion_charset_name(sconv));
-    ret = (ARCHIVE_WARN);
-  }
-  __archive_read_consume(a, rar->packed_size);
-  return ret;
-}
-
-static int
-read_data_stored(struct archive_read *a, const void **buff, size_t *size,
-                 int64_t *offset)
-{
-  struct rar *rar;
-  ssize_t bytes_avail;
-
-  rar = (struct rar *)(a->format->data);
-  if (rar->bytes_remaining == 0 &&
-    !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
-  {
-    *buff = NULL;
-    *size = 0;
-    *offset = rar->offset;
-    if (rar->file_crc != rar->crc_calculated) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "File CRC error");
-      return (ARCHIVE_FATAL);
-#endif
-    }
-    rar->entry_eof = 1;
-    return (ARCHIVE_EOF);
-  }
-
-  *buff = rar_read_ahead(a, 1, &bytes_avail);
-  if (bytes_avail <= 0)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Truncated RAR file data");
-    return (ARCHIVE_FATAL);
-  }
-
-  *size = bytes_avail;
-  *offset = rar->offset;
-  rar->offset += bytes_avail;
-  rar->offset_seek += bytes_avail;
-  rar->bytes_remaining -= bytes_avail;
-  rar->bytes_unconsumed = bytes_avail;
-  /* Calculate File CRC. */
-  rar->crc_calculated = crc32(rar->crc_calculated, *buff,
-    (unsigned)bytes_avail);
-  return (ARCHIVE_OK);
-}
-
-static int
-read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
-                     int64_t *offset, size_t looper)
-{
-  if (looper++ > MAX_COMPRESS_DEPTH)
-    return (ARCHIVE_FATAL);
-
-  struct rar *rar;
-  int64_t start, end;
-  size_t bs;
-  int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i;
-
-  rar = (struct rar *)(a->format->data);
-
-  do {
-    if (!rar->valid)
-      return (ARCHIVE_FATAL);
-
-    if (rar->filters.bytes_ready > 0)
-    {
-      /* Flush unp_buffer first */
-      if (rar->unp_offset > 0)
-      {
-        *buff = rar->unp_buffer;
-        *size = rar->unp_offset;
-        rar->unp_offset = 0;
-        *offset = rar->offset_outgoing;
-        rar->offset_outgoing += *size;
-      }
-      else
-      {
-        *buff = rar->filters.bytes;
-        *size = rar->filters.bytes_ready;
-
-        rar->offset += *size;
-        *offset = rar->offset_outgoing;
-        rar->offset_outgoing += *size;
-
-        rar->filters.bytes_ready -= *size;
-        rar->filters.bytes += *size;
-      }
-      goto ending_block;
-    }
-
-    if (rar->ppmd_eod ||
-       (rar->dictionary_size && rar->offset >= rar->unp_size))
-    {
-      if (rar->unp_offset > 0) {
-        /*
-         * We have unprocessed extracted data. write it out.
-         */
-        *buff = rar->unp_buffer;
-        *size = rar->unp_offset;
-        *offset = rar->offset_outgoing;
-        rar->offset_outgoing += *size;
-        /* Calculate File CRC. */
-        rar->crc_calculated = crc32(rar->crc_calculated, *buff,
-          (unsigned)*size);
-        rar->unp_offset = 0;
-        return (ARCHIVE_OK);
-      }
-      *buff = NULL;
-      *size = 0;
-      *offset = rar->offset;
-      if (rar->file_crc != rar->crc_calculated) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "File CRC error");
-        return (ARCHIVE_FATAL);
-#endif
-      }
-      rar->entry_eof = 1;
-      return (ARCHIVE_EOF);
-    }
-
-    if (!rar->is_ppmd_block && rar->dictionary_size && rar->bytes_uncopied > 0)
-    {
-      if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
-        bs = rar->unp_buffer_size - rar->unp_offset;
-      else
-        bs = (size_t)rar->bytes_uncopied;
-      ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
-      if (ret != ARCHIVE_OK)
-        return (ret);
-      rar->offset += bs;
-      rar->bytes_uncopied -= bs;
-      if (*buff != NULL) {
-        rar->unp_offset = 0;
-        *size = rar->unp_buffer_size;
-        *offset = rar->offset_outgoing;
-        rar->offset_outgoing += *size;
-        /* Calculate File CRC. */
-        rar->crc_calculated = crc32(rar->crc_calculated, *buff,
-          (unsigned)*size);
-        return (ret);
-      }
-      continue;
-    }
-
-    if (rar->filters.lastend == rar->filters.filterstart)
-    {
-      if (!run_filters(a))
-        return (ARCHIVE_FATAL);
-      continue;
-    }
-
-    if (!rar->br.next_in &&
-      (ret = rar_br_preparation(a, &(rar->br))) < ARCHIVE_WARN)
-      return (ret);
-    if (rar->start_new_table && ((ret = parse_codes(a)) < (ARCHIVE_WARN)))
-      return (ret);
-
-    if (rar->is_ppmd_block)
-    {
-      if ((sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-        &rar->ppmd7_context, &rar->range_dec.p)) < 0)
-      {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Invalid symbol");
-        return (ARCHIVE_FATAL);
-      }
-      if(sym != rar->ppmd_escape)
-      {
-        lzss_emit_literal(rar, sym);
-        rar->bytes_uncopied++;
-      }
-      else
-      {
-        if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-          &rar->ppmd7_context, &rar->range_dec.p)) < 0)
-        {
-          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                            "Invalid symbol");
-          return (ARCHIVE_FATAL);
-        }
-
-        switch(code)
-        {
-          case 0:
-            rar->start_new_table = 1;
-            return read_data_compressed(a, buff, size, offset, looper);
-
-          case 2:
-            rar->ppmd_eod = 1;/* End Of ppmd Data. */
-            continue;
-
-          case 3:
-            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-                              "Parsing filters is unsupported.");
-            return (ARCHIVE_FAILED);
-
-          case 4:
-            lzss_offset = 0;
-            for (i = 2; i >= 0; i--)
-            {
-              if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-                &rar->ppmd7_context, &rar->range_dec.p)) < 0)
-              {
-                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                                  "Invalid symbol");
-                return (ARCHIVE_FATAL);
-              }
-              lzss_offset |= code << (i * 8);
-            }
-            if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-              &rar->ppmd7_context, &rar->range_dec.p)) < 0)
-            {
-              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                                "Invalid symbol");
-              return (ARCHIVE_FATAL);
-            }
-            lzss_emit_match(rar, lzss_offset + 2, length + 32);
-            rar->bytes_uncopied += length + 32;
-            break;
-
-          case 5:
-            if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
-              &rar->ppmd7_context, &rar->range_dec.p)) < 0)
-            {
-              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                                "Invalid symbol");
-              return (ARCHIVE_FATAL);
-            }
-            lzss_emit_match(rar, 1, length + 4);
-            rar->bytes_uncopied += length + 4;
-            break;
-
-         default:
-           lzss_emit_literal(rar, sym);
-           rar->bytes_uncopied++;
-        }
-      }
-    }
-    else
-    {
-      start = rar->offset;
-      end = start + rar->dictionary_size;
-      if (rar->filters.filterstart < end) {
-        end = rar->filters.filterstart;
-      }
-
-      ret = expand(a, &end);
-      if (ret != ARCHIVE_OK)
-	      return (ret);
-
-      rar->bytes_uncopied = end - start;
-      rar->filters.lastend = end;
-      if (rar->filters.lastend != rar->filters.filterstart && rar->bytes_uncopied == 0) {
-          /* Broken RAR files cause this case.
-          * NOTE: If this case were possible on a normal RAR file
-          * we would find out where it was actually bad and
-          * what we would do to solve it. */
-          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                            "Internal error extracting RAR file");
-          return (ARCHIVE_FATAL);
-      }
-    }
-    if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
-      bs = rar->unp_buffer_size - rar->unp_offset;
-    else
-      bs = (size_t)rar->bytes_uncopied;
-    ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
-    if (ret != ARCHIVE_OK)
-      return (ret);
-    rar->offset += bs;
-    rar->bytes_uncopied -= bs;
-    /*
-     * If *buff is NULL, it means unp_buffer is not full.
-     * So we have to continue extracting a RAR file.
-     */
-  } while (*buff == NULL);
-
-  rar->unp_offset = 0;
-  *size = rar->unp_buffer_size;
-  *offset = rar->offset_outgoing;
-  rar->offset_outgoing += *size;
-ending_block:
-  /* Calculate File CRC. */
-  rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
-  return ret;
-}
-
-static int
-parse_codes(struct archive_read *a)
-{
-  int i, j, val, n, r;
-  unsigned char bitlengths[MAX_SYMBOLS], zerocount, ppmd_flags;
-  unsigned int maxorder;
-  struct huffman_code precode;
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_br *br = &(rar->br);
-
-  free_codes(a);
-
-  /* Skip to the next byte */
-  rar_br_consume_unalined_bits(br);
-
-  /* PPMd block flag */
-  if (!rar_br_read_ahead(a, br, 1))
-    goto truncated_data;
-  if ((rar->is_ppmd_block = rar_br_bits(br, 1)) != 0)
-  {
-    rar_br_consume(br, 1);
-    if (!rar_br_read_ahead(a, br, 7))
-      goto truncated_data;
-    ppmd_flags = rar_br_bits(br, 7);
-    rar_br_consume(br, 7);
-
-    /* Memory is allocated in MB */
-    if (ppmd_flags & 0x20)
-    {
-      if (!rar_br_read_ahead(a, br, 8))
-        goto truncated_data;
-      rar->dictionary_size = (rar_br_bits(br, 8) + 1) << 20;
-      rar_br_consume(br, 8);
-    }
-
-    if (ppmd_flags & 0x40)
-    {
-      if (!rar_br_read_ahead(a, br, 8))
-        goto truncated_data;
-      rar->ppmd_escape = rar->ppmd7_context.InitEsc = rar_br_bits(br, 8);
-      rar_br_consume(br, 8);
-    }
-    else
-      rar->ppmd_escape = 2;
-
-    if (ppmd_flags & 0x20)
-    {
-      maxorder = (ppmd_flags & 0x1F) + 1;
-      if(maxorder > 16)
-        maxorder = 16 + (maxorder - 16) * 3;
-
-      if (maxorder == 1)
-      {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Truncated RAR file data");
-        return (ARCHIVE_FATAL);
-      }
-
-      /* Make sure ppmd7_contest is freed before Ppmd7_Construct
-       * because reading a broken file cause this abnormal sequence. */
-      __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
-
-      rar->bytein.a = a;
-      rar->bytein.Read = &ppmd_read;
-      __archive_ppmd7_functions.PpmdRAR_RangeDec_CreateVTable(&rar->range_dec);
-      rar->range_dec.Stream = &rar->bytein;
-      __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
-
-      if (rar->dictionary_size == 0) {
-	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Invalid zero dictionary size");
-	      return (ARCHIVE_FATAL);
-      }
-
-      if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
-        rar->dictionary_size))
-      {
-        archive_set_error(&a->archive, ENOMEM,
-                          "Out of memory");
-        return (ARCHIVE_FATAL);
-      }
-      if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec))
-      {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Unable to initialize PPMd range decoder");
-        return (ARCHIVE_FATAL);
-      }
-      __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder);
-      rar->ppmd_valid = 1;
-    }
-    else
-    {
-      if (!rar->ppmd_valid) {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Invalid PPMd sequence");
-        return (ARCHIVE_FATAL);
-      }
-      if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec))
-      {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Unable to initialize PPMd range decoder");
-        return (ARCHIVE_FATAL);
-      }
-    }
-  }
-  else
-  {
-    rar_br_consume(br, 1);
-
-    /* Keep existing table flag */
-    if (!rar_br_read_ahead(a, br, 1))
-      goto truncated_data;
-    if (!rar_br_bits(br, 1))
-      memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
-    rar_br_consume(br, 1);
-
-    memset(&bitlengths, 0, sizeof(bitlengths));
-    for (i = 0; i < MAX_SYMBOLS;)
-    {
-      if (!rar_br_read_ahead(a, br, 4))
-        goto truncated_data;
-      bitlengths[i++] = rar_br_bits(br, 4);
-      rar_br_consume(br, 4);
-      if (bitlengths[i-1] == 0xF)
-      {
-        if (!rar_br_read_ahead(a, br, 4))
-          goto truncated_data;
-        zerocount = rar_br_bits(br, 4);
-        rar_br_consume(br, 4);
-        if (zerocount)
-        {
-          i--;
-          for (j = 0; j < zerocount + 2 && i < MAX_SYMBOLS; j++)
-            bitlengths[i++] = 0;
-        }
-      }
-    }
-
-    memset(&precode, 0, sizeof(precode));
-    r = create_code(a, &precode, bitlengths, MAX_SYMBOLS, MAX_SYMBOL_LENGTH);
-    if (r != ARCHIVE_OK) {
-      free(precode.tree);
-      free(precode.table);
-      return (r);
-    }
-
-    for (i = 0; i < HUFFMAN_TABLE_SIZE;)
-    {
-      if ((val = read_next_symbol(a, &precode)) < 0) {
-        free(precode.tree);
-        free(precode.table);
-        return (ARCHIVE_FATAL);
-      }
-      if (val < 16)
-      {
-        rar->lengthtable[i] = (rar->lengthtable[i] + val) & 0xF;
-        i++;
-      }
-      else if (val < 18)
-      {
-        if (i == 0)
-        {
-          free(precode.tree);
-          free(precode.table);
-          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                            "Internal error extracting RAR file.");
-          return (ARCHIVE_FATAL);
-        }
-
-        if(val == 16) {
-          if (!rar_br_read_ahead(a, br, 3)) {
-            free(precode.tree);
-            free(precode.table);
-            goto truncated_data;
-          }
-          n = rar_br_bits(br, 3) + 3;
-          rar_br_consume(br, 3);
-        } else {
-          if (!rar_br_read_ahead(a, br, 7)) {
-            free(precode.tree);
-            free(precode.table);
-            goto truncated_data;
-          }
-          n = rar_br_bits(br, 7) + 11;
-          rar_br_consume(br, 7);
-        }
-
-        for (j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++)
-        {
-          rar->lengthtable[i] = rar->lengthtable[i-1];
-          i++;
-        }
-      }
-      else
-      {
-        if(val == 18) {
-          if (!rar_br_read_ahead(a, br, 3)) {
-            free(precode.tree);
-            free(precode.table);
-            goto truncated_data;
-          }
-          n = rar_br_bits(br, 3) + 3;
-          rar_br_consume(br, 3);
-        } else {
-          if (!rar_br_read_ahead(a, br, 7)) {
-            free(precode.tree);
-            free(precode.table);
-            goto truncated_data;
-          }
-          n = rar_br_bits(br, 7) + 11;
-          rar_br_consume(br, 7);
-        }
-
-        for(j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++)
-          rar->lengthtable[i++] = 0;
-      }
-    }
-    free(precode.tree);
-    free(precode.table);
-
-    r = create_code(a, &rar->maincode, &rar->lengthtable[0], MAINCODE_SIZE,
-                MAX_SYMBOL_LENGTH);
-    if (r != ARCHIVE_OK)
-      return (r);
-    r = create_code(a, &rar->offsetcode, &rar->lengthtable[MAINCODE_SIZE],
-                OFFSETCODE_SIZE, MAX_SYMBOL_LENGTH);
-    if (r != ARCHIVE_OK)
-      return (r);
-    r = create_code(a, &rar->lowoffsetcode,
-                &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE],
-                LOWOFFSETCODE_SIZE, MAX_SYMBOL_LENGTH);
-    if (r != ARCHIVE_OK)
-      return (r);
-    r = create_code(a, &rar->lengthcode,
-                &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE +
-                LOWOFFSETCODE_SIZE], LENGTHCODE_SIZE, MAX_SYMBOL_LENGTH);
-    if (r != ARCHIVE_OK)
-      return (r);
-  }
-
-  if (!rar->dictionary_size || !rar->lzss.window)
-  {
-    /* Seems as though dictionary sizes are not used. Even so, minimize
-     * memory usage as much as possible.
-     */
-    void *new_window;
-    unsigned int new_size;
-
-    if (rar->unp_size >= DICTIONARY_MAX_SIZE)
-      new_size = DICTIONARY_MAX_SIZE;
-    else
-      new_size = rar_fls((unsigned int)rar->unp_size) << 1;
-    if (new_size == 0) {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Zero window size is invalid.");
-      return (ARCHIVE_FATAL);
-    }
-    new_window = realloc(rar->lzss.window, new_size);
-    if (new_window == NULL) {
-      archive_set_error(&a->archive, ENOMEM,
-                        "Unable to allocate memory for uncompressed data.");
-      return (ARCHIVE_FATAL);
-    }
-    rar->lzss.window = (unsigned char *)new_window;
-    rar->dictionary_size = new_size;
-    memset(rar->lzss.window, 0, rar->dictionary_size);
-    rar->lzss.mask = rar->dictionary_size - 1;
-  }
-
-  rar->start_new_table = 0;
-  return (ARCHIVE_OK);
-truncated_data:
-  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                    "Truncated RAR file data");
-  rar->valid = 0;
-  return (ARCHIVE_FATAL);
-}
-
-static void
-free_codes(struct archive_read *a)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  free(rar->maincode.tree);
-  free(rar->offsetcode.tree);
-  free(rar->lowoffsetcode.tree);
-  free(rar->lengthcode.tree);
-  free(rar->maincode.table);
-  free(rar->offsetcode.table);
-  free(rar->lowoffsetcode.table);
-  free(rar->lengthcode.table);
-  memset(&rar->maincode, 0, sizeof(rar->maincode));
-  memset(&rar->offsetcode, 0, sizeof(rar->offsetcode));
-  memset(&rar->lowoffsetcode, 0, sizeof(rar->lowoffsetcode));
-  memset(&rar->lengthcode, 0, sizeof(rar->lengthcode));
-}
-
-
-static int
-read_next_symbol(struct archive_read *a, struct huffman_code *code)
-{
-  unsigned char bit;
-  unsigned int bits;
-  int length, value, node;
-  struct rar *rar;
-  struct rar_br *br;
-
-  if (!code->table)
-  {
-    if (make_table(a, code) != (ARCHIVE_OK))
-      return -1;
-  }
-
-  rar = (struct rar *)(a->format->data);
-  br = &(rar->br);
-
-  /* Look ahead (peek) at bits */
-  if (!rar_br_read_ahead(a, br, code->tablesize)) {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Truncated RAR file data");
-    rar->valid = 0;
-    return -1;
-  }
-  bits = rar_br_bits(br, code->tablesize);
-
-  length = code->table[bits].length;
-  value = code->table[bits].value;
-
-  if (length < 0)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Invalid prefix code in bitstream");
-    return -1;
-  }
-
-  if (length <= code->tablesize)
-  {
-    /* Skip length bits */
-    rar_br_consume(br, length);
-    return value;
-  }
-
-  /* Skip tablesize bits */
-  rar_br_consume(br, code->tablesize);
-
-  node = value;
-  while (!(code->tree[node].branches[0] ==
-    code->tree[node].branches[1]))
-  {
-    if (!rar_br_read_ahead(a, br, 1)) {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Truncated RAR file data");
-      rar->valid = 0;
-      return -1;
-    }
-    bit = rar_br_bits(br, 1);
-    rar_br_consume(br, 1);
-
-    if (code->tree[node].branches[bit] < 0)
-    {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Invalid prefix code in bitstream");
-      return -1;
-    }
-    node = code->tree[node].branches[bit];
-  }
-
-  return code->tree[node].branches[0];
-}
-
-static int
-create_code(struct archive_read *a, struct huffman_code *code,
-            unsigned char *lengths, int numsymbols, char maxlength)
-{
-  int i, j, codebits = 0, symbolsleft = numsymbols;
-
-  code->numentries = 0;
-  code->numallocatedentries = 0;
-  if (new_node(code) < 0) {
-    archive_set_error(&a->archive, ENOMEM,
-                      "Unable to allocate memory for node data.");
-    return (ARCHIVE_FATAL);
-  }
-  code->numentries = 1;
-  code->minlength = INT_MAX;
-  code->maxlength = INT_MIN;
-  codebits = 0;
-  for(i = 1; i <= maxlength; i++)
-  {
-    for(j = 0; j < numsymbols; j++)
-    {
-      if (lengths[j] != i) continue;
-      if (add_value(a, code, j, codebits, i) != ARCHIVE_OK)
-        return (ARCHIVE_FATAL);
-      codebits++;
-      if (--symbolsleft <= 0)
-        break;
-    }
-    if (symbolsleft <= 0)
-      break;
-    codebits <<= 1;
-  }
-  return (ARCHIVE_OK);
-}
-
-static int
-add_value(struct archive_read *a, struct huffman_code *code, int value,
-          int codebits, int length)
-{
-  int lastnode, bitpos, bit;
-  /* int repeatpos, repeatnode, nextnode; */
-
-  free(code->table);
-  code->table = NULL;
-
-  if(length > code->maxlength)
-    code->maxlength = length;
-  if(length < code->minlength)
-    code->minlength = length;
-
-  /*
-   * Dead code, repeatpos was is -1
-   *
-  repeatpos = -1;
-  if (repeatpos == 0 || (repeatpos >= 0
-    && (((codebits >> (repeatpos - 1)) & 3) == 0
-    || ((codebits >> (repeatpos - 1)) & 3) == 3)))
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Invalid repeat position");
-    return (ARCHIVE_FATAL);
-  }
-  */
-
-  lastnode = 0;
-  for (bitpos = length - 1; bitpos >= 0; bitpos--)
-  {
-    bit = (codebits >> bitpos) & 1;
-
-    /* Leaf node check */
-    if (code->tree[lastnode].branches[0] ==
-      code->tree[lastnode].branches[1])
-    {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Prefix found");
-      return (ARCHIVE_FATAL);
-    }
-
-    /*
-     * Dead code, repeatpos was -1, bitpos >=0
-     *
-    if (bitpos == repeatpos)
-    {
-      * Open branch check *
-      if (!(code->tree[lastnode].branches[bit] < 0))
-      {
-        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                          "Invalid repeating code");
-        return (ARCHIVE_FATAL);
-      }
-
-      if ((repeatnode = new_node(code)) < 0) {
-        archive_set_error(&a->archive, ENOMEM,
-                          "Unable to allocate memory for node data.");
-        return (ARCHIVE_FATAL);
-      }
-      if ((nextnode = new_node(code)) < 0) {
-        archive_set_error(&a->archive, ENOMEM,
-                          "Unable to allocate memory for node data.");
-        return (ARCHIVE_FATAL);
-      }
-
-      * Set branches *
-      code->tree[lastnode].branches[bit] = repeatnode;
-      code->tree[repeatnode].branches[bit] = repeatnode;
-      code->tree[repeatnode].branches[bit^1] = nextnode;
-      lastnode = nextnode;
-
-      bitpos++; * terminating bit already handled, skip it *
-    }
-    else
-    {
-    */
-      /* Open branch check */
-      if (code->tree[lastnode].branches[bit] < 0)
-      {
-        if (new_node(code) < 0) {
-          archive_set_error(&a->archive, ENOMEM,
-                            "Unable to allocate memory for node data.");
-          return (ARCHIVE_FATAL);
-        }
-        code->tree[lastnode].branches[bit] = code->numentries++;
-      }
-
-      /* set to branch */
-      lastnode = code->tree[lastnode].branches[bit];
- /* } */
-  }
-
-  if (!(code->tree[lastnode].branches[0] == -1
-    && code->tree[lastnode].branches[1] == -2))
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Prefix found");
-    return (ARCHIVE_FATAL);
-  }
-
-  /* Set leaf value */
-  code->tree[lastnode].branches[0] = value;
-  code->tree[lastnode].branches[1] = value;
-
-  return (ARCHIVE_OK);
-}
-
-static int
-new_node(struct huffman_code *code)
-{
-  void *new_tree;
-  if (code->numallocatedentries == code->numentries) {
-    int new_num_entries = 256;
-    if (code->numentries > 0) {
-        new_num_entries = code->numentries * 2;
-    }
-    new_tree = realloc(code->tree, new_num_entries * sizeof(*code->tree));
-    if (new_tree == NULL)
-        return (-1);
-    code->tree = (struct huffman_tree_node *)new_tree;
-    code->numallocatedentries = new_num_entries;
-  }
-  code->tree[code->numentries].branches[0] = -1;
-  code->tree[code->numentries].branches[1] = -2;
-  return 1;
-}
-
-static int
-make_table(struct archive_read *a, struct huffman_code *code)
-{
-  if (code->maxlength < code->minlength || code->maxlength > 10)
-    code->tablesize = 10;
-  else
-    code->tablesize = code->maxlength;
-
-  code->table =
-    (struct huffman_table_entry *)calloc(1, sizeof(*code->table)
-    * ((size_t)1 << code->tablesize));
-
-  return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
-}
-
-static int
-make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
-                   struct huffman_table_entry *table, int depth,
-                   int maxdepth)
-{
-  int currtablesize, i, ret = (ARCHIVE_OK);
-
-  if (!code->tree)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Huffman tree was not created.");
-    return (ARCHIVE_FATAL);
-  }
-  if (node < 0 || node >= code->numentries)
-  {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Invalid location to Huffman tree specified.");
-    return (ARCHIVE_FATAL);
-  }
-
-  currtablesize = 1 << (maxdepth - depth);
-
-  if (code->tree[node].branches[0] ==
-    code->tree[node].branches[1])
-  {
-    for(i = 0; i < currtablesize; i++)
-    {
-      table[i].length = depth;
-      table[i].value = code->tree[node].branches[0];
-    }
-  }
-  /*
-   * Dead code, node >= 0
-   *
-  else if (node < 0)
-  {
-    for(i = 0; i < currtablesize; i++)
-      table[i].length = -1;
-  }
-   */
-  else
-  {
-    if(depth == maxdepth)
-    {
-      table[0].length = maxdepth + 1;
-      table[0].value = node;
-    }
-    else
-    {
-      ret |= make_table_recurse(a, code, code->tree[node].branches[0], table,
-                                depth + 1, maxdepth);
-      ret |= make_table_recurse(a, code, code->tree[node].branches[1],
-                         table + currtablesize / 2, depth + 1, maxdepth);
-    }
-  }
-  return ret;
-}
-
-static int
-expand(struct archive_read *a, int64_t *end)
-{
-  static const unsigned char lengthbases[] =
-    {   0,   1,   2,   3,   4,   5,   6,
-        7,   8,  10,  12,  14,  16,  20,
-       24,  28,  32,  40,  48,  56,  64,
-       80,  96, 112, 128, 160, 192, 224 };
-  static const unsigned char lengthbits[] =
-    { 0, 0, 0, 0, 0, 0, 0,
-      0, 1, 1, 1, 1, 2, 2,
-      2, 2, 3, 3, 3, 3, 4,
-      4, 4, 4, 5, 5, 5, 5 };
-  static const int lengthb_min = minimum(
-    (int)(sizeof(lengthbases)/sizeof(lengthbases[0])),
-    (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))
-  );
-  static const unsigned int offsetbases[] =
-    {       0,       1,       2,       3,       4,       6,
-            8,      12,      16,      24,      32,      48,
-           64,      96,     128,     192,     256,     384,
-          512,     768,    1024,    1536,    2048,    3072,
-         4096,    6144,    8192,   12288,   16384,   24576,
-        32768,   49152,   65536,   98304,  131072,  196608,
-       262144,  327680,  393216,  458752,  524288,  589824,
-       655360,  720896,  786432,  851968,  917504,  983040,
-      1048576, 1310720, 1572864, 1835008, 2097152, 2359296,
-      2621440, 2883584, 3145728, 3407872, 3670016, 3932160 };
-  static const unsigned char offsetbits[] =
-    {  0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,
-       5,  5,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10,
-      11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
-      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
-      18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
-  static const int offsetb_min = minimum(
-    (int)(sizeof(offsetbases)/sizeof(offsetbases[0])),
-    (int)(sizeof(offsetbits)/sizeof(offsetbits[0]))
-  );
-  static const unsigned char shortbases[] =
-    { 0, 4, 8, 16, 32, 64, 128, 192 };
-  static const unsigned char shortbits[] =
-    { 2, 2, 3, 4, 5, 6, 6, 6 };
-
-  int symbol, offs, len, offsindex, lensymbol, i, offssymbol, lowoffsetsymbol;
-  unsigned char newfile;
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_br *br = &(rar->br);
-
-  if (rar->filters.filterstart < *end)
-    *end = rar->filters.filterstart;
-
-  while (1)
-  {
-    if(lzss_position(&rar->lzss) >= *end) {
-      return (ARCHIVE_OK);
-    }
-
-    if(rar->is_ppmd_block) {
-      *end = lzss_position(&rar->lzss);
-      return (ARCHIVE_OK);
-    }
-
-    if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
-      return (ARCHIVE_FATAL);
-
-    if (symbol < 256)
-    {
-      lzss_emit_literal(rar, symbol);
-      continue;
-    }
-    else if (symbol == 256)
-    {
-      if (!rar_br_read_ahead(a, br, 1))
-        goto truncated_data;
-      newfile = !rar_br_bits(br, 1);
-      rar_br_consume(br, 1);
-
-      if(newfile)
-      {
-        rar->start_new_block = 1;
-        if (!rar_br_read_ahead(a, br, 1))
-          goto truncated_data;
-        rar->start_new_table = rar_br_bits(br, 1);
-        rar_br_consume(br, 1);
-        *end = lzss_position(&rar->lzss);
-        return (ARCHIVE_OK);
-      }
-      else
-      {
-        if (parse_codes(a) != ARCHIVE_OK)
-          return (ARCHIVE_FATAL);
-        continue;
-      }
-    }
-    else if(symbol==257)
-    {
-      if (!read_filter(a, end))
-          return (ARCHIVE_FATAL);
-      continue;
-    }
-    else if(symbol==258)
-    {
-      if(rar->lastlength == 0)
-        continue;
-
-      offs = rar->lastoffset;
-      len = rar->lastlength;
-    }
-    else if (symbol <= 262)
-    {
-      offsindex = symbol - 259;
-      offs = rar->oldoffset[offsindex];
-
-      if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0)
-        goto bad_data;
-      if (lensymbol > lengthb_min)
-        goto bad_data;
-      len = lengthbases[lensymbol] + 2;
-      if (lengthbits[lensymbol] > 0) {
-        if (!rar_br_read_ahead(a, br, lengthbits[lensymbol]))
-          goto truncated_data;
-        len += rar_br_bits(br, lengthbits[lensymbol]);
-        rar_br_consume(br, lengthbits[lensymbol]);
-      }
-
-      for (i = offsindex; i > 0; i--)
-        rar->oldoffset[i] = rar->oldoffset[i-1];
-      rar->oldoffset[0] = offs;
-    }
-    else if(symbol<=270)
-    {
-      offs = shortbases[symbol-263] + 1;
-      if(shortbits[symbol-263] > 0) {
-        if (!rar_br_read_ahead(a, br, shortbits[symbol-263]))
-          goto truncated_data;
-        offs += rar_br_bits(br, shortbits[symbol-263]);
-        rar_br_consume(br, shortbits[symbol-263]);
-      }
-
-      len = 2;
-
-      for(i = 3; i > 0; i--)
-        rar->oldoffset[i] = rar->oldoffset[i-1];
-      rar->oldoffset[0] = offs;
-    }
-    else
-    {
-      if (symbol-271 > lengthb_min)
-        goto bad_data;
-      len = lengthbases[symbol-271]+3;
-      if(lengthbits[symbol-271] > 0) {
-        if (!rar_br_read_ahead(a, br, lengthbits[symbol-271]))
-          goto truncated_data;
-        len += rar_br_bits(br, lengthbits[symbol-271]);
-        rar_br_consume(br, lengthbits[symbol-271]);
-      }
-
-      if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0)
-        goto bad_data;
-      if (offssymbol > offsetb_min)
-        goto bad_data;
-      offs = offsetbases[offssymbol]+1;
-      if(offsetbits[offssymbol] > 0)
-      {
-        if(offssymbol > 9)
-        {
-          if(offsetbits[offssymbol] > 4) {
-            if (!rar_br_read_ahead(a, br, offsetbits[offssymbol] - 4))
-              goto truncated_data;
-            offs += rar_br_bits(br, offsetbits[offssymbol] - 4) << 4;
-            rar_br_consume(br, offsetbits[offssymbol] - 4);
-          }
-
-          if(rar->numlowoffsetrepeats > 0)
-          {
-            rar->numlowoffsetrepeats--;
-            offs += rar->lastlowoffset;
-          }
-          else
-          {
-            if ((lowoffsetsymbol =
-              read_next_symbol(a, &rar->lowoffsetcode)) < 0)
-              return (ARCHIVE_FATAL);
-            if(lowoffsetsymbol == 16)
-            {
-              rar->numlowoffsetrepeats = 15;
-              offs += rar->lastlowoffset;
-            }
-            else
-            {
-              offs += lowoffsetsymbol;
-              rar->lastlowoffset = lowoffsetsymbol;
-            }
-          }
-        }
-        else {
-          if (!rar_br_read_ahead(a, br, offsetbits[offssymbol]))
-            goto truncated_data;
-          offs += rar_br_bits(br, offsetbits[offssymbol]);
-          rar_br_consume(br, offsetbits[offssymbol]);
-        }
-      }
-
-      if (offs >= 0x40000)
-        len++;
-      if (offs >= 0x2000)
-        len++;
-
-      for(i = 3; i > 0; i--)
-        rar->oldoffset[i] = rar->oldoffset[i-1];
-      rar->oldoffset[0] = offs;
-    }
-
-    rar->lastoffset = offs;
-    rar->lastlength = len;
-
-    lzss_emit_match(rar, rar->lastoffset, rar->lastlength);
-  }
-truncated_data:
-  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                    "Truncated RAR file data");
-  rar->valid = 0;
-  return (ARCHIVE_FATAL);
-bad_data:
-  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                    "Bad RAR file data");
-  return (ARCHIVE_FATAL);
-}
-
-static int
-copy_from_lzss_window(struct archive_read *a, void *buffer,
-                      int64_t startpos, int length)
-{
-  int windowoffs, firstpart;
-  struct rar *rar = (struct rar *)(a->format->data);
-
-  windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
-  firstpart = lzss_size(&rar->lzss) - windowoffs;
-  if (firstpart < 0) {
-    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                      "Bad RAR file data");
-    return (ARCHIVE_FATAL);
-  }
-  if (firstpart < length) {
-    memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
-    memcpy(buffer, &rar->lzss.window[0], length - firstpart);
-  } else {
-    memcpy(buffer, &rar->lzss.window[windowoffs], length);
-  }
-  return (ARCHIVE_OK);
-}
-
-static int
-copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer,
-                             int64_t startpos, int length)
-{
-  int windowoffs, firstpart;
-  struct rar *rar = (struct rar *)(a->format->data);
-
-  if (!rar->unp_buffer)
-  {
-    if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL)
-    {
-      archive_set_error(&a->archive, ENOMEM,
-                        "Unable to allocate memory for uncompressed data.");
-      return (ARCHIVE_FATAL);
-    }
-  }
-
-  windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
-  if(windowoffs + length <= lzss_size(&rar->lzss)) {
-    memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs],
-           length);
-  } else if (length <= lzss_size(&rar->lzss)) {
-    firstpart = lzss_size(&rar->lzss) - windowoffs;
-    if (firstpart < 0) {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Bad RAR file data");
-      return (ARCHIVE_FATAL);
-    }
-    if (firstpart < length) {
-      memcpy(&rar->unp_buffer[rar->unp_offset],
-             &rar->lzss.window[windowoffs], firstpart);
-      memcpy(&rar->unp_buffer[rar->unp_offset + firstpart],
-             &rar->lzss.window[0], length - firstpart);
-    } else {
-      memcpy(&rar->unp_buffer[rar->unp_offset],
-             &rar->lzss.window[windowoffs], length);
-    }
-  } else {
-      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-                        "Bad RAR file data");
-      return (ARCHIVE_FATAL);
-  }
-  rar->unp_offset += length;
-  if (rar->unp_offset >= rar->unp_buffer_size)
-    *buffer = rar->unp_buffer;
-  else
-    *buffer = NULL;
-  return (ARCHIVE_OK);
-}
-
-static const void *
-rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  const void *h = __archive_read_ahead(a, min, avail);
-  int ret;
-  if (avail)
-  {
-    if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
-      *avail = a->archive.read_data_requested;
-    if (*avail > rar->bytes_remaining)
-      *avail = (ssize_t)rar->bytes_remaining;
-    if (*avail < 0)
-      return NULL;
-    else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
-      rar->file_flags & FHD_SPLIT_AFTER)
-    {
-      rar->filename_must_match = 1;
-      ret = archive_read_format_rar_read_header(a, a->entry);
-      if (ret == (ARCHIVE_EOF))
-      {
-        rar->has_endarc_header = 1;
-        ret = archive_read_format_rar_read_header(a, a->entry);
-      }
-      rar->filename_must_match = 0;
-      if (ret != (ARCHIVE_OK))
-        return NULL;
-      return rar_read_ahead(a, min, avail);
-    }
-  }
-  return h;
-}
-
-static int
-parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint8_t flags)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_filters *filters = &rar->filters;
-
-  struct memory_bit_reader br = { 0 };
-  struct rar_program_code *prog;
-  struct rar_filter *filter, **nextfilter;
-
-  uint32_t numprogs, num, blocklength, globaldatalen;
-  uint8_t *globaldata;
-  size_t blockstartpos;
-  uint32_t registers[8] = { 0 };
-  uint32_t i;
-
-  br.bytes = bytes;
-  br.length = length;
-
-  numprogs = 0;
-  for (prog = filters->progs; prog; prog = prog->next)
-    numprogs++;
-
-  if ((flags & 0x80))
-  {
-    num = membr_next_rarvm_number(&br);
-    if (num == 0)
-    {
-      delete_filter(filters->stack);
-      filters->stack = NULL;
-      delete_program_code(filters->progs);
-      filters->progs = NULL;
-    }
-    else
-      num--;
-    if (num > numprogs) {
-      return 0;
-    }
-    filters->lastfilternum = num;
-  }
-  else
-    num = filters->lastfilternum;
-
-  prog = filters->progs;
-  for (i = 0; i < num; i++)
-    prog = prog->next;
-  if (prog)
-    prog->usagecount++;
-
-  blockstartpos = membr_next_rarvm_number(&br) + (size_t)lzss_position(&rar->lzss);
-  if ((flags & 0x40))
-    blockstartpos += 258;
-  if ((flags & 0x20))
-    blocklength = membr_next_rarvm_number(&br);
-  else
-    blocklength = prog ? prog->oldfilterlength : 0;
-
-  registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
-  registers[4] = blocklength;
-  registers[5] = prog ? prog->usagecount : 0;
-  registers[7] = VM_MEMORY_SIZE;
-
-  if ((flags & 0x10))
-  {
-    uint8_t mask = (uint8_t)membr_bits(&br, 7);
-    for (i = 0; i < 7; i++)
-      if ((mask & (1 << i)))
-        registers[i] = membr_next_rarvm_number(&br);
-  }
-
-  if (!prog)
-  {
-    uint32_t len = membr_next_rarvm_number(&br);
-    uint8_t *bytecode;
-    struct rar_program_code **next;
-
-    if (len == 0 || len > 0x10000)
-      return 0;
-    bytecode = malloc(len);
-    if (!bytecode)
-      return 0;
-    for (i = 0; i < len; i++)
-      bytecode[i] = (uint8_t)membr_bits(&br, 8);
-    prog = compile_program(bytecode, len);
-    if (!prog) {
-      free(bytecode);
-      return 0;
-    }
-    free(bytecode);
-    next = &filters->progs;
-    while (*next)
-      next = &(*next)->next;
-    *next = prog;
-  }
-  prog->oldfilterlength = blocklength;
-
-  globaldata = NULL;
-  globaldatalen = 0;
-  if ((flags & 0x08))
-  {
-    globaldatalen = membr_next_rarvm_number(&br);
-    if (globaldatalen > PROGRAM_USER_GLOBAL_SIZE)
-      return 0;
-    globaldata = malloc(globaldatalen + PROGRAM_SYSTEM_GLOBAL_SIZE);
-    if (!globaldata)
-      return 0;
-    for (i = 0; i < globaldatalen; i++)
-      globaldata[i + PROGRAM_SYSTEM_GLOBAL_SIZE] = (uint8_t)membr_bits(&br, 8);
-  }
-
-  if (br.at_eof)
-  {
-      free(globaldata);
-      return 0;
-  }
-
-  filter = create_filter(prog, globaldata, globaldatalen, registers, blockstartpos, blocklength);
-  free(globaldata);
-  if (!filter)
-    return 0;
-
-  for (i = 0; i < 7; i++)
-    archive_le32enc(&filter->globaldata[i * 4], registers[i]);
-  archive_le32enc(&filter->globaldata[0x1C], blocklength);
-  archive_le32enc(&filter->globaldata[0x20], 0);
-  archive_le32enc(&filter->globaldata[0x2C], prog->usagecount);
-
-  nextfilter = &filters->stack;
-  while (*nextfilter)
-    nextfilter = &(*nextfilter)->next;
-  *nextfilter = filter;
-
-  if (!filters->stack->next)
-    filters->filterstart = blockstartpos;
-
-  return 1;
-}
-
-static struct rar_filter *
-create_filter(struct rar_program_code *prog, const uint8_t *globaldata, uint32_t globaldatalen, uint32_t registers[8], size_t startpos, uint32_t length)
-{
-  struct rar_filter *filter;
-
-  filter = calloc(1, sizeof(*filter));
-  if (!filter)
-    return NULL;
-  filter->prog = prog;
-  filter->globaldatalen = globaldatalen > PROGRAM_SYSTEM_GLOBAL_SIZE ? globaldatalen : PROGRAM_SYSTEM_GLOBAL_SIZE;
-  filter->globaldata = calloc(1, filter->globaldatalen);
-  if (!filter->globaldata)
-    return NULL;
-  if (globaldata)
-    memcpy(filter->globaldata, globaldata, globaldatalen);
-  if (registers)
-    memcpy(filter->initialregisters, registers, sizeof(filter->initialregisters));
-  filter->blockstartpos = startpos;
-  filter->blocklength = length;
-
-  return filter;
-}
-
-static int
-run_filters(struct archive_read *a)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_filters *filters = &rar->filters;
-  struct rar_filter *filter = filters->stack;
-  struct rar_filter *f;
-  size_t start, end;
-  int64_t tend;
-  uint32_t lastfilteraddress;
-  uint32_t lastfilterlength;
-  int ret;
-
-  if (filters == NULL || filter == NULL)
-    return (0);
-
-  start = filters->filterstart;
-  end = start + filter->blocklength;
-
-  filters->filterstart = INT64_MAX;
-  tend = (int64_t)end;
-  ret = expand(a, &tend);
-  if (ret != ARCHIVE_OK)
-    return 0;
-
-  /* Check if filter stack was modified in expand() */
-  ret = ARCHIVE_FATAL;
-  f = filters->stack;
-  while (f)
-  {
-    if (f == filter)
-    {
-      ret = ARCHIVE_OK;
-      break;
-    }
-    f = f->next;
-  }
-  if (ret != ARCHIVE_OK)
-    return 0;
-
-  if (tend < 0)
-    return 0;
-  end = (size_t)tend;
-  if (end != start + filter->blocklength)
-    return 0;
-
-  if (!filters->vm)
-  {
-    filters->vm = calloc(1, sizeof(*filters->vm));
-    if (!filters->vm)
-      return 0;
-  }
-
-  ret = copy_from_lzss_window(a, filters->vm->memory, start, filter->blocklength);
-  if (ret != ARCHIVE_OK)
-    return 0;
-  if (!execute_filter(a, filter, filters->vm, rar->offset))
-    return 0;
-
-  lastfilteraddress = filter->filteredblockaddress;
-  lastfilterlength = filter->filteredblocklength;
-  filters->stack = filter->next;
-  filter->next = NULL;
-  delete_filter(filter);
-
-  while ((filter = filters->stack) != NULL && (int64_t)filter->blockstartpos == filters->filterstart && filter->blocklength == lastfilterlength)
-  {
-    memmove(&filters->vm->memory[0], &filters->vm->memory[lastfilteraddress], lastfilterlength);
-    if (!execute_filter(a, filter, filters->vm, rar->offset))
-      return 0;
-
-    lastfilteraddress = filter->filteredblockaddress;
-    lastfilterlength = filter->filteredblocklength;
-    filters->stack = filter->next;
-    filter->next = NULL;
-    delete_filter(filter);
-  }
-
-  if (filters->stack)
-  {
-    if (filters->stack->blockstartpos < end)
-      return 0;
-    filters->filterstart = filters->stack->blockstartpos;
-  }
-
-  filters->lastend = end;
-  filters->bytes = &filters->vm->memory[lastfilteraddress];
-  filters->bytes_ready = lastfilterlength;
-
-  return 1;
-}
-
-static struct rar_program_code *
-compile_program(const uint8_t *bytes, size_t length)
-{
-  struct memory_bit_reader br = { 0 };
-  struct rar_program_code *prog;
-  // uint32_t instrcount = 0;
-  uint8_t xor;
-  size_t i;
-
-  xor = 0;
-  for (i = 1; i < length; i++)
-    xor ^= bytes[i];
-  if (!length || xor != bytes[0])
-    return NULL;
-
-  br.bytes = bytes;
-  br.length = length;
-  br.offset = 1;
-
-  prog = calloc(1, sizeof(*prog));
-  if (!prog)
-    return NULL;
-  prog->fingerprint = crc32(0, bytes, (unsigned int)length) | ((uint64_t)length << 32);
-
-  if (membr_bits(&br, 1))
-  {
-    prog->staticdatalen = membr_next_rarvm_number(&br) + 1;
-    prog->staticdata = malloc(prog->staticdatalen);
-    if (!prog->staticdata)
-    {
-      delete_program_code(prog);
-      return NULL;
-    }
-    for (i = 0; i < prog->staticdatalen; i++)
-      prog->staticdata[i] = (uint8_t)membr_bits(&br, 8);
-  }
-
-  return prog;
-}
-
-static void
-delete_filter(struct rar_filter *filter)
-{
-  while (filter)
-  {
-    struct rar_filter *next = filter->next;
-    free(filter->globaldata);
-    free(filter);
-    filter = next;
-  }
-}
-
-static void
-clear_filters(struct rar_filters *filters)
-{
-  delete_filter(filters->stack);
-  delete_program_code(filters->progs);
-  free(filters->vm);
-}
-
-static void
-delete_program_code(struct rar_program_code *prog)
-{
-  while (prog)
-  {
-    struct rar_program_code *next = prog->next;
-    free(prog->staticdata);
-    free(prog->globalbackup);
-    free(prog);
-    prog = next;
-  }
-}
-
-static uint32_t
-membr_next_rarvm_number(struct memory_bit_reader *br)
-{
-  uint32_t val;
-  switch (membr_bits(br, 2))
-  {
-    case 0:
-      return membr_bits(br, 4);
-    case 1:
-      val = membr_bits(br, 8);
-      if (val >= 16)
-        return val;
-      return 0xFFFFFF00 | (val << 4) | membr_bits(br, 4);
-    case 2:
-      return membr_bits(br, 16);
-    default:
-      return membr_bits(br, 32);
-  }
-}
-
-static inline uint32_t
-membr_bits(struct memory_bit_reader *br, int bits)
-{
-  if (bits > br->available && (br->at_eof || !membr_fill(br, bits)))
-    return 0;
-  return (uint32_t)((br->bits >> (br->available -= bits)) & (((uint64_t)1 << bits) - 1));
-}
-
-static int
-membr_fill(struct memory_bit_reader *br, int bits)
-{
-  while (br->available < bits && br->offset < br->length)
-  {
-    br->bits = (br->bits << 8) | br->bytes[br->offset++];
-    br->available += 8;
-  }
-  if (bits > br->available)
-  {
-    br->at_eof = 1;
-    return 0;
-  }
-  return 1;
-}
-
-static int
-read_filter(struct archive_read *a, int64_t *end)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  uint8_t flags, val, *code;
-  uint16_t length, i;
-
-  if (!rar_decode_byte(a, &flags))
-    return 0;
-  length = (flags & 0x07) + 1;
-  if (length == 7)
-  {
-    if (!rar_decode_byte(a, &val))
-      return 0;
-    length = val + 7;
-  }
-  else if (length == 8)
-  {
-    if (!rar_decode_byte(a, &val))
-      return 0;
-    length = val << 8;
-    if (!rar_decode_byte(a, &val))
-      return 0;
-    length |= val;
-  }
-
-  code = malloc(length);
-  if (!code)
-    return 0;
-  for (i = 0; i < length; i++)
-  {
-    if (!rar_decode_byte(a, &code[i]))
-    {
-      free(code);
-      return 0;
-    }
-  }
-  if (!parse_filter(a, code, length, flags))
-  {
-    free(code);
-    return 0;
-  }
-  free(code);
-
-  if (rar->filters.filterstart < *end)
-    *end = rar->filters.filterstart;
-
-  return 1;
-}
-
-static int
-execute_filter_delta(struct rar_filter *filter, struct rar_virtual_machine *vm)
-{
-  uint32_t length = filter->initialregisters[4];
-  uint32_t numchannels = filter->initialregisters[0];
-  uint8_t *src, *dst;
-  uint32_t i, idx;
-
-  if (length > PROGRAM_WORK_SIZE / 2)
-    return 0;
-
-  src = &vm->memory[0];
-  dst = &vm->memory[length];
-  for (i = 0; i < numchannels; i++)
-  {
-    uint8_t lastbyte = 0;
-    for (idx = i; idx < length; idx += numchannels)
-      lastbyte = dst[idx] = lastbyte - *src++;
-  }
-
-  filter->filteredblockaddress = length;
-  filter->filteredblocklength = length;
-
-  return 1;
-}
-
-static int
-execute_filter_e8(struct rar_filter *filter, struct rar_virtual_machine *vm, size_t pos, int e9also)
-{
-  uint32_t length = filter->initialregisters[4];
-  uint32_t filesize = 0x1000000;
-  uint32_t i;
-
-  if (length > PROGRAM_WORK_SIZE || length < 4)
-    return 0;
-
-  for (i = 0; i <= length - 5; i++)
-  {
-    if (vm->memory[i] == 0xE8 || (e9also && vm->memory[i] == 0xE9))
-    {
-      uint32_t currpos = (uint32_t)pos + i + 1;
-      int32_t address = (int32_t)vm_read_32(vm, i + 1);
-      if (address < 0 && currpos >= (uint32_t)-address)
-        vm_write_32(vm, i + 1, address + filesize);
-      else if (address >= 0 && (uint32_t)address < filesize)
-        vm_write_32(vm, i + 1, address - currpos);
-      i += 4;
-    }
-  }
-
-  filter->filteredblockaddress = 0;
-  filter->filteredblocklength = length;
-
-  return 1;
-}
-
-static int
-execute_filter_rgb(struct rar_filter *filter, struct rar_virtual_machine *vm)
-{
-  uint32_t stride = filter->initialregisters[0];
-  uint32_t byteoffset = filter->initialregisters[1];
-  uint32_t blocklength = filter->initialregisters[4];
-  uint8_t *src, *dst;
-  uint32_t i, j;
-
-  if (blocklength > PROGRAM_WORK_SIZE / 2 || stride > blocklength)
-    return 0;
-
-  src = &vm->memory[0];
-  dst = &vm->memory[blocklength];
-  for (i = 0; i < 3; i++) {
-    uint8_t byte = 0;
-    uint8_t *prev = dst + i - stride;
-    for (j = i; j < blocklength; j += 3)
-    {
-      if (prev >= dst)
-      {
-        uint32_t delta1 = abs(prev[3] - prev[0]);
-        uint32_t delta2 = abs(byte - prev[0]);
-        uint32_t delta3 = abs(prev[3] - prev[0] + byte - prev[0]);
-        if (delta1 > delta2 || delta1 > delta3)
-          byte = delta2 <= delta3 ? prev[3] : prev[0];
-      }
-      byte -= *src++;
-      dst[j] = byte;
-      prev += 3;
-    }
-  }
-  for (i = byteoffset; i < blocklength - 2; i += 3)
-  {
-    dst[i] += dst[i + 1];
-    dst[i + 2] += dst[i + 1];
-  }
-
-  filter->filteredblockaddress = blocklength;
-  filter->filteredblocklength = blocklength;
-
-  return 1;
-}
-
-static int
-execute_filter_audio(struct rar_filter *filter, struct rar_virtual_machine *vm)
-{
-  uint32_t length = filter->initialregisters[4];
-  uint32_t numchannels = filter->initialregisters[0];
-  uint8_t *src, *dst;
-  uint32_t i, j;
-
-  if (length > PROGRAM_WORK_SIZE / 2)
-    return 0;
-
-  src = &vm->memory[0];
-  dst = &vm->memory[length];
-  for (i = 0; i < numchannels; i++)
-  {
-    struct audio_state state;
-    memset(&state, 0, sizeof(state));
-    for (j = i; j < length; j += numchannels)
-    {
-      int8_t delta = (int8_t)*src++;
-      uint8_t predbyte, byte;
-      int prederror;
-      state.delta[2] = state.delta[1];
-      state.delta[1] = state.lastdelta - state.delta[0];
-      state.delta[0] = state.lastdelta;
-      predbyte = ((8 * state.lastbyte + state.weight[0] * state.delta[0] + state.weight[1] * state.delta[1] + state.weight[2] * state.delta[2]) >> 3) & 0xFF;
-      byte = (predbyte - delta) & 0xFF;
-      prederror = delta << 3;
-      state.error[0] += abs(prederror);
-      state.error[1] += abs(prederror - state.delta[0]); state.error[2] += abs(prederror + state.delta[0]);
-      state.error[3] += abs(prederror - state.delta[1]); state.error[4] += abs(prederror + state.delta[1]);
-      state.error[5] += abs(prederror - state.delta[2]); state.error[6] += abs(prederror + state.delta[2]);
-      state.lastdelta = (int8_t)(byte - state.lastbyte);
-      dst[j] = state.lastbyte = byte;
-      if (!(state.count++ & 0x1F))
-      {
-        uint8_t k, idx = 0;
-        for (k = 1; k < 7; k++)
-        {
-          if (state.error[k] < state.error[idx])
-            idx = k;
-        }
-        memset(state.error, 0, sizeof(state.error));
-        switch (idx)
-        {
-          case 1: if (state.weight[0] >= -16) state.weight[0]--; break;
-          case 2: if (state.weight[0] < 16) state.weight[0]++; break;
-          case 3: if (state.weight[1] >= -16) state.weight[1]--; break;
-          case 4: if (state.weight[1] < 16) state.weight[1]++; break;
-          case 5: if (state.weight[2] >= -16) state.weight[2]--; break;
-          case 6: if (state.weight[2] < 16) state.weight[2]++; break;
-        }
-      }
-    }
-  }
-
-  filter->filteredblockaddress = length;
-  filter->filteredblocklength = length;
-
-  return 1;
-}
-
-
-static int
-execute_filter(struct archive_read *a, struct rar_filter *filter, struct rar_virtual_machine *vm, size_t pos)
-{
-  if (filter->prog->fingerprint == 0x1D0E06077D)
-    return execute_filter_delta(filter, vm);
-  if (filter->prog->fingerprint == 0x35AD576887)
-    return execute_filter_e8(filter, vm, pos, 0);
-  if (filter->prog->fingerprint == 0x393CD7E57E)
-    return execute_filter_e8(filter, vm, pos, 1);
-  if (filter->prog->fingerprint == 0x951C2C5DC8)
-    return execute_filter_rgb(filter, vm);
-  if (filter->prog->fingerprint == 0xD8BC85E701)
-    return execute_filter_audio(filter, vm);
-
-  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "No support for RAR VM program filter");
-  return 0;
-}
-
-static int
-rar_decode_byte(struct archive_read *a, uint8_t *byte)
-{
-  struct rar *rar = (struct rar *)(a->format->data);
-  struct rar_br *br = &(rar->br);
-  if (!rar_br_read_ahead(a, br, 8))
-    return 0;
-  *byte = (uint8_t)rar_br_bits(br, 8);
-  rar_br_consume(br, 8);
-  return 1;
-}
-
-static inline void
-vm_write_32(struct rar_virtual_machine* vm, size_t offset, uint32_t u32)
-{
-  archive_le32enc(vm->memory + offset, u32);
-}
-
-static inline uint32_t
-vm_read_32(struct rar_virtual_machine* vm, size_t offset)
-{
-  return archive_le32dec(vm->memory + offset);
-}
diff --git a/c/archive_read_support_format_rar5.c b/c/archive_read_support_format_rar5.c
deleted file mode 100644
--- a/c/archive_read_support_format_rar5.c
+++ /dev/null
@@ -1,4251 +0,0 @@
-/*-
-* Copyright (c) 2018 Grzegorz Antoniak (http://antoniak.org)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "archive_platform.h"
-#include "archive_endian.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <time.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h> /* crc32 */
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#include "archive.h"
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_ppmd7_private.h"
-#include "archive_entry_private.h"
-
-#ifdef HAVE_BLAKE2_H
-#include <blake2.h>
-#else
-#include "archive_blake2.h"
-#endif
-
-/*#define CHECK_CRC_ON_SOLID_SKIP*/
-/*#define DONT_FAIL_ON_CRC_ERROR*/
-/*#define DEBUG*/
-
-#define rar5_min(a, b) (((a) > (b)) ? (b) : (a))
-#define rar5_max(a, b) (((a) > (b)) ? (a) : (b))
-#define rar5_countof(X) ((const ssize_t) (sizeof(X) / sizeof(*X)))
-
-#if defined DEBUG
-#define DEBUG_CODE if(1)
-#define LOG(...) do { printf("rar5: " __VA_ARGS__); puts(""); } while(0)
-#else
-#define DEBUG_CODE if(0)
-#endif
-
-/* Real RAR5 magic number is:
- *
- * 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00
- * "Rar!→•☺·\x00"
- *
- * Retrieved with `rar5_signature()` by XOR'ing it with 0xA1, because I don't
- * want to put this magic sequence in each binary that uses libarchive, so
- * applications that scan through the file for this marker won't trigger on
- * this "false" one.
- *
- * The array itself is decrypted in `rar5_init` function. */
-
-static unsigned char rar5_signature_xor[] = { 243, 192, 211, 128, 187, 166, 160, 161 };
-static const size_t g_unpack_window_size = 0x20000;
-
-/* These could have been static const's, but they aren't, because of
- * Visual Studio. */
-#define MAX_NAME_IN_CHARS 2048
-#define MAX_NAME_IN_BYTES (4 * MAX_NAME_IN_CHARS)
-
-struct file_header {
-	ssize_t bytes_remaining;
-	ssize_t unpacked_size;
-	int64_t last_offset;         /* Used in sanity checks. */
-	int64_t last_size;           /* Used in sanity checks. */
-
-	uint8_t solid : 1;           /* Is this a solid stream? */
-	uint8_t service : 1;         /* Is this file a service data? */
-	uint8_t eof : 1;             /* Did we finish unpacking the file? */
-	uint8_t dir : 1;             /* Is this file entry a directory? */
-
-	/* Optional time fields. */
-	uint64_t e_mtime;
-	uint64_t e_ctime;
-	uint64_t e_atime;
-	uint32_t e_unix_ns;
-
-	/* Optional hash fields. */
-	uint32_t stored_crc32;
-	uint32_t calculated_crc32;
-	uint8_t blake2sp[32];
-	blake2sp_state b2state;
-	char has_blake2;
-
-	/* Optional redir fields */
-	uint64_t redir_type;
-	uint64_t redir_flags;
-
-	ssize_t solid_window_size; /* Used in file format check. */
-};
-
-enum EXTRA {
-	EX_CRYPT = 0x01,
-	EX_HASH = 0x02,
-	EX_HTIME = 0x03,
-	EX_VERSION = 0x04,
-	EX_REDIR = 0x05,
-	EX_UOWNER = 0x06,
-	EX_SUBDATA = 0x07
-};
-
-#define REDIR_SYMLINK_IS_DIR	1
-
-enum REDIR_TYPE {
-	REDIR_TYPE_NONE = 0,
-	REDIR_TYPE_UNIXSYMLINK = 1,
-	REDIR_TYPE_WINSYMLINK = 2,
-	REDIR_TYPE_JUNCTION = 3,
-	REDIR_TYPE_HARDLINK = 4,
-	REDIR_TYPE_FILECOPY = 5,
-};
-
-#define	OWNER_USER_NAME		0x01
-#define	OWNER_GROUP_NAME	0x02
-#define	OWNER_USER_UID		0x04
-#define	OWNER_GROUP_GID		0x08
-#define	OWNER_MAXNAMELEN	256
-
-enum FILTER_TYPE {
-	FILTER_DELTA = 0,   /* Generic pattern. */
-	FILTER_E8    = 1,   /* Intel x86 code. */
-	FILTER_E8E9  = 2,   /* Intel x86 code. */
-	FILTER_ARM   = 3,   /* ARM code. */
-	FILTER_AUDIO = 4,   /* Audio filter, not used in RARv5. */
-	FILTER_RGB   = 5,   /* Color palette, not used in RARv5. */
-	FILTER_ITANIUM = 6, /* Intel's Itanium, not used in RARv5. */
-	FILTER_PPM   = 7,   /* Predictive pattern matching, not used in
-			       RARv5. */
-	FILTER_NONE  = 8,
-};
-
-struct filter_info {
-	int type;
-	int channels;
-	int pos_r;
-
-	int64_t block_start;
-	ssize_t block_length;
-	uint16_t width;
-};
-
-struct data_ready {
-	char used;
-	const uint8_t* buf;
-	size_t size;
-	int64_t offset;
-};
-
-struct cdeque {
-	uint16_t beg_pos;
-	uint16_t end_pos;
-	uint16_t cap_mask;
-	uint16_t size;
-	size_t* arr;
-};
-
-struct decode_table {
-	uint32_t size;
-	int32_t decode_len[16];
-	uint32_t decode_pos[16];
-	uint32_t quick_bits;
-	uint8_t quick_len[1 << 10];
-	uint16_t quick_num[1 << 10];
-	uint16_t decode_num[306];
-};
-
-struct comp_state {
-	/* Flag used to specify if unpacker needs to reinitialize the
-	   uncompression context. */
-	uint8_t initialized : 1;
-
-	/* Flag used when applying filters. */
-	uint8_t all_filters_applied : 1;
-
-	/* Flag used to skip file context reinitialization, used when unpacker
-	   is skipping through different multivolume archives. */
-	uint8_t switch_multivolume : 1;
-
-	/* Flag used to specify if unpacker has processed the whole data block
-	   or just a part of it. */
-	uint8_t block_parsing_finished : 1;
-
-	signed int notused : 4;
-
-	int flags;                   /* Uncompression flags. */
-	int method;                  /* Uncompression algorithm method. */
-	int version;                 /* Uncompression algorithm version. */
-	ssize_t window_size;         /* Size of window_buf. */
-	uint8_t* window_buf;         /* Circular buffer used during
-	                                decompression. */
-	uint8_t* filtered_buf;       /* Buffer used when applying filters. */
-	const uint8_t* block_buf;    /* Buffer used when merging blocks. */
-	size_t window_mask;          /* Convenience field; window_size - 1. */
-	int64_t write_ptr;           /* This amount of data has been unpacked
-					in the window buffer. */
-	int64_t last_write_ptr;      /* This amount of data has been stored in
-	                                the output file. */
-	int64_t last_unstore_ptr;    /* Counter of bytes extracted during
-	                                unstoring. This is separate from
-	                                last_write_ptr because of how SERVICE
-	                                base blocks are handled during skipping
-	                                in solid multiarchive archives. */
-	int64_t solid_offset;        /* Additional offset inside the window
-	                                buffer, used in unpacking solid
-	                                archives. */
-	ssize_t cur_block_size;      /* Size of current data block. */
-	int last_len;                /* Flag used in lzss decompression. */
-
-	/* Decode tables used during lzss uncompression. */
-
-#define HUFF_BC 20
-	struct decode_table bd;      /* huffman bit lengths */
-#define HUFF_NC 306
-	struct decode_table ld;      /* literals */
-#define HUFF_DC 64
-	struct decode_table dd;      /* distances */
-#define HUFF_LDC 16
-	struct decode_table ldd;     /* lower bits of distances */
-#define HUFF_RC 44
-	struct decode_table rd;      /* repeating distances */
-#define HUFF_TABLE_SIZE (HUFF_NC + HUFF_DC + HUFF_RC + HUFF_LDC)
-
-	/* Circular deque for storing filters. */
-	struct cdeque filters;
-	int64_t last_block_start;    /* Used for sanity checking. */
-	ssize_t last_block_length;   /* Used for sanity checking. */
-
-	/* Distance cache used during lzss uncompression. */
-	int dist_cache[4];
-
-	/* Data buffer stack. */
-	struct data_ready dready[2];
-};
-
-/* Bit reader state. */
-struct bit_reader {
-	int8_t bit_addr;    /* Current bit pointer inside current byte. */
-	int in_addr;        /* Current byte pointer. */
-};
-
-/* RARv5 block header structure. Use bf_* functions to get values from
- * block_flags_u8 field. I.e. bf_byte_count, etc. */
-struct compressed_block_header {
-	/* block_flags_u8 contain fields encoded in little-endian bitfield:
-	 *
-	 * - table present flag (shr 7, and 1),
-	 * - last block flag    (shr 6, and 1),
-	 * - byte_count         (shr 3, and 7),
-	 * - bit_size           (shr 0, and 7).
-	 */
-	uint8_t block_flags_u8;
-	uint8_t block_cksum;
-};
-
-/* RARv5 main header structure. */
-struct main_header {
-	/* Does the archive contain solid streams? */
-	uint8_t solid : 1;
-
-	/* If this a multi-file archive? */
-	uint8_t volume : 1;
-	uint8_t endarc : 1;
-	uint8_t notused : 5;
-
-	unsigned int vol_no;
-};
-
-struct generic_header {
-	uint8_t split_after : 1;
-	uint8_t split_before : 1;
-	uint8_t padding : 6;
-	int size;
-	int last_header_id;
-};
-
-struct multivolume {
-	unsigned int expected_vol_no;
-	uint8_t* push_buf;
-};
-
-/* Main context structure. */
-struct rar5 {
-	int header_initialized;
-
-	/* Set to 1 if current file is positioned AFTER the magic value
-	 * of the archive file. This is used in header reading functions. */
-	int skipped_magic;
-
-	/* Set to not zero if we're in skip mode (either by calling
-	 * rar5_data_skip function or when skipping over solid streams).
-	 * Set to 0 when in * extraction mode. This is used during checksum
-	 * calculation functions. */
-	int skip_mode;
-
-	/* Set to not zero if we're in block merging mode (i.e. when switching
-	 * to another file in multivolume archive, last block from 1st archive
-	 * needs to be merged with 1st block from 2nd archive). This flag
-	 * guards against recursive use of the merging function, which doesn't
-	 * support recursive calls. */
-	int merge_mode;
-
-	/* An offset to QuickOpen list. This is not supported by this unpacker,
-	 * because we're focusing on streaming interface. QuickOpen is designed
-	 * to make things quicker for non-stream interfaces, so it's not our
-	 * use case. */
-	uint64_t qlist_offset;
-
-	/* An offset to additional Recovery data. This is not supported by this
-	 * unpacker. Recovery data are additional Reed-Solomon codes that could
-	 * be used to calculate bytes that are missing in archive or are
-	 * corrupted. */
-	uint64_t rr_offset;
-
-	/* Various context variables grouped to different structures. */
-	struct generic_header generic;
-	struct main_header main;
-	struct comp_state cstate;
-	struct file_header file;
-	struct bit_reader bits;
-	struct multivolume vol;
-
-	/* The header of currently processed RARv5 block. Used in main
-	 * decompression logic loop. */
-	struct compressed_block_header last_block_hdr;
-};
-
-/* Forward function declarations. */
-
-static void rar5_signature(char *buf);
-static int verify_global_checksums(struct archive_read* a);
-static int rar5_read_data_skip(struct archive_read *a);
-static int push_data_ready(struct archive_read* a, struct rar5* rar,
-	const uint8_t* buf, size_t size, int64_t offset);
-
-/* CDE_xxx = Circular Double Ended (Queue) return values. */
-enum CDE_RETURN_VALUES {
-	CDE_OK, CDE_ALLOC, CDE_PARAM, CDE_OUT_OF_BOUNDS,
-};
-
-/* Clears the contents of this circular deque. */
-static void cdeque_clear(struct cdeque* d) {
-	d->size = 0;
-	d->beg_pos = 0;
-	d->end_pos = 0;
-}
-
-/* Creates a new circular deque object. Capacity must be power of 2: 8, 16, 32,
- * 64, 256, etc. When the user will add another item above current capacity,
- * the circular deque will overwrite the oldest entry. */
-static int cdeque_init(struct cdeque* d, int max_capacity_power_of_2) {
-	if(d == NULL || max_capacity_power_of_2 == 0)
-		return CDE_PARAM;
-
-	d->cap_mask = max_capacity_power_of_2 - 1;
-	d->arr = NULL;
-
-	if((max_capacity_power_of_2 & d->cap_mask) != 0)
-		return CDE_PARAM;
-
-	cdeque_clear(d);
-	d->arr = malloc(sizeof(void*) * max_capacity_power_of_2);
-
-	return d->arr ? CDE_OK : CDE_ALLOC;
-}
-
-/* Return the current size (not capacity) of circular deque `d`. */
-static size_t cdeque_size(struct cdeque* d) {
-	return d->size;
-}
-
-/* Returns the first element of current circular deque. Note that this function
- * doesn't perform any bounds checking. If you need bounds checking, use
- * `cdeque_front()` function instead. */
-static void cdeque_front_fast(struct cdeque* d, void** value) {
-	*value = (void*) d->arr[d->beg_pos];
-}
-
-/* Returns the first element of current circular deque. This function
- * performs bounds checking. */
-static int cdeque_front(struct cdeque* d, void** value) {
-	if(d->size > 0) {
-		cdeque_front_fast(d, value);
-		return CDE_OK;
-	} else
-		return CDE_OUT_OF_BOUNDS;
-}
-
-/* Pushes a new element into the end of this circular deque object. If current
- * size will exceed capacity, the oldest element will be overwritten. */
-static int cdeque_push_back(struct cdeque* d, void* item) {
-	if(d == NULL)
-		return CDE_PARAM;
-
-	if(d->size == d->cap_mask + 1)
-		return CDE_OUT_OF_BOUNDS;
-
-	d->arr[d->end_pos] = (size_t) item;
-	d->end_pos = (d->end_pos + 1) & d->cap_mask;
-	d->size++;
-
-	return CDE_OK;
-}
-
-/* Pops a front element of this circular deque object and returns its value.
- * This function doesn't perform any bounds checking. */
-static void cdeque_pop_front_fast(struct cdeque* d, void** value) {
-	*value = (void*) d->arr[d->beg_pos];
-	d->beg_pos = (d->beg_pos + 1) & d->cap_mask;
-	d->size--;
-}
-
-/* Pops a front element of this circular deque object and returns its value.
- * This function performs bounds checking. */
-static int cdeque_pop_front(struct cdeque* d, void** value) {
-	if(!d || !value)
-		return CDE_PARAM;
-
-	if(d->size == 0)
-		return CDE_OUT_OF_BOUNDS;
-
-	cdeque_pop_front_fast(d, value);
-	return CDE_OK;
-}
-
-/* Convenience function to cast filter_info** to void **. */
-static void** cdeque_filter_p(struct filter_info** f) {
-	return (void**) (size_t) f;
-}
-
-/* Convenience function to cast filter_info* to void *. */
-static void* cdeque_filter(struct filter_info* f) {
-	return (void**) (size_t) f;
-}
-
-/* Destroys this circular deque object. Deallocates the memory of the
- * collection buffer, but doesn't deallocate the memory of any pointer passed
- * to this deque as a value. */
-static void cdeque_free(struct cdeque* d) {
-	if(!d)
-		return;
-
-	if(!d->arr)
-		return;
-
-	free(d->arr);
-
-	d->arr = NULL;
-	d->beg_pos = -1;
-	d->end_pos = -1;
-	d->cap_mask = 0;
-}
-
-static inline
-uint8_t bf_bit_size(const struct compressed_block_header* hdr) {
-	return hdr->block_flags_u8 & 7;
-}
-
-static inline
-uint8_t bf_byte_count(const struct compressed_block_header* hdr) {
-	return (hdr->block_flags_u8 >> 3) & 7;
-}
-
-static inline
-uint8_t bf_is_table_present(const struct compressed_block_header* hdr) {
-	return (hdr->block_flags_u8 >> 7) & 1;
-}
-
-static inline struct rar5* get_context(struct archive_read* a) {
-	return (struct rar5*) a->format->data;
-}
-
-/* Convenience functions used by filter implementations. */
-static void circular_memcpy(uint8_t* dst, uint8_t* window, const uint64_t mask,
-    int64_t start, int64_t end)
-{
-	if((start & mask) > (end & mask)) {
-		ssize_t len1 = mask + 1 - (start & mask);
-		ssize_t len2 = end & mask;
-
-		memcpy(dst, &window[start & mask], len1);
-		memcpy(dst + len1, window, len2);
-	} else {
-		memcpy(dst, &window[start & mask], (size_t) (end - start));
-	}
-}
-
-static uint32_t read_filter_data(struct rar5* rar, uint32_t offset) {
-	uint8_t linear_buf[4];
-	circular_memcpy(linear_buf, rar->cstate.window_buf,
-	    rar->cstate.window_mask, offset, offset + 4);
-	return archive_le32dec(linear_buf);
-}
-
-static void write_filter_data(struct rar5* rar, uint32_t offset,
-    uint32_t value)
-{
-	archive_le32enc(&rar->cstate.filtered_buf[offset], value);
-}
-
-/* Allocates a new filter descriptor and adds it to the filter array. */
-static struct filter_info* add_new_filter(struct rar5* rar) {
-	struct filter_info* f =
-		(struct filter_info*) calloc(1, sizeof(struct filter_info));
-
-	if(!f) {
-		return NULL;
-	}
-
-	cdeque_push_back(&rar->cstate.filters, cdeque_filter(f));
-	return f;
-}
-
-static int run_delta_filter(struct rar5* rar, struct filter_info* flt) {
-	int i;
-	ssize_t dest_pos, src_pos = 0;
-
-	for(i = 0; i < flt->channels; i++) {
-		uint8_t prev_byte = 0;
-		for(dest_pos = i;
-				dest_pos < flt->block_length;
-				dest_pos += flt->channels)
-		{
-			uint8_t byte;
-
-			byte = rar->cstate.window_buf[
-			    (rar->cstate.solid_offset + flt->block_start +
-			    src_pos) & rar->cstate.window_mask];
-
-			prev_byte -= byte;
-			rar->cstate.filtered_buf[dest_pos] = prev_byte;
-			src_pos++;
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int run_e8e9_filter(struct rar5* rar, struct filter_info* flt,
-		int extended)
-{
-	const uint32_t file_size = 0x1000000;
-	ssize_t i;
-
-	circular_memcpy(rar->cstate.filtered_buf,
-	    rar->cstate.window_buf, rar->cstate.window_mask,
-	    rar->cstate.solid_offset + flt->block_start,
-	    rar->cstate.solid_offset + flt->block_start + flt->block_length);
-
-	for(i = 0; i < flt->block_length - 4;) {
-		uint8_t b = rar->cstate.window_buf[
-		    (rar->cstate.solid_offset + flt->block_start +
-		    i++) & rar->cstate.window_mask];
-
-		/*
-		 * 0xE8 = x86's call <relative_addr_uint32> (function call)
-		 * 0xE9 = x86's jmp <relative_addr_uint32> (unconditional jump)
-		 */
-		if(b == 0xE8 || (extended && b == 0xE9)) {
-
-			uint32_t addr;
-			uint32_t offset = (i + flt->block_start) % file_size;
-
-			addr = read_filter_data(rar,
-			    (uint32_t)(rar->cstate.solid_offset +
-			    flt->block_start + i) & rar->cstate.window_mask);
-
-			if(addr & 0x80000000) {
-				if(((addr + offset) & 0x80000000) == 0) {
-					write_filter_data(rar, (uint32_t)i,
-					    addr + file_size);
-				}
-			} else {
-				if((addr - file_size) & 0x80000000) {
-					uint32_t naddr = addr - offset;
-					write_filter_data(rar, (uint32_t)i,
-					    naddr);
-				}
-			}
-
-			i += 4;
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int run_arm_filter(struct rar5* rar, struct filter_info* flt) {
-	ssize_t i = 0;
-	uint32_t offset;
-
-	circular_memcpy(rar->cstate.filtered_buf,
-	    rar->cstate.window_buf, rar->cstate.window_mask,
-	    rar->cstate.solid_offset + flt->block_start,
-	    rar->cstate.solid_offset + flt->block_start + flt->block_length);
-
-	for(i = 0; i < flt->block_length - 3; i += 4) {
-		uint8_t* b = &rar->cstate.window_buf[
-		    (rar->cstate.solid_offset +
-		    flt->block_start + i + 3) & rar->cstate.window_mask];
-
-		if(*b == 0xEB) {
-			/* 0xEB = ARM's BL (branch + link) instruction. */
-			offset = read_filter_data(rar,
-			    (rar->cstate.solid_offset + flt->block_start + i) &
-			     (uint32_t)rar->cstate.window_mask) & 0x00ffffff;
-
-			offset -= (uint32_t) ((i + flt->block_start) / 4);
-			offset = (offset & 0x00ffffff) | 0xeb000000;
-			write_filter_data(rar, (uint32_t)i, offset);
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int run_filter(struct archive_read* a, struct filter_info* flt) {
-	int ret;
-	struct rar5* rar = get_context(a);
-
-	free(rar->cstate.filtered_buf);
-
-	rar->cstate.filtered_buf = malloc(flt->block_length);
-	if(!rar->cstate.filtered_buf) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for filter data.");
-		return ARCHIVE_FATAL;
-	}
-
-	switch(flt->type) {
-		case FILTER_DELTA:
-			ret = run_delta_filter(rar, flt);
-			break;
-
-		case FILTER_E8:
-			/* fallthrough */
-		case FILTER_E8E9:
-			ret = run_e8e9_filter(rar, flt,
-			    flt->type == FILTER_E8E9);
-			break;
-
-		case FILTER_ARM:
-			ret = run_arm_filter(rar, flt);
-			break;
-
-		default:
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unsupported filter type: 0x%x", flt->type);
-			return ARCHIVE_FATAL;
-	}
-
-	if(ret != ARCHIVE_OK) {
-		/* Filter has failed. */
-		return ret;
-	}
-
-	if(ARCHIVE_OK != push_data_ready(a, rar, rar->cstate.filtered_buf,
-	    flt->block_length, rar->cstate.last_write_ptr))
-	{
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Stack overflow when submitting unpacked data");
-
-		return ARCHIVE_FATAL;
-	}
-
-	rar->cstate.last_write_ptr += flt->block_length;
-	return ARCHIVE_OK;
-}
-
-/* The `push_data` function submits the selected data range to the user.
- * Next call of `use_data` will use the pointer, size and offset arguments
- * that are specified here. These arguments are pushed to the FIFO stack here,
- * and popped from the stack by the `use_data` function. */
-static void push_data(struct archive_read* a, struct rar5* rar,
-    const uint8_t* buf, int64_t idx_begin, int64_t idx_end)
-{
-	const uint64_t wmask = rar->cstate.window_mask;
-	const ssize_t solid_write_ptr = (rar->cstate.solid_offset +
-	    rar->cstate.last_write_ptr) & wmask;
-
-	idx_begin += rar->cstate.solid_offset;
-	idx_end += rar->cstate.solid_offset;
-
-	/* Check if our unpacked data is wrapped inside the window circular
-	 * buffer.  If it's not wrapped, it can be copied out by using
-	 * a single memcpy, but when it's wrapped, we need to copy the first
-	 * part with one memcpy, and the second part with another memcpy. */
-
-	if((idx_begin & wmask) > (idx_end & wmask)) {
-		/* The data is wrapped (begin offset sis bigger than end
-		 * offset). */
-		const ssize_t frag1_size = rar->cstate.window_size -
-		    (idx_begin & wmask);
-		const ssize_t frag2_size = idx_end & wmask;
-
-		/* Copy the first part of the buffer first. */
-		push_data_ready(a, rar, buf + solid_write_ptr, frag1_size,
-		    rar->cstate.last_write_ptr);
-
-		/* Copy the second part of the buffer. */
-		push_data_ready(a, rar, buf, frag2_size,
-		    rar->cstate.last_write_ptr + frag1_size);
-
-		rar->cstate.last_write_ptr += frag1_size + frag2_size;
-	} else {
-		/* Data is not wrapped, so we can just use one call to copy the
-		 * data. */
-		push_data_ready(a, rar,
-		    buf + solid_write_ptr, (idx_end - idx_begin) & wmask,
-		    rar->cstate.last_write_ptr);
-
-		rar->cstate.last_write_ptr += idx_end - idx_begin;
-	}
-}
-
-/* Convenience function that submits the data to the user. It uses the
- * unpack window buffer as a source location. */
-static void push_window_data(struct archive_read* a, struct rar5* rar,
-    int64_t idx_begin, int64_t idx_end)
-{
-	push_data(a, rar, rar->cstate.window_buf, idx_begin, idx_end);
-}
-
-static int apply_filters(struct archive_read* a) {
-	struct filter_info* flt;
-	struct rar5* rar = get_context(a);
-	int ret;
-
-	rar->cstate.all_filters_applied = 0;
-
-	/* Get the first filter that can be applied to our data. The data
-	 * needs to be fully unpacked before the filter can be run. */
-	if(CDE_OK == cdeque_front(&rar->cstate.filters,
-	    cdeque_filter_p(&flt))) {
-		/* Check if our unpacked data fully covers this filter's
-		 * range. */
-		if(rar->cstate.write_ptr > flt->block_start &&
-		    rar->cstate.write_ptr >= flt->block_start +
-		    flt->block_length) {
-			/* Check if we have some data pending to be written
-			 * right before the filter's start offset. */
-			if(rar->cstate.last_write_ptr == flt->block_start) {
-				/* Run the filter specified by descriptor
-				 * `flt`. */
-				ret = run_filter(a, flt);
-				if(ret != ARCHIVE_OK) {
-					/* Filter failure, return error. */
-					return ret;
-				}
-
-				/* Filter descriptor won't be needed anymore
-				 * after it's used, * so remove it from the
-				 * filter list and free its memory. */
-				(void) cdeque_pop_front(&rar->cstate.filters,
-				    cdeque_filter_p(&flt));
-
-				free(flt);
-			} else {
-				/* We can't run filters yet, dump the memory
-				 * right before the filter. */
-				push_window_data(a, rar,
-				    rar->cstate.last_write_ptr,
-				    flt->block_start);
-			}
-
-			/* Return 'filter applied or not needed' state to the
-			 * caller. */
-			return ARCHIVE_RETRY;
-		}
-	}
-
-	rar->cstate.all_filters_applied = 1;
-	return ARCHIVE_OK;
-}
-
-static void dist_cache_push(struct rar5* rar, int value) {
-	int* q = rar->cstate.dist_cache;
-
-	q[3] = q[2];
-	q[2] = q[1];
-	q[1] = q[0];
-	q[0] = value;
-}
-
-static int dist_cache_touch(struct rar5* rar, int idx) {
-	int* q = rar->cstate.dist_cache;
-	int i, dist = q[idx];
-
-	for(i = idx; i > 0; i--)
-		q[i] = q[i - 1];
-
-	q[0] = dist;
-	return dist;
-}
-
-static void free_filters(struct rar5* rar) {
-	struct cdeque* d = &rar->cstate.filters;
-
-	/* Free any remaining filters. All filters should be naturally
-	 * consumed by the unpacking function, so remaining filters after
-	 * unpacking normally mean that unpacking wasn't successful.
-	 * But still of course we shouldn't leak memory in such case. */
-
-	/* cdeque_size() is a fast operation, so we can use it as a loop
-	 * expression. */
-	while(cdeque_size(d) > 0) {
-		struct filter_info* f = NULL;
-
-		/* Pop_front will also decrease the collection's size. */
-		if (CDE_OK == cdeque_pop_front(d, cdeque_filter_p(&f)))
-			free(f);
-	}
-
-	cdeque_clear(d);
-
-	/* Also clear out the variables needed for sanity checking. */
-	rar->cstate.last_block_start = 0;
-	rar->cstate.last_block_length = 0;
-}
-
-static void reset_file_context(struct rar5* rar) {
-	memset(&rar->file, 0, sizeof(rar->file));
-	blake2sp_init(&rar->file.b2state, 32);
-
-	if(rar->main.solid) {
-		rar->cstate.solid_offset += rar->cstate.write_ptr;
-	} else {
-		rar->cstate.solid_offset = 0;
-	}
-
-	rar->cstate.write_ptr = 0;
-	rar->cstate.last_write_ptr = 0;
-	rar->cstate.last_unstore_ptr = 0;
-
-	rar->file.redir_type = REDIR_TYPE_NONE;
-	rar->file.redir_flags = 0;
-
-	free_filters(rar);
-}
-
-static inline int get_archive_read(struct archive* a,
-    struct archive_read** ar)
-{
-	*ar = (struct archive_read*) a;
-	archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
-	    "archive_read_support_format_rar5");
-
-	return ARCHIVE_OK;
-}
-
-static int read_ahead(struct archive_read* a, size_t how_many,
-    const uint8_t** ptr)
-{
-	ssize_t avail = -1;
-	if(!ptr)
-		return 0;
-
-	*ptr = __archive_read_ahead(a, how_many, &avail);
-	if(*ptr == NULL) {
-		return 0;
-	}
-
-	return 1;
-}
-
-static int consume(struct archive_read* a, int64_t how_many) {
-	int ret;
-
-	ret = how_many == __archive_read_consume(a, how_many)
-		? ARCHIVE_OK
-		: ARCHIVE_FATAL;
-
-	return ret;
-}
-
-/**
- * Read a RAR5 variable sized numeric value. This value will be stored in
- * `pvalue`. The `pvalue_len` argument points to a variable that will receive
- * the byte count that was consumed in order to decode the `pvalue` value, plus
- * one.
- *
- * pvalue_len is optional and can be NULL.
- *
- * NOTE: if `pvalue_len` is NOT NULL, the caller needs to manually consume
- * the number of bytes that `pvalue_len` value contains. If the `pvalue_len`
- * is NULL, this consuming operation is done automatically.
- *
- * Returns 1 if *pvalue was successfully read.
- * Returns 0 if there was an error. In this case, *pvalue contains an
- *           invalid value.
- */
-
-static int read_var(struct archive_read* a, uint64_t* pvalue,
-    uint64_t* pvalue_len)
-{
-	uint64_t result = 0;
-	size_t shift, i;
-	const uint8_t* p;
-	uint8_t b;
-
-	/* We will read maximum of 8 bytes. We don't have to handle the
-	 * situation to read the RAR5 variable-sized value stored at the end of
-	 * the file, because such situation will never happen. */
-	if(!read_ahead(a, 8, &p))
-		return 0;
-
-	for(shift = 0, i = 0; i < 8; i++, shift += 7) {
-		b = p[i];
-
-		/* Strip the MSB from the input byte and add the resulting
-		 * number to the `result`. */
-		result += (b & (uint64_t)0x7F) << shift;
-
-		/* MSB set to 1 means we need to continue decoding process.
-		 * MSB set to 0 means we're done.
-		 *
-		 * This conditional checks for the second case. */
-		if((b & 0x80) == 0) {
-			if(pvalue) {
-				*pvalue = result;
-			}
-
-			/* If the caller has passed the `pvalue_len` pointer,
-			 * store the number of consumed bytes in it and do NOT
-			 * consume those bytes, since the caller has all the
-			 * information it needs to perform */
-			if(pvalue_len) {
-				*pvalue_len = 1 + i;
-			} else {
-				/* If the caller did not provide the
-				 * `pvalue_len` pointer, it will not have the
-				 * possibility to advance the file pointer,
-				 * because it will not know how many bytes it
-				 * needs to consume. This is why we handle
-				 * such situation here automatically. */
-				if(ARCHIVE_OK != consume(a, 1 + i)) {
-					return 0;
-				}
-			}
-
-			/* End of decoding process, return success. */
-			return 1;
-		}
-	}
-
-	/* The decoded value takes the maximum number of 8 bytes.
-	 * It's a maximum number of bytes, so end decoding process here
-	 * even if the first bit of last byte is 1. */
-	if(pvalue) {
-		*pvalue = result;
-	}
-
-	if(pvalue_len) {
-		*pvalue_len = 9;
-	} else {
-		if(ARCHIVE_OK != consume(a, 9)) {
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-static int read_var_sized(struct archive_read* a, size_t* pvalue,
-    size_t* pvalue_len)
-{
-	uint64_t v;
-	uint64_t v_size = 0;
-
-	const int ret = pvalue_len ? read_var(a, &v, &v_size)
-				   : read_var(a, &v, NULL);
-
-	if(ret == 1 && pvalue) {
-		*pvalue = (size_t) v;
-	}
-
-	if(pvalue_len) {
-		/* Possible data truncation should be safe. */
-		*pvalue_len = (size_t) v_size;
-	}
-
-	return ret;
-}
-
-static int read_bits_32(struct archive_read* a, struct rar5* rar,
-	const uint8_t* p, uint32_t* value)
-{
-	if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
-		archive_set_error(&a->archive,
-			ARCHIVE_ERRNO_PROGRAMMER,
-			"Premature end of stream during extraction of data (#1)");
-		return ARCHIVE_FATAL;
-	}
-
-	uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
-	bits |= p[rar->bits.in_addr + 1] << 16;
-	bits |= p[rar->bits.in_addr + 2] << 8;
-	bits |= p[rar->bits.in_addr + 3];
-	bits <<= rar->bits.bit_addr;
-	bits |= p[rar->bits.in_addr + 4] >> (8 - rar->bits.bit_addr);
-	*value = bits;
-	return ARCHIVE_OK;
-}
-
-static int read_bits_16(struct archive_read* a, struct rar5* rar,
-	const uint8_t* p, uint16_t* value)
-{
-	if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
-		archive_set_error(&a->archive,
-			ARCHIVE_ERRNO_PROGRAMMER,
-			"Premature end of stream during extraction of data (#2)");
-		return ARCHIVE_FATAL;
-	}
-
-	int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
-	bits |= (int) p[rar->bits.in_addr + 1] << 8;
-	bits |= (int) p[rar->bits.in_addr + 2];
-	bits >>= (8 - rar->bits.bit_addr);
-	*value = bits & 0xffff;
-	return ARCHIVE_OK;
-}
-
-static void skip_bits(struct rar5* rar, int bits) {
-	const int new_bits = rar->bits.bit_addr + bits;
-	rar->bits.in_addr += new_bits >> 3;
-	rar->bits.bit_addr = new_bits & 7;
-}
-
-/* n = up to 16 */
-static int read_consume_bits(struct archive_read* a, struct rar5* rar,
-	const uint8_t* p, int n, int* value)
-{
-	uint16_t v;
-	int ret, num;
-
-	if(n == 0 || n > 16) {
-		/* This is a programmer error and should never happen
-		 * in runtime. */
-		return ARCHIVE_FATAL;
-	}
-
-	ret = read_bits_16(a, rar, p, &v);
-	if(ret != ARCHIVE_OK)
-		return ret;
-
-	num = (int) v;
-	num >>= 16 - n;
-
-	skip_bits(rar, n);
-
-	if(value)
-		*value = num;
-
-	return ARCHIVE_OK;
-}
-
-static int read_u32(struct archive_read* a, uint32_t* pvalue) {
-	const uint8_t* p;
-	if(!read_ahead(a, 4, &p))
-		return 0;
-
-	*pvalue = archive_le32dec(p);
-	return ARCHIVE_OK == consume(a, 4) ? 1 : 0;
-}
-
-static int read_u64(struct archive_read* a, uint64_t* pvalue) {
-	const uint8_t* p;
-	if(!read_ahead(a, 8, &p))
-		return 0;
-
-	*pvalue = archive_le64dec(p);
-	return ARCHIVE_OK == consume(a, 8) ? 1 : 0;
-}
-
-static int bid_standard(struct archive_read* a) {
-	const uint8_t* p;
-	char signature[sizeof(rar5_signature_xor)];
-
-	rar5_signature(signature);
-
-	if(!read_ahead(a, sizeof(rar5_signature_xor), &p))
-		return -1;
-
-	if(!memcmp(signature, p, sizeof(rar5_signature_xor)))
-		return 30;
-
-	return -1;
-}
-
-static int bid_sfx(struct archive_read *a)
-{
-	const char *p;
-
-	if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
-		return -1;
-
-	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
-		/* This is a PE file */
-		char signature[sizeof(rar5_signature_xor)];
-		ssize_t offset = 0x10000;
-		ssize_t window = 4096;
-		ssize_t bytes_avail;
-
-		rar5_signature(signature);
-
-		while (offset + window <= (1024 * 512)) {
-			const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
-			if (buff == NULL) {
-				/* Remaining bytes are less than window. */
-				window >>= 1;
-				if (window < 0x40)
-					return 0;
-				continue;
-			}
-			p = buff + offset;
-			while (p + 8 < buff + bytes_avail) {
-				if (memcmp(p, signature, sizeof(signature)) == 0)
-					return 30;
-				p += 0x10;
-			}
-			offset = p - buff;
-		}
-	}
-
-	return 0;
-}
-
-static int rar5_bid(struct archive_read* a, int best_bid) {
-	int my_bid;
-
-	if(best_bid > 30)
-		return -1;
-
-	my_bid = bid_standard(a);
-	if(my_bid > -1) {
-		return my_bid;
-	}
-	my_bid = bid_sfx(a);
-	if (my_bid > -1) {
-		return my_bid;
-	}
-
-	return -1;
-}
-
-static int rar5_options(struct archive_read *a, const char *key,
-    const char *val) {
-	(void) a;
-	(void) key;
-	(void) val;
-
-	/* No options supported in this version. Return the ARCHIVE_WARN code
-	 * to signal the options supervisor that the unpacker didn't handle
-	 * setting this option. */
-
-	return ARCHIVE_WARN;
-}
-
-static void init_header(struct archive_read* a) {
-	a->archive.archive_format = ARCHIVE_FORMAT_RAR_V5;
-	a->archive.archive_format_name = "RAR5";
-}
-
-static void init_window_mask(struct rar5* rar) {
-	if (rar->cstate.window_size)
-		rar->cstate.window_mask = rar->cstate.window_size - 1;
-	else
-		rar->cstate.window_mask = 0;
-}
-
-enum HEADER_FLAGS {
-	HFL_EXTRA_DATA = 0x0001,
-	HFL_DATA = 0x0002,
-	HFL_SKIP_IF_UNKNOWN = 0x0004,
-	HFL_SPLIT_BEFORE = 0x0008,
-	HFL_SPLIT_AFTER = 0x0010,
-	HFL_CHILD = 0x0020,
-	HFL_INHERITED = 0x0040
-};
-
-static int process_main_locator_extra_block(struct archive_read* a,
-    struct rar5* rar)
-{
-	uint64_t locator_flags;
-
-	enum LOCATOR_FLAGS {
-		QLIST = 0x01, RECOVERY = 0x02,
-	};
-
-	if(!read_var(a, &locator_flags, NULL)) {
-		return ARCHIVE_EOF;
-	}
-
-	if(locator_flags & QLIST) {
-		if(!read_var(a, &rar->qlist_offset, NULL)) {
-			return ARCHIVE_EOF;
-		}
-
-		/* qlist is not used */
-	}
-
-	if(locator_flags & RECOVERY) {
-		if(!read_var(a, &rar->rr_offset, NULL)) {
-			return ARCHIVE_EOF;
-		}
-
-		/* rr is not used */
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
-    ssize_t* extra_data_size)
-{
-	size_t hash_type = 0;
-	size_t value_len;
-
-	enum HASH_TYPE {
-		BLAKE2sp = 0x00
-	};
-
-	if(!read_var_sized(a, &hash_type, &value_len))
-		return ARCHIVE_EOF;
-
-	*extra_data_size -= value_len;
-	if(ARCHIVE_OK != consume(a, value_len)) {
-		return ARCHIVE_EOF;
-	}
-
-	/* The file uses BLAKE2sp checksum algorithm instead of plain old
-	 * CRC32. */
-	if(hash_type == BLAKE2sp) {
-		const uint8_t* p;
-		const int hash_size = sizeof(rar->file.blake2sp);
-
-		if(!read_ahead(a, hash_size, &p))
-			return ARCHIVE_EOF;
-
-		rar->file.has_blake2 = 1;
-		memcpy(&rar->file.blake2sp, p, hash_size);
-
-		if(ARCHIVE_OK != consume(a, hash_size)) {
-			return ARCHIVE_EOF;
-		}
-
-		*extra_data_size -= hash_size;
-	} else {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported hash type (0x%x)", (int) hash_type);
-		return ARCHIVE_FATAL;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static uint64_t time_win_to_unix(uint64_t win_time) {
-	const size_t ns_in_sec = 10000000;
-	const uint64_t sec_to_unix = 11644473600LL;
-	return win_time / ns_in_sec - sec_to_unix;
-}
-
-static int parse_htime_item(struct archive_read* a, char unix_time,
-    uint64_t* where, ssize_t* extra_data_size)
-{
-	if(unix_time) {
-		uint32_t time_val;
-		if(!read_u32(a, &time_val))
-			return ARCHIVE_EOF;
-
-		*extra_data_size -= 4;
-		*where = (uint64_t) time_val;
-	} else {
-		uint64_t windows_time;
-		if(!read_u64(a, &windows_time))
-			return ARCHIVE_EOF;
-
-		*where = time_win_to_unix(windows_time);
-		*extra_data_size -= 8;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int parse_file_extra_version(struct archive_read* a,
-    struct archive_entry* e, ssize_t* extra_data_size)
-{
-	size_t flags = 0;
-	size_t version = 0;
-	size_t value_len = 0;
-	struct archive_string version_string;
-	struct archive_string name_utf8_string;
-	const char* cur_filename;
-
-	/* Flags are ignored. */
-	if(!read_var_sized(a, &flags, &value_len))
-		return ARCHIVE_EOF;
-
-	*extra_data_size -= value_len;
-	if(ARCHIVE_OK != consume(a, value_len))
-		return ARCHIVE_EOF;
-
-	if(!read_var_sized(a, &version, &value_len))
-		return ARCHIVE_EOF;
-
-	*extra_data_size -= value_len;
-	if(ARCHIVE_OK != consume(a, value_len))
-		return ARCHIVE_EOF;
-
-	/* extra_data_size should be zero here. */
-
-	cur_filename = archive_entry_pathname_utf8(e);
-	if(cur_filename == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Version entry without file name");
-		return ARCHIVE_FATAL;
-	}
-
-	archive_string_init(&version_string);
-	archive_string_init(&name_utf8_string);
-
-	/* Prepare a ;123 suffix for the filename, where '123' is the version
-	 * value of this file. */
-	archive_string_sprintf(&version_string, ";%zu", version);
-
-	/* Build the new filename. */
-	archive_strcat(&name_utf8_string, cur_filename);
-	archive_strcat(&name_utf8_string, version_string.s);
-
-	/* Apply the new filename into this file's context. */
-	archive_entry_update_pathname_utf8(e, name_utf8_string.s);
-
-	/* Free buffers. */
-	archive_string_free(&version_string);
-	archive_string_free(&name_utf8_string);
-	return ARCHIVE_OK;
-}
-
-static int parse_file_extra_htime(struct archive_read* a,
-    struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size)
-{
-	char unix_time = 0;
-	size_t flags = 0;
-	size_t value_len;
-
-	enum HTIME_FLAGS {
-		IS_UNIX       = 0x01,
-		HAS_MTIME     = 0x02,
-		HAS_CTIME     = 0x04,
-		HAS_ATIME     = 0x08,
-		HAS_UNIX_NS   = 0x10,
-	};
-
-	if(!read_var_sized(a, &flags, &value_len))
-		return ARCHIVE_EOF;
-
-	*extra_data_size -= value_len;
-	if(ARCHIVE_OK != consume(a, value_len)) {
-		return ARCHIVE_EOF;
-	}
-
-	unix_time = flags & IS_UNIX;
-
-	if(flags & HAS_MTIME) {
-		parse_htime_item(a, unix_time, &rar->file.e_mtime,
-		    extra_data_size);
-		archive_entry_set_mtime(e, rar->file.e_mtime, 0);
-	}
-
-	if(flags & HAS_CTIME) {
-		parse_htime_item(a, unix_time, &rar->file.e_ctime,
-		    extra_data_size);
-		archive_entry_set_ctime(e, rar->file.e_ctime, 0);
-	}
-
-	if(flags & HAS_ATIME) {
-		parse_htime_item(a, unix_time, &rar->file.e_atime,
-		    extra_data_size);
-		archive_entry_set_atime(e, rar->file.e_atime, 0);
-	}
-
-	if(flags & HAS_UNIX_NS) {
-		if(!read_u32(a, &rar->file.e_unix_ns))
-			return ARCHIVE_EOF;
-
-		*extra_data_size -= 4;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int parse_file_extra_redir(struct archive_read* a,
-    struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size)
-{
-	uint64_t value_size = 0;
-	size_t target_size = 0;
-	char target_utf8_buf[MAX_NAME_IN_BYTES];
-	const uint8_t* p;
-
-	if(!read_var(a, &rar->file.redir_type, &value_size))
-		return ARCHIVE_EOF;
-	if(ARCHIVE_OK != consume(a, (int64_t)value_size))
-		return ARCHIVE_EOF;
-	*extra_data_size -= value_size;
-
-	if(!read_var(a, &rar->file.redir_flags, &value_size))
-		return ARCHIVE_EOF;
-	if(ARCHIVE_OK != consume(a, (int64_t)value_size))
-		return ARCHIVE_EOF;
-	*extra_data_size -= value_size;
-
-	if(!read_var_sized(a, &target_size, NULL))
-		return ARCHIVE_EOF;
-	*extra_data_size -= target_size + 1;
-
-	if(!read_ahead(a, target_size, &p))
-		return ARCHIVE_EOF;
-
-	if(target_size > (MAX_NAME_IN_CHARS - 1)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Link target is too long");
-		return ARCHIVE_FATAL;
-	}
-
-	if(target_size == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "No link target specified");
-		return ARCHIVE_FATAL;
-	}
-
-	memcpy(target_utf8_buf, p, target_size);
-	target_utf8_buf[target_size] = 0;
-
-	if(ARCHIVE_OK != consume(a, (int64_t)target_size))
-		return ARCHIVE_EOF;
-
-	switch(rar->file.redir_type) {
-		case REDIR_TYPE_UNIXSYMLINK:
-		case REDIR_TYPE_WINSYMLINK:
-			archive_entry_set_filetype(e, AE_IFLNK);
-			archive_entry_update_symlink_utf8(e, target_utf8_buf);
-			if (rar->file.redir_flags & REDIR_SYMLINK_IS_DIR) {
-				archive_entry_set_symlink_type(e,
-					AE_SYMLINK_TYPE_DIRECTORY);
-			} else {
-				archive_entry_set_symlink_type(e,
-				AE_SYMLINK_TYPE_FILE);
-			}
-			break;
-
-		case REDIR_TYPE_HARDLINK:
-			archive_entry_set_filetype(e, AE_IFREG);
-			archive_entry_update_hardlink_utf8(e, target_utf8_buf);
-			break;
-
-		default:
-			/* Unknown redir type, skip it. */
-			break;
-	}
-	return ARCHIVE_OK;
-}
-
-static int parse_file_extra_owner(struct archive_read* a,
-    struct archive_entry* e, ssize_t* extra_data_size)
-{
-	uint64_t flags = 0;
-	uint64_t value_size = 0;
-	uint64_t id = 0;
-	size_t name_len = 0;
-	size_t name_size = 0;
-	char namebuf[OWNER_MAXNAMELEN];
-	const uint8_t* p;
-
-	if(!read_var(a, &flags, &value_size))
-		return ARCHIVE_EOF;
-	if(ARCHIVE_OK != consume(a, (int64_t)value_size))
-		return ARCHIVE_EOF;
-	*extra_data_size -= value_size;
-
-	if ((flags & OWNER_USER_NAME) != 0) {
-		if(!read_var_sized(a, &name_size, NULL))
-			return ARCHIVE_EOF;
-		*extra_data_size -= name_size + 1;
-
-		if(!read_ahead(a, name_size, &p))
-			return ARCHIVE_EOF;
-
-		if (name_size >= OWNER_MAXNAMELEN) {
-			name_len = OWNER_MAXNAMELEN - 1;
-		} else {
-			name_len = name_size;
-		}
-
-		memcpy(namebuf, p, name_len);
-		namebuf[name_len] = 0;
-		if(ARCHIVE_OK != consume(a, (int64_t)name_size))
-			return ARCHIVE_EOF;
-
-		archive_entry_set_uname(e, namebuf);
-	}
-	if ((flags & OWNER_GROUP_NAME) != 0) {
-		if(!read_var_sized(a, &name_size, NULL))
-			return ARCHIVE_EOF;
-		*extra_data_size -= name_size + 1;
-
-		if(!read_ahead(a, name_size, &p))
-			return ARCHIVE_EOF;
-
-		if (name_size >= OWNER_MAXNAMELEN) {
-			name_len = OWNER_MAXNAMELEN - 1;
-		} else {
-			name_len = name_size;
-		}
-
-		memcpy(namebuf, p, name_len);
-		namebuf[name_len] = 0;
-		if(ARCHIVE_OK != consume(a, (int64_t)name_size))
-			return ARCHIVE_EOF;
-
-		archive_entry_set_gname(e, namebuf);
-	}
-	if ((flags & OWNER_USER_UID) != 0) {
-		if(!read_var(a, &id, &value_size))
-			return ARCHIVE_EOF;
-		if(ARCHIVE_OK != consume(a, (int64_t)value_size))
-			return ARCHIVE_EOF;
-		*extra_data_size -= value_size;
-
-		archive_entry_set_uid(e, (la_int64_t)id);
-	}
-	if ((flags & OWNER_GROUP_GID) != 0) {
-		if(!read_var(a, &id, &value_size))
-			return ARCHIVE_EOF;
-		if(ARCHIVE_OK != consume(a, (int64_t)value_size))
-			return ARCHIVE_EOF;
-		*extra_data_size -= value_size;
-
-		archive_entry_set_gid(e, (la_int64_t)id);
-	}
-	return ARCHIVE_OK;
-}
-
-static int process_head_file_extra(struct archive_read* a,
-    struct archive_entry* e, struct rar5* rar, ssize_t extra_data_size)
-{
-	size_t extra_field_size;
-	size_t extra_field_id = 0;
-	int ret = ARCHIVE_FATAL;
-	size_t var_size;
-
-	while(extra_data_size > 0) {
-		if(!read_var_sized(a, &extra_field_size, &var_size))
-			return ARCHIVE_EOF;
-
-		extra_data_size -= var_size;
-		if(ARCHIVE_OK != consume(a, var_size)) {
-			return ARCHIVE_EOF;
-		}
-
-		if(!read_var_sized(a, &extra_field_id, &var_size))
-			return ARCHIVE_EOF;
-
-		extra_data_size -= var_size;
-		if(ARCHIVE_OK != consume(a, var_size)) {
-			return ARCHIVE_EOF;
-		}
-
-		switch(extra_field_id) {
-			case EX_HASH:
-				ret = parse_file_extra_hash(a, rar,
-				    &extra_data_size);
-				break;
-			case EX_HTIME:
-				ret = parse_file_extra_htime(a, e, rar,
-				    &extra_data_size);
-				break;
-			case EX_REDIR:
-				ret = parse_file_extra_redir(a, e, rar,
-				    &extra_data_size);
-				break;
-			case EX_UOWNER:
-				ret = parse_file_extra_owner(a, e,
-				    &extra_data_size);
-				break;
-			case EX_VERSION:
-				ret = parse_file_extra_version(a, e,
-				    &extra_data_size);
-				break;
-			case EX_CRYPT:
-				/* fallthrough */
-			case EX_SUBDATA:
-				/* fallthrough */
-			default:
-				/* Skip unsupported entry. */
-				return consume(a, extra_data_size);
-		}
-	}
-
-	if(ret != ARCHIVE_OK) {
-		/* Attribute not implemented. */
-		return ret;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int process_head_file(struct archive_read* a, struct rar5* rar,
-    struct archive_entry* entry, size_t block_flags)
-{
-	ssize_t extra_data_size = 0;
-	size_t data_size = 0;
-	size_t file_flags = 0;
-	size_t file_attr = 0;
-	size_t compression_info = 0;
-	size_t host_os = 0;
-	size_t name_size = 0;
-	uint64_t unpacked_size, window_size;
-	uint32_t mtime = 0, crc = 0;
-	int c_method = 0, c_version = 0;
-	char name_utf8_buf[MAX_NAME_IN_BYTES];
-	const uint8_t* p;
-
-	enum FILE_FLAGS {
-		DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004,
-		UNKNOWN_UNPACKED_SIZE = 0x0008,
-	};
-
-	enum FILE_ATTRS {
-		ATTR_READONLY = 0x1, ATTR_HIDDEN = 0x2, ATTR_SYSTEM = 0x4,
-		ATTR_DIRECTORY = 0x10,
-	};
-
-	enum COMP_INFO_FLAGS {
-		SOLID = 0x0040,
-	};
-
-	enum HOST_OS {
-		HOST_WINDOWS = 0,
-		HOST_UNIX = 1,
-	};
-
-	archive_entry_clear(entry);
-
-	/* Do not reset file context if we're switching archives. */
-	if(!rar->cstate.switch_multivolume) {
-		reset_file_context(rar);
-	}
-
-	if(block_flags & HFL_EXTRA_DATA) {
-		size_t edata_size = 0;
-		if(!read_var_sized(a, &edata_size, NULL))
-			return ARCHIVE_EOF;
-
-		/* Intentional type cast from unsigned to signed. */
-		extra_data_size = (ssize_t) edata_size;
-	}
-
-	if(block_flags & HFL_DATA) {
-		if(!read_var_sized(a, &data_size, NULL))
-			return ARCHIVE_EOF;
-
-		rar->file.bytes_remaining = data_size;
-	} else {
-		rar->file.bytes_remaining = 0;
-
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				"no data found in file/service block");
-		return ARCHIVE_FATAL;
-	}
-
-	if(!read_var_sized(a, &file_flags, NULL))
-		return ARCHIVE_EOF;
-
-	if(!read_var(a, &unpacked_size, NULL))
-		return ARCHIVE_EOF;
-
-	if(file_flags & UNKNOWN_UNPACKED_SIZE) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Files with unknown unpacked size are not supported");
-		return ARCHIVE_FATAL;
-	}
-
-	rar->file.dir = (uint8_t) ((file_flags & DIRECTORY) > 0);
-
-	if(!read_var_sized(a, &file_attr, NULL))
-		return ARCHIVE_EOF;
-
-	if(file_flags & UTIME) {
-		if(!read_u32(a, &mtime))
-			return ARCHIVE_EOF;
-	}
-
-	if(file_flags & CRC32) {
-		if(!read_u32(a, &crc))
-			return ARCHIVE_EOF;
-	}
-
-	if(!read_var_sized(a, &compression_info, NULL))
-		return ARCHIVE_EOF;
-
-	c_method = (int) (compression_info >> 7) & 0x7;
-	c_version = (int) (compression_info & 0x3f);
-
-	/* RAR5 seems to limit the dictionary size to 64MB. */
-	window_size = (rar->file.dir > 0) ?
-		0 :
-		g_unpack_window_size << ((compression_info >> 10) & 15);
-	rar->cstate.method = c_method;
-	rar->cstate.version = c_version + 50;
-	rar->file.solid = (compression_info & SOLID) > 0;
-
-	/* Archives which declare solid files without initializing the window
-	 * buffer first are invalid. */
-
-	if(rar->file.solid > 0 && rar->cstate.window_buf == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				  "Declared solid file, but no window buffer "
-				  "initialized yet.");
-		return ARCHIVE_FATAL;
-	}
-
-	/* Check if window_size is a sane value. Also, if the file is not
-	 * declared as a directory, disallow window_size == 0. */
-	if(window_size > (64 * 1024 * 1024) ||
-	    (rar->file.dir == 0 && window_size == 0))
-	{
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Declared dictionary size is not supported.");
-		return ARCHIVE_FATAL;
-	}
-
-	if(rar->file.solid > 0) {
-		/* Re-check if current window size is the same as previous
-		 * window size (for solid files only). */
-		if(rar->file.solid_window_size > 0 &&
-		    rar->file.solid_window_size != (ssize_t) window_size)
-		{
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Window size for this solid file doesn't match "
-			    "the window size used in previous solid file. ");
-			return ARCHIVE_FATAL;
-		}
-	}
-
-	if(rar->cstate.window_size < (ssize_t) window_size &&
-	    rar->cstate.window_buf)
-	{
-		/* If window_buf has been allocated before, reallocate it, so
-		 * that its size will match new window_size. */
-
-		uint8_t* new_window_buf =
-			realloc(rar->cstate.window_buf, window_size);
-
-		if(!new_window_buf) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-				"Not enough memory when trying to realloc the window "
-				"buffer.");
-			return ARCHIVE_FATAL;
-		}
-
-		rar->cstate.window_buf = new_window_buf;
-	}
-
-	/* Values up to 64M should fit into ssize_t on every
-	 * architecture. */
-	rar->cstate.window_size = (ssize_t) window_size;
-
-	if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
-		/* Solid files have to have the same window_size across
-		   whole archive. Remember the window_size parameter
-		   for first solid file found. */
-		rar->file.solid_window_size = rar->cstate.window_size;
-	}
-
-	init_window_mask(rar);
-
-	rar->file.service = 0;
-
-	if(!read_var_sized(a, &host_os, NULL))
-		return ARCHIVE_EOF;
-
-	if(host_os == HOST_WINDOWS) {
-		/* Host OS is Windows */
-
-		__LA_MODE_T mode;
-
-		if(file_attr & ATTR_DIRECTORY) {
-			if (file_attr & ATTR_READONLY) {
-				mode = 0555 | AE_IFDIR;
-			} else {
-				mode = 0755 | AE_IFDIR;
-			}
-		} else {
-			if (file_attr & ATTR_READONLY) {
-				mode = 0444 | AE_IFREG;
-			} else {
-				mode = 0644 | AE_IFREG;
-			}
-		}
-
-		archive_entry_set_mode(entry, mode);
-
-		if (file_attr & (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM)) {
-			char *fflags_text, *ptr;
-			/* allocate for "rdonly,hidden,system," */
-			fflags_text = malloc(22 * sizeof(char));
-			if (fflags_text != NULL) {
-				ptr = fflags_text;
-				if (file_attr & ATTR_READONLY) {
-					strcpy(ptr, "rdonly,");
-					ptr = ptr + 7;
-				}
-				if (file_attr & ATTR_HIDDEN) {
-					strcpy(ptr, "hidden,");
-					ptr = ptr + 7;
-				}
-				if (file_attr & ATTR_SYSTEM) {
-					strcpy(ptr, "system,");
-					ptr = ptr + 7;
-				}
-				if (ptr > fflags_text) {
-					/* Delete trailing comma */
-					*(ptr - 1) = '\0';
-					archive_entry_copy_fflags_text(entry,
-					    fflags_text);
-				}
-				free(fflags_text);
-			}
-		}
-	} else if(host_os == HOST_UNIX) {
-		/* Host OS is Unix */
-		archive_entry_set_mode(entry, (__LA_MODE_T) file_attr);
-	} else {
-		/* Unknown host OS */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				"Unsupported Host OS: 0x%x", (int) host_os);
-
-		return ARCHIVE_FATAL;
-	}
-
-	if(!read_var_sized(a, &name_size, NULL))
-		return ARCHIVE_EOF;
-
-	if(!read_ahead(a, name_size, &p))
-		return ARCHIVE_EOF;
-
-	if(name_size > (MAX_NAME_IN_CHARS - 1)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				"Filename is too long");
-
-		return ARCHIVE_FATAL;
-	}
-
-	if(name_size == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-				"No filename specified");
-
-		return ARCHIVE_FATAL;
-	}
-
-	memcpy(name_utf8_buf, p, name_size);
-	name_utf8_buf[name_size] = 0;
-	if(ARCHIVE_OK != consume(a, name_size)) {
-		return ARCHIVE_EOF;
-	}
-
-	archive_entry_update_pathname_utf8(entry, name_utf8_buf);
-
-	if(extra_data_size > 0) {
-		int ret = process_head_file_extra(a, entry, rar,
-		    extra_data_size);
-
-		/*
-		 * TODO: rewrite or remove useless sanity check
-		 *       as extra_data_size is not passed as a pointer
-		 *
-		if(extra_data_size < 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-			    "File extra data size is not zero");
-			return ARCHIVE_FATAL;
-		}
-		 */
-
-		if(ret != ARCHIVE_OK)
-			return ret;
-	}
-
-	if((file_flags & UNKNOWN_UNPACKED_SIZE) == 0) {
-		rar->file.unpacked_size = (ssize_t) unpacked_size;
-		if(rar->file.redir_type == REDIR_TYPE_NONE)
-			archive_entry_set_size(entry, unpacked_size);
-	}
-
-	if(file_flags & UTIME) {
-		archive_entry_set_mtime(entry, (time_t) mtime, 0);
-	}
-
-	if(file_flags & CRC32) {
-		rar->file.stored_crc32 = crc;
-	}
-
-	if(!rar->cstate.switch_multivolume) {
-		/* Do not reinitialize unpacking state if we're switching
-		 * archives. */
-		rar->cstate.block_parsing_finished = 1;
-		rar->cstate.all_filters_applied = 1;
-		rar->cstate.initialized = 0;
-	}
-
-	if(rar->generic.split_before > 0) {
-		/* If now we're standing on a header that has a 'split before'
-		 * mark, it means we're standing on a 'continuation' file
-		 * header. Signal the caller that if it wants to move to
-		 * another file, it must call rar5_read_header() function
-		 * again. */
-
-		return ARCHIVE_RETRY;
-	} else {
-		return ARCHIVE_OK;
-	}
-}
-
-static int process_head_service(struct archive_read* a, struct rar5* rar,
-    struct archive_entry* entry, size_t block_flags)
-{
-	/* Process this SERVICE block the same way as FILE blocks. */
-	int ret = process_head_file(a, rar, entry, block_flags);
-	if(ret != ARCHIVE_OK)
-		return ret;
-
-	rar->file.service = 1;
-
-	/* But skip the data part automatically. It's no use for the user
-	 * anyway.  It contains only service data, not even needed to
-	 * properly unpack the file. */
-	ret = rar5_read_data_skip(a);
-	if(ret != ARCHIVE_OK)
-		return ret;
-
-	/* After skipping, try parsing another block automatically. */
-	return ARCHIVE_RETRY;
-}
-
-static int process_head_main(struct archive_read* a, struct rar5* rar,
-    struct archive_entry* entry, size_t block_flags)
-{
-	int ret;
-	size_t extra_data_size = 0;
-	size_t extra_field_size = 0;
-	size_t extra_field_id = 0;
-	size_t archive_flags = 0;
-
-	enum MAIN_FLAGS {
-		VOLUME = 0x0001,         /* multi-volume archive */
-		VOLUME_NUMBER = 0x0002,  /* volume number, first vol doesn't
-					  * have it */
-		SOLID = 0x0004,          /* solid archive */
-		PROTECT = 0x0008,        /* contains Recovery info */
-		LOCK = 0x0010,           /* readonly flag, not used */
-	};
-
-	enum MAIN_EXTRA {
-		// Just one attribute here.
-		LOCATOR = 0x01,
-	};
-
-	(void) entry;
-
-	if(block_flags & HFL_EXTRA_DATA) {
-		if(!read_var_sized(a, &extra_data_size, NULL))
-			return ARCHIVE_EOF;
-	} else {
-		extra_data_size = 0;
-	}
-
-	if(!read_var_sized(a, &archive_flags, NULL)) {
-		return ARCHIVE_EOF;
-	}
-
-	rar->main.volume = (archive_flags & VOLUME) > 0;
-	rar->main.solid = (archive_flags & SOLID) > 0;
-
-	if(archive_flags & VOLUME_NUMBER) {
-		size_t v = 0;
-		if(!read_var_sized(a, &v, NULL)) {
-			return ARCHIVE_EOF;
-		}
-
-		if (v > UINT_MAX) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Invalid volume number");
-			return ARCHIVE_FATAL;
-		}
-
-		rar->main.vol_no = (unsigned int) v;
-	} else {
-		rar->main.vol_no = 0;
-	}
-
-	if(rar->vol.expected_vol_no > 0 &&
-		rar->main.vol_no != rar->vol.expected_vol_no)
-	{
-		/* Returning EOF instead of FATAL because of strange
-		 * libarchive behavior. When opening multiple files via
-		 * archive_read_open_filenames(), after reading up the whole
-		 * last file, the __archive_read_ahead function wraps up to
-		 * the first archive instead of returning EOF. */
-		return ARCHIVE_EOF;
-	}
-
-	if(extra_data_size == 0) {
-		/* Early return. */
-		return ARCHIVE_OK;
-	}
-
-	if(!read_var_sized(a, &extra_field_size, NULL)) {
-		return ARCHIVE_EOF;
-	}
-
-	if(!read_var_sized(a, &extra_field_id, NULL)) {
-		return ARCHIVE_EOF;
-	}
-
-	if(extra_field_size == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid extra field size");
-		return ARCHIVE_FATAL;
-	}
-
-	switch(extra_field_id) {
-		case LOCATOR:
-			ret = process_main_locator_extra_block(a, rar);
-			if(ret != ARCHIVE_OK) {
-				/* Error while parsing main locator extra
-				 * block. */
-				return ret;
-			}
-
-			break;
-		default:
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Unsupported extra type (0x%x)",
-			    (int) extra_field_id);
-			return ARCHIVE_FATAL;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int skip_unprocessed_bytes(struct archive_read* a) {
-	struct rar5* rar = get_context(a);
-	int ret;
-
-	if(rar->file.bytes_remaining) {
-		/* Use different skipping method in block merging mode than in
-		 * normal mode. If merge mode is active, rar5_read_data_skip
-		 * can't be used, because it could allow recursive use of
-		 * merge_block() * function, and this function doesn't support
-		 * recursive use. */
-		if(rar->merge_mode) {
-			/* Discard whole merged block. This is valid in solid
-			 * mode as well, because the code will discard blocks
-			 * only if those blocks are safe to discard (i.e.
-			 * they're not FILE blocks).  */
-			ret = consume(a, rar->file.bytes_remaining);
-			if(ret != ARCHIVE_OK) {
-				return ret;
-			}
-			rar->file.bytes_remaining = 0;
-		} else {
-			/* If we're not in merge mode, use safe skipping code.
-			 * This will ensure we'll handle solid archives
-			 * properly. */
-			ret = rar5_read_data_skip(a);
-			if(ret != ARCHIVE_OK) {
-				return ret;
-			}
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int scan_for_signature(struct archive_read* a);
-
-/* Base block processing function. A 'base block' is a RARv5 header block
- * that tells the reader what kind of data is stored inside the block.
- *
- * From the birds-eye view a RAR file looks file this:
- *
- * <magic><base_block_1><base_block_2>...<base_block_n>
- *
- * There are a few types of base blocks. Those types are specified inside
- * the 'switch' statement in this function. For example purposes, I'll write
- * how a standard RARv5 file could look like here:
- *
- * <magic><MAIN><FILE><FILE><FILE><SERVICE><ENDARC>
- *
- * The structure above could describe an archive file with 3 files in it,
- * one service "QuickOpen" block (that is ignored by this parser), and an
- * end of file base block marker.
- *
- * If the file is stored in multiple archive files ("multiarchive"), it might
- * look like this:
- *
- * .part01.rar: <magic><MAIN><FILE><ENDARC>
- * .part02.rar: <magic><MAIN><FILE><ENDARC>
- * .part03.rar: <magic><MAIN><FILE><ENDARC>
- *
- * This example could describe 3 RAR files that contain ONE archived file.
- * Or it could describe 3 RAR files that contain 3 different files. Or 3
- * RAR files than contain 2 files. It all depends what metadata is stored in
- * the headers of <FILE> blocks.
- *
- * Each <FILE> block contains info about its size, the name of the file it's
- * storing inside, and whether this FILE block is a continuation block of
- * previous archive ('split before'), and is this FILE block should be
- * continued in another archive ('split after'). By parsing the 'split before'
- * and 'split after' flags, we're able to tell if multiple <FILE> base blocks
- * are describing one file, or multiple files (with the same filename, for
- * example).
- *
- * One thing to note is that if we're parsing the first <FILE> block, and
- * we see 'split after' flag, then we need to jump over to another <FILE>
- * block to be able to decompress rest of the data. To do this, we need
- * to skip the <ENDARC> block, then switch to another file, then skip the
- * <magic> block, <MAIN> block, and then we're standing on the proper
- * <FILE> block.
- */
-
-static int process_base_block(struct archive_read* a,
-    struct archive_entry* entry)
-{
-	const size_t SMALLEST_RAR5_BLOCK_SIZE = 3;
-
-	struct rar5* rar = get_context(a);
-	uint32_t hdr_crc, computed_crc;
-	size_t raw_hdr_size = 0, hdr_size_len, hdr_size;
-	size_t header_id = 0;
-	size_t header_flags = 0;
-	const uint8_t* p;
-	int ret;
-
-	enum HEADER_TYPE {
-		HEAD_MARK    = 0x00, HEAD_MAIN  = 0x01, HEAD_FILE   = 0x02,
-		HEAD_SERVICE = 0x03, HEAD_CRYPT = 0x04, HEAD_ENDARC = 0x05,
-		HEAD_UNKNOWN = 0xff,
-	};
-
-	/* Skip any unprocessed data for this file. */
-	ret = skip_unprocessed_bytes(a);
-	if(ret != ARCHIVE_OK)
-		return ret;
-
-	/* Read the expected CRC32 checksum. */
-	if(!read_u32(a, &hdr_crc)) {
-		return ARCHIVE_EOF;
-	}
-
-	/* Read header size. */
-	if(!read_var_sized(a, &raw_hdr_size, &hdr_size_len)) {
-		return ARCHIVE_EOF;
-	}
-
-	hdr_size = raw_hdr_size + hdr_size_len;
-
-	/* Sanity check, maximum header size for RAR5 is 2MB. */
-	if(hdr_size > (2 * 1024 * 1024)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Base block header is too large");
-
-		return ARCHIVE_FATAL;
-	}
-
-	/* Additional sanity checks to weed out invalid files. */
-	if(raw_hdr_size == 0 || hdr_size_len == 0 ||
-		hdr_size < SMALLEST_RAR5_BLOCK_SIZE)
-	{
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Too small block encountered (%zu bytes)",
-		    raw_hdr_size);
-
-		return ARCHIVE_FATAL;
-	}
-
-	/* Read the whole header data into memory, maximum memory use here is
-	 * 2MB. */
-	if(!read_ahead(a, hdr_size, &p)) {
-		return ARCHIVE_EOF;
-	}
-
-	/* Verify the CRC32 of the header data. */
-	computed_crc = (uint32_t) crc32(0, p, (int) hdr_size);
-	if(computed_crc != hdr_crc) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Header CRC error");
-
-		return ARCHIVE_FATAL;
-	}
-
-	/* If the checksum is OK, we proceed with parsing. */
-	if(ARCHIVE_OK != consume(a, hdr_size_len)) {
-		return ARCHIVE_EOF;
-	}
-
-	if(!read_var_sized(a, &header_id, NULL))
-		return ARCHIVE_EOF;
-
-	if(!read_var_sized(a, &header_flags, NULL))
-		return ARCHIVE_EOF;
-
-	rar->generic.split_after = (header_flags & HFL_SPLIT_AFTER) > 0;
-	rar->generic.split_before = (header_flags & HFL_SPLIT_BEFORE) > 0;
-	rar->generic.size = (int)hdr_size;
-	rar->generic.last_header_id = (int)header_id;
-	rar->main.endarc = 0;
-
-	/* Those are possible header ids in RARv5. */
-	switch(header_id) {
-		case HEAD_MAIN:
-			ret = process_head_main(a, rar, entry, header_flags);
-
-			/* Main header doesn't have any files in it, so it's
-			 * pointless to return to the caller. Retry to next
-			 * header, which should be HEAD_FILE/HEAD_SERVICE. */
-			if(ret == ARCHIVE_OK)
-				return ARCHIVE_RETRY;
-
-			return ret;
-		case HEAD_SERVICE:
-			ret = process_head_service(a, rar, entry, header_flags);
-			return ret;
-		case HEAD_FILE:
-			ret = process_head_file(a, rar, entry, header_flags);
-			return ret;
-		case HEAD_CRYPT:
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Encryption is not supported");
-			return ARCHIVE_FATAL;
-		case HEAD_ENDARC:
-			rar->main.endarc = 1;
-
-			/* After encountering an end of file marker, we need
-			 * to take into consideration if this archive is
-			 * continued in another file (i.e. is it part01.rar:
-			 * is there a part02.rar?) */
-			if(rar->main.volume) {
-				/* In case there is part02.rar, position the
-				 * read pointer in a proper place, so we can
-				 * resume parsing. */
-				ret = scan_for_signature(a);
-				if(ret == ARCHIVE_FATAL) {
-					return ARCHIVE_EOF;
-				} else {
-					if(rar->vol.expected_vol_no ==
-					    UINT_MAX) {
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_FILE_FORMAT,
-						    "Header error");
-							return ARCHIVE_FATAL;
-					}
-
-					rar->vol.expected_vol_no =
-					    rar->main.vol_no + 1;
-					return ARCHIVE_OK;
-				}
-			} else {
-				return ARCHIVE_EOF;
-			}
-		case HEAD_MARK:
-			return ARCHIVE_EOF;
-		default:
-			if((header_flags & HFL_SKIP_IF_UNKNOWN) == 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Header type error");
-				return ARCHIVE_FATAL;
-			} else {
-				/* If the block is marked as 'skip if unknown',
-				 * do as the flag says: skip the block
-				 * instead on failing on it. */
-				return ARCHIVE_RETRY;
-			}
-	}
-
-#if !defined WIN32
-	// Not reached.
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-	    "Internal unpacker error");
-	return ARCHIVE_FATAL;
-#endif
-}
-
-static int skip_base_block(struct archive_read* a) {
-	int ret;
-	struct rar5* rar = get_context(a);
-
-	/* Create a new local archive_entry structure that will be operated on
-	 * by header reader; operations on this archive_entry will be discarded.
-	 */
-	struct archive_entry* entry = archive_entry_new();
-	ret = process_base_block(a, entry);
-
-	/* Discard operations on this archive_entry structure. */
-	archive_entry_free(entry);
-	if(ret == ARCHIVE_FATAL)
-		return ret;
-
-	if(rar->generic.last_header_id == 2 && rar->generic.split_before > 0)
-		return ARCHIVE_OK;
-
-	if(ret == ARCHIVE_OK)
-		return ARCHIVE_RETRY;
-	else
-		return ret;
-}
-
-static int try_skip_sfx(struct archive_read *a)
-{
-	const char *p;
-
-	if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
-		return ARCHIVE_EOF;
-
-	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)
-	{
-		char signature[sizeof(rar5_signature_xor)];
-		const void *h;
-		const char *q;
-		size_t skip, total = 0;
-		ssize_t bytes, window = 4096;
-
-		rar5_signature(signature);
-
-		while (total + window <= (1024 * 512)) {
-			h = __archive_read_ahead(a, window, &bytes);
-			if (h == NULL) {
-				/* Remaining bytes are less than window. */
-				window >>= 1;
-				if (window < 0x40)
-					goto fatal;
-				continue;
-			}
-			if (bytes < 0x40)
-				goto fatal;
-			p = h;
-			q = p + bytes;
-
-			/*
-			 * Scan ahead until we find something that looks
-			 * like the RAR header.
-			 */
-			while (p + 8 < q) {
-				if (memcmp(p, signature, sizeof(signature)) == 0) {
-					skip = p - (const char *)h;
-					__archive_read_consume(a, skip);
-					return (ARCHIVE_OK);
-				}
-				p += 0x10;
-			}
-			skip = p - (const char *)h;
-			__archive_read_consume(a, skip);
-			total += skip;
-		}
-	}
-
-	return ARCHIVE_OK;
-fatal:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-			"Couldn't find out RAR header");
-	return (ARCHIVE_FATAL);
-}
-
-static int rar5_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct rar5* rar = get_context(a);
-	int ret;
-
-	if(rar->header_initialized == 0) {
-		init_header(a);
-		if ((ret = try_skip_sfx(a)) < ARCHIVE_WARN)
-			return ret;
-		rar->header_initialized = 1;
-	}
-
-	if(rar->skipped_magic == 0) {
-		if(ARCHIVE_OK != consume(a, sizeof(rar5_signature_xor))) {
-			return ARCHIVE_EOF;
-		}
-
-		rar->skipped_magic = 1;
-	}
-
-	do {
-		ret = process_base_block(a, entry);
-	} while(ret == ARCHIVE_RETRY ||
-			(rar->main.endarc > 0 && ret == ARCHIVE_OK));
-
-	return ret;
-}
-
-static void init_unpack(struct rar5* rar) {
-	rar->file.calculated_crc32 = 0;
-	init_window_mask(rar);
-
-	free(rar->cstate.window_buf);
-	free(rar->cstate.filtered_buf);
-
-	if(rar->cstate.window_size > 0) {
-		rar->cstate.window_buf = calloc(1, rar->cstate.window_size);
-		rar->cstate.filtered_buf = calloc(1, rar->cstate.window_size);
-	} else {
-		rar->cstate.window_buf = NULL;
-		rar->cstate.filtered_buf = NULL;
-	}
-
-	rar->cstate.write_ptr = 0;
-	rar->cstate.last_write_ptr = 0;
-
-	memset(&rar->cstate.bd, 0, sizeof(rar->cstate.bd));
-	memset(&rar->cstate.ld, 0, sizeof(rar->cstate.ld));
-	memset(&rar->cstate.dd, 0, sizeof(rar->cstate.dd));
-	memset(&rar->cstate.ldd, 0, sizeof(rar->cstate.ldd));
-	memset(&rar->cstate.rd, 0, sizeof(rar->cstate.rd));
-}
-
-static void update_crc(struct rar5* rar, const uint8_t* p, size_t to_read) {
-    int verify_crc;
-
-	if(rar->skip_mode) {
-#if defined CHECK_CRC_ON_SOLID_SKIP
-		verify_crc = 1;
-#else
-		verify_crc = 0;
-#endif
-	} else
-		verify_crc = 1;
-
-	if(verify_crc) {
-		/* Don't update CRC32 if the file doesn't have the
-		 * `stored_crc32` info filled in. */
-		if(rar->file.stored_crc32 > 0) {
-			rar->file.calculated_crc32 =
-				crc32(rar->file.calculated_crc32, p, (unsigned int)to_read);
-		}
-
-		/* Check if the file uses an optional BLAKE2sp checksum
-		 * algorithm. */
-		if(rar->file.has_blake2 > 0) {
-			/* Return value of the `update` function is always 0,
-			 * so we can explicitly ignore it here. */
-			(void) blake2sp_update(&rar->file.b2state, p, to_read);
-		}
-	}
-}
-
-static int create_decode_tables(uint8_t* bit_length,
-    struct decode_table* table, int size)
-{
-	int code, upper_limit = 0, i, lc[16];
-	uint32_t decode_pos_clone[rar5_countof(table->decode_pos)];
-	ssize_t cur_len, quick_data_size;
-
-	memset(&lc, 0, sizeof(lc));
-	memset(table->decode_num, 0, sizeof(table->decode_num));
-	table->size = size;
-	table->quick_bits = size == HUFF_NC ? 10 : 7;
-
-	for(i = 0; i < size; i++) {
-		lc[bit_length[i] & 15]++;
-	}
-
-	lc[0] = 0;
-	table->decode_pos[0] = 0;
-	table->decode_len[0] = 0;
-
-	for(i = 1; i < 16; i++) {
-		upper_limit += lc[i];
-
-		table->decode_len[i] = upper_limit << (16 - i);
-		table->decode_pos[i] = table->decode_pos[i - 1] + lc[i - 1];
-
-		upper_limit <<= 1;
-	}
-
-	memcpy(decode_pos_clone, table->decode_pos, sizeof(decode_pos_clone));
-
-	for(i = 0; i < size; i++) {
-		uint8_t clen = bit_length[i] & 15;
-		if(clen > 0) {
-			int last_pos = decode_pos_clone[clen];
-			table->decode_num[last_pos] = i;
-			decode_pos_clone[clen]++;
-		}
-	}
-
-	quick_data_size = (int64_t)1 << table->quick_bits;
-	cur_len = 1;
-	for(code = 0; code < quick_data_size; code++) {
-		int bit_field = code << (16 - table->quick_bits);
-		int dist, pos;
-
-		while(cur_len < rar5_countof(table->decode_len) &&
-				bit_field >= table->decode_len[cur_len]) {
-			cur_len++;
-		}
-
-		table->quick_len[code] = (uint8_t) cur_len;
-
-		dist = bit_field - table->decode_len[cur_len - 1];
-		dist >>= (16 - cur_len);
-
-		pos = table->decode_pos[cur_len & 15] + dist;
-		if(cur_len < rar5_countof(table->decode_pos) && pos < size) {
-			table->quick_num[code] = table->decode_num[pos];
-		} else {
-			table->quick_num[code] = 0;
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int decode_number(struct archive_read* a, struct decode_table* table,
-    const uint8_t* p, uint16_t* num)
-{
-	int i, bits, dist, ret;
-	uint16_t bitfield;
-	uint32_t pos;
-	struct rar5* rar = get_context(a);
-
-	if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
-		return ret;
-	}
-
-	bitfield &= 0xfffe;
-
-	if(bitfield < table->decode_len[table->quick_bits]) {
-		int code = bitfield >> (16 - table->quick_bits);
-		skip_bits(rar, table->quick_len[code]);
-		*num = table->quick_num[code];
-		return ARCHIVE_OK;
-	}
-
-	bits = 15;
-
-	for(i = table->quick_bits + 1; i < 15; i++) {
-		if(bitfield < table->decode_len[i]) {
-			bits = i;
-			break;
-		}
-	}
-
-	skip_bits(rar, bits);
-
-	dist = bitfield - table->decode_len[bits - 1];
-	dist >>= (16 - bits);
-	pos = table->decode_pos[bits] + dist;
-
-	if(pos >= table->size)
-		pos = 0;
-
-	*num = table->decode_num[pos];
-	return ARCHIVE_OK;
-}
-
-/* Reads and parses Huffman tables from the beginning of the block. */
-static int parse_tables(struct archive_read* a, struct rar5* rar,
-    const uint8_t* p)
-{
-	int ret, value, i, w, idx = 0;
-	uint8_t bit_length[HUFF_BC],
-		table[HUFF_TABLE_SIZE],
-		nibble_mask = 0xF0,
-		nibble_shift = 4;
-
-	enum { ESCAPE = 15 };
-
-	/* The data for table generation is compressed using a simple RLE-like
-	 * algorithm when storing zeroes, so we need to unpack it first. */
-	for(w = 0, i = 0; w < HUFF_BC;) {
-		if(i >= rar->cstate.cur_block_size) {
-			/* Truncated data, can't continue. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated data in huffman tables");
-			return ARCHIVE_FATAL;
-		}
-
-		value = (p[i] & nibble_mask) >> nibble_shift;
-
-		if(nibble_mask == 0x0F)
-			++i;
-
-		nibble_mask ^= 0xFF;
-		nibble_shift ^= 4;
-
-		/* Values smaller than 15 is data, so we write it directly.
-		 * Value 15 is a flag telling us that we need to unpack more
-		 * bytes. */
-		if(value == ESCAPE) {
-			value = (p[i] & nibble_mask) >> nibble_shift;
-			if(nibble_mask == 0x0F)
-				++i;
-			nibble_mask ^= 0xFF;
-			nibble_shift ^= 4;
-
-			if(value == 0) {
-				/* We sometimes need to write the actual value
-				 * of 15, so this case handles that. */
-				bit_length[w++] = ESCAPE;
-			} else {
-				int k;
-
-				/* Fill zeroes. */
-				for(k = 0; (k < value + 2) && (w < HUFF_BC);
-				    k++) {
-					bit_length[w++] = 0;
-				}
-			}
-		} else {
-			bit_length[w++] = value;
-		}
-	}
-
-	rar->bits.in_addr = i;
-	rar->bits.bit_addr = nibble_shift ^ 4;
-
-	ret = create_decode_tables(bit_length, &rar->cstate.bd, HUFF_BC);
-	if(ret != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Decoding huffman tables failed");
-		return ARCHIVE_FATAL;
-	}
-
-	for(i = 0; i < HUFF_TABLE_SIZE;) {
-		uint16_t num;
-
-		ret = decode_number(a, &rar->cstate.bd, p, &num);
-		if(ret != ARCHIVE_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Decoding huffman tables failed");
-			return ARCHIVE_FATAL;
-		}
-
-		if(num < 16) {
-			/* 0..15: store directly */
-			table[i] = (uint8_t) num;
-			i++;
-		} else if(num < 18) {
-			/* 16..17: repeat previous code */
-			uint16_t n;
-
-			if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
-				return ret;
-
-			if(num == 16) {
-				n >>= 13;
-				n += 3;
-				skip_bits(rar, 3);
-			} else {
-				n >>= 9;
-				n += 11;
-				skip_bits(rar, 7);
-			}
-
-			if(i > 0) {
-				while(n-- > 0 && i < HUFF_TABLE_SIZE) {
-					table[i] = table[i - 1];
-					i++;
-				}
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Unexpected error when decoding "
-				    "huffman tables");
-				return ARCHIVE_FATAL;
-			}
-		} else {
-			/* other codes: fill with zeroes `n` times */
-			uint16_t n;
-
-			if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
-				return ret;
-
-			if(num == 18) {
-				n >>= 13;
-				n += 3;
-				skip_bits(rar, 3);
-			} else {
-				n >>= 9;
-				n += 11;
-				skip_bits(rar, 7);
-			}
-
-			while(n-- > 0 && i < HUFF_TABLE_SIZE)
-				table[i++] = 0;
-		}
-	}
-
-	ret = create_decode_tables(&table[idx], &rar->cstate.ld, HUFF_NC);
-	if(ret != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		     "Failed to create literal table");
-		return ARCHIVE_FATAL;
-	}
-
-	idx += HUFF_NC;
-
-	ret = create_decode_tables(&table[idx], &rar->cstate.dd, HUFF_DC);
-	if(ret != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Failed to create distance table");
-		return ARCHIVE_FATAL;
-	}
-
-	idx += HUFF_DC;
-
-	ret = create_decode_tables(&table[idx], &rar->cstate.ldd, HUFF_LDC);
-	if(ret != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Failed to create lower bits of distances table");
-		return ARCHIVE_FATAL;
-	}
-
-	idx += HUFF_LDC;
-
-	ret = create_decode_tables(&table[idx], &rar->cstate.rd, HUFF_RC);
-	if(ret != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Failed to create repeating distances table");
-		return ARCHIVE_FATAL;
-	}
-
-	return ARCHIVE_OK;
-}
-
-/* Parses the block header, verifies its CRC byte, and saves the header
- * fields inside the `hdr` pointer. */
-static int parse_block_header(struct archive_read* a, const uint8_t* p,
-    ssize_t* block_size, struct compressed_block_header* hdr)
-{
-	uint8_t calculated_cksum;
-	memcpy(hdr, p, sizeof(struct compressed_block_header));
-
-	if(bf_byte_count(hdr) > 2) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported block header size (was %d, max is 2)",
-		    bf_byte_count(hdr));
-		return ARCHIVE_FATAL;
-	}
-
-	/* This should probably use bit reader interface in order to be more
-	 * future-proof. */
-	*block_size = 0;
-	switch(bf_byte_count(hdr)) {
-		/* 1-byte block size */
-		case 0:
-			*block_size = *(const uint8_t*) &p[2];
-			break;
-
-		/* 2-byte block size */
-		case 1:
-			*block_size = archive_le16dec(&p[2]);
-			break;
-
-		/* 3-byte block size */
-		case 2:
-			*block_size = archive_le32dec(&p[2]);
-			*block_size &= 0x00FFFFFF;
-			break;
-
-		/* Other block sizes are not supported. This case is not
-		 * reached, because we have an 'if' guard before the switch
-		 * that makes sure of it. */
-		default:
-			return ARCHIVE_FATAL;
-	}
-
-	/* Verify the block header checksum. 0x5A is a magic value and is
-	 * always * constant. */
-	calculated_cksum = 0x5A
-	    ^ (uint8_t) hdr->block_flags_u8
-	    ^ (uint8_t) *block_size
-	    ^ (uint8_t) (*block_size >> 8)
-	    ^ (uint8_t) (*block_size >> 16);
-
-	if(calculated_cksum != hdr->block_cksum) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Block checksum error: got 0x%x, expected 0x%x",
-		    hdr->block_cksum, calculated_cksum);
-
-		return ARCHIVE_FATAL;
-#endif
-	}
-
-	return ARCHIVE_OK;
-}
-
-/* Convenience function used during filter processing. */
-static int parse_filter_data(struct archive_read* a, struct rar5* rar,
-	const uint8_t* p, uint32_t* filter_data)
-{
-	int i, bytes, ret;
-	uint32_t data = 0;
-
-	if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
-		return ret;
-
-	bytes++;
-
-	for(i = 0; i < bytes; i++) {
-		uint16_t byte;
-
-		if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
-			return ret;
-		}
-
-		/* Cast to uint32_t will ensure the shift operation will not
-		 * produce undefined result. */
-		data += ((uint32_t) byte >> 8) << (i * 8);
-		skip_bits(rar, 8);
-	}
-
-	*filter_data = data;
-	return ARCHIVE_OK;
-}
-
-/* Function is used during sanity checking. */
-static int is_valid_filter_block_start(struct rar5* rar,
-    uint32_t start)
-{
-	const int64_t block_start = (ssize_t) start + rar->cstate.write_ptr;
-	const int64_t last_bs = rar->cstate.last_block_start;
-	const ssize_t last_bl = rar->cstate.last_block_length;
-
-	if(last_bs == 0 || last_bl == 0) {
-		/* We didn't have any filters yet, so accept this offset. */
-		return 1;
-	}
-
-	if(block_start >= last_bs + last_bl) {
-		/* Current offset is bigger than last block's end offset, so
-		 * accept current offset. */
-		return 1;
-	}
-
-	/* Any other case is not a normal situation and we should fail. */
-	return 0;
-}
-
-/* The function will create a new filter, read its parameters from the input
- * stream and add it to the filter collection. */
-static int parse_filter(struct archive_read* ar, const uint8_t* p) {
-	uint32_t block_start, block_length;
-	uint16_t filter_type;
-	struct filter_info* filt = NULL;
-	struct rar5* rar = get_context(ar);
-	int ret;
-
-	/* Read the parameters from the input stream. */
-	if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
-		return ret;
-
-	if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
-		return ret;
-
-	if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
-		return ret;
-
-	filter_type >>= 13;
-	skip_bits(rar, 3);
-
-	/* Perform some sanity checks on this filter parameters. Note that we
-	 * allow only DELTA, E8/E9 and ARM filters here, because rest of
-	 * filters are not used in RARv5. */
-
-	if(block_length < 4 ||
-	    block_length > 0x400000 ||
-	    filter_type > FILTER_ARM ||
-	    !is_valid_filter_block_start(rar, block_start))
-	{
-		archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid filter encountered");
-		return ARCHIVE_FATAL;
-	}
-
-	/* Allocate a new filter. */
-	filt = add_new_filter(rar);
-	if(filt == NULL) {
-		archive_set_error(&ar->archive, ENOMEM,
-		    "Can't allocate memory for a filter descriptor.");
-		return ARCHIVE_FATAL;
-	}
-
-	filt->type = filter_type;
-	filt->block_start = rar->cstate.write_ptr + block_start;
-	filt->block_length = block_length;
-
-	rar->cstate.last_block_start = filt->block_start;
-	rar->cstate.last_block_length = filt->block_length;
-
-	/* Read some more data in case this is a DELTA filter. Other filter
-	 * types don't require any additional data over what was already
-	 * read. */
-	if(filter_type == FILTER_DELTA) {
-		int channels;
-
-		if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
-			return ret;
-
-		filt->channels = channels + 1;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int decode_code_length(struct archive_read* a, struct rar5* rar,
-	const uint8_t* p, uint16_t code)
-{
-	int lbits, length = 2;
-
-	if(code < 8) {
-		lbits = 0;
-		length += code;
-	} else {
-		lbits = code / 4 - 1;
-		length += (4 | (code & 3)) << lbits;
-	}
-
-	if(lbits > 0) {
-		int add;
-
-		if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add))
-			return -1;
-
-		length += add;
-	}
-
-	return length;
-}
-
-static int copy_string(struct archive_read* a, int len, int dist) {
-	struct rar5* rar = get_context(a);
-	const uint64_t cmask = rar->cstate.window_mask;
-	const uint64_t write_ptr = rar->cstate.write_ptr +
-	    rar->cstate.solid_offset;
-	int i;
-
-	if (rar->cstate.window_buf == NULL)
-		return ARCHIVE_FATAL;
-
-	/* The unpacker spends most of the time in this function. It would be
-	 * a good idea to introduce some optimizations here.
-	 *
-	 * Just remember that this loop treats buffers that overlap differently
-	 * than buffers that do not overlap. This is why a simple memcpy(3)
-	 * call will not be enough. */
-
-	for(i = 0; i < len; i++) {
-		const ssize_t write_idx = (write_ptr + i) & cmask;
-		const ssize_t read_idx = (write_ptr + i - dist) & cmask;
-		rar->cstate.window_buf[write_idx] =
-		    rar->cstate.window_buf[read_idx];
-	}
-
-	rar->cstate.write_ptr += len;
-	return ARCHIVE_OK;
-}
-
-static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
-	struct rar5* rar = get_context(a);
-	uint16_t num;
-	int ret;
-
-	const uint64_t cmask = rar->cstate.window_mask;
-	const struct compressed_block_header* hdr = &rar->last_block_hdr;
-	const uint8_t bit_size = 1 + bf_bit_size(hdr);
-
-	while(1) {
-		if(rar->cstate.write_ptr - rar->cstate.last_write_ptr >
-		    (rar->cstate.window_size >> 1)) {
-			/* Don't allow growing data by more than half of the
-			 * window size at a time. In such case, break the loop;
-			 *  next call to this function will continue processing
-			 *  from this moment. */
-			break;
-		}
-
-		if(rar->bits.in_addr > rar->cstate.cur_block_size - 1 ||
-		    (rar->bits.in_addr == rar->cstate.cur_block_size - 1 &&
-		    rar->bits.bit_addr >= bit_size))
-		{
-			/* If the program counter is here, it means the
-			 * function has finished processing the block. */
-			rar->cstate.block_parsing_finished = 1;
-			break;
-		}
-
-		/* Decode the next literal. */
-		if(ARCHIVE_OK != decode_number(a, &rar->cstate.ld, p, &num)) {
-			return ARCHIVE_EOF;
-		}
-
-		/* Num holds a decompression literal, or 'command code'.
-		 *
-		 * - Values lower than 256 are just bytes. Those codes
-		 *   can be stored in the output buffer directly.
-		 *
-		 * - Code 256 defines a new filter, which is later used to
-		 *   ransform the data block accordingly to the filter type.
-		 *   The data block needs to be fully uncompressed first.
-		 *
-		 * - Code bigger than 257 and smaller than 262 define
-		 *   a repetition pattern that should be copied from
-		 *   an already uncompressed chunk of data.
-		 */
-
-		if(num < 256) {
-			/* Directly store the byte. */
-			int64_t write_idx = rar->cstate.solid_offset +
-			    rar->cstate.write_ptr++;
-
-			rar->cstate.window_buf[write_idx & cmask] =
-			    (uint8_t) num;
-			continue;
-		} else if(num >= 262) {
-			uint16_t dist_slot;
-			int len = decode_code_length(a, rar, p, num - 262),
-				dbits,
-				dist = 1;
-
-			if(len == -1) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_PROGRAMMER,
-				    "Failed to decode the code length");
-
-				return ARCHIVE_FATAL;
-			}
-
-			if(ARCHIVE_OK != decode_number(a, &rar->cstate.dd, p,
-			    &dist_slot))
-			{
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_PROGRAMMER,
-				    "Failed to decode the distance slot");
-
-				return ARCHIVE_FATAL;
-			}
-
-			if(dist_slot < 4) {
-				dbits = 0;
-				dist += dist_slot;
-			} else {
-				dbits = dist_slot / 2 - 1;
-
-				/* Cast to uint32_t will make sure the shift
-				 * left operation won't produce undefined
-				 * result. Then, the uint32_t type will
-				 * be implicitly casted to int. */
-				dist += (uint32_t) (2 |
-				    (dist_slot & 1)) << dbits;
-			}
-
-			if(dbits > 0) {
-				if(dbits >= 4) {
-					uint32_t add = 0;
-					uint16_t low_dist;
-
-					if(dbits > 4) {
-						if(ARCHIVE_OK != (ret = read_bits_32(
-						    a, rar, p, &add))) {
-							/* Return EOF if we
-							 * can't read more
-							 * data. */
-							return ret;
-						}
-
-						skip_bits(rar, dbits - 4);
-						add = (add >> (
-						    36 - dbits)) << 4;
-						dist += add;
-					}
-
-					if(ARCHIVE_OK != decode_number(a,
-					    &rar->cstate.ldd, p, &low_dist))
-					{
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_PROGRAMMER,
-						    "Failed to decode the "
-						    "distance slot");
-
-						return ARCHIVE_FATAL;
-					}
-
-					if(dist >= INT_MAX - low_dist - 1) {
-						/* This only happens in
-						 * invalid archives. */
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_FILE_FORMAT,
-						    "Distance pointer "
-						    "overflow");
-						return ARCHIVE_FATAL;
-					}
-
-					dist += low_dist;
-				} else {
-					/* dbits is one of [0,1,2,3] */
-					int add;
-
-					if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
-					     p, dbits, &add))) {
-						/* Return EOF if we can't read
-						 * more data. */
-						return ret;
-					}
-
-					dist += add;
-				}
-			}
-
-			if(dist > 0x100) {
-				len++;
-
-				if(dist > 0x2000) {
-					len++;
-
-					if(dist > 0x40000) {
-						len++;
-					}
-				}
-			}
-
-			dist_cache_push(rar, dist);
-			rar->cstate.last_len = len;
-
-			if(ARCHIVE_OK != copy_string(a, len, dist))
-				return ARCHIVE_FATAL;
-
-			continue;
-		} else if(num == 256) {
-			/* Create a filter. */
-			ret = parse_filter(a, p);
-			if(ret != ARCHIVE_OK)
-				return ret;
-
-			continue;
-		} else if(num == 257) {
-			if(rar->cstate.last_len != 0) {
-				if(ARCHIVE_OK != copy_string(a,
-				    rar->cstate.last_len,
-				    rar->cstate.dist_cache[0]))
-				{
-					return ARCHIVE_FATAL;
-				}
-			}
-
-			continue;
-		} else {
-			/* num < 262 */
-			const int idx = num - 258;
-			const int dist = dist_cache_touch(rar, idx);
-
-			uint16_t len_slot;
-			int len;
-
-			if(ARCHIVE_OK != decode_number(a, &rar->cstate.rd, p,
-			    &len_slot)) {
-				return ARCHIVE_FATAL;
-			}
-
-			len = decode_code_length(a, rar, p, len_slot);
-			if (len == -1) {
-				return ARCHIVE_FATAL;
-			}
-
-			rar->cstate.last_len = len;
-
-			if(ARCHIVE_OK != copy_string(a, len, dist))
-				return ARCHIVE_FATAL;
-
-			continue;
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-/* Binary search for the RARv5 signature. */
-static int scan_for_signature(struct archive_read* a) {
-	const uint8_t* p;
-	const int chunk_size = 512;
-	ssize_t i;
-	char signature[sizeof(rar5_signature_xor)];
-
-	/* If we're here, it means we're on an 'unknown territory' data.
-	 * There's no indication what kind of data we're reading here.
-	 * It could be some text comment, any kind of binary data,
-	 * digital sign, dragons, etc.
-	 *
-	 * We want to find a valid RARv5 magic header inside this unknown
-	 * data. */
-
-	/* Is it possible in libarchive to just skip everything until the
-	 * end of the file? If so, it would be a better approach than the
-	 * current implementation of this function. */
-
-	rar5_signature(signature);
-
-	while(1) {
-		if(!read_ahead(a, chunk_size, &p))
-			return ARCHIVE_EOF;
-
-		for(i = 0; i < chunk_size - (int)sizeof(rar5_signature_xor);
-		    i++) {
-			if(memcmp(&p[i], signature,
-			    sizeof(rar5_signature_xor)) == 0) {
-				/* Consume the number of bytes we've used to
-				 * search for the signature, as well as the
-				 * number of bytes used by the signature
-				 * itself. After this we should be standing
-				 * on a valid base block header. */
-				(void) consume(a,
-				    i + sizeof(rar5_signature_xor));
-				return ARCHIVE_OK;
-			}
-		}
-
-		consume(a, chunk_size);
-	}
-
-	return ARCHIVE_FATAL;
-}
-
-/* This function will switch the multivolume archive file to another file,
- * i.e. from part03 to part 04. */
-static int advance_multivolume(struct archive_read* a) {
-	int lret;
-	struct rar5* rar = get_context(a);
-
-	/* A small state machine that will skip unnecessary data, needed to
-	 * switch from one multivolume to another. Such skipping is needed if
-	 * we want to be an stream-oriented (instead of file-oriented)
-	 * unpacker.
-	 *
-	 * The state machine starts with `rar->main.endarc` == 0. It also
-	 * assumes that current stream pointer points to some base block
-	 * header.
-	 *
-	 * The `endarc` field is being set when the base block parsing
-	 * function encounters the 'end of archive' marker.
-	 */
-
-	while(1) {
-		if(rar->main.endarc == 1) {
-			int looping = 1;
-
-			rar->main.endarc = 0;
-
-			while(looping) {
-				lret = skip_base_block(a);
-				switch(lret) {
-					case ARCHIVE_RETRY:
-						/* Continue looping. */
-						break;
-					case ARCHIVE_OK:
-						/* Break loop. */
-						looping = 0;
-						break;
-					default:
-						/* Forward any errors to the
-						 * caller. */
-						return lret;
-				}
-			}
-
-			break;
-		} else {
-			/* Skip current base block. In order to properly skip
-			 * it, we really need to simply parse it and discard
-			 * the results. */
-
-			lret = skip_base_block(a);
-			if(lret == ARCHIVE_FATAL || lret == ARCHIVE_FAILED)
-				return lret;
-
-			/* The `skip_base_block` function tells us if we
-			 * should continue with skipping, or we should stop
-			 * skipping. We're trying to skip everything up to
-			 * a base FILE block. */
-
-			if(lret != ARCHIVE_RETRY) {
-				/* If there was an error during skipping, or we
-				 * have just skipped a FILE base block... */
-
-				if(rar->main.endarc == 0) {
-					return lret;
-				} else {
-					continue;
-				}
-			}
-		}
-	}
-
-	return ARCHIVE_OK;
-}
-
-/* Merges the partial block from the first multivolume archive file, and
- * partial block from the second multivolume archive file. The result is
- * a chunk of memory containing the whole block, and the stream pointer
- * is advanced to the next block in the second multivolume archive file. */
-static int merge_block(struct archive_read* a, ssize_t block_size,
-    const uint8_t** p)
-{
-	struct rar5* rar = get_context(a);
-	ssize_t cur_block_size, partial_offset = 0;
-	const uint8_t* lp;
-	int ret;
-
-	if(rar->merge_mode) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Recursive merge is not allowed");
-
-		return ARCHIVE_FATAL;
-	}
-
-	/* Set a flag that we're in the switching mode. */
-	rar->cstate.switch_multivolume = 1;
-
-	/* Reallocate the memory which will hold the whole block. */
-	if(rar->vol.push_buf)
-		free((void*) rar->vol.push_buf);
-
-	/* Increasing the allocation block by 8 is due to bit reading functions,
-	 * which are using additional 2 or 4 bytes. Allocating the block size
-	 * by exact value would make bit reader perform reads from invalid
-	 * memory block when reading the last byte from the buffer. */
-	rar->vol.push_buf = malloc(block_size + 8);
-	if(!rar->vol.push_buf) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for a merge block buffer.");
-		return ARCHIVE_FATAL;
-	}
-
-	/* Valgrind complains if the extension block for bit reader is not
-	 * initialized, so initialize it. */
-	memset(&rar->vol.push_buf[block_size], 0, 8);
-
-	/* A single block can span across multiple multivolume archive files,
-	 * so we use a loop here. This loop will consume enough multivolume
-	 * archive files until the whole block is read. */
-
-	while(1) {
-		/* Get the size of current block chunk in this multivolume
-		 * archive file and read it. */
-		cur_block_size = rar5_min(rar->file.bytes_remaining,
-		    block_size - partial_offset);
-
-		if(cur_block_size == 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Encountered block size == 0 during block merge");
-			return ARCHIVE_FATAL;
-		}
-
-		if(!read_ahead(a, cur_block_size, &lp))
-			return ARCHIVE_EOF;
-
-		/* Sanity check; there should never be a situation where this
-		 * function reads more data than the block's size. */
-		if(partial_offset + cur_block_size > block_size) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_PROGRAMMER,
-			    "Consumed too much data when merging blocks.");
-			return ARCHIVE_FATAL;
-		}
-
-		/* Merge previous block chunk with current block chunk,
-		 * or create first block chunk if this is our first
-		 * iteration. */
-		memcpy(&rar->vol.push_buf[partial_offset], lp, cur_block_size);
-
-		/* Advance the stream read pointer by this block chunk size. */
-		if(ARCHIVE_OK != consume(a, cur_block_size))
-			return ARCHIVE_EOF;
-
-		/* Update the pointers. `partial_offset` contains information
-		 * about the sum of merged block chunks. */
-		partial_offset += cur_block_size;
-		rar->file.bytes_remaining -= cur_block_size;
-
-		/* If `partial_offset` is the same as `block_size`, this means
-		 * we've merged all block chunks and we have a valid full
-		 * block. */
-		if(partial_offset == block_size) {
-			break;
-		}
-
-		/* If we don't have any bytes to read, this means we should
-		 * switch to another multivolume archive file. */
-		if(rar->file.bytes_remaining == 0) {
-			rar->merge_mode++;
-			ret = advance_multivolume(a);
-			rar->merge_mode--;
-			if(ret != ARCHIVE_OK) {
-				return ret;
-			}
-		}
-	}
-
-	*p = rar->vol.push_buf;
-
-	/* If we're here, we can resume unpacking by processing the block
-	 * pointed to by the `*p` memory pointer. */
-
-	return ARCHIVE_OK;
-}
-
-static int process_block(struct archive_read* a) {
-	const uint8_t* p;
-	struct rar5* rar = get_context(a);
-	int ret;
-
-	/* If we don't have any data to be processed, this most probably means
-	 * we need to switch to the next volume. */
-	if(rar->main.volume && rar->file.bytes_remaining == 0) {
-		ret = advance_multivolume(a);
-		if(ret != ARCHIVE_OK)
-			return ret;
-	}
-
-	if(rar->cstate.block_parsing_finished) {
-		ssize_t block_size;
-		ssize_t to_skip;
-		ssize_t cur_block_size;
-
-		/* The header size won't be bigger than 6 bytes. */
-		if(!read_ahead(a, 6, &p)) {
-			/* Failed to prefetch data block header. */
-			return ARCHIVE_EOF;
-		}
-
-		/*
-		 * Read block_size by parsing block header. Validate the header
-		 * by calculating CRC byte stored inside the header. Size of
-		 * the header is not constant (block size can be stored either
-		 * in 1 or 2 bytes), that's why block size is left out from the
-		 * `compressed_block_header` structure and returned by
-		 * `parse_block_header` as the second argument. */
-
-		ret = parse_block_header(a, p, &block_size,
-		    &rar->last_block_hdr);
-		if(ret != ARCHIVE_OK) {
-			return ret;
-		}
-
-		/* Skip block header. Next data is huffman tables,
-		 * if present. */
-		to_skip = sizeof(struct compressed_block_header) +
-			bf_byte_count(&rar->last_block_hdr) + 1;
-
-		if(ARCHIVE_OK != consume(a, to_skip))
-			return ARCHIVE_EOF;
-
-		rar->file.bytes_remaining -= to_skip;
-
-		/* The block size gives information about the whole block size,
-		 * but the block could be stored in split form when using
-		 * multi-volume archives. In this case, the block size will be
-		 * bigger than the actual data stored in this file. Remaining
-		 * part of the data will be in another file. */
-
-		cur_block_size =
-			rar5_min(rar->file.bytes_remaining, block_size);
-
-		if(block_size > rar->file.bytes_remaining) {
-			/* If current blocks' size is bigger than our data
-			 * size, this means we have a multivolume archive.
-			 * In this case, skip all base headers until the end
-			 * of the file, proceed to next "partXXX.rar" volume,
-			 * find its signature, skip all headers up to the first
-			 * FILE base header, and continue from there.
-			 *
-			 * Note that `merge_block` will update the `rar`
-			 * context structure quite extensively. */
-
-			ret = merge_block(a, block_size, &p);
-			if(ret != ARCHIVE_OK) {
-				return ret;
-			}
-
-			cur_block_size = block_size;
-
-			/* Current stream pointer should be now directly
-			 * *after* the block that spanned through multiple
-			 * archive files. `p` pointer should have the data of
-			 * the *whole* block (merged from partial blocks
-			 * stored in multiple archives files). */
-		} else {
-			rar->cstate.switch_multivolume = 0;
-
-			/* Read the whole block size into memory. This can take
-			 * up to  8 megabytes of memory in theoretical cases.
-			 * Might be worth to optimize this and use a standard
-			 * chunk of 4kb's. */
-			if(!read_ahead(a, 4 + cur_block_size, &p)) {
-				/* Failed to prefetch block data. */
-				return ARCHIVE_EOF;
-			}
-		}
-
-		rar->cstate.block_buf = p;
-		rar->cstate.cur_block_size = cur_block_size;
-		rar->cstate.block_parsing_finished = 0;
-
-		rar->bits.in_addr = 0;
-		rar->bits.bit_addr = 0;
-
-		if(bf_is_table_present(&rar->last_block_hdr)) {
-			/* Load Huffman tables. */
-			ret = parse_tables(a, rar, p);
-			if(ret != ARCHIVE_OK) {
-				/* Error during decompression of Huffman
-				 * tables. */
-				return ret;
-			}
-		}
-	} else {
-		/* Block parsing not finished, reuse previous memory buffer. */
-		p = rar->cstate.block_buf;
-	}
-
-	/* Uncompress the block, or a part of it, depending on how many bytes
-	 * will be generated by uncompressing the block.
-	 *
-	 * In case too many bytes will be generated, calling this function
-	 * again will resume the uncompression operation. */
-	ret = do_uncompress_block(a, p);
-	if(ret != ARCHIVE_OK) {
-		return ret;
-	}
-
-	if(rar->cstate.block_parsing_finished &&
-	    rar->cstate.switch_multivolume == 0 &&
-	    rar->cstate.cur_block_size > 0)
-	{
-		/* If we're processing a normal block, consume the whole
-		 * block. We can do this because we've already read the whole
-		 * block to memory. */
-		if(ARCHIVE_OK != consume(a, rar->cstate.cur_block_size))
-			return ARCHIVE_FATAL;
-
-		rar->file.bytes_remaining -= rar->cstate.cur_block_size;
-	} else if(rar->cstate.switch_multivolume) {
-		/* Don't consume the block if we're doing multivolume
-		 * processing. The volume switching function will consume
-		 * the proper count of bytes instead. */
-		rar->cstate.switch_multivolume = 0;
-	}
-
-	return ARCHIVE_OK;
-}
-
-/* Pops the `buf`, `size` and `offset` from the "data ready" stack.
- *
- * Returns ARCHIVE_OK when those arguments can be used, ARCHIVE_RETRY
- * when there is no data on the stack. */
-static int use_data(struct rar5* rar, const void** buf, size_t* size,
-    int64_t* offset)
-{
-	int i;
-
-	for(i = 0; i < rar5_countof(rar->cstate.dready); i++) {
-		struct data_ready *d = &rar->cstate.dready[i];
-
-		if(d->used) {
-			if(buf)    *buf = d->buf;
-			if(size)   *size = d->size;
-			if(offset) *offset = d->offset;
-
-			d->used = 0;
-			return ARCHIVE_OK;
-		}
-	}
-
-	return ARCHIVE_RETRY;
-}
-
-/* Pushes the `buf`, `size` and `offset` arguments to the rar->cstate.dready
- * FIFO stack. Those values will be popped from this stack by the `use_data`
- * function. */
-static int push_data_ready(struct archive_read* a, struct rar5* rar,
-    const uint8_t* buf, size_t size, int64_t offset)
-{
-	int i;
-
-	/* Don't push if we're in skip mode. This is needed because solid
-	 * streams need full processing even if we're skipping data. After
-	 * fully processing the stream, we need to discard the generated bytes,
-	 * because we're interested only in the side effect: building up the
-	 * internal window circular buffer. This window buffer will be used
-	 * later during unpacking of requested data. */
-	if(rar->skip_mode)
-		return ARCHIVE_OK;
-
-	/* Sanity check. */
-	if(offset != rar->file.last_offset + rar->file.last_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Sanity check error: output stream is not continuous");
-		return ARCHIVE_FATAL;
-	}
-
-	for(i = 0; i < rar5_countof(rar->cstate.dready); i++) {
-		struct data_ready* d = &rar->cstate.dready[i];
-		if(!d->used) {
-			d->used = 1;
-			d->buf = buf;
-			d->size = size;
-			d->offset = offset;
-
-			/* These fields are used only in sanity checking. */
-			rar->file.last_offset = offset;
-			rar->file.last_size = size;
-
-			/* Calculate the checksum of this new block before
-			 * submitting data to libarchive's engine. */
-			update_crc(rar, d->buf, d->size);
-
-			return ARCHIVE_OK;
-		}
-	}
-
-	/* Program counter will reach this code if the `rar->cstate.data_ready`
-	 * stack will be filled up so that no new entries will be allowed. The
-	 * code shouldn't allow such situation to occur. So we treat this case
-	 * as an internal error. */
-
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-	    "Error: premature end of data_ready stack");
-	return ARCHIVE_FATAL;
-}
-
-/* This function uncompresses the data that is stored in the <FILE> base
- * block.
- *
- * The FILE base block looks like this:
- *
- * <header><huffman tables><block_1><block_2>...<block_n>
- *
- * The <header> is a block header, that is parsed in parse_block_header().
- * It's a "compressed_block_header" structure, containing metadata needed
- * to know when we should stop looking for more <block_n> blocks.
- *
- * <huffman tables> contain data needed to set up the huffman tables, needed
- * for the actual decompression.
- *
- * Each <block_n> consists of series of literals:
- *
- * <literal><literal><literal>...<literal>
- *
- * Those literals generate the uncompression data. They operate on a circular
- * buffer, sometimes writing raw data into it, sometimes referencing
- * some previous data inside this buffer, and sometimes declaring a filter
- * that will need to be executed on the data stored in the circular buffer.
- * It all depends on the literal that is used.
- *
- * Sometimes blocks produce output data, sometimes they don't. For example, for
- * some huge files that use lots of filters, sometimes a block is filled with
- * only filter declaration literals. Such blocks won't produce any data in the
- * circular buffer.
- *
- * Sometimes blocks will produce 4 bytes of data, and sometimes 1 megabyte,
- * because a literal can reference previously decompressed data. For example,
- * there can be a literal that says: 'append a byte 0xFE here', and after
- * it another literal can say 'append 1 megabyte of data from circular buffer
- * offset 0x12345'. This is how RAR format handles compressing repeated
- * patterns.
- *
- * The RAR compressor creates those literals and the actual efficiency of
- * compression depends on what those literals are. The literals can also
- * be seen as a kind of a non-turing-complete virtual machine that simply
- * tells the decompressor what it should do.
- * */
-
-static int do_uncompress_file(struct archive_read* a) {
-	struct rar5* rar = get_context(a);
-	int ret;
-	int64_t max_end_pos;
-
-	if(!rar->cstate.initialized) {
-		/* Don't perform full context reinitialization if we're
-		 * processing a solid archive. */
-		if(!rar->main.solid || !rar->cstate.window_buf) {
-			init_unpack(rar);
-		}
-
-		rar->cstate.initialized = 1;
-	}
-
-	/* Don't allow extraction if window_size is invalid. */
-	if(rar->cstate.window_size == 0) {
-		archive_set_error(&a->archive,
-			ARCHIVE_ERRNO_FILE_FORMAT,
-			"Invalid window size declaration in this file");
-
-		/* This should never happen in valid files. */
-		return ARCHIVE_FATAL;
-	}
-
-	if(rar->cstate.all_filters_applied == 1) {
-		/* We use while(1) here, but standard case allows for just 1
-		 * iteration. The loop will iterate if process_block() didn't
-		 * generate any data at all. This can happen if the block
-		 * contains only filter definitions (this is common in big
-		 * files). */
-		while(1) {
-			ret = process_block(a);
-			if(ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL)
-				return ret;
-
-			if(rar->cstate.last_write_ptr ==
-			    rar->cstate.write_ptr) {
-				/* The block didn't generate any new data,
-				 * so just process a new block. */
-				continue;
-			}
-
-			/* The block has generated some new data, so break
-			 * the loop. */
-			break;
-		}
-	}
-
-	/* Try to run filters. If filters won't be applied, it means that
-	 * insufficient data was generated. */
-	ret = apply_filters(a);
-	if(ret == ARCHIVE_RETRY) {
-		return ARCHIVE_OK;
-	} else if(ret == ARCHIVE_FATAL) {
-		return ARCHIVE_FATAL;
-	}
-
-	/* If apply_filters() will return ARCHIVE_OK, we can continue here. */
-
-	if(cdeque_size(&rar->cstate.filters) > 0) {
-		/* Check if we can write something before hitting first
-		 * filter. */
-		struct filter_info* flt;
-
-		/* Get the block_start offset from the first filter. */
-		if(CDE_OK != cdeque_front(&rar->cstate.filters,
-		    cdeque_filter_p(&flt)))
-		{
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_PROGRAMMER,
-			    "Can't read first filter");
-			return ARCHIVE_FATAL;
-		}
-
-		max_end_pos = rar5_min(flt->block_start,
-		    rar->cstate.write_ptr);
-	} else {
-		/* There are no filters defined, or all filters were applied.
-		 * This means we can just store the data without any
-		 * postprocessing. */
-		max_end_pos = rar->cstate.write_ptr;
-	}
-
-	if(max_end_pos == rar->cstate.last_write_ptr) {
-		/* We can't write anything yet. The block uncompression
-		 * function did not generate enough data, and no filter can be
-		 * applied. At the same time we don't have any data that can be
-		 *  stored without filter postprocessing. This means we need to
-		 *  wait for more data to be generated, so we can apply the
-		 * filters.
-		 *
-		 * Signal the caller that we need more data to be able to do
-		 * anything.
-		 */
-		return ARCHIVE_RETRY;
-	} else {
-		/* We can write the data before hitting the first filter.
-		 * So let's do it. The push_window_data() function will
-		 * effectively return the selected data block to the user
-		 * application. */
-		push_window_data(a, rar, rar->cstate.last_write_ptr,
-		    max_end_pos);
-		rar->cstate.last_write_ptr = max_end_pos;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int uncompress_file(struct archive_read* a) {
-	int ret;
-
-	while(1) {
-		/* Sometimes the uncompression function will return a
-		 * 'retry' signal. If this will happen, we have to retry
-		 * the function. */
-		ret = do_uncompress_file(a);
-		if(ret != ARCHIVE_RETRY)
-			return ret;
-	}
-}
-
-
-static int do_unstore_file(struct archive_read* a,
-    struct rar5* rar, const void** buf, size_t* size, int64_t* offset)
-{
-	size_t to_read;
-	const uint8_t* p;
-
-	if(rar->file.bytes_remaining == 0 && rar->main.volume > 0 &&
-	    rar->generic.split_after > 0)
-	{
-		int ret;
-
-		rar->cstate.switch_multivolume = 1;
-		ret = advance_multivolume(a);
-		rar->cstate.switch_multivolume = 0;
-
-		if(ret != ARCHIVE_OK) {
-			/* Failed to advance to next multivolume archive
-			 * file. */
-			return ret;
-		}
-	}
-
-	to_read = rar5_min(rar->file.bytes_remaining, 64 * 1024);
-	if(to_read == 0) {
-		return ARCHIVE_EOF;
-	}
-
-	if(!read_ahead(a, to_read, &p)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "I/O error when unstoring file");
-		return ARCHIVE_FATAL;
-	}
-
-	if(ARCHIVE_OK != consume(a, to_read)) {
-		return ARCHIVE_EOF;
-	}
-
-	if(buf)    *buf = p;
-	if(size)   *size = to_read;
-	if(offset) *offset = rar->cstate.last_unstore_ptr;
-
-	rar->file.bytes_remaining -= to_read;
-	rar->cstate.last_unstore_ptr += to_read;
-
-	update_crc(rar, p, to_read);
-	return ARCHIVE_OK;
-}
-
-static int do_unpack(struct archive_read* a, struct rar5* rar,
-    const void** buf, size_t* size, int64_t* offset)
-{
-	enum COMPRESSION_METHOD {
-		STORE = 0, FASTEST = 1, FAST = 2, NORMAL = 3, GOOD = 4,
-		BEST = 5
-	};
-
-	if(rar->file.service > 0) {
-		return do_unstore_file(a, rar, buf, size, offset);
-	} else {
-		switch(rar->cstate.method) {
-			case STORE:
-				return do_unstore_file(a, rar, buf, size,
-				    offset);
-			case FASTEST:
-				/* fallthrough */
-			case FAST:
-				/* fallthrough */
-			case NORMAL:
-				/* fallthrough */
-			case GOOD:
-				/* fallthrough */
-			case BEST:
-				/* No data is returned here. But because a sparse-file aware
-				 * caller (like archive_read_data_into_fd) may treat zero-size
-				 * as a sparse file block, we need to update the offset
-				 * accordingly. At this point the decoder doesn't have any
-				 * pending uncompressed data blocks, so the current position in
-				 * the output file should be last_write_ptr. */
-				if (offset) *offset = rar->cstate.last_write_ptr;
-				return uncompress_file(a);
-			default:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Compression method not supported: 0x%x",
-				    rar->cstate.method);
-
-				return ARCHIVE_FATAL;
-		}
-	}
-
-#if !defined WIN32
-	/* Not reached. */
-	return ARCHIVE_OK;
-#endif
-}
-
-static int verify_checksums(struct archive_read* a) {
-	int verify_crc;
-	struct rar5* rar = get_context(a);
-
-	/* Check checksums only when actually unpacking the data. There's no
-	 * need to calculate checksum when we're skipping data in solid archives
-	 * (skipping in solid archives is the same thing as unpacking compressed
-	 * data and discarding the result). */
-
-	if(!rar->skip_mode) {
-		/* Always check checksums if we're not in skip mode */
-		verify_crc = 1;
-	} else {
-		/* We can override the logic above with a compile-time option
-		 * NO_CRC_ON_SOLID_SKIP. This option is used during debugging,
-		 * and it will check checksums of unpacked data even when
-		 * we're skipping it. */
-
-#if defined CHECK_CRC_ON_SOLID_SKIP
-		/* Debug case */
-		verify_crc = 1;
-#else
-		/* Normal case */
-		verify_crc = 0;
-#endif
-	}
-
-	if(verify_crc) {
-		/* During unpacking, on each unpacked block we're calling the
-		 * update_crc() function. Since we are here, the unpacking
-		 * process is already over and we can check if calculated
-		 * checksum (CRC32 or BLAKE2sp) is the same as what is stored
-		 * in the archive. */
-		if(rar->file.stored_crc32 > 0) {
-			/* Check CRC32 only when the file contains a CRC32
-			 * value for this file. */
-
-			if(rar->file.calculated_crc32 !=
-			    rar->file.stored_crc32) {
-				/* Checksums do not match; the unpacked file
-				 * is corrupted. */
-
-				DEBUG_CODE {
-					printf("Checksum error: CRC32 "
-					    "(was: %08" PRIx32 ", expected: %08" PRIx32 ")\n",
-					    rar->file.calculated_crc32,
-					    rar->file.stored_crc32);
-				}
-
-#ifndef DONT_FAIL_ON_CRC_ERROR
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Checksum error: CRC32");
-				return ARCHIVE_FATAL;
-#endif
-			} else {
-				DEBUG_CODE {
-					printf("Checksum OK: CRC32 "
-					    "(%08" PRIx32 "/%08" PRIx32 ")\n",
-					    rar->file.stored_crc32,
-					    rar->file.calculated_crc32);
-				}
-			}
-		}
-
-		if(rar->file.has_blake2 > 0) {
-			/* BLAKE2sp is an optional checksum algorithm that is
-			 * added to RARv5 archives when using the `-htb` switch
-			 *  during creation of archive.
-			 *
-			 * We now finalize the hash calculation by calling the
-			 * `final` function. This will generate the final hash
-			 * value we can use to compare it with the BLAKE2sp
-			 * checksum that is stored in the archive.
-			 *
-			 * The return value of this `final` function is not
-			 * very helpful, as it guards only against improper use.
- 			 * This is why we're explicitly ignoring it. */
-
-			uint8_t b2_buf[32];
-			(void) blake2sp_final(&rar->file.b2state, b2_buf, 32);
-
-			if(memcmp(&rar->file.blake2sp, b2_buf, 32) != 0) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Checksum error: BLAKE2");
-
-				return ARCHIVE_FATAL;
-#endif
-			}
-		}
-	}
-
-	/* Finalization for this file has been successfully completed. */
-	return ARCHIVE_OK;
-}
-
-static int verify_global_checksums(struct archive_read* a) {
-	return verify_checksums(a);
-}
-
-/*
- * Decryption function for the magic signature pattern. Check the comment near
- * the `rar5_signature_xor` symbol to read the rationale behind this.
- */
-static void rar5_signature(char *buf) {
-		size_t i;
-
-		for(i = 0; i < sizeof(rar5_signature_xor); i++) {
-			buf[i] = rar5_signature_xor[i] ^ 0xA1;
-		}
-}
-
-static int rar5_read_data(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset) {
-	int ret;
-	struct rar5* rar = get_context(a);
-
-	if (size)
-		*size = 0;
-
-	if(rar->file.dir > 0) {
-		/* Don't process any data if this file entry was declared
-		 * as a directory. This is needed, because entries marked as
-		 * directory doesn't have any dictionary buffer allocated, so
-		 * it's impossible to perform any decompression. */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't decompress an entry marked as a directory");
-		return ARCHIVE_FAILED;
-	}
-
-	if(!rar->skip_mode && (rar->cstate.last_write_ptr > rar->file.unpacked_size)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Unpacker has written too many bytes");
-		return ARCHIVE_FATAL;
-	}
-
-	ret = use_data(rar, buff, size, offset);
-	if(ret == ARCHIVE_OK) {
-		return ret;
-	}
-
-	if(rar->file.eof == 1) {
-		return ARCHIVE_EOF;
-	}
-
-	ret = do_unpack(a, rar, buff, size, offset);
-	if(ret != ARCHIVE_OK) {
-		return ret;
-	}
-
-	if(rar->file.bytes_remaining == 0 &&
-			rar->cstate.last_write_ptr == rar->file.unpacked_size)
-	{
-		/* If all bytes of current file were processed, run
-		 * finalization.
-		 *
-		 * Finalization will check checksum against proper values. If
-		 * some of the checksums will not match, we'll return an error
-		 * value in the last `archive_read_data` call to signal an error
-		 * to the user. */
-
-		rar->file.eof = 1;
-		return verify_global_checksums(a);
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int rar5_read_data_skip(struct archive_read *a) {
-	struct rar5* rar = get_context(a);
-
-	if(rar->main.solid) {
-		/* In solid archives, instead of skipping the data, we need to
-		 * extract it, and dispose the result. The side effect of this
-		 * operation will be setting up the initial window buffer state
-		 * needed to be able to extract the selected file. */
-
-		int ret;
-
-		/* Make sure to process all blocks in the compressed stream. */
-		while(rar->file.bytes_remaining > 0) {
-			/* Setting the "skip mode" will allow us to skip
-			 * checksum checks during data skipping. Checking the
-			 * checksum of skipped data isn't really necessary and
-			 * it's only slowing things down.
-			 *
-			 * This is incremented instead of setting to 1 because
-			 * this data skipping function can be called
-			 * recursively. */
-			rar->skip_mode++;
-
-			/* We're disposing 1 block of data, so we use triple
-			 * NULLs in arguments. */
-			ret = rar5_read_data(a, NULL, NULL, NULL);
-
-			/* Turn off "skip mode". */
-			rar->skip_mode--;
-
-			if(ret < 0 || ret == ARCHIVE_EOF) {
-				/* Propagate any potential error conditions
-				 * to the caller. */
-				return ret;
-			}
-		}
-	} else {
-		/* In standard archives, we can just jump over the compressed
-		 * stream. Each file in non-solid archives starts from an empty
-		 * window buffer. */
-
-		if(ARCHIVE_OK != consume(a, rar->file.bytes_remaining)) {
-			return ARCHIVE_FATAL;
-		}
-
-		rar->file.bytes_remaining = 0;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int64_t rar5_seek_data(struct archive_read *a, int64_t offset,
-    int whence)
-{
-	(void) a;
-	(void) offset;
-	(void) whence;
-
-	/* We're a streaming unpacker, and we don't support seeking. */
-
-	return ARCHIVE_FATAL;
-}
-
-static int rar5_cleanup(struct archive_read *a) {
-	struct rar5* rar = get_context(a);
-
-	free(rar->cstate.window_buf);
-	free(rar->cstate.filtered_buf);
-
-	free(rar->vol.push_buf);
-
-	free_filters(rar);
-	cdeque_free(&rar->cstate.filters);
-
-	free(rar);
-	a->format->data = NULL;
-
-	return ARCHIVE_OK;
-}
-
-static int rar5_capabilities(struct archive_read * a) {
-	(void) a;
-	return 0;
-}
-
-static int rar5_has_encrypted_entries(struct archive_read *_a) {
-	(void) _a;
-
-	/* Unsupported for now. */
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
-}
-
-static int rar5_init(struct rar5* rar) {
-	memset(rar, 0, sizeof(struct rar5));
-
-	if(CDE_OK != cdeque_init(&rar->cstate.filters, 8192))
-		return ARCHIVE_FATAL;
-
-	return ARCHIVE_OK;
-}
-
-int archive_read_support_format_rar5(struct archive *_a) {
-	struct archive_read* ar;
-	int ret;
-	struct rar5* rar;
-
-	if(ARCHIVE_OK != (ret = get_archive_read(_a, &ar)))
-		return ret;
-
-	rar = malloc(sizeof(*rar));
-	if(rar == NULL) {
-		archive_set_error(&ar->archive, ENOMEM,
-		    "Can't allocate rar5 data");
-		return ARCHIVE_FATAL;
-	}
-
-	if(ARCHIVE_OK != rar5_init(rar)) {
-		archive_set_error(&ar->archive, ENOMEM,
-		    "Can't allocate rar5 filter buffer");
-		free(rar);
-		return ARCHIVE_FATAL;
-	}
-
-	ret = __archive_read_register_format(ar,
-	    rar,
-	    "rar5",
-	    rar5_bid,
-	    rar5_options,
-	    rar5_read_header,
-	    rar5_read_data,
-	    rar5_read_data_skip,
-	    rar5_seek_data,
-	    rar5_cleanup,
-	    rar5_capabilities,
-	    rar5_has_encrypted_entries);
-
-	if(ret != ARCHIVE_OK) {
-		(void) rar5_cleanup(ar);
-	}
-
-	return ret;
-}
diff --git a/c/archive_read_support_format_raw.c b/c/archive_read_support_format_raw.c
deleted file mode 100644
--- a/c/archive_read_support_format_raw.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_raw.c 201107 2009-12-28 03:25:33Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-struct raw_info {
-	int64_t offset; /* Current position in the file. */
-	int64_t unconsumed;
-	int     end_of_file;
-};
-
-static int	archive_read_format_raw_bid(struct archive_read *, int);
-static int	archive_read_format_raw_cleanup(struct archive_read *);
-static int	archive_read_format_raw_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	archive_read_format_raw_read_data_skip(struct archive_read *);
-static int	archive_read_format_raw_read_header(struct archive_read *,
-		    struct archive_entry *);
-
-int
-archive_read_support_format_raw(struct archive *_a)
-{
-	struct raw_info *info;
-	struct archive_read *a = (struct archive_read *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_raw");
-
-	info = (struct raw_info *)calloc(1, sizeof(*info));
-	if (info == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate raw_info data");
-		return (ARCHIVE_FATAL);
-	}
-
-	r = __archive_read_register_format(a,
-	    info,
-	    "raw",
-	    archive_read_format_raw_bid,
-	    NULL,
-	    archive_read_format_raw_read_header,
-	    archive_read_format_raw_read_data,
-	    archive_read_format_raw_read_data_skip,
-	    NULL,
-	    archive_read_format_raw_cleanup,
-	    NULL,
-	    NULL);
-	if (r != ARCHIVE_OK)
-		free(info);
-	return (r);
-}
-
-/*
- * Bid 1 if this is a non-empty file.  Anyone who can really support
- * this should outbid us, so it should generally be safe to use "raw"
- * in conjunction with other formats.  But, this could really confuse
- * folks if there are bid errors or minor file damage, so we don't
- * include "raw" as part of support_format_all().
- */
-static int
-archive_read_format_raw_bid(struct archive_read *a, int best_bid)
-{
-	if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) != NULL)
-		return (1);
-	return (-1);
-}
-
-/*
- * Mock up a fake header.
- */
-static int
-archive_read_format_raw_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct raw_info *info;
-
-	info = (struct raw_info *)(a->format->data);
-	if (info->end_of_file)
-		return (ARCHIVE_EOF);
-
-	a->archive.archive_format = ARCHIVE_FORMAT_RAW;
-	a->archive.archive_format_name = "raw";
-	archive_entry_set_pathname(entry, "data");
-	archive_entry_set_filetype(entry, AE_IFREG);
-	archive_entry_set_perm(entry, 0644);
-	/* I'm deliberately leaving most fields unset here. */
-
-	/* Let the filter fill out any fields it might have. */
-	return __archive_read_header(a, entry);
-}
-
-static int
-archive_read_format_raw_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct raw_info *info;
-	ssize_t avail;
-
-	info = (struct raw_info *)(a->format->data);
-
-	/* Consume the bytes we read last time. */
-	if (info->unconsumed) {
-		__archive_read_consume(a, info->unconsumed);
-		info->unconsumed = 0;
-	}
-
-	if (info->end_of_file)
-		return (ARCHIVE_EOF);
-
-	/* Get whatever bytes are immediately available. */
-	*buff = __archive_read_ahead(a, 1, &avail);
-	if (avail > 0) {
-		/* Return the bytes we just read */
-		*size = avail;
-		*offset = info->offset;
-		info->offset += *size;
-		info->unconsumed = avail;
-		return (ARCHIVE_OK);
-	} else if (0 == avail) {
-		/* Record and return end-of-file. */
-		info->end_of_file = 1;
-		*size = 0;
-		*offset = info->offset;
-		return (ARCHIVE_EOF);
-	} else {
-		/* Record and return an error. */
-		*size = 0;
-		*offset = info->offset;
-		return ((int)avail);
-	}
-}
-
-static int
-archive_read_format_raw_read_data_skip(struct archive_read *a)
-{
-	struct raw_info *info = (struct raw_info *)(a->format->data);
-
-	/* Consume the bytes we read last time. */
-	if (info->unconsumed) {
-		__archive_read_consume(a, info->unconsumed);
-		info->unconsumed = 0;
-	}
-	info->end_of_file = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_raw_cleanup(struct archive_read *a)
-{
-	struct raw_info *info;
-
-	info = (struct raw_info *)(a->format->data);
-	free(info);
-	a->format->data = NULL;
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_read_support_format_tar.c b/c/archive_read_support_format_tar.c
deleted file mode 100644
--- a/c/archive_read_support_format_tar.c
+++ /dev/null
@@ -1,2946 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_tar.c 201161 2009-12-29 05:44:39Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stddef.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_acl_private.h" /* For ACL parsing routines. */
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#define tar_min(a,b) ((a) < (b) ? (a) : (b))
-
-/*
- * Layout of POSIX 'ustar' tar header.
- */
-struct archive_entry_header_ustar {
-	char	name[100];
-	char	mode[8];
-	char	uid[8];
-	char	gid[8];
-	char	size[12];
-	char	mtime[12];
-	char	checksum[8];
-	char	typeflag[1];
-	char	linkname[100];	/* "old format" header ends here */
-	char	magic[6];	/* For POSIX: "ustar\0" */
-	char	version[2];	/* For POSIX: "00" */
-	char	uname[32];
-	char	gname[32];
-	char	rdevmajor[8];
-	char	rdevminor[8];
-	char	prefix[155];
-};
-
-/*
- * Structure of GNU tar header
- */
-struct gnu_sparse {
-	char	offset[12];
-	char	numbytes[12];
-};
-
-struct archive_entry_header_gnutar {
-	char	name[100];
-	char	mode[8];
-	char	uid[8];
-	char	gid[8];
-	char	size[12];
-	char	mtime[12];
-	char	checksum[8];
-	char	typeflag[1];
-	char	linkname[100];
-	char	magic[8];  /* "ustar  \0" (note blank/blank/null at end) */
-	char	uname[32];
-	char	gname[32];
-	char	rdevmajor[8];
-	char	rdevminor[8];
-	char	atime[12];
-	char	ctime[12];
-	char	offset[12];
-	char	longnames[4];
-	char	unused[1];
-	struct gnu_sparse sparse[4];
-	char	isextended[1];
-	char	realsize[12];
-	/*
-	 * Old GNU format doesn't use POSIX 'prefix' field; they use
-	 * the 'L' (longname) entry instead.
-	 */
-};
-
-/*
- * Data specific to this format.
- */
-struct sparse_block {
-	struct sparse_block	*next;
-	int64_t	offset;
-	int64_t	remaining;
-	int hole;
-};
-
-struct tar {
-	struct archive_string	 acl_text;
-	struct archive_string	 entry_pathname;
-	/* For "GNU.sparse.name" and other similar path extensions. */
-	struct archive_string	 entry_pathname_override;
-	struct archive_string	 entry_linkpath;
-	struct archive_string	 entry_uname;
-	struct archive_string	 entry_gname;
-	struct archive_string	 longlink;
-	struct archive_string	 longname;
-	struct archive_string	 pax_header;
-	struct archive_string	 pax_global;
-	struct archive_string	 line;
-	int			 pax_hdrcharset_binary;
-	int			 header_recursion_depth;
-	int64_t			 entry_bytes_remaining;
-	int64_t			 entry_offset;
-	int64_t			 entry_padding;
-	int64_t 		 entry_bytes_unconsumed;
-	int64_t			 realsize;
-	int			 sparse_allowed;
-	struct sparse_block	*sparse_list;
-	struct sparse_block	*sparse_last;
-	int64_t			 sparse_offset;
-	int64_t			 sparse_numbytes;
-	int			 sparse_gnu_major;
-	int			 sparse_gnu_minor;
-	char			 sparse_gnu_pending;
-
-	struct archive_string	 localname;
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv;
-	struct archive_string_conv *sconv_acl;
-	struct archive_string_conv *sconv_default;
-	int			 init_default_conversion;
-	int			 compat_2x;
-	int			 process_mac_extensions;
-	int			 read_concatenated_archives;
-	int			 realsize_override;
-};
-
-static int	archive_block_is_null(const char *p);
-static char	*base64_decode(const char *, size_t, size_t *);
-static int	gnu_add_sparse_entry(struct archive_read *, struct tar *,
-		    int64_t offset, int64_t remaining);
-
-static void	gnu_clear_sparse_list(struct tar *);
-static int	gnu_sparse_old_read(struct archive_read *, struct tar *,
-		    const struct archive_entry_header_gnutar *header, size_t *);
-static int	gnu_sparse_old_parse(struct archive_read *, struct tar *,
-		    const struct gnu_sparse *sparse, int length);
-static int	gnu_sparse_01_parse(struct archive_read *, struct tar *,
-		    const char *);
-static ssize_t	gnu_sparse_10_read(struct archive_read *, struct tar *,
-			size_t *);
-static int	header_Solaris_ACL(struct archive_read *,  struct tar *,
-		    struct archive_entry *, const void *, size_t *);
-static int	header_common(struct archive_read *,  struct tar *,
-		    struct archive_entry *, const void *);
-static int	header_old_tar(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *);
-static int	header_pax_extensions(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *, size_t *);
-static int	header_pax_global(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	header_longlink(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	header_longname(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	read_mac_metadata_blob(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	header_volume(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	header_ustar(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h);
-static int	header_gnutar(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
-static int	archive_read_format_tar_bid(struct archive_read *, int);
-static int	archive_read_format_tar_options(struct archive_read *,
-		    const char *, const char *);
-static int	archive_read_format_tar_cleanup(struct archive_read *);
-static int	archive_read_format_tar_read_data(struct archive_read *a,
-		    const void **buff, size_t *size, int64_t *offset);
-static int	archive_read_format_tar_skip(struct archive_read *a);
-static int	archive_read_format_tar_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	checksum(struct archive_read *, const void *);
-static int 	pax_attribute(struct archive_read *, struct tar *,
-		    struct archive_entry *, const char *key, const char *value,
-		    size_t value_length);
-static int	pax_attribute_acl(struct archive_read *, struct tar *,
-		    struct archive_entry *, const char *, int);
-static int	pax_attribute_xattr(struct archive_entry *, const char *,
-		    const char *);
-static int 	pax_header(struct archive_read *, struct tar *,
-		    struct archive_entry *, struct archive_string *);
-static void	pax_time(const char *, int64_t *sec, long *nanos);
-static ssize_t	readline(struct archive_read *, struct tar *, const char **,
-		    ssize_t limit, size_t *);
-static int	read_body_to_string(struct archive_read *, struct tar *,
-		    struct archive_string *, const void *h, size_t *);
-static int	solaris_sparse_parse(struct archive_read *, struct tar *,
-		    struct archive_entry *, const char *);
-static int64_t	tar_atol(const char *, size_t);
-static int64_t	tar_atol10(const char *, size_t);
-static int64_t	tar_atol256(const char *, size_t);
-static int64_t	tar_atol8(const char *, size_t);
-static int	tar_read_header(struct archive_read *, struct tar *,
-		    struct archive_entry *, size_t *);
-static int	tohex(int c);
-static char	*url_decode(const char *);
-static void	tar_flush_unconsumed(struct archive_read *, size_t *);
-
-
-int
-archive_read_support_format_gnutar(struct archive *a)
-{
-	archive_check_magic(a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_gnutar");
-	return (archive_read_support_format_tar(a));
-}
-
-
-int
-archive_read_support_format_tar(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct tar *tar;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
-
-	tar = (struct tar *)calloc(1, sizeof(*tar));
-	if (tar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate tar data");
-		return (ARCHIVE_FATAL);
-	}
-#ifdef HAVE_COPYFILE_H
-	/* Set this by default on Mac OS. */
-	tar->process_mac_extensions = 1;
-#endif
-
-	r = __archive_read_register_format(a, tar, "tar",
-	    archive_read_format_tar_bid,
-	    archive_read_format_tar_options,
-	    archive_read_format_tar_read_header,
-	    archive_read_format_tar_read_data,
-	    archive_read_format_tar_skip,
-	    NULL,
-	    archive_read_format_tar_cleanup,
-	    NULL,
-	    NULL);
-
-	if (r != ARCHIVE_OK)
-		free(tar);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_tar_cleanup(struct archive_read *a)
-{
-	struct tar *tar;
-
-	tar = (struct tar *)(a->format->data);
-	gnu_clear_sparse_list(tar);
-	archive_string_free(&tar->acl_text);
-	archive_string_free(&tar->entry_pathname);
-	archive_string_free(&tar->entry_pathname_override);
-	archive_string_free(&tar->entry_linkpath);
-	archive_string_free(&tar->entry_uname);
-	archive_string_free(&tar->entry_gname);
-	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);
-	archive_string_free(&tar->localname);
-	free(tar);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Validate number field
- *
- * This has to be pretty lenient in order to accommodate the enormous
- * variety of tar writers in the world:
- *  = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
- *    zeros and allows fields to be terminated with space or null characters
- *  = Many writers use different termination (in particular, libarchive
- *    omits terminator bytes to squeeze one or two more digits)
- *  = Many writers pad with space and omit leading zeros
- *  = GNU tar and star write base-256 values if numbers are too
- *    big to be represented in octal
- *
- *  Examples of specific tar headers that we should support:
- *  = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
- *    null bytes, pads size with spaces and other numeric fields with zeroes
- *  = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
- *    may have uid and gid fields filled with spaces without any octal digits
- *    at all and pads all numeric fields with spaces
- *
- * This should tolerate all variants in use.  It will reject a field
- * where the writer just left garbage after a trailing NUL.
- */
-static int
-validate_number_field(const char* p_field, size_t i_size)
-{
-	unsigned char marker = (unsigned char)p_field[0];
-	if (marker == 128 || marker == 255 || marker == 0) {
-		/* Base-256 marker, there's nothing we can check. */
-		return 1;
-	} else {
-		/* Must be octal */
-		size_t i = 0;
-		/* Skip any leading spaces */
-		while (i < i_size && p_field[i] == ' ') {
-			++i;
-		}
-		/* Skip octal digits. */
-		while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
-			++i;
-		}
-		/* Any remaining characters must be space or NUL padding. */
-		while (i < i_size) {
-			if (p_field[i] != ' ' && p_field[i] != 0) {
-				return 0;
-			}
-			++i;
-		}
-		return 1;
-	}
-}
-
-static int
-archive_read_format_tar_bid(struct archive_read *a, int best_bid)
-{
-	int bid;
-	const char *h;
-	const struct archive_entry_header_ustar *header;
-
-	(void)best_bid; /* UNUSED */
-
-	bid = 0;
-
-	/* Now let's look at the actual header and see if it matches. */
-	h = __archive_read_ahead(a, 512, NULL);
-	if (h == NULL)
-		return (-1);
-
-	/* If it's an end-of-archive mark, we can handle it. */
-	if (h[0] == 0 && archive_block_is_null(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.*/
-	if (!checksum(a, h))
-		return (0);
-	bid += 48;  /* Checksum is usually 6 octal digits. */
-
-	header = (const struct archive_entry_header_ustar *)h;
-
-	/* Recognize POSIX formats. */
-	if ((memcmp(header->magic, "ustar\0", 6) == 0)
-	    && (memcmp(header->version, "00", 2) == 0))
-		bid += 56;
-
-	/* Recognize GNU tar format. */
-	if ((memcmp(header->magic, "ustar ", 6) == 0)
-	    && (memcmp(header->version, " \0", 2) == 0))
-		bid += 56;
-
-	/* Type flag must be null, digit or A-Z, a-z. */
-	if (header->typeflag[0] != 0 &&
-	    !( header->typeflag[0] >= '0' && header->typeflag[0] <= '9') &&
-	    !( header->typeflag[0] >= 'A' && header->typeflag[0] <= 'Z') &&
-	    !( header->typeflag[0] >= 'a' && header->typeflag[0] <= 'z') )
-		return (0);
-	bid += 2;  /* 6 bits of variation in an 8-bit field leaves 2 bits. */
-
-	/*
-	 * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
-	 */
-	if (validate_number_field(header->mode, sizeof(header->mode)) == 0
-	    || validate_number_field(header->uid, sizeof(header->uid)) == 0
-	    || validate_number_field(header->gid, sizeof(header->gid)) == 0
-	    || validate_number_field(header->mtime, sizeof(header->mtime)) == 0
-	    || validate_number_field(header->size, sizeof(header->size)) == 0
-	    || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
-	    || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0) {
-		bid = 0;
-	}
-
-	return (bid);
-}
-
-static int
-archive_read_format_tar_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct tar *tar;
-	int ret = ARCHIVE_FAILED;
-
-	tar = (struct tar *)(a->format->data);
-	if (strcmp(key, "compat-2x")  == 0) {
-		/* Handle UTF-8 filenames as libarchive 2.x */
-		tar->compat_2x = (val != NULL && val[0] != 0);
-		tar->init_default_conversion = tar->compat_2x;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "tar: hdrcharset option needs a character-set name");
-		else {
-			tar->opt_sconv =
-			    archive_string_conversion_from_charset(
-				&a->archive, val, 0);
-			if (tar->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	} else if (strcmp(key, "mac-ext") == 0) {
-		tar->process_mac_extensions = (val != NULL && val[0] != 0);
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "read_concatenated_archives") == 0) {
-		tar->read_concatenated_archives = (val != NULL && val[0] != 0);
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/* utility function- this exists to centralize the logic of tracking
- * how much unconsumed data we have floating around, and to consume
- * anything outstanding since we're going to do read_aheads
- */
-static void
-tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
-{
-	if (*unconsumed) {
-/*
-		void *data = (void *)__archive_read_ahead(a, *unconsumed, NULL);
-		 * this block of code is to poison claimed unconsumed space, ensuring
-		 * things break if it is in use still.
-		 * currently it WILL break things, so enable it only for debugging this issue
-		if (data) {
-			memset(data, 0xff, *unconsumed);
-		}
-*/
-		__archive_read_consume(a, *unconsumed);
-		*unconsumed = 0;
-	}
-}
-
-/*
- * The function invoked by archive_read_next_header().  This
- * just sets up a few things and then calls the internal
- * tar_read_header() function below.
- */
-static int
-archive_read_format_tar_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	/*
-	 * When converting tar archives to cpio archives, it is
-	 * essential that each distinct file have a distinct inode
-	 * number.  To simplify this, we keep a static count here to
-	 * assign fake dev/inode numbers to each tar entry.  Note that
-	 * pax format archives may overwrite this with something more
-	 * useful.
-	 *
-	 * Ideally, we would track every file read from the archive so
-	 * that we could assign the same dev/ino pair to hardlinks,
-	 * but the memory required to store a complete lookup table is
-	 * probably not worthwhile just to support the relatively
-	 * obscure tar->cpio conversion case.
-	 */
-	static int default_inode;
-	static int default_dev;
-	struct tar *tar;
-	const char *p;
-	const wchar_t *wp;
-	int r;
-	size_t l, unconsumed = 0;
-
-	/* Assign default device/inode values. */
-	archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */
-	archive_entry_set_ino(entry, ++default_inode); /* Don't use zero. */
-	/* Limit generated st_ino number to 16 bits. */
-	if (default_inode >= 0xffff) {
-		++default_dev;
-		default_inode = 0;
-	}
-
-	tar = (struct tar *)(a->format->data);
-	tar->entry_offset = 0;
-	gnu_clear_sparse_list(tar);
-	tar->realsize = -1; /* Mark this as "unset" */
-	tar->realsize_override = 0;
-
-	/* Setup default string conversion. */
-	tar->sconv = tar->opt_sconv;
-	if (tar->sconv == NULL) {
-		if (!tar->init_default_conversion) {
-			tar->sconv_default =
-			    archive_string_default_conversion_for_read(&(a->archive));
-			tar->init_default_conversion = 1;
-		}
-		tar->sconv = tar->sconv_default;
-	}
-
-	r = tar_read_header(a, tar, entry, &unconsumed);
-
-	tar_flush_unconsumed(a, &unconsumed);
-
-	/*
-	 * "non-sparse" files are really just sparse files with
-	 * a single block.
-	 */
-	if (tar->sparse_list == NULL) {
-		if (gnu_add_sparse_entry(a, tar, 0, tar->entry_bytes_remaining)
-		    != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	} else {
-		struct sparse_block *sb;
-
-		for (sb = tar->sparse_list; sb != NULL; sb = sb->next) {
-			if (!sb->hole)
-				archive_entry_sparse_add_entry(entry,
-				    sb->offset, sb->remaining);
-		}
-	}
-
-	if (r == ARCHIVE_OK && archive_entry_filetype(entry) == AE_IFREG) {
-		/*
-		 * "Regular" entry with trailing '/' is really
-		 * directory: This is needed for certain old tar
-		 * variants and even for some broken newer ones.
-		 */
-		if ((wp = archive_entry_pathname_w(entry)) != NULL) {
-			l = wcslen(wp);
-			if (l > 0 && wp[l - 1] == L'/') {
-				archive_entry_set_filetype(entry, AE_IFDIR);
-				tar->entry_bytes_remaining = 0;
-				tar->entry_padding = 0;
-			}
-		} else if ((p = archive_entry_pathname(entry)) != NULL) {
-			l = strlen(p);
-			if (l > 0 && p[l - 1] == '/') {
-				archive_entry_set_filetype(entry, AE_IFDIR);
-				tar->entry_bytes_remaining = 0;
-				tar->entry_padding = 0;
-			}
-		}
-	}
-	return (r);
-}
-
-static int
-archive_read_format_tar_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	ssize_t bytes_read;
-	struct tar *tar;
-	struct sparse_block *p;
-
-	tar = (struct tar *)(a->format->data);
-
-	for (;;) {
-		/* Remove exhausted entries from sparse list. */
-		while (tar->sparse_list != NULL &&
-		    tar->sparse_list->remaining == 0) {
-			p = tar->sparse_list;
-			tar->sparse_list = p->next;
-			free(p);
-		}
-
-		if (tar->entry_bytes_unconsumed) {
-			__archive_read_consume(a, tar->entry_bytes_unconsumed);
-			tar->entry_bytes_unconsumed = 0;
-		}
-
-		/* If we're at end of file, return EOF. */
-		if (tar->sparse_list == NULL ||
-		    tar->entry_bytes_remaining == 0) {
-			if (__archive_read_consume(a, tar->entry_padding) < 0)
-				return (ARCHIVE_FATAL);
-			tar->entry_padding = 0;
-			*buff = NULL;
-			*size = 0;
-			*offset = tar->realsize;
-			return (ARCHIVE_EOF);
-		}
-
-		*buff = __archive_read_ahead(a, 1, &bytes_read);
-		if (bytes_read < 0)
-			return (ARCHIVE_FATAL);
-		if (*buff == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Truncated tar archive");
-			return (ARCHIVE_FATAL);
-		}
-		if (bytes_read > tar->entry_bytes_remaining)
-			bytes_read = (ssize_t)tar->entry_bytes_remaining;
-		/* Don't read more than is available in the
-		 * current sparse block. */
-		if (tar->sparse_list->remaining < bytes_read)
-			bytes_read = (ssize_t)tar->sparse_list->remaining;
-		*size = bytes_read;
-		*offset = tar->sparse_list->offset;
-		tar->sparse_list->remaining -= bytes_read;
-		tar->sparse_list->offset += bytes_read;
-		tar->entry_bytes_remaining -= bytes_read;
-		tar->entry_bytes_unconsumed = bytes_read;
-
-		if (!tar->sparse_list->hole)
-			return (ARCHIVE_OK);
-		/* Current is hole data and skip this. */
-	}
-}
-
-static int
-archive_read_format_tar_skip(struct archive_read *a)
-{
-	int64_t bytes_skipped;
-	int64_t request;
-	struct sparse_block *p;
-	struct tar* tar;
-
-	tar = (struct tar *)(a->format->data);
-
-	/* Do not consume the hole of a sparse file. */
-	request = 0;
-	for (p = tar->sparse_list; p != NULL; p = p->next) {
-		if (!p->hole) {
-			if (p->remaining >= INT64_MAX - request) {
-				return ARCHIVE_FATAL;
-			}
-			request += p->remaining;
-		}
-	}
-	if (request > tar->entry_bytes_remaining)
-		request = tar->entry_bytes_remaining;
-	request += tar->entry_padding + tar->entry_bytes_unconsumed;
-
-	bytes_skipped = __archive_read_consume(a, request);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-
-	tar->entry_bytes_remaining = 0;
-	tar->entry_bytes_unconsumed = 0;
-	tar->entry_padding = 0;
-
-	/* Free the sparse list. */
-	gnu_clear_sparse_list(tar);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * This function recursively interprets all of the headers associated
- * with a single entry.
- */
-static int
-tar_read_header(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, size_t *unconsumed)
-{
-	ssize_t bytes;
-	int err, eof_vol_header;
-	const char *h;
-	const struct archive_entry_header_ustar *header;
-	const struct archive_entry_header_gnutar *gnuheader;
-
-	eof_vol_header = 0;
-
-	/* Loop until we find a workable header record. */
-	for (;;) {
-		tar_flush_unconsumed(a, unconsumed);
-
-		/* Read 512-byte header record */
-		h = __archive_read_ahead(a, 512, &bytes);
-		if (bytes < 0)
-			return ((int)bytes);
-		if (bytes == 0) { /* EOF at a block boundary. */
-			/* Some writers do omit the block of nulls. <sigh> */
-			return (ARCHIVE_EOF);
-		}
-		if (bytes < 512) {  /* Short block at EOF; this is bad. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated tar archive");
-			return (ARCHIVE_FATAL);
-		}
-		*unconsumed = 512;
-
-		/* Header is workable if it's not an end-of-archive mark. */
-		if (h[0] != 0 || !archive_block_is_null(h))
-			break;
-
-		/* Ensure format is set for archives with only null blocks. */
-		if (a->archive.archive_format_name == NULL) {
-			a->archive.archive_format = ARCHIVE_FORMAT_TAR;
-			a->archive.archive_format_name = "tar";
-		}
-
-		if (!tar->read_concatenated_archives) {
-			/* Try to consume a second all-null record, as well. */
-			tar_flush_unconsumed(a, unconsumed);
-			h = __archive_read_ahead(a, 512, NULL);
-			if (h != NULL && h[0] == 0 && archive_block_is_null(h))
-				__archive_read_consume(a, 512);
-			archive_clear_error(&a->archive);
-			return (ARCHIVE_EOF);
-		}
-
-		/*
-		 * We're reading concatenated archives, ignore this block and
-		 * loop to get the next.
-		 */
-	}
-
-	/*
-	 * Note: If the checksum fails and we return ARCHIVE_RETRY,
-	 * then the client is likely to just retry.  This is a very
-	 * crude way to search for the next valid header!
-	 *
-	 * TODO: Improve this by implementing a real header scan.
-	 */
-	if (!checksum(a, h)) {
-		tar_flush_unconsumed(a, unconsumed);
-		archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
-		return (ARCHIVE_RETRY); /* Retryable: Invalid header */
-	}
-
-	if (++tar->header_recursion_depth > 32) {
-		tar_flush_unconsumed(a, unconsumed);
-		archive_set_error(&a->archive, EINVAL, "Too many special headers");
-		return (ARCHIVE_WARN);
-	}
-
-	/* Determine the format variant. */
-	header = (const struct archive_entry_header_ustar *)h;
-
-	switch(header->typeflag[0]) {
-	case 'A': /* Solaris tar ACL */
-		a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
-		a->archive.archive_format_name = "Solaris tar";
-		err = header_Solaris_ACL(a, tar, entry, h, unconsumed);
-		break;
-	case 'g': /* POSIX-standard 'g' header. */
-		a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
-		a->archive.archive_format_name = "POSIX pax interchange format";
-		err = header_pax_global(a, tar, entry, h, unconsumed);
-		if (err == ARCHIVE_EOF)
-			return (err);
-		break;
-	case 'K': /* Long link name (GNU tar, others) */
-		err = header_longlink(a, tar, entry, h, unconsumed);
-		break;
-	case 'L': /* Long filename (GNU tar, others) */
-		err = header_longname(a, tar, entry, h, unconsumed);
-		break;
-	case 'V': /* GNU volume header */
-		err = header_volume(a, tar, entry, h, unconsumed);
-		if (err == ARCHIVE_EOF)
-			eof_vol_header = 1;
-		break;
-	case 'X': /* Used by SUN tar; same as 'x'. */
-		a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
-		a->archive.archive_format_name =
-		    "POSIX pax interchange format (Sun variant)";
-		err = header_pax_extensions(a, tar, entry, h, unconsumed);
-		break;
-	case 'x': /* POSIX-standard 'x' header. */
-		a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
-		a->archive.archive_format_name = "POSIX pax interchange format";
-		err = header_pax_extensions(a, tar, entry, h, unconsumed);
-		break;
-	default:
-		gnuheader = (const struct archive_entry_header_gnutar *)h;
-		if (memcmp(gnuheader->magic, "ustar  \0", 8) == 0) {
-			a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
-			a->archive.archive_format_name = "GNU tar format";
-			err = header_gnutar(a, tar, entry, h, unconsumed);
-		} else if (memcmp(header->magic, "ustar", 5) == 0) {
-			if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) {
-				a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
-				a->archive.archive_format_name = "POSIX ustar format";
-			}
-			err = header_ustar(a, tar, entry, h);
-		} else {
-			a->archive.archive_format = ARCHIVE_FORMAT_TAR;
-			a->archive.archive_format_name = "tar (non-POSIX)";
-			err = header_old_tar(a, tar, entry, h);
-		}
-	}
-	if (err == ARCHIVE_FATAL)
-		return (err);
-
-	tar_flush_unconsumed(a, unconsumed);
-
-	h = NULL;
-	header = NULL;
-
-	--tar->header_recursion_depth;
-	/* Yuck.  Apple's design here ends up storing long pathname
-	 * extensions for both the AppleDouble extension entry and the
-	 * regular entry.
-	 */
-	if ((err == ARCHIVE_WARN || err == ARCHIVE_OK) &&
-	    tar->header_recursion_depth == 0 &&
-	    tar->process_mac_extensions) {
-		int err2 = read_mac_metadata_blob(a, tar, entry, h, unconsumed);
-		if (err2 < err)
-			err = err2;
-	}
-
-	/* We return warnings or success as-is.  Anything else is fatal. */
-	if (err == ARCHIVE_WARN || err == ARCHIVE_OK) {
-		if (tar->sparse_gnu_pending) {
-			if (tar->sparse_gnu_major == 1 &&
-			    tar->sparse_gnu_minor == 0) {
-				ssize_t bytes_read;
-
-				tar->sparse_gnu_pending = 0;
-				/* Read initial sparse map. */
-				bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
-				if (bytes_read < 0)
-					return ((int)bytes_read);
-				tar->entry_bytes_remaining -= bytes_read;
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Unrecognized GNU sparse file format");
-				return (ARCHIVE_WARN);
-			}
-			tar->sparse_gnu_pending = 0;
-		}
-		return (err);
-	}
-	if (err == ARCHIVE_EOF) {
-		if (!eof_vol_header) {
-			/* EOF when recursively reading a header is bad. */
-			archive_set_error(&a->archive, EINVAL,
-			    "Damaged tar archive");
-		} else {
-			/* If we encounter just a GNU volume header treat
-			 * this situation as an empty archive */
-			return (ARCHIVE_EOF);
-		}
-	}
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Return true if block checksum is correct.
- */
-static int
-checksum(struct archive_read *a, const void *h)
-{
-	const unsigned char *bytes;
-	const struct archive_entry_header_ustar	*header;
-	int check, sum;
-	size_t i;
-
-	(void)a; /* UNUSED */
-	bytes = (const unsigned char *)h;
-	header = (const struct archive_entry_header_ustar *)h;
-
-	/* Checksum field must hold an octal number */
-	for (i = 0; i < sizeof(header->checksum); ++i) {
-		char c = header->checksum[i];
-		if (c != ' ' && c != '\0' && (c < '0' || c > '7'))
-			return 0;
-	}
-
-	/*
-	 * Test the checksum.  Note that POSIX specifies _unsigned_
-	 * bytes for this calculation.
-	 */
-	sum = (int)tar_atol(header->checksum, sizeof(header->checksum));
-	check = 0;
-	for (i = 0; i < 148; i++)
-		check += (unsigned char)bytes[i];
-	for (; i < 156; i++)
-		check += 32;
-	for (; i < 512; i++)
-		check += (unsigned char)bytes[i];
-	if (sum == check)
-		return (1);
-
-	/*
-	 * Repeat test with _signed_ bytes, just in case this archive
-	 * was created by an old BSD, Solaris, or HP-UX tar with a
-	 * broken checksum calculation.
-	 */
-	check = 0;
-	for (i = 0; i < 148; i++)
-		check += (signed char)bytes[i];
-	for (; i < 156; i++)
-		check += 32;
-	for (; i < 512; i++)
-		check += (signed char)bytes[i];
-	if (sum == check)
-		return (1);
-
-	return (0);
-}
-
-/*
- * Return true if this block contains only nulls.
- */
-static int
-archive_block_is_null(const char *p)
-{
-	unsigned i;
-
-	for (i = 0; i < 512; i++)
-		if (*p++)
-			return (0);
-	return (1);
-}
-
-/*
- * Interpret 'A' Solaris ACL header
- */
-static int
-header_Solaris_ACL(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	const struct archive_entry_header_ustar *header;
-	size_t size;
-	int err, acl_type;
-	int64_t type;
-	char *acl, *p;
-
-	/*
-	 * read_body_to_string adds a NUL terminator, but we need a little
-	 * more to make sure that we don't overrun acl_text later.
-	 */
-	header = (const struct archive_entry_header_ustar *)h;
-	size = (size_t)tar_atol(header->size, sizeof(header->size));
-	err = read_body_to_string(a, tar, &(tar->acl_text), h, unconsumed);
-	if (err != ARCHIVE_OK)
-		return (err);
-
-	/* Recursively read next header */
-	err = tar_read_header(a, tar, entry, unconsumed);
-	if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
-		return (err);
-
-	/* TODO: Examine the first characters to see if this
-	 * is an AIX ACL descriptor.  We'll likely never support
-	 * them, but it would be polite to recognize and warn when
-	 * we do see them. */
-
-	/* Leading octal number indicates ACL type and number of entries. */
-	p = acl = tar->acl_text.s;
-	type = 0;
-	while (*p != '\0' && p < acl + size) {
-		if (*p < '0' || *p > '7') {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Malformed Solaris ACL attribute (invalid digit)");
-			return(ARCHIVE_WARN);
-		}
-		type <<= 3;
-		type += *p - '0';
-		if (type > 077777777) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Malformed Solaris ACL attribute (count too large)");
-			return (ARCHIVE_WARN);
-		}
-		p++;
-	}
-	switch ((int)type & ~0777777) {
-	case 01000000:
-		/* POSIX.1e ACL */
-		acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
-		break;
-	case 03000000:
-		/* NFSv4 ACL */
-		acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4;
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Malformed Solaris ACL attribute (unsupported type %o)",
-		    (int)type);
-		return (ARCHIVE_WARN);
-	}
-	p++;
-
-	if (p >= acl + size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Malformed Solaris ACL attribute (body overflow)");
-		return(ARCHIVE_WARN);
-	}
-
-	/* ACL text is null-terminated; find the end. */
-	size -= (p - acl);
-	acl = p;
-
-	while (*p != '\0' && p < acl + size)
-		p++;
-
-	if (tar->sconv_acl == NULL) {
-		tar->sconv_acl = archive_string_conversion_from_charset(
-		    &(a->archive), "UTF-8", 1);
-		if (tar->sconv_acl == NULL)
-			return (ARCHIVE_FATAL);
-	}
-	archive_strncpy(&(tar->localname), acl, p - acl);
-	err = archive_acl_from_text_l(archive_entry_acl(entry),
-	    tar->localname.s, acl_type, tar->sconv_acl);
-	if (err != ARCHIVE_OK) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for ACL");
-		} else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Malformed Solaris ACL attribute (unparsable)");
-	}
-	return (err);
-}
-
-/*
- * Interpret 'K' long linkname header.
- */
-static int
-header_longlink(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	int err;
-
-	err = read_body_to_string(a, tar, &(tar->longlink), h, unconsumed);
-	if (err != ARCHIVE_OK)
-		return (err);
-	err = tar_read_header(a, tar, entry, unconsumed);
-	if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
-		return (err);
-	/* Set symlink if symlink already set, else hardlink. */
-	archive_entry_copy_link(entry, tar->longlink.s);
-	return (ARCHIVE_OK);
-}
-
-static int
-set_conversion_failed_error(struct archive_read *a,
-    struct archive_string_conv *sconv, const char *name)
-{
-	if (errno == ENOMEM) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for %s", name);
-		return (ARCHIVE_FATAL);
-	}
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "%s can't be converted from %s to current locale.",
-	    name, archive_string_conversion_charset_name(sconv));
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Interpret 'L' long filename header.
- */
-static int
-header_longname(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	int err;
-
-	err = read_body_to_string(a, tar, &(tar->longname), h, unconsumed);
-	if (err != ARCHIVE_OK)
-		return (err);
-	/* Read and parse "real" header, then override name. */
-	err = tar_read_header(a, tar, entry, unconsumed);
-	if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
-		return (err);
-	if (archive_entry_copy_pathname_l(entry, tar->longname.s,
-	    archive_strlen(&(tar->longname)), tar->sconv) != 0)
-		err = set_conversion_failed_error(a, tar->sconv, "Pathname");
-	return (err);
-}
-
-
-/*
- * Interpret 'V' GNU tar volume header.
- */
-static int
-header_volume(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	(void)h;
-
-	/* Just skip this and read the next header. */
-	return (tar_read_header(a, tar, entry, unconsumed));
-}
-
-/*
- * Read body of an archive entry into an archive_string object.
- */
-static int
-read_body_to_string(struct archive_read *a, struct tar *tar,
-    struct archive_string *as, const void *h, size_t *unconsumed)
-{
-	int64_t size;
-	const struct archive_entry_header_ustar *header;
-	const void *src;
-
-	(void)tar; /* UNUSED */
-	header = (const struct archive_entry_header_ustar *)h;
-	size  = tar_atol(header->size, sizeof(header->size));
-	if ((size > 1048576) || (size < 0)) {
-		archive_set_error(&a->archive, EINVAL,
-		    "Special header too large");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Fail if we can't make our buffer big enough. */
-	if (archive_string_ensure(as, (size_t)size+1) == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	tar_flush_unconsumed(a, unconsumed);
-
-	/* Read the body into the string. */
-	*unconsumed = (size_t)((size + 511) & ~ 511);
-	src = __archive_read_ahead(a, *unconsumed, NULL);
-	if (src == NULL) {
-		*unconsumed = 0;
-		return (ARCHIVE_FATAL);
-	}
-	memcpy(as->s, src, (size_t)size);
-	as->s[size] = '\0';
-	as->length = (size_t)size;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Parse out common header elements.
- *
- * This would be the same as header_old_tar, except that the
- * filename is handled slightly differently for old and POSIX
- * entries  (POSIX entries support a 'prefix').  This factoring
- * allows header_old_tar and header_ustar
- * to handle filenames differently, while still putting most of the
- * common parsing into one place.
- */
-static int
-header_common(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h)
-{
-	const struct archive_entry_header_ustar	*header;
-	char	tartype;
-	int     err = ARCHIVE_OK;
-
-	header = (const struct archive_entry_header_ustar *)h;
-	if (header->linkname[0])
-		archive_strncpy(&(tar->entry_linkpath),
-		    header->linkname, sizeof(header->linkname));
-	else
-		archive_string_empty(&(tar->entry_linkpath));
-
-	/* Parse out the numeric fields (all are octal) */
-	archive_entry_set_mode(entry,
-		(mode_t)tar_atol(header->mode, sizeof(header->mode)));
-	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));
-	if (tar->entry_bytes_remaining < 0) {
-		tar->entry_bytes_remaining = 0;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Tar entry has negative size");
-		return (ARCHIVE_FATAL);
-	}
-	if (tar->entry_bytes_remaining == INT64_MAX) {
-		/* Note: tar_atol returns INT64_MAX on overflow */
-		tar->entry_bytes_remaining = 0;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Tar entry size overflow");
-		return (ARCHIVE_FATAL);
-	}
-	tar->realsize = tar->entry_bytes_remaining;
-	archive_entry_set_size(entry, tar->entry_bytes_remaining);
-	archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
-
-	/* Handle the tar type flag appropriately. */
-	tartype = header->typeflag[0];
-
-	switch (tartype) {
-	case '1': /* Hard link */
-		if (archive_entry_copy_hardlink_l(entry, tar->entry_linkpath.s,
-		    archive_strlen(&(tar->entry_linkpath)), tar->sconv) != 0) {
-			err = set_conversion_failed_error(a, tar->sconv,
-			    "Linkname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-		}
-		/*
-		 * The following may seem odd, but: Technically, tar
-		 * does not store the file type for a "hard link"
-		 * entry, only the fact that it is a hard link.  So, I
-		 * leave the type zero normally.  But, pax interchange
-		 * format allows hard links to have data, which
-		 * implies that the underlying entry is a regular
-		 * file.
-		 */
-		if (archive_entry_size(entry) > 0)
-			archive_entry_set_filetype(entry, AE_IFREG);
-
-		/*
-		 * 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 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) {
-			/* 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) > 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);
-		archive_entry_set_size(entry, 0);
-		tar->entry_bytes_remaining = 0;
-		if (archive_entry_copy_symlink_l(entry, tar->entry_linkpath.s,
-		    archive_strlen(&(tar->entry_linkpath)), tar->sconv) != 0) {
-			err = set_conversion_failed_error(a, tar->sconv,
-			    "Linkname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-		}
-		break;
-	case '3': /* Character device */
-		archive_entry_set_filetype(entry, AE_IFCHR);
-		archive_entry_set_size(entry, 0);
-		tar->entry_bytes_remaining = 0;
-		break;
-	case '4': /* Block device */
-		archive_entry_set_filetype(entry, AE_IFBLK);
-		archive_entry_set_size(entry, 0);
-		tar->entry_bytes_remaining = 0;
-		break;
-	case '5': /* Dir */
-		archive_entry_set_filetype(entry, AE_IFDIR);
-		archive_entry_set_size(entry, 0);
-		tar->entry_bytes_remaining = 0;
-		break;
-	case '6': /* FIFO device */
-		archive_entry_set_filetype(entry, AE_IFIFO);
-		archive_entry_set_size(entry, 0);
-		tar->entry_bytes_remaining = 0;
-		break;
-	case 'D': /* GNU incremental directory type */
-		/*
-		 * No special handling is actually required here.
-		 * It might be nice someday to preprocess the file list and
-		 * provide it to the client, though.
-		 */
-		archive_entry_set_filetype(entry, AE_IFDIR);
-		break;
-	case 'M': /* GNU "Multi-volume" (remainder of file from last archive)*/
-		/*
-		 * As far as I can tell, this is just like a regular file
-		 * entry, except that the contents should be _appended_ to
-		 * the indicated file at the indicated offset.  This may
-		 * require some API work to fully support.
-		 */
-		break;
-	case 'N': /* Old GNU "long filename" entry. */
-		/* The body of this entry is a script for renaming
-		 * previously-extracted entries.  Ugh.  It will never
-		 * be supported by libarchive. */
-		archive_entry_set_filetype(entry, AE_IFREG);
-		break;
-	case 'S': /* GNU sparse files */
-		/*
-		 * Sparse files are really just regular files with
-		 * sparse information in the extended area.
-		 */
-		/* FALLTHROUGH */
-	case '0':
-		/*
-		 * Enable sparse file "read" support only for regular
-		 * files and explicit GNU sparse files.  However, we
-		 * don't allow non-standard file types to be sparse.
-		 */
-		tar->sparse_allowed = 1;
-		/* FALLTHROUGH */
-	default: /* Regular file  and non-standard types */
-		/*
-		 * Per POSIX: non-recognized types should always be
-		 * treated as regular files.
-		 */
-		archive_entry_set_filetype(entry, AE_IFREG);
-		break;
-	}
-	return (err);
-}
-
-/*
- * Parse out header elements for "old-style" tar archives.
- */
-static int
-header_old_tar(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h)
-{
-	const struct archive_entry_header_ustar	*header;
-	int err = ARCHIVE_OK, err2;
-
-	/* Copy filename over (to ensure null termination). */
-	header = (const struct archive_entry_header_ustar *)h;
-	if (archive_entry_copy_pathname_l(entry,
-	    header->name, sizeof(header->name), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Pathname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	/* Grab rest of common fields */
-	err2 = header_common(a, tar, entry, h);
-	if (err > err2)
-		err = err2;
-
-	tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
-	return (err);
-}
-
-/*
- * Read a Mac AppleDouble-encoded blob of file metadata,
- * if there is one.
- */
-static int
-read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	int64_t size;
-	size_t msize;
-	const void *data;
-	const char *p, *name;
-	const wchar_t *wp, *wname;
-
-	(void)h; /* UNUSED */
-
-	wname = wp = archive_entry_pathname_w(entry);
-	if (wp != NULL) {
-		/* Find the last path element. */
-		for (; *wp != L'\0'; ++wp) {
-			if (wp[0] == '/' && wp[1] != L'\0')
-				wname = wp + 1;
-		}
-		/*
-		 * If last path element starts with "._", then
-		 * this is a Mac extension.
-		 */
-		if (wname[0] != L'.' || wname[1] != L'_' || wname[2] == L'\0')
-			return ARCHIVE_OK;
-	} else {
-		/* Find the last path element. */
-		name = p = archive_entry_pathname(entry);
-		if (p == NULL)
-			return (ARCHIVE_FAILED);
-		for (; *p != '\0'; ++p) {
-			if (p[0] == '/' && p[1] != '\0')
-				name = p + 1;
-		}
-		/*
-		 * If last path element starts with "._", then
-		 * this is a Mac extension.
-		 */
-		if (name[0] != '.' || name[1] != '_' || name[2] == '\0')
-			return ARCHIVE_OK;
-	}
-
- 	/* Read the body as a Mac OS metadata blob. */
-	size = archive_entry_size(entry);
-	msize = (size_t)size;
-	if (size < 0 || (uintmax_t)msize != (uintmax_t)size) {
-		*unconsumed = 0;
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * TODO: Look beyond the body here to peek at the next header.
-	 * If it's a regular header (not an extension header)
-	 * that has the wrong name, just return the current
-	 * entry as-is, without consuming the body here.
-	 * That would reduce the risk of us mis-identifying
-	 * an ordinary file that just happened to have
-	 * a name starting with "._".
-	 *
-	 * Q: Is the above idea really possible?  Even
-	 * when there are GNU or pax extension entries?
-	 */
-	data = __archive_read_ahead(a, msize, NULL);
-	if (data == NULL) {
-		*unconsumed = 0;
-		return (ARCHIVE_FATAL);
-	}
-	archive_entry_copy_mac_metadata(entry, data, msize);
-	*unconsumed = (msize + 511) & ~ 511;
-	tar_flush_unconsumed(a, unconsumed);
-	return (tar_read_header(a, tar, entry, unconsumed));
-}
-
-/*
- * Parse a file header for a pax extended archive entry.
- */
-static int
-header_pax_global(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	int err;
-
-	err = read_body_to_string(a, tar, &(tar->pax_global), h, unconsumed);
-	if (err != ARCHIVE_OK)
-		return (err);
-	err = tar_read_header(a, tar, entry, unconsumed);
-	return (err);
-}
-
-static int
-header_pax_extensions(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	int err, err2;
-
-	err = read_body_to_string(a, tar, &(tar->pax_header), h, unconsumed);
-	if (err != ARCHIVE_OK)
-		return (err);
-
-	/* Parse the next header. */
-	err = tar_read_header(a, tar, entry, unconsumed);
-	if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
-		return (err);
-
-	/*
-	 * TODO: Parse global/default options into 'entry' struct here
-	 * before handling file-specific options.
-	 *
-	 * This design (parse standard header, then overwrite with pax
-	 * extended attribute data) usually works well, but isn't ideal;
-	 * it would be better to parse the pax extended attributes first
-	 * and then skip any fields in the standard header that were
-	 * defined in the pax header.
-	 */
-	err2 = pax_header(a, tar, entry, &tar->pax_header);
-	err =  err_combine(err, err2);
-	tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
-	return (err);
-}
-
-
-/*
- * Parse a file header for a Posix "ustar" archive entry.  This also
- * handles "pax" or "extended ustar" entries.
- */
-static int
-header_ustar(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h)
-{
-	const struct archive_entry_header_ustar	*header;
-	struct archive_string *as;
-	int err = ARCHIVE_OK, r;
-
-	header = (const struct archive_entry_header_ustar *)h;
-
-	/* Copy name into an internal buffer to ensure null-termination. */
-	as = &(tar->entry_pathname);
-	if (header->prefix[0]) {
-		archive_strncpy(as, header->prefix, sizeof(header->prefix));
-		if (as->s[archive_strlen(as) - 1] != '/')
-			archive_strappend_char(as, '/');
-		archive_strncat(as, header->name, sizeof(header->name));
-	} else {
-		archive_strncpy(as, header->name, sizeof(header->name));
-	}
-	if (archive_entry_copy_pathname_l(entry, as->s, archive_strlen(as),
-	    tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Pathname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	/* Handle rest of common fields. */
-	r = header_common(a, tar, entry, h);
-	if (r == ARCHIVE_FATAL)
-		return (r);
-	if (r < err)
-		err = r;
-
-	/* Handle POSIX ustar fields. */
-	if (archive_entry_copy_uname_l(entry,
-	    header->uname, sizeof(header->uname), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Uname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	if (archive_entry_copy_gname_l(entry,
-	    header->gname, sizeof(header->gname), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Gname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	/* Parse out device numbers only for char and block specials. */
-	if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
-		archive_entry_set_rdevmajor(entry, (dev_t)
-		    tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
-		archive_entry_set_rdevminor(entry, (dev_t)
-		    tar_atol(header->rdevminor, sizeof(header->rdevminor)));
-	}
-
-	tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
-
-	return (err);
-}
-
-
-/*
- * Parse the pax extended attributes record.
- *
- * Returns non-zero if there's an error in the data.
- */
-static int
-pax_header(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, struct archive_string *in_as)
-{
-	size_t attr_length, l, line_length, value_length;
-	char *p;
-	char *key, *value;
-	struct archive_string *as;
-	struct archive_string_conv *sconv;
-	int err, err2;
-	char *attr = in_as->s;
-
-	attr_length = in_as->length;
-	tar->pax_hdrcharset_binary = 0;
-	archive_string_empty(&(tar->entry_gname));
-	archive_string_empty(&(tar->entry_linkpath));
-	archive_string_empty(&(tar->entry_pathname));
-	archive_string_empty(&(tar->entry_pathname_override));
-	archive_string_empty(&(tar->entry_uname));
-	err = ARCHIVE_OK;
-	while (attr_length > 0) {
-		/* Parse decimal length field at start of line. */
-		line_length = 0;
-		l = attr_length;
-		p = attr; /* Record start of line. */
-		while (l>0) {
-			if (*p == ' ') {
-				p++;
-				l--;
-				break;
-			}
-			if (*p < '0' || *p > '9') {
-				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-				    "Ignoring malformed pax extended attributes");
-				return (ARCHIVE_WARN);
-			}
-			line_length *= 10;
-			line_length += *p - '0';
-			if (line_length > 999999) {
-				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-				    "Rejecting pax extended attribute > 1MB");
-				return (ARCHIVE_WARN);
-			}
-			p++;
-			l--;
-		}
-
-		/*
-		 * Parsed length must be no bigger than available data,
-		 * at least 1, and the last character of the line must
-		 * be '\n'.
-		 */
-		if (line_length > attr_length
-		    || line_length < 1
-		    || attr[line_length - 1] != '\n')
-		{
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Ignoring malformed pax extended attribute");
-			return (ARCHIVE_WARN);
-		}
-
-		/* Null-terminate the line. */
-		attr[line_length - 1] = '\0';
-
-		/* Find end of key and null terminate it. */
-		key = p;
-		if (key[0] == '=')
-			return (-1);
-		while (*p && *p != '=')
-			++p;
-		if (*p == '\0') {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid pax extended attributes");
-			return (ARCHIVE_WARN);
-		}
-		*p = '\0';
-
-		value = p + 1;
-
-		/* Some values may be binary data */
-		value_length = attr + line_length - 1 - value;
-
-		/* Identify this attribute and set it in the entry. */
-		err2 = pax_attribute(a, tar, entry, key, value, value_length);
-		if (err2 == ARCHIVE_FATAL)
-			return (err2);
-		err = err_combine(err, err2);
-
-		/* Skip to next line */
-		attr += line_length;
-		attr_length -= line_length;
-	}
-
-	/*
-	 * PAX format uses UTF-8 as default charset for its metadata
-	 * unless hdrcharset=BINARY is present in its header.
-	 * We apply the charset specified by the hdrcharset option only
-	 * when the hdrcharset attribute(in PAX header) is BINARY because
-	 * we respect the charset described in PAX header and BINARY also
-	 * means that metadata(filename,uname and gname) character-set
-	 * is unknown.
-	 */
-	if (tar->pax_hdrcharset_binary)
-		sconv = tar->opt_sconv;
-	else {
-		sconv = archive_string_conversion_from_charset(
-		    &(a->archive), "UTF-8", 1);
-		if (sconv == NULL)
-			return (ARCHIVE_FATAL);
-		if (tar->compat_2x)
-			archive_string_conversion_set_opt(sconv,
-			    SCONV_SET_OPT_UTF8_LIBARCHIVE2X);
-	}
-
-	if (archive_strlen(&(tar->entry_gname)) > 0) {
-		if (archive_entry_copy_gname_l(entry, tar->entry_gname.s,
-		    archive_strlen(&(tar->entry_gname)), sconv) != 0) {
-			err = set_conversion_failed_error(a, sconv, "Gname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-			/* Use a converted an original name. */
-			archive_entry_copy_gname(entry, tar->entry_gname.s);
-		}
-	}
-	if (archive_strlen(&(tar->entry_linkpath)) > 0) {
-		if (archive_entry_copy_link_l(entry, tar->entry_linkpath.s,
-		    archive_strlen(&(tar->entry_linkpath)), sconv) != 0) {
-			err = set_conversion_failed_error(a, sconv, "Linkname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-			/* Use a converted an original name. */
-			archive_entry_copy_link(entry, tar->entry_linkpath.s);
-		}
-	}
-	/*
-	 * Some extensions (such as the GNU sparse file extensions)
-	 * deliberately store a synthetic name under the regular 'path'
-	 * attribute and the real file name under a different attribute.
-	 * Since we're supposed to not care about the order, we
-	 * have no choice but to store all of the various filenames
-	 * we find and figure it all out afterwards.  This is the
-	 * figuring out part.
-	 */
-	as = NULL;
-	if (archive_strlen(&(tar->entry_pathname_override)) > 0)
-		as = &(tar->entry_pathname_override);
-	else if (archive_strlen(&(tar->entry_pathname)) > 0)
-		as = &(tar->entry_pathname);
-	if (as != NULL) {
-		if (archive_entry_copy_pathname_l(entry, as->s,
-		    archive_strlen(as), sconv) != 0) {
-			err = set_conversion_failed_error(a, sconv, "Pathname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-			/* Use a converted an original name. */
-			archive_entry_copy_pathname(entry, as->s);
-		}
-	}
-	if (archive_strlen(&(tar->entry_uname)) > 0) {
-		if (archive_entry_copy_uname_l(entry, tar->entry_uname.s,
-		    archive_strlen(&(tar->entry_uname)), sconv) != 0) {
-			err = set_conversion_failed_error(a, sconv, "Uname");
-			if (err == ARCHIVE_FATAL)
-				return (err);
-			/* Use a converted an original name. */
-			archive_entry_copy_uname(entry, tar->entry_uname.s);
-		}
-	}
-	return (err);
-}
-
-static int
-pax_attribute_xattr(struct archive_entry *entry,
-	const char *name, const char *value)
-{
-	char *name_decoded;
-	void *value_decoded;
-	size_t value_len;
-
-	if (strlen(name) < 18 || (memcmp(name, "LIBARCHIVE.xattr.", 17)) != 0)
-		return 3;
-
-	name += 17;
-
-	/* URL-decode name */
-	name_decoded = url_decode(name);
-	if (name_decoded == NULL)
-		return 2;
-
-	/* Base-64 decode value */
-	value_decoded = base64_decode(value, strlen(value), &value_len);
-	if (value_decoded == NULL) {
-		free(name_decoded);
-		return 1;
-	}
-
-	archive_entry_xattr_add_entry(entry, name_decoded,
-		value_decoded, value_len);
-
-	free(name_decoded);
-	free(value_decoded);
-	return 0;
-}
-
-static int
-pax_attribute_schily_xattr(struct archive_entry *entry,
-	const char *name, const char *value, size_t value_length)
-{
-	if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0)
-		return 1;
-
-	name += 13;
-
-	archive_entry_xattr_add_entry(entry, name, value, value_length);
-
-	return 0;
-}
-
-static int
-pax_attribute_rht_security_selinux(struct archive_entry *entry,
-	const char *value, size_t value_length)
-{
-	archive_entry_xattr_add_entry(entry, "security.selinux",
-            value, value_length);
-
-	return 0;
-}
-
-static int
-pax_attribute_acl(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const char *value, int type)
-{
-	int r;
-	const char* errstr;
-
-	switch (type) {
-	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
-		errstr = "SCHILY.acl.access";
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
-		errstr = "SCHILY.acl.default";
-		break;
-	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
-		errstr = "SCHILY.acl.ace";
-		break;
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Unknown ACL type: %d", type);
-		return(ARCHIVE_FATAL);
-	}
-
-	if (tar->sconv_acl == NULL) {
-		tar->sconv_acl =
-		    archive_string_conversion_from_charset(
-			&(a->archive), "UTF-8", 1);
-		if (tar->sconv_acl == NULL)
-			return (ARCHIVE_FATAL);
-	}
-
-	r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
-	    tar->sconv_acl);
-	if (r != ARCHIVE_OK) {
-		if (r == ARCHIVE_FATAL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "%s %s", "Can't allocate memory for ",
-			    errstr);
-			return (r);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
-	}
-	return (r);
-}
-
-/*
- * Parse a single key=value attribute.  key/value pointers are
- * assumed to point into reasonably long-lived storage.
- *
- * Note that POSIX reserves all-lowercase keywords.  Vendor-specific
- * extensions should always have keywords of the form "VENDOR.attribute"
- * In particular, it's quite feasible to support many different
- * vendor extensions here.  I'm using "LIBARCHIVE" for extensions
- * unique to this library.
- *
- * Investigate other vendor-specific extensions and see if
- * any of them look useful.
- */
-static int
-pax_attribute(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const char *key, const char *value, size_t value_length)
-{
-	int64_t s;
-	long n;
-	int err = ARCHIVE_OK, r;
-
-	if (value == NULL)
-		value = "";	/* Disable compiler warning; do not pass
-				 * NULL pointer to strlen().  */
-	switch (key[0]) {
-	case 'G':
-		/* Reject GNU.sparse.* headers on non-regular files. */
-		if (strncmp(key, "GNU.sparse", 10) == 0 &&
-		    !tar->sparse_allowed) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Non-regular file cannot be sparse");
-			return (ARCHIVE_FATAL);
-		}
-
-		/* GNU "0.0" sparse pax format. */
-		if (strcmp(key, "GNU.sparse.numblocks") == 0) {
-			tar->sparse_offset = -1;
-			tar->sparse_numbytes = -1;
-			tar->sparse_gnu_major = 0;
-			tar->sparse_gnu_minor = 0;
-		}
-		if (strcmp(key, "GNU.sparse.offset") == 0) {
-			tar->sparse_offset = tar_atol10(value, strlen(value));
-			if (tar->sparse_numbytes != -1) {
-				if (gnu_add_sparse_entry(a, tar,
-				    tar->sparse_offset, tar->sparse_numbytes)
-				    != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-				tar->sparse_offset = -1;
-				tar->sparse_numbytes = -1;
-			}
-		}
-		if (strcmp(key, "GNU.sparse.numbytes") == 0) {
-			tar->sparse_numbytes = tar_atol10(value, strlen(value));
-			if (tar->sparse_offset != -1) {
-				if (gnu_add_sparse_entry(a, tar,
-				    tar->sparse_offset, tar->sparse_numbytes)
-				    != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-				tar->sparse_offset = -1;
-				tar->sparse_numbytes = -1;
-			}
-		}
-		if (strcmp(key, "GNU.sparse.size") == 0) {
-			tar->realsize = tar_atol10(value, strlen(value));
-			archive_entry_set_size(entry, tar->realsize);
-			tar->realsize_override = 1;
-		}
-
-		/* GNU "0.1" sparse pax format. */
-		if (strcmp(key, "GNU.sparse.map") == 0) {
-			tar->sparse_gnu_major = 0;
-			tar->sparse_gnu_minor = 1;
-			if (gnu_sparse_01_parse(a, tar, value) != ARCHIVE_OK)
-				return (ARCHIVE_WARN);
-		}
-
-		/* GNU "1.0" sparse pax format */
-		if (strcmp(key, "GNU.sparse.major") == 0) {
-			tar->sparse_gnu_major = (int)tar_atol10(value, strlen(value));
-			tar->sparse_gnu_pending = 1;
-		}
-		if (strcmp(key, "GNU.sparse.minor") == 0) {
-			tar->sparse_gnu_minor = (int)tar_atol10(value, strlen(value));
-			tar->sparse_gnu_pending = 1;
-		}
-		if (strcmp(key, "GNU.sparse.name") == 0) {
-			/*
-			 * The real filename; when storing sparse
-			 * files, GNU tar puts a synthesized name into
-			 * the regular 'path' attribute in an attempt
-			 * to limit confusion. ;-)
-			 */
-			archive_strcpy(&(tar->entry_pathname_override), value);
-		}
-		if (strcmp(key, "GNU.sparse.realsize") == 0) {
-			tar->realsize = tar_atol10(value, strlen(value));
-			archive_entry_set_size(entry, tar->realsize);
-			tar->realsize_override = 1;
-		}
-		break;
-	case 'L':
-		/* Our extensions */
-/* TODO: Handle arbitrary extended attributes... */
-/*
-		if (strcmp(key, "LIBARCHIVE.xxxxxxx") == 0)
-			archive_entry_set_xxxxxx(entry, value);
-*/
-		if (strcmp(key, "LIBARCHIVE.creationtime") == 0) {
-			pax_time(value, &s, &n);
-			archive_entry_set_birthtime(entry, s, n);
-		}
-		if (strcmp(key, "LIBARCHIVE.symlinktype") == 0) {
-			if (strcmp(value, "file") == 0) {
-				archive_entry_set_symlink_type(entry,
-				    AE_SYMLINK_TYPE_FILE);
-			} else if (strcmp(value, "dir") == 0) {
-				archive_entry_set_symlink_type(entry,
-				    AE_SYMLINK_TYPE_DIRECTORY);
-			}
-		}
-		if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0)
-			pax_attribute_xattr(entry, key, value);
-		break;
-	case 'R':
-		/* GNU tar uses RHT.security header to store SELinux xattrs
-		 * SCHILY.xattr.security.selinux == RHT.security.selinux */
-		if (strcmp(key, "RHT.security.selinux") == 0) {
-			pax_attribute_rht_security_selinux(entry, value,
-			    value_length);
-			}
-		break;
-	case 'S':
-		/* We support some keys used by the "star" archiver */
-		if (strcmp(key, "SCHILY.acl.access") == 0) {
-			r = pax_attribute_acl(a, tar, entry, value,
-			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
-			if (r == ARCHIVE_FATAL)
-				return (r);
-		} else if (strcmp(key, "SCHILY.acl.default") == 0) {
-			r = pax_attribute_acl(a, tar, entry, value,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
-			if (r == ARCHIVE_FATAL)
-				return (r);
-		} else if (strcmp(key, "SCHILY.acl.ace") == 0) {
-			r = pax_attribute_acl(a, tar, entry, value,
-			    ARCHIVE_ENTRY_ACL_TYPE_NFS4);
-			if (r == ARCHIVE_FATAL)
-				return (r);
-		} else if (strcmp(key, "SCHILY.devmajor") == 0) {
-			archive_entry_set_rdevmajor(entry,
-			    (dev_t)tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "SCHILY.devminor") == 0) {
-			archive_entry_set_rdevminor(entry,
-			    (dev_t)tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "SCHILY.fflags") == 0) {
-			archive_entry_copy_fflags_text(entry, value);
-		} else if (strcmp(key, "SCHILY.dev") == 0) {
-			archive_entry_set_dev(entry,
-			    (dev_t)tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "SCHILY.ino") == 0) {
-			archive_entry_set_ino(entry,
-			    tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "SCHILY.nlink") == 0) {
-			archive_entry_set_nlink(entry, (unsigned)
-			    tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "SCHILY.realsize") == 0) {
-			tar->realsize = tar_atol10(value, strlen(value));
-			tar->realsize_override = 1;
-			archive_entry_set_size(entry, tar->realsize);
-		} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
-			pax_attribute_schily_xattr(entry, key, value,
-			    value_length);
-		} else if (strcmp(key, "SUN.holesdata") == 0) {
-			/* A Solaris extension for sparse. */
-			r = solaris_sparse_parse(a, tar, entry, value);
-			if (r < err) {
-				if (r == ARCHIVE_FATAL)
-					return (r);
-				err = r;
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Parse error: SUN.holesdata");
-			}
-		}
-		break;
-	case 'a':
-		if (strcmp(key, "atime") == 0) {
-			pax_time(value, &s, &n);
-			archive_entry_set_atime(entry, s, n);
-		}
-		break;
-	case 'c':
-		if (strcmp(key, "ctime") == 0) {
-			pax_time(value, &s, &n);
-			archive_entry_set_ctime(entry, s, n);
-		} else if (strcmp(key, "charset") == 0) {
-			/* TODO: Publish charset information in entry. */
-		} else if (strcmp(key, "comment") == 0) {
-			/* TODO: Publish comment in entry. */
-		}
-		break;
-	case 'g':
-		if (strcmp(key, "gid") == 0) {
-			archive_entry_set_gid(entry,
-			    tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "gname") == 0) {
-			archive_strcpy(&(tar->entry_gname), value);
-		}
-		break;
-	case 'h':
-		if (strcmp(key, "hdrcharset") == 0) {
-			if (strcmp(value, "BINARY") == 0)
-				/* Binary  mode. */
-				tar->pax_hdrcharset_binary = 1;
-			else if (strcmp(value, "ISO-IR 10646 2000 UTF-8") == 0)
-				tar->pax_hdrcharset_binary = 0;
-		}
-		break;
-	case 'l':
-		/* pax interchange doesn't distinguish hardlink vs. symlink. */
-		if (strcmp(key, "linkpath") == 0) {
-			archive_strcpy(&(tar->entry_linkpath), value);
-		}
-		break;
-	case 'm':
-		if (strcmp(key, "mtime") == 0) {
-			pax_time(value, &s, &n);
-			archive_entry_set_mtime(entry, s, n);
-		}
-		break;
-	case 'p':
-		if (strcmp(key, "path") == 0) {
-			archive_strcpy(&(tar->entry_pathname), value);
-		}
-		break;
-	case 'r':
-		/* POSIX has reserved 'realtime.*' */
-		break;
-	case 's':
-		/* POSIX has reserved 'security.*' */
-		/* Someday: if (strcmp(key, "security.acl") == 0) { ... } */
-		if (strcmp(key, "size") == 0) {
-			/* "size" is the size of the data in the entry. */
-			tar->entry_bytes_remaining
-			    = tar_atol10(value, strlen(value));
-			if (tar->entry_bytes_remaining < 0) {
-				tar->entry_bytes_remaining = 0;
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Tar size attribute is negative");
-				return (ARCHIVE_FATAL);
-			}
-			if (tar->entry_bytes_remaining == INT64_MAX) {
-				/* Note: tar_atol returns INT64_MAX on overflow */
-				tar->entry_bytes_remaining = 0;
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Tar size attribute overflow");
-				return (ARCHIVE_FATAL);
-			}
-			/*
-			 * The "size" pax header keyword always overrides the
-			 * "size" field in the tar header.
-			 * GNU.sparse.realsize, GNU.sparse.size and
-			 * SCHILY.realsize override this value.
-			 */
-			if (!tar->realsize_override) {
-				archive_entry_set_size(entry,
-				    tar->entry_bytes_remaining);
-				tar->realsize
-				    = tar->entry_bytes_remaining;
-			}
-		}
-		break;
-	case 'u':
-		if (strcmp(key, "uid") == 0) {
-			archive_entry_set_uid(entry,
-			    tar_atol10(value, strlen(value)));
-		} else if (strcmp(key, "uname") == 0) {
-			archive_strcpy(&(tar->entry_uname), value);
-		}
-		break;
-	}
-	return (err);
-}
-
-
-
-/*
- * parse a decimal time value, which may include a fractional portion
- */
-static void
-pax_time(const char *p, int64_t *ps, long *pn)
-{
-	char digit;
-	int64_t	s;
-	unsigned long l;
-	int sign;
-	int64_t limit, last_digit_limit;
-
-	limit = INT64_MAX / 10;
-	last_digit_limit = INT64_MAX % 10;
-
-	s = 0;
-	sign = 1;
-	if (*p == '-') {
-		sign = -1;
-		p++;
-	}
-	while (*p >= '0' && *p <= '9') {
-		digit = *p - '0';
-		if (s > limit ||
-		    (s == limit && digit > last_digit_limit)) {
-			s = INT64_MAX;
-			break;
-		}
-		s = (s * 10) + digit;
-		++p;
-	}
-
-	*ps = s * sign;
-
-	/* Calculate nanoseconds. */
-	*pn = 0;
-
-	if (*p != '.')
-		return;
-
-	l = 100000000UL;
-	do {
-		++p;
-		if (*p >= '0' && *p <= '9')
-			*pn += (*p - '0') * l;
-		else
-			break;
-	} while (l /= 10);
-}
-
-/*
- * Parse GNU tar header
- */
-static int
-header_gnutar(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
-{
-	const struct archive_entry_header_gnutar *header;
-	int64_t t;
-	int err = ARCHIVE_OK;
-
-	/*
-	 * GNU header is like POSIX ustar, except 'prefix' is
-	 * replaced with some other fields. This also means the
-	 * filename is stored as in old-style archives.
-	 */
-
-	/* Grab fields common to all tar variants. */
-	err = header_common(a, tar, entry, h);
-	if (err == ARCHIVE_FATAL)
-		return (err);
-
-	/* Copy filename over (to ensure null termination). */
-	header = (const struct archive_entry_header_gnutar *)h;
-	if (archive_entry_copy_pathname_l(entry,
-	    header->name, sizeof(header->name), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Pathname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	/* Fields common to ustar and GNU */
-	/* XXX Can the following be factored out since it's common
-	 * to ustar and gnu tar?  Is it okay to move it down into
-	 * header_common, perhaps?  */
-	if (archive_entry_copy_uname_l(entry,
-	    header->uname, sizeof(header->uname), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Uname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	if (archive_entry_copy_gname_l(entry,
-	    header->gname, sizeof(header->gname), tar->sconv) != 0) {
-		err = set_conversion_failed_error(a, tar->sconv, "Gname");
-		if (err == ARCHIVE_FATAL)
-			return (err);
-	}
-
-	/* Parse out device numbers only for char and block specials */
-	if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
-		archive_entry_set_rdevmajor(entry, (dev_t)
-		    tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
-		archive_entry_set_rdevminor(entry, (dev_t)
-		    tar_atol(header->rdevminor, sizeof(header->rdevminor)));
-	} else
-		archive_entry_set_rdev(entry, 0);
-
-	tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
-
-	/* Grab GNU-specific fields. */
-	t = tar_atol(header->atime, sizeof(header->atime));
-	if (t > 0)
-		archive_entry_set_atime(entry, t, 0);
-	t = tar_atol(header->ctime, sizeof(header->ctime));
-	if (t > 0)
-		archive_entry_set_ctime(entry, t, 0);
-
-	if (header->realsize[0] != 0) {
-		tar->realsize
-		    = tar_atol(header->realsize, sizeof(header->realsize));
-		archive_entry_set_size(entry, tar->realsize);
-		tar->realsize_override = 1;
-	}
-
-	if (header->sparse[0].offset[0] != 0) {
-		if (gnu_sparse_old_read(a, tar, header, unconsumed)
-		    != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	} else {
-		if (header->isextended[0] != 0) {
-			/* XXX WTF? XXX */
-		}
-	}
-
-	return (err);
-}
-
-static int
-gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
-    int64_t offset, int64_t remaining)
-{
-	struct sparse_block *p;
-
-	p = (struct sparse_block *)calloc(1, sizeof(*p));
-	if (p == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	if (tar->sparse_last != NULL)
-		tar->sparse_last->next = p;
-	else
-		tar->sparse_list = p;
-	tar->sparse_last = p;
-	if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
-		return (ARCHIVE_FATAL);
-	}
-	p->offset = offset;
-	p->remaining = remaining;
-	return (ARCHIVE_OK);
-}
-
-static void
-gnu_clear_sparse_list(struct tar *tar)
-{
-	struct sparse_block *p;
-
-	while (tar->sparse_list != NULL) {
-		p = tar->sparse_list;
-		tar->sparse_list = p->next;
-		free(p);
-	}
-	tar->sparse_last = NULL;
-}
-
-/*
- * GNU tar old-format sparse data.
- *
- * GNU old-format sparse data is stored in a fixed-field
- * format.  Offset/size values are 11-byte octal fields (same
- * format as 'size' field in ustart header).  These are
- * stored in the header, allocating subsequent header blocks
- * as needed.  Extending the header in this way is a pretty
- * severe POSIX violation; this design has earned GNU tar a
- * lot of criticism.
- */
-
-static int
-gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
-    const struct archive_entry_header_gnutar *header, size_t *unconsumed)
-{
-	ssize_t bytes_read;
-	const void *data;
-	struct extended {
-		struct gnu_sparse sparse[21];
-		char	isextended[1];
-		char	padding[7];
-	};
-	const struct extended *ext;
-
-	if (gnu_sparse_old_parse(a, tar, header->sparse, 4) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	if (header->isextended[0] == 0)
-		return (ARCHIVE_OK);
-
-	do {
-		tar_flush_unconsumed(a, unconsumed);
-		data = __archive_read_ahead(a, 512, &bytes_read);
-		if (bytes_read < 0)
-			return (ARCHIVE_FATAL);
-		if (bytes_read < 512) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated tar archive "
-			    "detected while reading sparse file data");
-			return (ARCHIVE_FATAL);
-		}
-		*unconsumed = 512;
-		ext = (const struct extended *)data;
-		if (gnu_sparse_old_parse(a, tar, ext->sparse, 21) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	} while (ext->isextended[0] != 0);
-	if (tar->sparse_list != NULL)
-		tar->entry_offset = tar->sparse_list->offset;
-	return (ARCHIVE_OK);
-}
-
-static int
-gnu_sparse_old_parse(struct archive_read *a, struct tar *tar,
-    const struct gnu_sparse *sparse, int length)
-{
-	while (length > 0 && sparse->offset[0] != 0) {
-		if (gnu_add_sparse_entry(a, tar,
-		    tar_atol(sparse->offset, sizeof(sparse->offset)),
-		    tar_atol(sparse->numbytes, sizeof(sparse->numbytes)))
-		    != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		sparse++;
-		length--;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * GNU tar sparse format 0.0
- *
- * Beginning with GNU tar 1.15, sparse files are stored using
- * information in the pax extended header.  The GNU tar maintainers
- * have gone through a number of variations in the process of working
- * out this scheme; fortunately, they're all numbered.
- *
- * Sparse format 0.0 uses attribute GNU.sparse.numblocks to store the
- * number of blocks, and GNU.sparse.offset/GNU.sparse.numbytes to
- * store offset/size for each block.  The repeated instances of these
- * latter fields violate the pax specification (which frowns on
- * duplicate keys), so this format was quickly replaced.
- */
-
-/*
- * GNU tar sparse format 0.1
- *
- * This version replaced the offset/numbytes attributes with
- * a single "map" attribute that stored a list of integers.  This
- * format had two problems: First, the "map" attribute could be very
- * long, which caused problems for some implementations.  More
- * importantly, the sparse data was lost when extracted by archivers
- * that didn't recognize this extension.
- */
-
-static int
-gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p)
-{
-	const char *e;
-	int64_t offset = -1, size = -1;
-
-	for (;;) {
-		e = p;
-		while (*e != '\0' && *e != ',') {
-			if (*e < '0' || *e > '9')
-				return (ARCHIVE_WARN);
-			e++;
-		}
-		if (offset < 0) {
-			offset = tar_atol10(p, e - p);
-			if (offset < 0)
-				return (ARCHIVE_WARN);
-		} else {
-			size = tar_atol10(p, e - p);
-			if (size < 0)
-				return (ARCHIVE_WARN);
-			if (gnu_add_sparse_entry(a, tar, offset, size)
-			    != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			offset = -1;
-		}
-		if (*e == '\0')
-			return (ARCHIVE_OK);
-		p = e + 1;
-	}
-}
-
-/*
- * GNU tar sparse format 1.0
- *
- * The idea: The offset/size data is stored as a series of base-10
- * ASCII numbers prepended to the file data, so that dearchivers that
- * don't support this format will extract the block map along with the
- * data and a separate post-process can restore the sparseness.
- *
- * Unfortunately, GNU tar 1.16 had a bug that added unnecessary
- * padding to the body of the file when using this format.  GNU tar
- * 1.17 corrected this bug without bumping the version number, so
- * it's not possible to support both variants.  This code supports
- * the later variant at the expense of not supporting the former.
- *
- * This variant also replaced GNU.sparse.size with GNU.sparse.realsize
- * and introduced the GNU.sparse.major/GNU.sparse.minor attributes.
- */
-
-/*
- * Read the next line from the input, and parse it as a decimal
- * integer followed by '\n'.  Returns positive integer value or
- * negative on error.
- */
-static int64_t
-gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
-    int64_t *remaining, size_t *unconsumed)
-{
-	int64_t l, limit, last_digit_limit;
-	const char *p;
-	ssize_t bytes_read;
-	int base, digit;
-
-	base = 10;
-	limit = INT64_MAX / base;
-	last_digit_limit = INT64_MAX % base;
-
-	/*
-	 * Skip any lines starting with '#'; GNU tar specs
-	 * don't require this, but they should.
-	 */
-	do {
-		bytes_read = readline(a, tar, &p,
-			(ssize_t)tar_min(*remaining, 100), unconsumed);
-		if (bytes_read <= 0)
-			return (ARCHIVE_FATAL);
-		*remaining -= bytes_read;
-	} while (p[0] == '#');
-
-	l = 0;
-	while (bytes_read > 0) {
-		if (*p == '\n')
-			return (l);
-		if (*p < '0' || *p >= '0' + base)
-			return (ARCHIVE_WARN);
-		digit = *p - '0';
-		if (l > limit || (l == limit && digit > last_digit_limit))
-			l = INT64_MAX; /* Truncate on overflow. */
-		else
-			l = (l * base) + digit;
-		p++;
-		bytes_read--;
-	}
-	/* TODO: Error message. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Returns length (in bytes) of the sparse data description
- * that was read.
- */
-static ssize_t
-gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
-{
-	ssize_t bytes_read;
-	int entries;
-	int64_t offset, size, to_skip, remaining;
-
-	/* Clear out the existing sparse list. */
-	gnu_clear_sparse_list(tar);
-
-	remaining = tar->entry_bytes_remaining;
-
-	/* Parse entries. */
-	entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
-	if (entries < 0)
-		return (ARCHIVE_FATAL);
-	/* Parse the individual entries. */
-	while (entries-- > 0) {
-		/* Parse offset/size */
-		offset = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
-		if (offset < 0)
-			return (ARCHIVE_FATAL);
-		size = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
-		if (size < 0)
-			return (ARCHIVE_FATAL);
-		/* Add a new sparse entry. */
-		if (gnu_add_sparse_entry(a, tar, offset, size) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-	/* Skip rest of block... */
-	tar_flush_unconsumed(a, unconsumed);
-	bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
-	to_skip = 0x1ff & -bytes_read;
-	/* Fail if tar->entry_bytes_remaing would get negative */
-	if (to_skip > remaining)
-		return (ARCHIVE_FATAL);
-	if (to_skip != __archive_read_consume(a, to_skip))
-		return (ARCHIVE_FATAL);
-	return ((ssize_t)(bytes_read + to_skip));
-}
-
-/*
- * Solaris pax extension for a sparse file. This is recorded with the
- * data and hole pairs. The way recording sparse information by Solaris'
- * pax simply indicates where data and sparse are, so the stored contents
- * consist of both data and hole.
- */
-static int
-solaris_sparse_parse(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const char *p)
-{
-	const char *e;
-	int64_t start, end;
-	int hole = 1;
-
-	(void)entry; /* UNUSED */
-
-	end = 0;
-	if (*p == ' ')
-		p++;
-	else
-		return (ARCHIVE_WARN);
-	for (;;) {
-		e = p;
-		while (*e != '\0' && *e != ' ') {
-			if (*e < '0' || *e > '9')
-				return (ARCHIVE_WARN);
-			e++;
-		}
-		start = end;
-		end = tar_atol10(p, e - p);
-		if (end < 0)
-			return (ARCHIVE_WARN);
-		if (start < end) {
-			if (gnu_add_sparse_entry(a, tar, start,
-			    end - start) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			tar->sparse_last->hole = hole;
-		}
-		if (*e == '\0')
-			return (ARCHIVE_OK);
-		p = e + 1;
-		hole = hole == 0;
-	}
-}
-
-/*-
- * Convert text->integer.
- *
- * Traditional tar formats (including POSIX) specify base-8 for
- * all of the standard numeric fields.  This is a significant limitation
- * in practice:
- *   = file size is limited to 8GB
- *   = rdevmajor and rdevminor are limited to 21 bits
- *   = uid/gid are limited to 21 bits
- *
- * There are two workarounds for this:
- *   = pax extended headers, which use variable-length string fields
- *   = GNU tar and STAR both allow either base-8 or base-256 in
- *      most fields.  The high bit is set to indicate base-256.
- *
- * On read, this implementation supports both extensions.
- */
-static int64_t
-tar_atol(const char *p, size_t char_cnt)
-{
-	/*
-	 * Technically, GNU tar considers a field to be in base-256
-	 * only if the first byte is 0xff or 0x80.
-	 */
-	if (*p & 0x80)
-		return (tar_atol256(p, char_cnt));
-	return (tar_atol8(p, char_cnt));
-}
-
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
-static int64_t
-tar_atol_base_n(const char *p, size_t char_cnt, int base)
-{
-	int64_t	l, maxval, limit, last_digit_limit;
-	int digit, sign;
-
-	maxval = INT64_MAX;
-	limit = INT64_MAX / base;
-	last_digit_limit = INT64_MAX % base;
-
-	/* the pointer will not be dereferenced if char_cnt is zero
-	 * due to the way the && operator is evaluated.
-	 */
-	while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
-		p++;
-		char_cnt--;
-	}
-
-	sign = 1;
-	if (char_cnt != 0 && *p == '-') {
-		sign = -1;
-		p++;
-		char_cnt--;
-
-		maxval = INT64_MIN;
-		limit = -(INT64_MIN / base);
-		last_digit_limit = -(INT64_MIN % base);
-	}
-
-	l = 0;
-	if (char_cnt != 0) {
-		digit = *p - '0';
-		while (digit >= 0 && digit < base  && char_cnt != 0) {
-			if (l>limit || (l == limit && digit >= last_digit_limit)) {
-				return maxval; /* Truncate on overflow. */
-			}
-			l = (l * base) + digit;
-			digit = *++p - '0';
-			char_cnt--;
-		}
-	}
-	return (sign < 0) ? -l : l;
-}
-
-static int64_t
-tar_atol8(const char *p, size_t char_cnt)
-{
-	return tar_atol_base_n(p, char_cnt, 8);
-}
-
-static int64_t
-tar_atol10(const char *p, size_t char_cnt)
-{
-	return tar_atol_base_n(p, char_cnt, 10);
-}
-
-/*
- * Parse a base-256 integer.  This is just a variable-length
- * twos-complement signed binary value in big-endian order, except
- * that the high-order bit is ignored.  The values here can be up to
- * 12 bytes, so we need to be careful about overflowing 64-bit
- * (8-byte) integers.
- *
- * This code unashamedly assumes that the local machine uses 8-bit
- * bytes and twos-complement arithmetic.
- */
-static int64_t
-tar_atol256(const char *_p, size_t char_cnt)
-{
-	uint64_t l;
-	const unsigned char *p = (const unsigned char *)_p;
-	unsigned char c, neg;
-
-	/* Extend 7-bit 2s-comp to 8-bit 2s-comp, decide sign. */
-	c = *p;
-	if (c & 0x40) {
-		neg = 0xff;
-		c |= 0x80;
-		l = ~ARCHIVE_LITERAL_ULL(0);
-	} else {
-		neg = 0;
-		c &= 0x7f;
-		l = 0;
-	}
-
-	/* If more than 8 bytes, check that we can ignore
-	 * high-order bits without overflow. */
-	while (char_cnt > sizeof(int64_t)) {
-		--char_cnt;
-		if (c != neg)
-			return neg ? INT64_MIN : INT64_MAX;
-		c = *++p;
-	}
-
-	/* c is first byte that fits; if sign mismatch, return overflow */
-	if ((c ^ neg) & 0x80) {
-		return neg ? INT64_MIN : INT64_MAX;
-	}
-
-	/* Accumulate remaining bytes. */
-	while (--char_cnt > 0) {
-		l = (l << 8) | c;
-		c = *++p;
-	}
-	l = (l << 8) | c;
-	/* Return signed twos-complement value. */
-	return (int64_t)(l);
-}
-
-/*
- * Returns length of line (including trailing newline)
- * or negative on error.  'start' argument is updated to
- * point to first character of line.  This avoids copying
- * when possible.
- */
-static ssize_t
-readline(struct archive_read *a, struct tar *tar, const char **start,
-    ssize_t limit, size_t *unconsumed)
-{
-	ssize_t bytes_read;
-	ssize_t total_size = 0;
-	const void *t;
-	const char *s;
-	void *p;
-
-	tar_flush_unconsumed(a, unconsumed);
-
-	t = __archive_read_ahead(a, 1, &bytes_read);
-	if (bytes_read <= 0)
-		return (ARCHIVE_FATAL);
-	s = t;  /* Start of line? */
-	p = memchr(t, '\n', bytes_read);
-	/* If we found '\n' in the read buffer, return pointer to that. */
-	if (p != NULL) {
-		bytes_read = 1 + ((const char *)p) - s;
-		if (bytes_read > limit) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Line too long");
-			return (ARCHIVE_FATAL);
-		}
-		*unconsumed = bytes_read;
-		*start = s;
-		return (bytes_read);
-	}
-	*unconsumed = bytes_read;
-	/* Otherwise, we need to accumulate in a line buffer. */
-	for (;;) {
-		if (total_size + bytes_read > limit) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Line too long");
-			return (ARCHIVE_FATAL);
-		}
-		if (archive_string_ensure(&tar->line, total_size + bytes_read) == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate working buffer");
-			return (ARCHIVE_FATAL);
-		}
-		memcpy(tar->line.s + total_size, t, bytes_read);
-		tar_flush_unconsumed(a, unconsumed);
-		total_size += bytes_read;
-		/* If we found '\n', clean up and return. */
-		if (p != NULL) {
-			*start = tar->line.s;
-			return (total_size);
-		}
-		/* Read some more. */
-		t = __archive_read_ahead(a, 1, &bytes_read);
-		if (bytes_read <= 0)
-			return (ARCHIVE_FATAL);
-		s = t;  /* Start of line? */
-		p = memchr(t, '\n', bytes_read);
-		/* If we found '\n', trim the read. */
-		if (p != NULL) {
-			bytes_read = 1 + ((const char *)p) - s;
-		}
-		*unconsumed = bytes_read;
-	}
-}
-
-/*
- * base64_decode - Base64 decode
- *
- * This accepts most variations of base-64 encoding, including:
- *    * with or without line breaks
- *    * with or without the final group padded with '=' or '_' characters
- * (The most economical Base-64 variant does not pad the last group and
- * omits line breaks; RFC1341 used for MIME requires both.)
- */
-static char *
-base64_decode(const char *s, size_t len, size_t *out_len)
-{
-	static const unsigned char digits[64] = {
-		'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
-		'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b',
-		'c','d','e','f','g','h','i','j','k','l','m','n','o','p',
-		'q','r','s','t','u','v','w','x','y','z','0','1','2','3',
-		'4','5','6','7','8','9','+','/' };
-	static unsigned char decode_table[128];
-	char *out, *d;
-	const unsigned char *src = (const unsigned char *)s;
-
-	/* If the decode table is not yet initialized, prepare it. */
-	if (decode_table[digits[1]] != 1) {
-		unsigned i;
-		memset(decode_table, 0xff, sizeof(decode_table));
-		for (i = 0; i < sizeof(digits); i++)
-			decode_table[digits[i]] = i;
-	}
-
-	/* Allocate enough space to hold the entire output. */
-	/* Note that we may not use all of this... */
-	out = (char *)malloc(len - len / 4 + 1);
-	if (out == NULL) {
-		*out_len = 0;
-		return (NULL);
-	}
-	d = out;
-
-	while (len > 0) {
-		/* Collect the next group of (up to) four characters. */
-		int v = 0;
-		int group_size = 0;
-		while (group_size < 4 && len > 0) {
-			/* '=' or '_' padding indicates final group. */
-			if (*src == '=' || *src == '_') {
-				len = 0;
-				break;
-			}
-			/* Skip illegal characters (including line breaks) */
-			if (*src > 127 || *src < 32
-			    || decode_table[*src] == 0xff) {
-				len--;
-				src++;
-				continue;
-			}
-			v <<= 6;
-			v |= decode_table[*src++];
-			len --;
-			group_size++;
-		}
-		/* Align a short group properly. */
-		v <<= 6 * (4 - group_size);
-		/* Unpack the group we just collected. */
-		switch (group_size) {
-		case 4: d[2] = v & 0xff;
-			/* FALLTHROUGH */
-		case 3: d[1] = (v >> 8) & 0xff;
-			/* FALLTHROUGH */
-		case 2: d[0] = (v >> 16) & 0xff;
-			break;
-		case 1: /* this is invalid! */
-			break;
-		}
-		d += group_size * 3 / 4;
-	}
-
-	*out_len = d - out;
-	return (out);
-}
-
-static char *
-url_decode(const char *in)
-{
-	char *out, *d;
-	const char *s;
-
-	out = (char *)malloc(strlen(in) + 1);
-	if (out == NULL)
-		return (NULL);
-	for (s = in, d = out; *s != '\0'; ) {
-		if (s[0] == '%' && s[1] != '\0' && s[2] != '\0') {
-			/* Try to convert % escape */
-			int digit1 = tohex(s[1]);
-			int digit2 = tohex(s[2]);
-			if (digit1 >= 0 && digit2 >= 0) {
-				/* Looks good, consume three chars */
-				s += 3;
-				/* Convert output */
-				*d++ = ((digit1 << 4) | digit2);
-				continue;
-			}
-			/* Else fall through and treat '%' as normal char */
-		}
-		*d++ = *s++;
-	}
-	*d = '\0';
-	return (out);
-}
-
-static int
-tohex(int c)
-{
-	if (c >= '0' && c <= '9')
-		return (c - '0');
-	else if (c >= 'A' && c <= 'F')
-		return (c - 'A' + 10);
-	else if (c >= 'a' && c <= 'f')
-		return (c - 'a' + 10);
-	else
-		return (-1);
-}
diff --git a/c/archive_read_support_format_warc.c b/c/archive_read_support_format_warc.c
deleted file mode 100644
--- a/c/archive_read_support_format_warc.c
+++ /dev/null
@@ -1,848 +0,0 @@
-/*-
- * Copyright (c) 2014 Sebastian Freundt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-/**
- * WARC is standardised by ISO TC46/SC4/WG12 and currently available as
- * ISO 28500:2009.
- * For the purposes of this file we used the final draft from:
- * http://bibnum.bnf.fr/warc/WARC_ISO_28500_version1_latestdraft.pdf
- *
- * Todo:
- * [ ] real-world warcs can contain resources at endpoints ending in /
- *     e.g. http://bibnum.bnf.fr/warc/
- *     if you're lucky their response contains a Content-Location: header
- *     pointing to a unix-compliant filename, in the example above it's
- *     Content-Location: http://bibnum.bnf.fr/warc/index.html
- *     however, that's not mandated and github for example doesn't follow
- *     this convention.
- *     We need a set of archive options to control what to do with
- *     entries like these, at the moment care is taken to skip them.
- *
- **/
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-typedef enum {
-	WT_NONE,
-	/* warcinfo */
-	WT_INFO,
-	/* metadata */
-	WT_META,
-	/* resource */
-	WT_RSRC,
-	/* request, unsupported */
-	WT_REQ,
-	/* response, unsupported */
-	WT_RSP,
-	/* revisit, unsupported */
-	WT_RVIS,
-	/* conversion, unsupported */
-	WT_CONV,
-	/* continuation, unsupported at the moment */
-	WT_CONT,
-	/* invalid type */
-	LAST_WT
-} warc_type_t;
-
-typedef struct {
-	size_t len;
-	const char *str;
-} warc_string_t;
-
-typedef struct {
-	size_t len;
-	char *str;
-} warc_strbuf_t;
-
-struct warc_s {
-	/* content length ahead */
-	size_t cntlen;
-	/* and how much we've processed so far */
-	size_t cntoff;
-	/* and how much we need to consume between calls */
-	size_t unconsumed;
-
-	/* string pool */
-	warc_strbuf_t pool;
-	/* previous version */
-	unsigned int pver;
-	/* stringified format name */
-	struct archive_string sver;
-};
-
-static int _warc_bid(struct archive_read *a, int);
-static int _warc_cleanup(struct archive_read *a);
-static int _warc_read(struct archive_read*, const void**, size_t*, int64_t*);
-static int _warc_skip(struct archive_read *a);
-static int _warc_rdhdr(struct archive_read *a, struct archive_entry *e);
-
-/* private routines */
-static unsigned int _warc_rdver(const char *buf, size_t bsz);
-static unsigned int _warc_rdtyp(const char *buf, size_t bsz);
-static warc_string_t _warc_rduri(const char *buf, size_t bsz);
-static ssize_t _warc_rdlen(const char *buf, size_t bsz);
-static time_t _warc_rdrtm(const char *buf, size_t bsz);
-static time_t _warc_rdmtm(const char *buf, size_t bsz);
-static const char *_warc_find_eoh(const char *buf, size_t bsz);
-static const char *_warc_find_eol(const char *buf, size_t bsz);
-
-int
-archive_read_support_format_warc(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct warc_s *w;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
-
-	if ((w = calloc(1, sizeof(*w))) == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate warc data");
-		return (ARCHIVE_FATAL);
-	}
-
-	r = __archive_read_register_format(
-		a, w, "warc",
-		_warc_bid, NULL, _warc_rdhdr, _warc_read,
-		_warc_skip, NULL, _warc_cleanup, NULL, NULL);
-
-	if (r != ARCHIVE_OK) {
-		free(w);
-		return (r);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_cleanup(struct archive_read *a)
-{
-	struct warc_s *w = a->format->data;
-
-	if (w->pool.len > 0U) {
-		free(w->pool.str);
-	}
-	archive_string_free(&w->sver);
-	free(w);
-	a->format->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_bid(struct archive_read *a, int best_bid)
-{
-	const char *hdr;
-	ssize_t nrd;
-	unsigned int ver;
-
-	(void)best_bid; /* UNUSED */
-
-	/* check first line of file, it should be a record already */
-	if ((hdr = __archive_read_ahead(a, 12U, &nrd)) == NULL) {
-		/* no idea what to do */
-		return -1;
-	} else if (nrd < 12) {
-		/* nah, not for us, our magic cookie is at least 12 bytes */
-		return -1;
-	}
-
-	/* otherwise snarf the record's version number */
-	ver = _warc_rdver(hdr, nrd);
-	if (ver < 1200U || ver > 10000U) {
-		/* we only support WARC 0.12 to 1.0 */
-		return -1;
-	}
-
-	/* otherwise be confident */
-	return (64);
-}
-
-static int
-_warc_rdhdr(struct archive_read *a, struct archive_entry *entry)
-{
-#define HDR_PROBE_LEN		(12U)
-	struct warc_s *w = a->format->data;
-	unsigned int ver;
-	const char *buf;
-	ssize_t nrd;
-	const char *eoh;
-	/* for the file name, saves some strndup()'ing */
-	warc_string_t fnam;
-	/* warc record type, not that we really use it a lot */
-	warc_type_t ftyp;
-	/* content-length+error monad */
-	ssize_t cntlen;
-	/* record time is the WARC-Date time we reinterpret it as ctime */
-	time_t rtime;
-	/* mtime is the Last-Modified time which will be the entry's mtime */
-	time_t mtime;
-
-start_over:
-	/* just use read_ahead() they keep track of unconsumed
-	 * bits and bobs for us; no need to put an extra shift in
-	 * and reproduce that functionality here */
-	buf = __archive_read_ahead(a, HDR_PROBE_LEN, &nrd);
-
-	if (nrd < 0) {
-		/* no good */
-		archive_set_error(
-			&a->archive, ARCHIVE_ERRNO_MISC,
-			"Bad record header");
-		return (ARCHIVE_FATAL);
-	} else if (buf == NULL) {
-		/* there should be room for at least WARC/bla\r\n
-		 * must be EOF therefore */
-		return (ARCHIVE_EOF);
-	}
- 	/* looks good so far, try and find the end of the header now */
-	eoh = _warc_find_eoh(buf, nrd);
-	if (eoh == NULL) {
-		/* still no good, the header end might be beyond the
-		 * probe we've requested, but then again who'd cram
-		 * so much stuff into the header *and* be 28500-compliant */
-		archive_set_error(
-			&a->archive, ARCHIVE_ERRNO_MISC,
-			"Bad record header");
-		return (ARCHIVE_FATAL);
-	}
-	ver = _warc_rdver(buf, eoh - buf);
-	/* we currently support WARC 0.12 to 1.0 */
-	if (ver == 0U) {
-		archive_set_error(
-			&a->archive, ARCHIVE_ERRNO_MISC,
-			"Invalid record version");
-		return (ARCHIVE_FATAL);
-	} else if (ver < 1200U || ver > 10000U) {
-		archive_set_error(
-			&a->archive, ARCHIVE_ERRNO_MISC,
-			"Unsupported record version: %u.%u",
-			ver / 10000, (ver % 10000) / 100);
-		return (ARCHIVE_FATAL);
-	}
-	cntlen = _warc_rdlen(buf, eoh - buf);
-	if (cntlen < 0) {
-		/* nightmare!  the specs say content-length is mandatory
-		 * so I don't feel overly bad stopping the reader here */
-		archive_set_error(
-			&a->archive, EINVAL,
-			"Bad content length");
-		return (ARCHIVE_FATAL);
-	}
-	rtime = _warc_rdrtm(buf, eoh - buf);
-	if (rtime == (time_t)-1) {
-		/* record time is mandatory as per WARC/1.0,
-		 * so just barf here, fast and loud */
-		archive_set_error(
-			&a->archive, EINVAL,
-			"Bad record time");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* let the world know we're a WARC archive */
-	a->archive.archive_format = ARCHIVE_FORMAT_WARC;
-	if (ver != w->pver) {
-		/* stringify this entry's version */
-		archive_string_sprintf(&w->sver,
-			"WARC/%u.%u", ver / 10000, (ver % 10000) / 100);
-		/* remember the version */
-		w->pver = ver;
-	}
-	/* start off with the type */
-	ftyp = _warc_rdtyp(buf, eoh - buf);
-	/* and let future calls know about the content */
-	w->cntlen = cntlen;
-	w->cntoff = 0U;
-	mtime = 0;/* Avoid compiling error on some platform. */
-
-	switch (ftyp) {
-	case WT_RSRC:
-	case WT_RSP:
-		/* only try and read the filename in the cases that are
-		 * guaranteed to have one */
-		fnam = _warc_rduri(buf, eoh - buf);
-		/* check the last character in the URI to avoid creating
-		 * directory endpoints as files, see Todo above */
-		if (fnam.len == 0 || fnam.str[fnam.len - 1] == '/') {
-			/* break here for now */
-			fnam.len = 0U;
-			fnam.str = NULL;
-			break;
-		}
-		/* bang to our string pool, so we save a
-		 * malloc()+free() roundtrip */
-		if (fnam.len + 1U > w->pool.len) {
-			w->pool.len = ((fnam.len + 64U) / 64U) * 64U;
-			w->pool.str = realloc(w->pool.str, w->pool.len);
-		}
-		memcpy(w->pool.str, fnam.str, fnam.len);
-		w->pool.str[fnam.len] = '\0';
-		/* let no one else know about the pool, it's a secret, shhh */
-		fnam.str = w->pool.str;
-
-		/* snarf mtime or deduce from rtime
-		 * this is a custom header added by our writer, it's quite
-		 * hard to believe anyone else would go through with it
-		 * (apart from being part of some http responses of course) */
-		if ((mtime = _warc_rdmtm(buf, eoh - buf)) == (time_t)-1) {
-			mtime = rtime;
-		}
-		break;
-	case WT_NONE:
-	case WT_INFO:
-	case WT_META:
-	case WT_REQ:
-	case WT_RVIS:
-	case WT_CONV:
-	case WT_CONT:
-	case LAST_WT:
-	default:
-		fnam.len = 0U;
-		fnam.str = NULL;
-		break;
-	}
-
-	/* now eat some of those delicious buffer bits */
-	__archive_read_consume(a, eoh - buf);
-
-	switch (ftyp) {
-	case WT_RSRC:
-	case WT_RSP:
-		if (fnam.len > 0U) {
-			/* populate entry object */
-			archive_entry_set_filetype(entry, AE_IFREG);
-			archive_entry_copy_pathname(entry, fnam.str);
-			archive_entry_set_size(entry, cntlen);
-			archive_entry_set_perm(entry, 0644);
-			/* rtime is the new ctime, mtime stays mtime */
-			archive_entry_set_ctime(entry, rtime, 0L);
-			archive_entry_set_mtime(entry, mtime, 0L);
-			break;
-		}
-		/* FALLTHROUGH */
-	case WT_NONE:
-	case WT_INFO:
-	case WT_META:
-	case WT_REQ:
-	case WT_RVIS:
-	case WT_CONV:
-	case WT_CONT:
-	case LAST_WT:
-	default:
-		/* consume the content and start over */
-		_warc_skip(a);
-		goto start_over;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off)
-{
-	struct warc_s *w = a->format->data;
-	const char *rab;
-	ssize_t nrd;
-
-	if (w->cntoff >= w->cntlen) {
-	eof:
-		/* it's our lucky day, no work, we can leave early */
-		*buf = NULL;
-		*bsz = 0U;
-		*off = w->cntoff + 4U/*for \r\n\r\n separator*/;
-		w->unconsumed = 0U;
-		return (ARCHIVE_EOF);
-	}
-
-	if (w->unconsumed) {
-		__archive_read_consume(a, w->unconsumed);
-		w->unconsumed = 0U;
-	}
-
-	rab = __archive_read_ahead(a, 1U, &nrd);
-	if (nrd < 0) {
-		*bsz = 0U;
-		/* big catastrophe */
-		return (int)nrd;
-	} else if (nrd == 0) {
-		goto eof;
-	} else if ((size_t)nrd > w->cntlen - w->cntoff) {
-		/* clamp to content-length */
-		nrd = w->cntlen - w->cntoff;
-	}
-	*off = w->cntoff;
-	*bsz = nrd;
-	*buf = rab;
-
-	w->cntoff += nrd;
-	w->unconsumed = (size_t)nrd;
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_skip(struct archive_read *a)
-{
-	struct warc_s *w = a->format->data;
-
-	__archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/);
-	w->cntlen = 0U;
-	w->cntoff = 0U;
-	return (ARCHIVE_OK);
-}
-
-
-/* private routines */
-static void*
-deconst(const void *c)
-{
-	return (void *)(uintptr_t)c;
-}
-
-static char*
-xmemmem(const char *hay, const size_t haysize,
-	const char *needle, const size_t needlesize)
-{
-	const char *const eoh = hay + haysize;
-	const char *const eon = needle + needlesize;
-	const char *hp;
-	const char *np;
-	const char *cand;
-	unsigned int hsum;
-	unsigned int nsum;
-	unsigned int eqp;
-
-	/* trivial checks first
-         * a 0-sized needle is defined to be found anywhere in haystack
-         * then run strchr() to find a candidate in HAYSTACK (i.e. a portion
-         * that happens to begin with *NEEDLE) */
-	if (needlesize == 0UL) {
-		return deconst(hay);
-	} else if ((hay = memchr(hay, *needle, haysize)) == NULL) {
-		/* trivial */
-		return NULL;
-	}
-
-	/* First characters of haystack and needle are the same now. Both are
-	 * guaranteed to be at least one character long.  Now computes the sum
-	 * of characters values of needle together with the sum of the first
-	 * needle_len characters of haystack. */
-	for (hp = hay + 1U, np = needle + 1U, hsum = *hay, nsum = *hay, eqp = 1U;
-	     hp < eoh && np < eon;
-	     hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++);
-
-	/* HP now references the (NEEDLESIZE + 1)-th character. */
-	if (np < eon) {
-		/* haystack is smaller than needle, :O */
-		return NULL;
-	} else if (eqp) {
-		/* found a match */
-		return deconst(hay);
-	}
-
-	/* now loop through the rest of haystack,
-	 * updating the sum iteratively */
-	for (cand = hay; hp < eoh; hp++) {
-		hsum ^= *cand++;
-		hsum ^= *hp;
-
-		/* Since the sum of the characters is already known to be
-		 * equal at that point, it is enough to check just NEEDLESIZE - 1
-		 * characters for equality,
-		 * also CAND is by design < HP, so no need for range checks */
-		if (hsum == nsum && memcmp(cand, needle, needlesize - 1U) == 0) {
-			return deconst(cand);
-		}
-	}
-	return NULL;
-}
-
-static int
-strtoi_lim(const char *str, const char **ep, int llim, int ulim)
-{
-	int res = 0;
-	const char *sp;
-	/* we keep track of the number of digits via rulim */
-	int rulim;
-
-	for (sp = str, rulim = ulim > 10 ? ulim : 10;
-	     res * 10 <= ulim && rulim && *sp >= '0' && *sp <= '9';
-	     sp++, rulim /= 10) {
-		res *= 10;
-		res += *sp - '0';
-	}
-	if (sp == str) {
-		res = -1;
-	} else if (res < llim || res > ulim) {
-		res = -2;
-	}
-	*ep = (const char*)sp;
-	return res;
-}
-
-static time_t
-time_from_tm(struct tm *t)
-{
-#if HAVE__MKGMTIME
-        return _mkgmtime(t);
-#elif HAVE_TIMEGM
-        /* Use platform timegm() if available. */
-        return (timegm(t));
-#else
-        /* Else use direct calculation using POSIX assumptions. */
-        /* First, fix up tm_yday based on the year/month/day. */
-        if (mktime(t) == (time_t)-1)
-                return ((time_t)-1);
-        /* Then we can compute timegm() from first principles. */
-        return (t->tm_sec
-            + t->tm_min * 60
-            + t->tm_hour * 3600
-            + t->tm_yday * 86400
-            + (t->tm_year - 70) * 31536000
-            + ((t->tm_year - 69) / 4) * 86400
-            - ((t->tm_year - 1) / 100) * 86400
-            + ((t->tm_year + 299) / 400) * 86400);
-#endif
-}
-
-static time_t
-xstrpisotime(const char *s, char **endptr)
-{
-/** like strptime() but strictly for ISO 8601 Zulu strings */
-	struct tm tm;
-	time_t res = (time_t)-1;
-
-	/* make sure tm is clean */
-	memset(&tm, 0, sizeof(tm));
-
-	/* as a courtesy to our callers, and since this is a non-standard
-	 * routine, we skip leading whitespace */
-	while (*s == ' ' || *s == '\t')
-		++s;
-
-	/* read year */
-	if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') {
-		goto out;
-	}
-	/* read month */
-	if ((tm.tm_mon = strtoi_lim(s, &s, 1, 12)) < 0 || *s++ != '-') {
-		goto out;
-	}
-	/* read day-of-month */
-	if ((tm.tm_mday = strtoi_lim(s, &s, 1, 31)) < 0 || *s++ != 'T') {
-		goto out;
-	}
-	/* read hour */
-	if ((tm.tm_hour = strtoi_lim(s, &s, 0, 23)) < 0 || *s++ != ':') {
-		goto out;
-	}
-	/* read minute */
-	if ((tm.tm_min = strtoi_lim(s, &s, 0, 59)) < 0 || *s++ != ':') {
-		goto out;
-	}
-	/* read second */
-	if ((tm.tm_sec = strtoi_lim(s, &s, 0, 60)) < 0 || *s++ != 'Z') {
-		goto out;
-	}
-
-	/* massage TM to fulfill some of POSIX' constraints */
-	tm.tm_year -= 1900;
-	tm.tm_mon--;
-
-	/* now convert our custom tm struct to a unix stamp using UTC */
-	res = time_from_tm(&tm);
-
-out:
-	if (endptr != NULL) {
-		*endptr = deconst(s);
-	}
-	return res;
-}
-
-static unsigned int
-_warc_rdver(const char *buf, size_t bsz)
-{
-	static const char magic[] = "WARC/";
-	const char *c;
-	unsigned int ver = 0U;
-	unsigned int end = 0U;
-
-	if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
-		/* buffer too small or invalid magic */
-		return ver;
-	}
-	/* looks good so far, read the version number for a laugh */
-	buf += sizeof(magic) - 1U;
-
-	if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') &&
-	    isdigit((unsigned char)buf[2U])) {
-		/* we support a maximum of 2 digits in the minor version */
-		if (isdigit((unsigned char)buf[3U]))
-			end = 1U;
-		/* set up major version */
-		ver = (buf[0U] - '0') * 10000U;
-		/* set up minor version */
-		if (end == 1U) {
-			ver += (buf[2U] - '0') * 1000U;
-			ver += (buf[3U] - '0') * 100U;
-		} else
-			ver += (buf[2U] - '0') * 100U;
-		/*
-		 * WARC below version 0.12 has a space-separated header
-		 * WARC 0.12 and above terminates the version with a CRLF
-		 */
-		c = buf + 3U + end;
-		if (ver >= 1200U) {
-			if (memcmp(c, "\r\n", 2U) != 0)
-				ver = 0U;
-		} else {
-			/* ver < 1200U */
-			if (*c != ' ' && *c != '\t')
-				ver = 0U;
-		}
-	}
-	return ver;
-}
-
-static unsigned int
-_warc_rdtyp(const char *buf, size_t bsz)
-{
-	static const char _key[] = "\r\nWARC-Type:";
-	const char *val, *eol;
-
-	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
-		/* no bother */
-		return WT_NONE;
-	}
-	val += sizeof(_key) - 1U;
-	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
-		/* no end of line */
-		return WT_NONE;
-	}
-
-	/* overread whitespace */
-	while (val < eol && (*val == ' ' || *val == '\t'))
-		++val;
-
-	if (val + 8U == eol) {
-		if (memcmp(val, "resource", 8U) == 0)
-			return WT_RSRC;
-		else if (memcmp(val, "response", 8U) == 0)
-			return WT_RSP;
-	}
-	return WT_NONE;
-}
-
-static warc_string_t
-_warc_rduri(const char *buf, size_t bsz)
-{
-	static const char _key[] = "\r\nWARC-Target-URI:";
-	const char *val, *uri, *eol, *p;
-	warc_string_t res = {0U, NULL};
-
-	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
-		/* no bother */
-		return res;
-	}
-	/* overread whitespace */
-	val += sizeof(_key) - 1U;
-	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
-		/* no end of line */
-		return res;
-	}
-
-	while (val < eol && (*val == ' ' || *val == '\t'))
-		++val;
-
-	/* overread URL designators */
-	if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
-		/* not touching that! */
-		return res;
-	}
-
-	/* spaces inside uri are not allowed, CRLF should follow */
-	for (p = val; p < eol; p++) {
-		if (isspace((unsigned char)*p))
-			return res;
-	}
-
-	/* there must be at least space for ftp */
-	if (uri < (val + 3U))
-		return res;
-
-	/* move uri to point to after :// */
-	uri += 3U;
-
-	/* now then, inspect the URI */
-	if (memcmp(val, "file", 4U) == 0) {
-		/* perfect, nothing left to do here */
-
-	} else if (memcmp(val, "http", 4U) == 0 ||
-		   memcmp(val, "ftp", 3U) == 0) {
-		/* overread domain, and the first / */
-		while (uri < eol && *uri++ != '/');
-	} else {
-		/* not sure what to do? best to bugger off */
-		return res;
-	}
-	res.str = uri;
-	res.len = eol - uri;
-	return res;
-}
-
-static ssize_t
-_warc_rdlen(const char *buf, size_t bsz)
-{
-	static const char _key[] = "\r\nContent-Length:";
-	const char *val, *eol;
-	char *on = NULL;
-	long int len;
-
-	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
-		/* no bother */
-		return -1;
-	}
-	val += sizeof(_key) - 1U;
-	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
-		/* no end of line */
-		return -1;
-	}
-
-	/* skip leading whitespace */
-	while (val < eol && (*val == ' ' || *val == '\t'))
-		val++;
-	/* there must be at least one digit */
-	if (!isdigit((unsigned char)*val))
-		return -1;
-	errno = 0;
-	len = strtol(val, &on, 10);
-	if (errno != 0 || on != eol) {
-		/* line must end here */
-		return -1;
-	}
-
-	return (size_t)len;
-}
-
-static time_t
-_warc_rdrtm(const char *buf, size_t bsz)
-{
-	static const char _key[] = "\r\nWARC-Date:";
-	const char *val, *eol;
-	char *on = NULL;
-	time_t res;
-
-	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
-		/* no bother */
-		return (time_t)-1;
-	}
-	val += sizeof(_key) - 1U;
-	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
-		/* no end of line */
-		return -1;
-	}
-
-	/* xstrpisotime() kindly overreads whitespace for us, so use that */
-	res = xstrpisotime(val, &on);
-	if (on != eol) {
-		/* line must end here */
-		return -1;
-	}
-	return res;
-}
-
-static time_t
-_warc_rdmtm(const char *buf, size_t bsz)
-{
-	static const char _key[] = "\r\nLast-Modified:";
-	const char *val, *eol;
-	char *on = NULL;
-	time_t res;
-
-	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
-		/* no bother */
-		return (time_t)-1;
-	}
-	val += sizeof(_key) - 1U;
-	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
-		/* no end of line */
-		return -1;
-	}
-
-	/* xstrpisotime() kindly overreads whitespace for us, so use that */
-	res = xstrpisotime(val, &on);
-	if (on != eol) {
-		/* line must end here */
-		return -1;
-	}
-	return res;
-}
-
-static const char*
-_warc_find_eoh(const char *buf, size_t bsz)
-{
-	static const char _marker[] = "\r\n\r\n";
-	const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
-
-	if (hit != NULL) {
-		hit += sizeof(_marker) - 1U;
-	}
-	return hit;
-}
-
-static const char*
-_warc_find_eol(const char *buf, size_t bsz)
-{
-	static const char _marker[] = "\r\n";
-	const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
-
-	return hit;
-}
-/* archive_read_support_format_warc.c ends here */
diff --git a/c/archive_read_support_format_xar.c b/c/archive_read_support_format_xar.c
deleted file mode 100644
--- a/c/archive_read_support_format_xar.c
+++ /dev/null
@@ -1,3332 +0,0 @@
-/*-
- * Copyright (c) 2009 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_LIBXML_XMLREADER_H
-#include <libxml/xmlreader.h>
-#elif HAVE_BSDXML_H
-#include <bsdxml.h>
-#elif HAVE_EXPAT_H
-#include <expat.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#if HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_digest_private.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-
-#if (!defined(HAVE_LIBXML_XMLREADER_H) && \
-     !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\
-	!defined(HAVE_ZLIB_H) || \
-	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
-/*
- * xar needs several external libraries.
- *   o libxml2 or expat --- XML parser
- *   o openssl or MD5/SHA1 hash function
- *   o zlib
- *   o bzlib2 (option)
- *   o liblzma (option)
- */
-int
-archive_read_support_format_xar(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_xar");
-
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Xar not supported on this platform");
-	return (ARCHIVE_WARN);
-}
-
-#else	/* Support xar format */
-
-/* #define DEBUG 1 */
-/* #define DEBUG_PRINT_TOC 1 */
-#if DEBUG_PRINT_TOC
-#define PRINT_TOC(d, outbytes)	do {				\
-	unsigned char *x = (unsigned char *)(uintptr_t)d;	\
-	unsigned char c = x[outbytes-1];			\
-	x[outbytes - 1] = 0;					\
-	fprintf(stderr, "%s", x);				\
-	fprintf(stderr, "%c", c);				\
-	x[outbytes - 1] = c;					\
-} while (0)
-#else
-#define PRINT_TOC(d, outbytes)
-#endif
-
-#define HEADER_MAGIC	0x78617221
-#define HEADER_SIZE	28
-#define HEADER_VERSION	1
-#define CKSUM_NONE	0
-#define CKSUM_SHA1	1
-#define CKSUM_MD5	2
-
-#define MD5_SIZE	16
-#define SHA1_SIZE	20
-#define MAX_SUM_SIZE	20
-
-enum enctype {
-	NONE,
-	GZIP,
-	BZIP2,
-	LZMA,
-	XZ,
-};
-
-struct chksumval {
-	int			 alg;
-	size_t			 len;
-	unsigned char		 val[MAX_SUM_SIZE];
-};
-
-struct chksumwork {
-	int			 alg;
-#ifdef ARCHIVE_HAS_MD5
-	archive_md5_ctx		 md5ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	archive_sha1_ctx	 sha1ctx;
-#endif
-};
-
-struct xattr {
-	struct xattr		*next;
-	struct archive_string	 name;
-	uint64_t		 id;
-	uint64_t		 length;
-	uint64_t		 offset;
-	uint64_t		 size;
-	enum enctype		 encoding;
-	struct chksumval	 a_sum;
-	struct chksumval	 e_sum;
-	struct archive_string	 fstype;
-};
-
-struct xar_file {
-	struct xar_file		*next;
-	struct xar_file		*hdnext;
-	struct xar_file		*parent;
-	int			 subdirs;
-
-	unsigned int		 has;
-#define HAS_DATA		0x00001
-#define HAS_PATHNAME		0x00002
-#define HAS_SYMLINK		0x00004
-#define HAS_TIME		0x00008
-#define HAS_UID			0x00010
-#define HAS_GID			0x00020
-#define HAS_MODE		0x00040
-#define HAS_TYPE		0x00080
-#define HAS_DEV			0x00100
-#define HAS_DEVMAJOR		0x00200
-#define HAS_DEVMINOR		0x00400
-#define HAS_INO			0x00800
-#define HAS_FFLAGS		0x01000
-#define HAS_XATTR		0x02000
-#define HAS_ACL			0x04000
-#define HAS_CTIME		0x08000
-#define HAS_MTIME		0x10000
-#define HAS_ATIME		0x20000
-
-	uint64_t		 id;
-	uint64_t		 length;
-	uint64_t		 offset;
-	uint64_t		 size;
-	enum enctype		 encoding;
-	struct chksumval	 a_sum;
-	struct chksumval	 e_sum;
-	struct archive_string	 pathname;
-	struct archive_string	 symlink;
-	time_t			 ctime;
-	time_t			 mtime;
-	time_t			 atime;
-	struct archive_string	 uname;
-	int64_t			 uid;
-	struct archive_string	 gname;
-	int64_t			 gid;
-	mode_t			 mode;
-	dev_t			 dev;
-	dev_t			 devmajor;
-	dev_t			 devminor;
-	int64_t			 ino64;
-	struct archive_string	 fflags_text;
-	unsigned int		 link;
-	unsigned int		 nlink;
-	struct archive_string	 hardlink;
-	struct xattr		*xattr_list;
-};
-
-struct hdlink {
-	struct hdlink		 *next;
-
-	unsigned int		 id;
-	int			 cnt;
-	struct xar_file		 *files;
-};
-
-struct heap_queue {
-	struct xar_file		**files;
-	int			 allocated;
-	int			 used;
-};
-
-enum xmlstatus {
-	INIT,
-	XAR,
-	TOC,
-	TOC_CREATION_TIME,
-	TOC_CHECKSUM,
-	TOC_CHECKSUM_OFFSET,
-	TOC_CHECKSUM_SIZE,
-	TOC_FILE,
-	FILE_DATA,
-	FILE_DATA_LENGTH,
-	FILE_DATA_OFFSET,
-	FILE_DATA_SIZE,
-	FILE_DATA_ENCODING,
-	FILE_DATA_A_CHECKSUM,
-	FILE_DATA_E_CHECKSUM,
-	FILE_DATA_CONTENT,
-	FILE_EA,
-	FILE_EA_LENGTH,
-	FILE_EA_OFFSET,
-	FILE_EA_SIZE,
-	FILE_EA_ENCODING,
-	FILE_EA_A_CHECKSUM,
-	FILE_EA_E_CHECKSUM,
-	FILE_EA_NAME,
-	FILE_EA_FSTYPE,
-	FILE_CTIME,
-	FILE_MTIME,
-	FILE_ATIME,
-	FILE_GROUP,
-	FILE_GID,
-	FILE_USER,
-	FILE_UID,
-	FILE_MODE,
-	FILE_DEVICE,
-	FILE_DEVICE_MAJOR,
-	FILE_DEVICE_MINOR,
-	FILE_DEVICENO,
-	FILE_INODE,
-	FILE_LINK,
-	FILE_TYPE,
-	FILE_NAME,
-	FILE_ACL,
-	FILE_ACL_DEFAULT,
-	FILE_ACL_ACCESS,
-	FILE_ACL_APPLEEXTENDED,
-	/* BSD file flags. */
-	FILE_FLAGS,
-	FILE_FLAGS_USER_NODUMP,
-	FILE_FLAGS_USER_IMMUTABLE,
-	FILE_FLAGS_USER_APPEND,
-	FILE_FLAGS_USER_OPAQUE,
-	FILE_FLAGS_USER_NOUNLINK,
-	FILE_FLAGS_SYS_ARCHIVED,
-	FILE_FLAGS_SYS_IMMUTABLE,
-	FILE_FLAGS_SYS_APPEND,
-	FILE_FLAGS_SYS_NOUNLINK,
-	FILE_FLAGS_SYS_SNAPSHOT,
-	/* Linux file flags. */
-	FILE_EXT2,
-	FILE_EXT2_SecureDeletion,
-	FILE_EXT2_Undelete,
-	FILE_EXT2_Compress,
-	FILE_EXT2_Synchronous,
-	FILE_EXT2_Immutable,
-	FILE_EXT2_AppendOnly,
-	FILE_EXT2_NoDump,
-	FILE_EXT2_NoAtime,
-	FILE_EXT2_CompDirty,
-	FILE_EXT2_CompBlock,
-	FILE_EXT2_NoCompBlock,
-	FILE_EXT2_CompError,
-	FILE_EXT2_BTree,
-	FILE_EXT2_HashIndexed,
-	FILE_EXT2_iMagic,
-	FILE_EXT2_Journaled,
-	FILE_EXT2_NoTail,
-	FILE_EXT2_DirSync,
-	FILE_EXT2_TopDir,
-	FILE_EXT2_Reserved,
-	UNKNOWN,
-};
-
-struct unknown_tag {
-	struct unknown_tag	*next;
-	struct archive_string	 name;
-};
-
-struct xar {
-	uint64_t		 offset; /* Current position in the file. */
-	int64_t			 total;
-	uint64_t		 h_base;
-	int			 end_of_file;
-#define OUTBUFF_SIZE	(1024 * 64)
-	unsigned char		*outbuff;
-
-	enum xmlstatus		 xmlsts;
-	enum xmlstatus		 xmlsts_unknown;
-	struct unknown_tag	*unknowntags;
-	int			 base64text;
-
-	/*
-	 * TOC
-	 */
-	uint64_t		 toc_remaining;
-	uint64_t		 toc_total;
-	uint64_t		 toc_chksum_offset;
-	uint64_t		 toc_chksum_size;
-
-	/*
-	 * For Decoding data.
-	 */
-	enum enctype 		 rd_encoding;
-	z_stream		 stream;
-	int			 stream_valid;
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	bz_stream		 bzstream;
-	int			 bzstream_valid;
-#endif
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	lzma_stream		 lzstream;
-	int			 lzstream_valid;
-#endif
-	/*
-	 * For Checksum data.
-	 */
-	struct chksumwork	 a_sumwrk;
-	struct chksumwork	 e_sumwrk;
-
-	struct xar_file		*file;	/* current reading file. */
-	struct xattr		*xattr; /* current reading extended attribute. */
-	struct heap_queue	 file_queue;
-	struct xar_file		*hdlink_orgs;
-	struct hdlink		*hdlink_list;
-
-	int	 		 entry_init;
-	uint64_t		 entry_total;
-	uint64_t		 entry_remaining;
-	size_t			 entry_unconsumed;
-	uint64_t		 entry_size;
-	enum enctype 		 entry_encoding;
-	struct chksumval	 entry_a_sum;
-	struct chksumval	 entry_e_sum;
-
-	struct archive_string_conv *sconv;
-};
-
-struct xmlattr {
-	struct xmlattr	*next;
-	char		*name;
-	char		*value;
-};
-
-struct xmlattr_list {
-	struct xmlattr	*first;
-	struct xmlattr	**last;
-};
-
-static int	xar_bid(struct archive_read *, int);
-static int	xar_read_header(struct archive_read *,
-		    struct archive_entry *);
-static int	xar_read_data(struct archive_read *,
-		    const void **, size_t *, int64_t *);
-static int	xar_read_data_skip(struct archive_read *);
-static int	xar_cleanup(struct archive_read *);
-static int	move_reading_point(struct archive_read *, uint64_t);
-static int	rd_contents_init(struct archive_read *,
-		    enum enctype, int, int);
-static int	rd_contents(struct archive_read *, const void **,
-		    size_t *, size_t *, uint64_t);
-static uint64_t	atol10(const char *, size_t);
-static int64_t	atol8(const char *, size_t);
-static size_t	atohex(unsigned char *, size_t, const char *, size_t);
-static time_t	parse_time(const char *p, size_t n);
-static int	heap_add_entry(struct archive_read *a,
-    struct heap_queue *, struct xar_file *);
-static struct xar_file *heap_get_entry(struct heap_queue *);
-static int	add_link(struct archive_read *,
-    struct xar *, struct xar_file *);
-static void	checksum_init(struct archive_read *, int, int);
-static void	checksum_update(struct archive_read *, const void *,
-		    size_t, const void *, size_t);
-static int	checksum_final(struct archive_read *, const void *,
-		    size_t, const void *, size_t);
-static void	checksum_cleanup(struct archive_read *);
-static int	decompression_init(struct archive_read *, enum enctype);
-static int	decompress(struct archive_read *, const void **,
-		    size_t *, const void *, size_t *);
-static int	decompression_cleanup(struct archive_read *);
-static void	xmlattr_cleanup(struct xmlattr_list *);
-static int	file_new(struct archive_read *,
-    struct xar *, struct xmlattr_list *);
-static void	file_free(struct xar_file *);
-static int	xattr_new(struct archive_read *,
-    struct xar *, struct xmlattr_list *);
-static void	xattr_free(struct xattr *);
-static int	getencoding(struct xmlattr_list *);
-static int	getsumalgorithm(struct xmlattr_list *);
-static int	unknowntag_start(struct archive_read *,
-    struct xar *, const char *);
-static void	unknowntag_end(struct xar *, const char *);
-static int	xml_start(struct archive_read *,
-    const char *, struct xmlattr_list *);
-static void	xml_end(void *, const char *);
-static void	xml_data(void *, const char *, int);
-static int	xml_parse_file_flags(struct xar *, const char *);
-static int	xml_parse_file_ext2(struct xar *, const char *);
-#if defined(HAVE_LIBXML_XMLREADER_H)
-static int	xml2_xmlattr_setup(struct archive_read *,
-    struct xmlattr_list *, xmlTextReaderPtr);
-static int	xml2_read_cb(void *, char *, int);
-static int	xml2_close_cb(void *);
-static void	xml2_error_hdr(void *, const char *, xmlParserSeverities,
-		    xmlTextReaderLocatorPtr);
-static int	xml2_read_toc(struct archive_read *);
-#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
-struct expat_userData {
-	int state;
-	struct archive_read *archive;
-};
-static int	expat_xmlattr_setup(struct archive_read *,
-    struct xmlattr_list *, const XML_Char **);
-static void	expat_start_cb(void *, const XML_Char *, const XML_Char **);
-static void	expat_end_cb(void *, const XML_Char *);
-static void	expat_data_cb(void *, const XML_Char *, int);
-static int	expat_read_toc(struct archive_read *);
-#endif
-
-int
-archive_read_support_format_xar(struct archive *_a)
-{
-	struct xar *xar;
-	struct archive_read *a = (struct archive_read *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_xar");
-
-	xar = (struct xar *)calloc(1, sizeof(*xar));
-	if (xar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate xar data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* initialize xar->file_queue */
-	xar->file_queue.allocated = 0;
-	xar->file_queue.used = 0;
-	xar->file_queue.files = NULL;
-
-	r = __archive_read_register_format(a,
-	    xar,
-	    "xar",
-	    xar_bid,
-	    NULL,
-	    xar_read_header,
-	    xar_read_data,
-	    xar_read_data_skip,
-	    NULL,
-	    xar_cleanup,
-	    NULL,
-	    NULL);
-	if (r != ARCHIVE_OK)
-		free(xar);
-	return (r);
-}
-
-static int
-xar_bid(struct archive_read *a, int best_bid)
-{
-	const unsigned char *b;
-	int bid;
-
-	(void)best_bid; /* UNUSED */
-
-	b = __archive_read_ahead(a, HEADER_SIZE, NULL);
-	if (b == NULL)
-		return (-1);
-
-	bid = 0;
-	/*
-	 * Verify magic code
-	 */
-	if (archive_be32dec(b) != HEADER_MAGIC)
-		return (0);
-	bid += 32;
-	/*
-	 * Verify header size
-	 */
-	if (archive_be16dec(b+4) != HEADER_SIZE)
-		return (0);
-	bid += 16;
-	/*
-	 * Verify header version
-	 */
-	if (archive_be16dec(b+6) != HEADER_VERSION)
-		return (0);
-	bid += 16;
-	/*
-	 * Verify type of checksum
-	 */
-	switch (archive_be32dec(b+24)) {
-	case CKSUM_NONE:
-	case CKSUM_SHA1:
-	case CKSUM_MD5:
-		bid += 32;
-		break;
-	default:
-		return (0);
-	}
-
-	return (bid);
-}
-
-static int
-read_toc(struct archive_read *a)
-{
-	struct xar *xar;
-	struct xar_file *file;
-	const unsigned char *b;
-	uint64_t toc_compressed_size;
-	uint64_t toc_uncompressed_size;
-	uint32_t toc_chksum_alg;
-	ssize_t bytes;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-
-	/*
-	 * Read xar header.
-	 */
-	b = __archive_read_ahead(a, HEADER_SIZE, &bytes);
-	if (bytes < 0)
-		return ((int)bytes);
-	if (bytes < HEADER_SIZE) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated archive header");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (archive_be32dec(b) != HEADER_MAGIC) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid header magic");
-		return (ARCHIVE_FATAL);
-	}
-	if (archive_be16dec(b+6) != HEADER_VERSION) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported header version(%d)",
-		    archive_be16dec(b+6));
-		return (ARCHIVE_FATAL);
-	}
-	toc_compressed_size = archive_be64dec(b+8);
-	xar->toc_remaining = toc_compressed_size;
-	toc_uncompressed_size = archive_be64dec(b+16);
-	toc_chksum_alg = archive_be32dec(b+24);
-	__archive_read_consume(a, HEADER_SIZE);
-	xar->offset += HEADER_SIZE;
-	xar->toc_total = 0;
-
-	/*
-	 * Read TOC(Table of Contents).
-	 */
-	/* Initialize reading contents. */
-	r = move_reading_point(a, HEADER_SIZE);
-	if (r != ARCHIVE_OK)
-		return (r);
-	r = rd_contents_init(a, GZIP, toc_chksum_alg, CKSUM_NONE);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-#ifdef HAVE_LIBXML_XMLREADER_H
-	r = xml2_read_toc(a);
-#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
-	r = expat_read_toc(a);
-#endif
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	/* Set 'The HEAP' base. */
-	xar->h_base = xar->offset;
-	if (xar->toc_total != toc_uncompressed_size) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "TOC uncompressed size error");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Checksum TOC
-	 */
-	if (toc_chksum_alg != CKSUM_NONE) {
-		r = move_reading_point(a, xar->toc_chksum_offset);
-		if (r != ARCHIVE_OK)
-			return (r);
-		b = __archive_read_ahead(a,
-			(size_t)xar->toc_chksum_size, &bytes);
-		if (bytes < 0)
-			return ((int)bytes);
-		if ((uint64_t)bytes < xar->toc_chksum_size) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated archive file");
-			return (ARCHIVE_FATAL);
-		}
-		r = checksum_final(a, b,
-			(size_t)xar->toc_chksum_size, NULL, 0);
-		__archive_read_consume(a, xar->toc_chksum_size);
-		xar->offset += xar->toc_chksum_size;
-		if (r != ARCHIVE_OK)
-#ifndef DONT_FAIL_ON_CRC_ERROR
-			return (ARCHIVE_FATAL);
-#endif
-	}
-
-	/*
-	 * Connect hardlinked files.
-	 */
-	for (file = xar->hdlink_orgs; file != NULL; file = file->hdnext) {
-		struct hdlink **hdlink;
-
-		for (hdlink = &(xar->hdlink_list); *hdlink != NULL;
-		    hdlink = &((*hdlink)->next)) {
-			if ((*hdlink)->id == file->id) {
-				struct hdlink *hltmp;
-				struct xar_file *f2;
-				int nlink = (*hdlink)->cnt + 1;
-
-				file->nlink = nlink;
-				for (f2 = (*hdlink)->files; f2 != NULL;
-				    f2 = f2->hdnext) {
-					f2->nlink = nlink;
-					archive_string_copy(
-					    &(f2->hardlink), &(file->pathname));
-				}
-				/* Remove resolved files from hdlist_list. */
-				hltmp = *hdlink;
-				*hdlink = hltmp->next;
-				free(hltmp);
-				break;
-			}
-		}
-	}
-	a->archive.archive_format = ARCHIVE_FORMAT_XAR;
-	a->archive.archive_format_name = "xar";
-
-	return (ARCHIVE_OK);
-}
-
-static int
-xar_read_header(struct archive_read *a, struct archive_entry *entry)
-{
-	struct xar *xar;
-	struct xar_file *file;
-	struct xattr *xattr;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	r = ARCHIVE_OK;
-
-	if (xar->offset == 0) {
-		/* Create a character conversion object. */
-		if (xar->sconv == NULL) {
-			xar->sconv = archive_string_conversion_from_charset(
-			    &(a->archive), "UTF-8", 1);
-			if (xar->sconv == NULL)
-				return (ARCHIVE_FATAL);
-		}
-
-		/* Read TOC. */
-		r = read_toc(a);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	for (;;) {
-		file = xar->file = heap_get_entry(&(xar->file_queue));
-		if (file == NULL) {
-			xar->end_of_file = 1;
-			return (ARCHIVE_EOF);
-		}
-		if ((file->mode & AE_IFMT) != AE_IFDIR)
-			break;
-		if (file->has != (HAS_PATHNAME | HAS_TYPE))
-			break;
-		/*
-		 * If a file type is a directory and it does not have
-		 * any metadata, do not export.
-		 */
-		file_free(file);
-	}
-        if (file->has & HAS_ATIME) {
-          archive_entry_set_atime(entry, file->atime, 0);
-        }
-        if (file->has & HAS_CTIME) {
-          archive_entry_set_ctime(entry, file->ctime, 0);
-        }
-        if (file->has & HAS_MTIME) {
-          archive_entry_set_mtime(entry, file->mtime, 0);
-        }
-	archive_entry_set_gid(entry, file->gid);
-	if (file->gname.length > 0 &&
-	    archive_entry_copy_gname_l(entry, file->gname.s,
-		archive_strlen(&(file->gname)), xar->sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Gname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Gname cannot be converted from %s to current locale.",
-		    archive_string_conversion_charset_name(xar->sconv));
-		r = ARCHIVE_WARN;
-	}
-	archive_entry_set_uid(entry, file->uid);
-	if (file->uname.length > 0 &&
-	    archive_entry_copy_uname_l(entry, file->uname.s,
-		archive_strlen(&(file->uname)), xar->sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Uname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Uname cannot be converted from %s to current locale.",
-		    archive_string_conversion_charset_name(xar->sconv));
-		r = ARCHIVE_WARN;
-	}
-	archive_entry_set_mode(entry, file->mode);
-	if (archive_entry_copy_pathname_l(entry, file->pathname.s,
-	    archive_strlen(&(file->pathname)), xar->sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Pathname cannot be converted from %s to current locale.",
-		    archive_string_conversion_charset_name(xar->sconv));
-		r = ARCHIVE_WARN;
-	}
-
-
-	if (file->symlink.length > 0 &&
-	    archive_entry_copy_symlink_l(entry, file->symlink.s,
-		archive_strlen(&(file->symlink)), xar->sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Linkname cannot be converted from %s to current locale.",
-		    archive_string_conversion_charset_name(xar->sconv));
-		r = ARCHIVE_WARN;
-	}
-	/* Set proper nlink. */
-	if ((file->mode & AE_IFMT) == AE_IFDIR)
-		archive_entry_set_nlink(entry, file->subdirs + 2);
-	else
-		archive_entry_set_nlink(entry, file->nlink);
-	archive_entry_set_size(entry, file->size);
-	if (archive_strlen(&(file->hardlink)) > 0)
-		archive_entry_set_hardlink(entry, file->hardlink.s);
-	archive_entry_set_ino64(entry, file->ino64);
-	if (file->has & HAS_DEV)
-		archive_entry_set_dev(entry, file->dev);
-	if (file->has & HAS_DEVMAJOR)
-		archive_entry_set_devmajor(entry, file->devmajor);
-	if (file->has & HAS_DEVMINOR)
-		archive_entry_set_devminor(entry, file->devminor);
-	if (archive_strlen(&(file->fflags_text)) > 0)
-		archive_entry_copy_fflags_text(entry, file->fflags_text.s);
-
-	xar->entry_init = 1;
-	xar->entry_total = 0;
-	xar->entry_remaining = file->length;
-	xar->entry_size = file->size;
-	xar->entry_encoding = file->encoding;
-	xar->entry_a_sum = file->a_sum;
-	xar->entry_e_sum = file->e_sum;
-	/*
-	 * Read extended attributes.
-	 */
-	xattr = file->xattr_list;
-	while (xattr != NULL) {
-		const void *d;
-		size_t outbytes = 0;
-		size_t used = 0;
-
-		r = move_reading_point(a, xattr->offset);
-		if (r != ARCHIVE_OK)
-			break;
-		r = rd_contents_init(a, xattr->encoding,
-		    xattr->a_sum.alg, xattr->e_sum.alg);
-		if (r != ARCHIVE_OK)
-			break;
-		d = NULL;
-		r = rd_contents(a, &d, &outbytes, &used, xattr->length);
-		if (r != ARCHIVE_OK)
-			break;
-		if (outbytes != xattr->size) {
-			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-			    "Decompressed size error");
-			r = ARCHIVE_FATAL;
-			break;
-		}
-		r = checksum_final(a,
-		    xattr->a_sum.val, xattr->a_sum.len,
-		    xattr->e_sum.val, xattr->e_sum.len);
-		if (r != ARCHIVE_OK) {
-#ifndef DONT_FAIL_ON_CRC_ERROR
-			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-			    "Xattr checksum error");
-			r = ARCHIVE_WARN;
-			break;
-#endif
-		}
-		if (xattr->name.s == NULL) {
-			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-			    "Xattr name error");
-			r = ARCHIVE_WARN;
-			break;
-		}
-		archive_entry_xattr_add_entry(entry,
-		    xattr->name.s, d, outbytes);
-		xattr = xattr->next;
-	}
-	if (r != ARCHIVE_OK) {
-		file_free(file);
-		return (r);
-	}
-
-	if (xar->entry_remaining > 0)
-		/* Move reading point to the beginning of current
-		 * file contents. */
-		r = move_reading_point(a, file->offset);
-	else
-		r = ARCHIVE_OK;
-
-	file_free(file);
-	return (r);
-}
-
-static int
-xar_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	struct xar *xar;
-	size_t used = 0;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-
-	if (xar->entry_unconsumed) {
-		__archive_read_consume(a, xar->entry_unconsumed);
-		xar->entry_unconsumed = 0;
-	}
-
-	if (xar->end_of_file || xar->entry_remaining <= 0) {
-		r = ARCHIVE_EOF;
-		goto abort_read_data;
-	}
-
-	if (xar->entry_init) {
-		r = rd_contents_init(a, xar->entry_encoding,
-		    xar->entry_a_sum.alg, xar->entry_e_sum.alg);
-		if (r != ARCHIVE_OK) {
-			xar->entry_remaining = 0;
-			return (r);
-		}
-		xar->entry_init = 0;
-	}
-
-	*buff = NULL;
-	r = rd_contents(a, buff, size, &used, xar->entry_remaining);
-	if (r != ARCHIVE_OK)
-		goto abort_read_data;
-
-	*offset = xar->entry_total;
-	xar->entry_total += *size;
-	xar->total += *size;
-	xar->offset += used;
-	xar->entry_remaining -= used;
-	xar->entry_unconsumed = used;
-
-	if (xar->entry_remaining == 0) {
-		if (xar->entry_total != xar->entry_size) {
-			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-			    "Decompressed size error");
-			r = ARCHIVE_FATAL;
-			goto abort_read_data;
-		}
-		r = checksum_final(a,
-		    xar->entry_a_sum.val, xar->entry_a_sum.len,
-		    xar->entry_e_sum.val, xar->entry_e_sum.len);
-		if (r != ARCHIVE_OK)
-			goto abort_read_data;
-	}
-
-	return (ARCHIVE_OK);
-abort_read_data:
-	*buff = NULL;
-	*size = 0;
-	*offset = xar->total;
-	return (r);
-}
-
-static int
-xar_read_data_skip(struct archive_read *a)
-{
-	struct xar *xar;
-	int64_t bytes_skipped;
-
-	xar = (struct xar *)(a->format->data);
-	if (xar->end_of_file)
-		return (ARCHIVE_EOF);
-	bytes_skipped = __archive_read_consume(a, xar->entry_remaining +
-		xar->entry_unconsumed);
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-	xar->offset += bytes_skipped;
-	xar->entry_unconsumed = 0;
-	return (ARCHIVE_OK);
-}
-
-static int
-xar_cleanup(struct archive_read *a)
-{
-	struct xar *xar;
-	struct hdlink *hdlink;
-	int i;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	checksum_cleanup(a);
-	r = decompression_cleanup(a);
-	hdlink = xar->hdlink_list;
-	while (hdlink != NULL) {
-		struct hdlink *next = hdlink->next;
-
-		free(hdlink);
-		hdlink = next;
-	}
-	for (i = 0; i < xar->file_queue.used; i++)
-		file_free(xar->file_queue.files[i]);
-	free(xar->file_queue.files);
-	while (xar->unknowntags != NULL) {
-		struct unknown_tag *tag;
-
-		tag = xar->unknowntags;
-		xar->unknowntags = tag->next;
-		archive_string_free(&(tag->name));
-		free(tag);
-	}
-	free(xar->outbuff);
-	free(xar);
-	a->format->data = NULL;
-	return (r);
-}
-
-static int
-move_reading_point(struct archive_read *a, uint64_t offset)
-{
-	struct xar *xar;
-
-	xar = (struct xar *)(a->format->data);
-	if (xar->offset - xar->h_base != offset) {
-		/* Seek forward to the start of file contents. */
-		int64_t step;
-
-		step = offset - (xar->offset - xar->h_base);
-		if (step > 0) {
-			step = __archive_read_consume(a, step);
-			if (step < 0)
-				return ((int)step);
-			xar->offset += step;
-		} else {
-			int64_t pos = __archive_read_seek(a, xar->h_base + offset, SEEK_SET);
-			if (pos == ARCHIVE_FAILED) {
-				archive_set_error(&(a->archive),
-				    ARCHIVE_ERRNO_MISC,
-				    "Cannot seek.");
-				return (ARCHIVE_FAILED);
-			}
-			xar->offset = pos;
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-rd_contents_init(struct archive_read *a, enum enctype encoding,
-    int a_sum_alg, int e_sum_alg)
-{
-	int r;
-
-	/* Init decompress library. */
-	if ((r = decompression_init(a, encoding)) != ARCHIVE_OK)
-		return (r);
-	/* Init checksum library. */
-	checksum_init(a, a_sum_alg, e_sum_alg);
-	return (ARCHIVE_OK);
-}
-
-static int
-rd_contents(struct archive_read *a, const void **buff, size_t *size,
-    size_t *used, uint64_t remaining)
-{
-	const unsigned char *b;
-	ssize_t bytes;
-
-	/* Get whatever bytes are immediately available. */
-	b = __archive_read_ahead(a, 1, &bytes);
-	if (bytes < 0)
-		return ((int)bytes);
-	if (bytes == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Truncated archive file");
-		return (ARCHIVE_FATAL);
-	}
-	if ((uint64_t)bytes > remaining)
-		bytes = (ssize_t)remaining;
-
-	/*
-	 * Decompress contents of file.
-	 */
-	*used = bytes;
-	if (decompress(a, buff, size, b, used) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/*
-	 * Update checksum of a compressed data and a extracted data.
-	 */
-	checksum_update(a, b, *used, *buff, *size);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
-
-static uint64_t
-atol10(const char *p, size_t char_cnt)
-{
-	uint64_t l;
-	int digit;
-
-	if (char_cnt == 0)
-		return (0);
-
-	l = 0;
-	digit = *p - '0';
-	while (digit >= 0 && digit < 10  && char_cnt-- > 0) {
-		l = (l * 10) + digit;
-		digit = *++p - '0';
-	}
-	return (l);
-}
-
-static int64_t
-atol8(const char *p, size_t char_cnt)
-{
-	int64_t l;
-	int digit;
-
-	if (char_cnt == 0)
-		return (0);
-
-	l = 0;
-	while (char_cnt-- > 0) {
-		if (*p >= '0' && *p <= '7')
-			digit = *p - '0';
-		else
-			break;
-		p++;
-		l <<= 3;
-		l |= digit;
-	}
-	return (l);
-}
-
-static size_t
-atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
-{
-	size_t fbsize = bsize;
-
-	while (bsize && psize > 1) {
-		unsigned char x;
-
-		if (p[0] >= 'a' && p[0] <= 'z')
-			x = (p[0] - 'a' + 0x0a) << 4;
-		else if (p[0] >= 'A' && p[0] <= 'Z')
-			x = (p[0] - 'A' + 0x0a) << 4;
-		else if (p[0] >= '0' && p[0] <= '9')
-			x = (p[0] - '0') << 4;
-		else
-			return (-1);
-		if (p[1] >= 'a' && p[1] <= 'z')
-			x |= p[1] - 'a' + 0x0a;
-		else if (p[1] >= 'A' && p[1] <= 'Z')
-			x |= p[1] - 'A' + 0x0a;
-		else if (p[1] >= '0' && p[1] <= '9')
-			x |= p[1] - '0';
-		else
-			return (-1);
-
-		*b++ = x;
-		bsize--;
-		p += 2;
-		psize -= 2;
-	}
-	return (fbsize - bsize);
-}
-
-static time_t
-time_from_tm(struct tm *t)
-{
-#if HAVE__MKGMTIME
-        return _mkgmtime(t);
-#elif HAVE_TIMEGM
-        /* Use platform timegm() if available. */
-        return (timegm(t));
-#else
-        /* Else use direct calculation using POSIX assumptions. */
-        /* First, fix up tm_yday based on the year/month/day. */
-        mktime(t);
-        /* Then we can compute timegm() from first principles. */
-        return (t->tm_sec
-            + t->tm_min * 60
-            + t->tm_hour * 3600
-            + t->tm_yday * 86400
-            + (t->tm_year - 70) * 31536000
-            + ((t->tm_year - 69) / 4) * 86400
-            - ((t->tm_year - 1) / 100) * 86400
-            + ((t->tm_year + 299) / 400) * 86400);
-#endif
-}
-
-static time_t
-parse_time(const char *p, size_t n)
-{
-	struct tm tm;
-	time_t t = 0;
-	int64_t data;
-
-	memset(&tm, 0, sizeof(tm));
-	if (n != 20)
-		return (t);
-	data = atol10(p, 4);
-	if (data < 1900)
-		return (t);
-	tm.tm_year = (int)data - 1900;
-	p += 4;
-	if (*p++ != '-')
-		return (t);
-	data = atol10(p, 2);
-	if (data < 1 || data > 12)
-		return (t);
-	tm.tm_mon = (int)data -1;
-	p += 2;
-	if (*p++ != '-')
-		return (t);
-	data = atol10(p, 2);
-	if (data < 1 || data > 31)
-		return (t);
-	tm.tm_mday = (int)data;
-	p += 2;
-	if (*p++ != 'T')
-		return (t);
-	data = atol10(p, 2);
-	if (data < 0 || data > 23)
-		return (t);
-	tm.tm_hour = (int)data;
-	p += 2;
-	if (*p++ != ':')
-		return (t);
-	data = atol10(p, 2);
-	if (data < 0 || data > 59)
-		return (t);
-	tm.tm_min = (int)data;
-	p += 2;
-	if (*p++ != ':')
-		return (t);
-	data = atol10(p, 2);
-	if (data < 0 || data > 60)
-		return (t);
-	tm.tm_sec = (int)data;
-#if 0
-	p += 2;
-	if (*p != 'Z')
-		return (t);
-#endif
-
-	t = time_from_tm(&tm);
-
-	return (t);
-}
-
-static int
-heap_add_entry(struct archive_read *a,
-    struct heap_queue *heap, struct xar_file *file)
-{
-	uint64_t file_id, parent_id;
-	int hole, parent;
-
-	/* Expand our pending files list as necessary. */
-	if (heap->used >= heap->allocated) {
-		struct xar_file **new_pending_files;
-		int new_size;
-
-		if (heap->allocated < 1024)
-			new_size = 1024;
-		else
-			new_size = heap->allocated * 2;
-		/* Overflow might keep us from growing the list. */
-		if (new_size <= heap->allocated) {
-			archive_set_error(&a->archive,
-			    ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		new_pending_files = (struct xar_file **)
-		    malloc(new_size * sizeof(new_pending_files[0]));
-		if (new_pending_files == NULL) {
-			archive_set_error(&a->archive,
-			    ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		if (heap->allocated) {
-			memcpy(new_pending_files, heap->files,
-			    heap->allocated * sizeof(new_pending_files[0]));
-			free(heap->files);
-		}
-		heap->files = new_pending_files;
-		heap->allocated = new_size;
-	}
-
-	file_id = file->id;
-
-	/*
-	 * Start with hole at end, walk it up tree to find insertion point.
-	 */
-	hole = heap->used++;
-	while (hole > 0) {
-		parent = (hole - 1)/2;
-		parent_id = heap->files[parent]->id;
-		if (file_id >= parent_id) {
-			heap->files[hole] = file;
-			return (ARCHIVE_OK);
-		}
-		/* Move parent into hole <==> move hole up tree. */
-		heap->files[hole] = heap->files[parent];
-		hole = parent;
-	}
-	heap->files[0] = file;
-
-	return (ARCHIVE_OK);
-}
-
-static struct xar_file *
-heap_get_entry(struct heap_queue *heap)
-{
-	uint64_t a_id, b_id, c_id;
-	int a, b, c;
-	struct xar_file *r, *tmp;
-
-	if (heap->used < 1)
-		return (NULL);
-
-	/*
-	 * The first file in the list is the earliest; we'll return this.
-	 */
-	r = heap->files[0];
-
-	/*
-	 * Move the last item in the heap to the root of the tree
-	 */
-	heap->files[0] = heap->files[--(heap->used)];
-
-	/*
-	 * Rebalance the heap.
-	 */
-	a = 0; /* Starting element and its heap key */
-	a_id = heap->files[a]->id;
-	for (;;) {
-		b = a + a + 1; /* First child */
-		if (b >= heap->used)
-			return (r);
-		b_id = heap->files[b]->id;
-		c = b + 1; /* Use second child if it is smaller. */
-		if (c < heap->used) {
-			c_id = heap->files[c]->id;
-			if (c_id < b_id) {
-				b = c;
-				b_id = c_id;
-			}
-		}
-		if (a_id <= b_id)
-			return (r);
-		tmp = heap->files[a];
-		heap->files[a] = heap->files[b];
-		heap->files[b] = tmp;
-		a = b;
-	}
-}
-
-static int
-add_link(struct archive_read *a, struct xar *xar, struct xar_file *file)
-{
-	struct hdlink *hdlink;
-
-	for (hdlink = xar->hdlink_list; hdlink != NULL; hdlink = hdlink->next) {
-		if (hdlink->id == file->link) {
-			file->hdnext = hdlink->files;
-			hdlink->cnt++;
-			hdlink->files = file;
-			return (ARCHIVE_OK);
-		}
-	}
-	hdlink = malloc(sizeof(*hdlink));
-	if (hdlink == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	file->hdnext = NULL;
-	hdlink->id = file->link;
-	hdlink->cnt = 1;
-	hdlink->files = file;
-	hdlink->next = xar->hdlink_list;
-	xar->hdlink_list = hdlink;
-	return (ARCHIVE_OK);
-}
-
-static void
-_checksum_init(struct chksumwork *sumwrk, int sum_alg)
-{
-	sumwrk->alg = sum_alg;
-	switch (sum_alg) {
-	case CKSUM_NONE:
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_init(&(sumwrk->sha1ctx));
-		break;
-	case CKSUM_MD5:
-		archive_md5_init(&(sumwrk->md5ctx));
-		break;
-	}
-}
-
-static void
-_checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
-{
-
-	switch (sumwrk->alg) {
-	case CKSUM_NONE:
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
-		break;
-	case CKSUM_MD5:
-		archive_md5_update(&(sumwrk->md5ctx), buff, size);
-		break;
-	}
-}
-
-static int
-_checksum_final(struct chksumwork *sumwrk, const void *val, size_t len)
-{
-	unsigned char sum[MAX_SUM_SIZE];
-	int r = ARCHIVE_OK;
-
-	switch (sumwrk->alg) {
-	case CKSUM_NONE:
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_final(&(sumwrk->sha1ctx), sum);
-		if (len != SHA1_SIZE ||
-		    memcmp(val, sum, SHA1_SIZE) != 0)
-			r = ARCHIVE_FAILED;
-		break;
-	case CKSUM_MD5:
-		archive_md5_final(&(sumwrk->md5ctx), sum);
-		if (len != MD5_SIZE ||
-		    memcmp(val, sum, MD5_SIZE) != 0)
-			r = ARCHIVE_FAILED;
-		break;
-	}
-	return (r);
-}
-
-static void
-checksum_init(struct archive_read *a, int a_sum_alg, int e_sum_alg)
-{
-	struct xar *xar;
-
-	xar = (struct xar *)(a->format->data);
-	_checksum_init(&(xar->a_sumwrk), a_sum_alg);
-	_checksum_init(&(xar->e_sumwrk), e_sum_alg);
-}
-
-static void
-checksum_update(struct archive_read *a, const void *abuff, size_t asize,
-    const void *ebuff, size_t esize)
-{
-	struct xar *xar;
-
-	xar = (struct xar *)(a->format->data);
-	_checksum_update(&(xar->a_sumwrk), abuff, asize);
-	_checksum_update(&(xar->e_sumwrk), ebuff, esize);
-}
-
-static int
-checksum_final(struct archive_read *a, const void *a_sum_val,
-    size_t a_sum_len, const void *e_sum_val, size_t e_sum_len)
-{
-	struct xar *xar;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	r = _checksum_final(&(xar->a_sumwrk), a_sum_val, a_sum_len);
-	if (r == ARCHIVE_OK)
-		r = _checksum_final(&(xar->e_sumwrk), e_sum_val, e_sum_len);
-	if (r != ARCHIVE_OK)
-		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-		    "Sumcheck error");
-	return (r);
-}
-
-static int
-decompression_init(struct archive_read *a, enum enctype encoding)
-{
-	struct xar *xar;
-	const char *detail;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	xar->rd_encoding = encoding;
-	switch (encoding) {
-	case NONE:
-		break;
-	case GZIP:
-		if (xar->stream_valid)
-			r = inflateReset(&(xar->stream));
-		else
-			r = inflateInit(&(xar->stream));
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Couldn't initialize zlib stream.");
-			return (ARCHIVE_FATAL);
-		}
-		xar->stream_valid = 1;
-		xar->stream.total_in = 0;
-		xar->stream.total_out = 0;
-		break;
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	case BZIP2:
-		if (xar->bzstream_valid) {
-			BZ2_bzDecompressEnd(&(xar->bzstream));
-			xar->bzstream_valid = 0;
-		}
-		r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 0);
-		if (r == BZ_MEM_ERROR)
-			r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 1);
-		if (r != BZ_OK) {
-			int err = ARCHIVE_ERRNO_MISC;
-			detail = NULL;
-			switch (r) {
-			case BZ_PARAM_ERROR:
-				detail = "invalid setup parameter";
-				break;
-			case BZ_MEM_ERROR:
-				err = ENOMEM;
-				detail = "out of memory";
-				break;
-			case BZ_CONFIG_ERROR:
-				detail = "mis-compiled library";
-				break;
-			}
-			archive_set_error(&a->archive, err,
-			    "Internal error initializing decompressor: %s",
-			    detail == NULL ? "??" : detail);
-			xar->bzstream_valid = 0;
-			return (ARCHIVE_FATAL);
-		}
-		xar->bzstream_valid = 1;
-		xar->bzstream.total_in_lo32 = 0;
-		xar->bzstream.total_in_hi32 = 0;
-		xar->bzstream.total_out_lo32 = 0;
-		xar->bzstream.total_out_hi32 = 0;
-		break;
-#endif
-#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
-#if LZMA_VERSION_MAJOR >= 5
-/* Effectively disable the limiter. */
-#define LZMA_MEMLIMIT   UINT64_MAX
-#else
-/* NOTE: This needs to check memory size which running system has. */
-#define LZMA_MEMLIMIT   (1U << 30)
-#endif
-	case XZ:
-	case LZMA:
-		if (xar->lzstream_valid) {
-			lzma_end(&(xar->lzstream));
-			xar->lzstream_valid = 0;
-		}
-		if (xar->entry_encoding == XZ)
-			r = lzma_stream_decoder(&(xar->lzstream),
-			    LZMA_MEMLIMIT,/* memlimit */
-			    LZMA_CONCATENATED);
-		else
-			r = lzma_alone_decoder(&(xar->lzstream),
-			    LZMA_MEMLIMIT);/* memlimit */
-		if (r != LZMA_OK) {
-			switch (r) {
-			case LZMA_MEM_ERROR:
-				archive_set_error(&a->archive,
-				    ENOMEM,
-				    "Internal error initializing "
-				    "compression library: "
-				    "Cannot allocate memory");
-				break;
-			case LZMA_OPTIONS_ERROR:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Internal error initializing "
-				    "compression library: "
-				    "Invalid or unsupported options");
-				break;
-			default:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Internal error initializing "
-				    "lzma library");
-				break;
-			}
-			return (ARCHIVE_FATAL);
-		}
-		xar->lzstream_valid = 1;
-		xar->lzstream.total_in = 0;
-		xar->lzstream.total_out = 0;
-		break;
-#endif
-	/*
-	 * Unsupported compression.
-	 */
-	default:
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-	case BZIP2:
-#endif
-#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-	case LZMA:
-	case XZ:
-#endif
-		switch (xar->entry_encoding) {
-		case BZIP2: detail = "bzip2"; break;
-		case LZMA: detail = "lzma"; break;
-		case XZ: detail = "xz"; break;
-		default: detail = "??"; break;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "%s compression not supported on this platform",
-		    detail);
-		return (ARCHIVE_FAILED);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-decompress(struct archive_read *a, const void **buff, size_t *outbytes,
-    const void *b, size_t *used)
-{
-	struct xar *xar;
-	void *outbuff;
-	size_t avail_in, avail_out;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	avail_in = *used;
-	outbuff = (void *)(uintptr_t)*buff;
-	if (outbuff == NULL) {
-		if (xar->outbuff == NULL) {
-			xar->outbuff = malloc(OUTBUFF_SIZE);
-			if (xar->outbuff == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Couldn't allocate memory for out buffer");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		outbuff = xar->outbuff;
-		*buff = outbuff;
-		avail_out = OUTBUFF_SIZE;
-	} else
-		avail_out = *outbytes;
-	switch (xar->rd_encoding) {
-	case GZIP:
-		xar->stream.next_in = (Bytef *)(uintptr_t)b;
-		xar->stream.avail_in = avail_in;
-		xar->stream.next_out = (unsigned char *)outbuff;
-		xar->stream.avail_out = avail_out;
-		r = inflate(&(xar->stream), 0);
-		switch (r) {
-		case Z_OK: /* Decompressor made some progress.*/
-		case Z_STREAM_END: /* Found end of stream. */
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "File decompression failed (%d)", r);
-			return (ARCHIVE_FATAL);
-		}
-		*used = avail_in - xar->stream.avail_in;
-		*outbytes = avail_out - xar->stream.avail_out;
-		break;
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	case BZIP2:
-		xar->bzstream.next_in = (char *)(uintptr_t)b;
-		xar->bzstream.avail_in = avail_in;
-		xar->bzstream.next_out = (char *)outbuff;
-		xar->bzstream.avail_out = avail_out;
-		r = BZ2_bzDecompress(&(xar->bzstream));
-		switch (r) {
-		case BZ_STREAM_END: /* Found end of stream. */
-			switch (BZ2_bzDecompressEnd(&(xar->bzstream))) {
-			case BZ_OK:
-				break;
-			default:
-				archive_set_error(&(a->archive),
-				    ARCHIVE_ERRNO_MISC,
-				    "Failed to clean up decompressor");
-				return (ARCHIVE_FATAL);
-			}
-			xar->bzstream_valid = 0;
-			/* FALLTHROUGH */
-		case BZ_OK: /* Decompressor made some progress. */
-			break;
-		default:
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "bzip decompression failed");
-			return (ARCHIVE_FATAL);
-		}
-		*used = avail_in - xar->bzstream.avail_in;
-		*outbytes = avail_out - xar->bzstream.avail_out;
-		break;
-#endif
-#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
-	case LZMA:
-	case XZ:
-		xar->lzstream.next_in = b;
-		xar->lzstream.avail_in = avail_in;
-		xar->lzstream.next_out = (unsigned char *)outbuff;
-		xar->lzstream.avail_out = avail_out;
-		r = lzma_code(&(xar->lzstream), LZMA_RUN);
-		switch (r) {
-		case LZMA_STREAM_END: /* Found end of stream. */
-			lzma_end(&(xar->lzstream));
-			xar->lzstream_valid = 0;
-			/* FALLTHROUGH */
-		case LZMA_OK: /* Decompressor made some progress. */
-			break;
-		default:
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "%s decompression failed(%d)",
-			    (xar->entry_encoding == XZ)?"xz":"lzma",
-			    r);
-			return (ARCHIVE_FATAL);
-		}
-		*used = avail_in - xar->lzstream.avail_in;
-		*outbytes = avail_out - xar->lzstream.avail_out;
-		break;
-#endif
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-	case BZIP2:
-#endif
-#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-	case LZMA:
-	case XZ:
-#endif
-	case NONE:
-	default:
-		if (outbuff == xar->outbuff) {
-			*buff = b;
-			*used = avail_in;
-			*outbytes = avail_in;
-		} else {
-			if (avail_out > avail_in)
-				avail_out = avail_in;
-			memcpy(outbuff, b, avail_out);
-			*used = avail_out;
-			*outbytes = avail_out;
-		}
-		break;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-decompression_cleanup(struct archive_read *a)
-{
-	struct xar *xar;
-	int r;
-
-	xar = (struct xar *)(a->format->data);
-	r = ARCHIVE_OK;
-	if (xar->stream_valid) {
-		if (inflateEnd(&(xar->stream)) != Z_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up zlib decompressor");
-			r = ARCHIVE_FATAL;
-		}
-	}
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	if (xar->bzstream_valid) {
-		if (BZ2_bzDecompressEnd(&(xar->bzstream)) != BZ_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up bzip2 decompressor");
-			r = ARCHIVE_FATAL;
-		}
-	}
-#endif
-#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
-	if (xar->lzstream_valid)
-		lzma_end(&(xar->lzstream));
-#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
-	if (xar->lzstream_valid) {
-		if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up lzmadec decompressor");
-			r = ARCHIVE_FATAL;
-		}
-	}
-#endif
-	return (r);
-}
-
-static void
-checksum_cleanup(struct archive_read *a) {
-	struct xar *xar;
-
-	xar = (struct xar *)(a->format->data);
-
-	_checksum_final(&(xar->a_sumwrk), NULL, 0);
-	_checksum_final(&(xar->e_sumwrk), NULL, 0);
-}
-
-static void
-xmlattr_cleanup(struct xmlattr_list *list)
-{
-	struct xmlattr *attr, *next;
-
-	attr = list->first;
-	while (attr != NULL) {
-		next = attr->next;
-		free(attr->name);
-		free(attr->value);
-		free(attr);
-		attr = next;
-	}
-	list->first = NULL;
-	list->last = &(list->first);
-}
-
-static int
-file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list)
-{
-	struct xar_file *file;
-	struct xmlattr *attr;
-
-	file = calloc(1, sizeof(*file));
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	file->parent = xar->file;
-	file->mode = 0777 | AE_IFREG;
-	file->atime =  0;
-	file->mtime = 0;
-	xar->file = file;
-	xar->xattr = NULL;
-	for (attr = list->first; attr != NULL; attr = attr->next) {
-		if (strcmp(attr->name, "id") == 0)
-			file->id = atol10(attr->value, strlen(attr->value));
-	}
-	file->nlink = 1;
-	if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	return (ARCHIVE_OK);
-}
-
-static void
-file_free(struct xar_file *file)
-{
-	struct xattr *xattr;
-
-	archive_string_free(&(file->pathname));
-	archive_string_free(&(file->symlink));
-	archive_string_free(&(file->uname));
-	archive_string_free(&(file->gname));
-	archive_string_free(&(file->hardlink));
-	xattr = file->xattr_list;
-	while (xattr != NULL) {
-		struct xattr *next;
-
-		next = xattr->next;
-		xattr_free(xattr);
-		xattr = next;
-	}
-
-	free(file);
-}
-
-static int
-xattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list)
-{
-	struct xattr *xattr, **nx;
-	struct xmlattr *attr;
-
-	xattr = calloc(1, sizeof(*xattr));
-	if (xattr == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	xar->xattr = xattr;
-	for (attr = list->first; attr != NULL; attr = attr->next) {
-		if (strcmp(attr->name, "id") == 0)
-			xattr->id = atol10(attr->value, strlen(attr->value));
-	}
-	/* Chain to xattr list. */
-	for (nx = &(xar->file->xattr_list);
-	    *nx != NULL; nx = &((*nx)->next)) {
-		if (xattr->id < (*nx)->id)
-			break;
-	}
-	xattr->next = *nx;
-	*nx = xattr;
-
-	return (ARCHIVE_OK);
-}
-
-static void
-xattr_free(struct xattr *xattr)
-{
-	archive_string_free(&(xattr->name));
-	free(xattr);
-}
-
-static int
-getencoding(struct xmlattr_list *list)
-{
-	struct xmlattr *attr;
-	enum enctype encoding = NONE;
-
-	for (attr = list->first; attr != NULL; attr = attr->next) {
-		if (strcmp(attr->name, "style") == 0) {
-			if (strcmp(attr->value, "application/octet-stream") == 0)
-				encoding = NONE;
-			else if (strcmp(attr->value, "application/x-gzip") == 0)
-				encoding = GZIP;
-			else if (strcmp(attr->value, "application/x-bzip2") == 0)
-				encoding = BZIP2;
-			else if (strcmp(attr->value, "application/x-lzma") == 0)
-				encoding = LZMA;
-			else if (strcmp(attr->value, "application/x-xz") == 0)
-				encoding = XZ;
-		}
-	}
-	return (encoding);
-}
-
-static int
-getsumalgorithm(struct xmlattr_list *list)
-{
-	struct xmlattr *attr;
-	int alg = CKSUM_NONE;
-
-	for (attr = list->first; attr != NULL; attr = attr->next) {
-		if (strcmp(attr->name, "style") == 0) {
-			const char *v = attr->value;
-			if ((v[0] == 'S' || v[0] == 's') &&
-			    (v[1] == 'H' || v[1] == 'h') &&
-			    (v[2] == 'A' || v[2] == 'a') &&
-			    v[3] == '1' && v[4] == '\0')
-				alg = CKSUM_SHA1;
-			if ((v[0] == 'M' || v[0] == 'm') &&
-			    (v[1] == 'D' || v[1] == 'd') &&
-			    v[2] == '5' && v[3] == '\0')
-				alg = CKSUM_MD5;
-		}
-	}
-	return (alg);
-}
-
-static int
-unknowntag_start(struct archive_read *a, struct xar *xar, const char *name)
-{
-	struct unknown_tag *tag;
-
-	tag = malloc(sizeof(*tag));
-	if (tag == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	tag->next = xar->unknowntags;
-	archive_string_init(&(tag->name));
-	archive_strcpy(&(tag->name), name);
-	if (xar->unknowntags == NULL) {
-#if DEBUG
-		fprintf(stderr, "UNKNOWNTAG_START:%s\n", name);
-#endif
-		xar->xmlsts_unknown = xar->xmlsts;
-		xar->xmlsts = UNKNOWN;
-	}
-	xar->unknowntags = tag;
-	return (ARCHIVE_OK);
-}
-
-static void
-unknowntag_end(struct xar *xar, const char *name)
-{
-	struct unknown_tag *tag;
-
-	tag = xar->unknowntags;
-	if (tag == NULL || name == NULL)
-		return;
-	if (strcmp(tag->name.s, name) == 0) {
-		xar->unknowntags = tag->next;
-		archive_string_free(&(tag->name));
-		free(tag);
-		if (xar->unknowntags == NULL) {
-#if DEBUG
-			fprintf(stderr, "UNKNOWNTAG_END:%s\n", name);
-#endif
-			xar->xmlsts = xar->xmlsts_unknown;
-		}
-	}
-}
-
-static int
-xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
-{
-	struct xar *xar;
-	struct xmlattr *attr;
-
-	xar = (struct xar *)(a->format->data);
-
-#if DEBUG
-	fprintf(stderr, "xml_sta:[%s]\n", name);
-	for (attr = list->first; attr != NULL; attr = attr->next)
-		fprintf(stderr, "    attr:\"%s\"=\"%s\"\n",
-		    attr->name, attr->value);
-#endif
-	xar->base64text = 0;
-	switch (xar->xmlsts) {
-	case INIT:
-		if (strcmp(name, "xar") == 0)
-			xar->xmlsts = XAR;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case XAR:
-		if (strcmp(name, "toc") == 0)
-			xar->xmlsts = TOC;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case TOC:
-		if (strcmp(name, "creation-time") == 0)
-			xar->xmlsts = TOC_CREATION_TIME;
-		else if (strcmp(name, "checksum") == 0)
-			xar->xmlsts = TOC_CHECKSUM;
-		else if (strcmp(name, "file") == 0) {
-			if (file_new(a, xar, list) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			xar->xmlsts = TOC_FILE;
-		}
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case TOC_CHECKSUM:
-		if (strcmp(name, "offset") == 0)
-			xar->xmlsts = TOC_CHECKSUM_OFFSET;
-		else if (strcmp(name, "size") == 0)
-			xar->xmlsts = TOC_CHECKSUM_SIZE;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case TOC_FILE:
-		if (strcmp(name, "file") == 0) {
-			if (file_new(a, xar, list) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		}
-		else if (strcmp(name, "data") == 0)
-			xar->xmlsts = FILE_DATA;
-		else if (strcmp(name, "ea") == 0) {
-			if (xattr_new(a, xar, list) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			xar->xmlsts = FILE_EA;
-		}
-		else if (strcmp(name, "ctime") == 0)
-			xar->xmlsts = FILE_CTIME;
-		else if (strcmp(name, "mtime") == 0)
-			xar->xmlsts = FILE_MTIME;
-		else if (strcmp(name, "atime") == 0)
-			xar->xmlsts = FILE_ATIME;
-		else if (strcmp(name, "group") == 0)
-			xar->xmlsts = FILE_GROUP;
-		else if (strcmp(name, "gid") == 0)
-			xar->xmlsts = FILE_GID;
-		else if (strcmp(name, "user") == 0)
-			xar->xmlsts = FILE_USER;
-		else if (strcmp(name, "uid") == 0)
-			xar->xmlsts = FILE_UID;
-		else if (strcmp(name, "mode") == 0)
-			xar->xmlsts = FILE_MODE;
-		else if (strcmp(name, "device") == 0)
-			xar->xmlsts = FILE_DEVICE;
-		else if (strcmp(name, "deviceno") == 0)
-			xar->xmlsts = FILE_DEVICENO;
-		else if (strcmp(name, "inode") == 0)
-			xar->xmlsts = FILE_INODE;
-		else if (strcmp(name, "link") == 0)
-			xar->xmlsts = FILE_LINK;
-		else if (strcmp(name, "type") == 0) {
-			xar->xmlsts = FILE_TYPE;
-			for (attr = list->first; attr != NULL;
-			    attr = attr->next) {
-				if (strcmp(attr->name, "link") != 0)
-					continue;
-				if (strcmp(attr->value, "original") == 0) {
-					xar->file->hdnext = xar->hdlink_orgs;
-					xar->hdlink_orgs = xar->file;
-				} else {
-					xar->file->link = (unsigned)atol10(attr->value,
-					    strlen(attr->value));
-					if (xar->file->link > 0)
-						if (add_link(a, xar, xar->file) != ARCHIVE_OK) {
-							return (ARCHIVE_FATAL);
-						};
-				}
-			}
-		}
-		else if (strcmp(name, "name") == 0) {
-			xar->xmlsts = FILE_NAME;
-			for (attr = list->first; attr != NULL;
-			    attr = attr->next) {
-				if (strcmp(attr->name, "enctype") == 0 &&
-				    strcmp(attr->value, "base64") == 0)
-					xar->base64text = 1;
-			}
-		}
-		else if (strcmp(name, "acl") == 0)
-			xar->xmlsts = FILE_ACL;
-		else if (strcmp(name, "flags") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		else if (strcmp(name, "ext2") == 0)
-			xar->xmlsts = FILE_EXT2;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_DATA:
-		if (strcmp(name, "length") == 0)
-			xar->xmlsts = FILE_DATA_LENGTH;
-		else if (strcmp(name, "offset") == 0)
-			xar->xmlsts = FILE_DATA_OFFSET;
-		else if (strcmp(name, "size") == 0)
-			xar->xmlsts = FILE_DATA_SIZE;
-		else if (strcmp(name, "encoding") == 0) {
-			xar->xmlsts = FILE_DATA_ENCODING;
-			xar->file->encoding = getencoding(list);
-		}
-		else if (strcmp(name, "archived-checksum") == 0) {
-			xar->xmlsts = FILE_DATA_A_CHECKSUM;
-			xar->file->a_sum.alg = getsumalgorithm(list);
-		}
-		else if (strcmp(name, "extracted-checksum") == 0) {
-			xar->xmlsts = FILE_DATA_E_CHECKSUM;
-			xar->file->e_sum.alg = getsumalgorithm(list);
-		}
-		else if (strcmp(name, "content") == 0)
-			xar->xmlsts = FILE_DATA_CONTENT;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_DEVICE:
-		if (strcmp(name, "major") == 0)
-			xar->xmlsts = FILE_DEVICE_MAJOR;
-		else if (strcmp(name, "minor") == 0)
-			xar->xmlsts = FILE_DEVICE_MINOR;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_DATA_CONTENT:
-		if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		break;
-	case FILE_EA:
-		if (strcmp(name, "length") == 0)
-			xar->xmlsts = FILE_EA_LENGTH;
-		else if (strcmp(name, "offset") == 0)
-			xar->xmlsts = FILE_EA_OFFSET;
-		else if (strcmp(name, "size") == 0)
-			xar->xmlsts = FILE_EA_SIZE;
-		else if (strcmp(name, "encoding") == 0) {
-			xar->xmlsts = FILE_EA_ENCODING;
-			xar->xattr->encoding = getencoding(list);
-		} else if (strcmp(name, "archived-checksum") == 0)
-			xar->xmlsts = FILE_EA_A_CHECKSUM;
-		else if (strcmp(name, "extracted-checksum") == 0)
-			xar->xmlsts = FILE_EA_E_CHECKSUM;
-		else if (strcmp(name, "name") == 0)
-			xar->xmlsts = FILE_EA_NAME;
-		else if (strcmp(name, "fstype") == 0)
-			xar->xmlsts = FILE_EA_FSTYPE;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_ACL:
-		if (strcmp(name, "appleextended") == 0)
-			xar->xmlsts = FILE_ACL_APPLEEXTENDED;
-		else if (strcmp(name, "default") == 0)
-			xar->xmlsts = FILE_ACL_DEFAULT;
-		else if (strcmp(name, "access") == 0)
-			xar->xmlsts = FILE_ACL_ACCESS;
-		else
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_FLAGS:
-		if (!xml_parse_file_flags(xar, name))
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case FILE_EXT2:
-		if (!xml_parse_file_ext2(xar, name))
-			if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		break;
-	case TOC_CREATION_TIME:
-	case TOC_CHECKSUM_OFFSET:
-	case TOC_CHECKSUM_SIZE:
-	case FILE_DATA_LENGTH:
-	case FILE_DATA_OFFSET:
-	case FILE_DATA_SIZE:
-	case FILE_DATA_ENCODING:
-	case FILE_DATA_A_CHECKSUM:
-	case FILE_DATA_E_CHECKSUM:
-	case FILE_EA_LENGTH:
-	case FILE_EA_OFFSET:
-	case FILE_EA_SIZE:
-	case FILE_EA_ENCODING:
-	case FILE_EA_A_CHECKSUM:
-	case FILE_EA_E_CHECKSUM:
-	case FILE_EA_NAME:
-	case FILE_EA_FSTYPE:
-	case FILE_CTIME:
-	case FILE_MTIME:
-	case FILE_ATIME:
-	case FILE_GROUP:
-	case FILE_GID:
-	case FILE_USER:
-	case FILE_UID:
-	case FILE_INODE:
-	case FILE_DEVICE_MAJOR:
-	case FILE_DEVICE_MINOR:
-	case FILE_DEVICENO:
-	case FILE_MODE:
-	case FILE_TYPE:
-	case FILE_LINK:
-	case FILE_NAME:
-	case FILE_ACL_DEFAULT:
-	case FILE_ACL_ACCESS:
-	case FILE_ACL_APPLEEXTENDED:
-	case FILE_FLAGS_USER_NODUMP:
-	case FILE_FLAGS_USER_IMMUTABLE:
-	case FILE_FLAGS_USER_APPEND:
-	case FILE_FLAGS_USER_OPAQUE:
-	case FILE_FLAGS_USER_NOUNLINK:
-	case FILE_FLAGS_SYS_ARCHIVED:
-	case FILE_FLAGS_SYS_IMMUTABLE:
-	case FILE_FLAGS_SYS_APPEND:
-	case FILE_FLAGS_SYS_NOUNLINK:
-	case FILE_FLAGS_SYS_SNAPSHOT:
-	case FILE_EXT2_SecureDeletion:
-	case FILE_EXT2_Undelete:
-	case FILE_EXT2_Compress:
-	case FILE_EXT2_Synchronous:
-	case FILE_EXT2_Immutable:
-	case FILE_EXT2_AppendOnly:
-	case FILE_EXT2_NoDump:
-	case FILE_EXT2_NoAtime:
-	case FILE_EXT2_CompDirty:
-	case FILE_EXT2_CompBlock:
-	case FILE_EXT2_NoCompBlock:
-	case FILE_EXT2_CompError:
-	case FILE_EXT2_BTree:
-	case FILE_EXT2_HashIndexed:
-	case FILE_EXT2_iMagic:
-	case FILE_EXT2_Journaled:
-	case FILE_EXT2_NoTail:
-	case FILE_EXT2_DirSync:
-	case FILE_EXT2_TopDir:
-	case FILE_EXT2_Reserved:
-	case UNKNOWN:
-		if (unknowntag_start(a, xar, name) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		break;
-	}
-	return (ARCHIVE_OK);
-}
-
-static void
-xml_end(void *userData, const char *name)
-{
-	struct archive_read *a;
-	struct xar *xar;
-
-	a = (struct archive_read *)userData;
-	xar = (struct xar *)(a->format->data);
-
-#if DEBUG
-	fprintf(stderr, "xml_end:[%s]\n", name);
-#endif
-	switch (xar->xmlsts) {
-	case INIT:
-		break;
-	case XAR:
-		if (strcmp(name, "xar") == 0)
-			xar->xmlsts = INIT;
-		break;
-	case TOC:
-		if (strcmp(name, "toc") == 0)
-			xar->xmlsts = XAR;
-		break;
-	case TOC_CREATION_TIME:
-		if (strcmp(name, "creation-time") == 0)
-			xar->xmlsts = TOC;
-		break;
-	case TOC_CHECKSUM:
-		if (strcmp(name, "checksum") == 0)
-			xar->xmlsts = TOC;
-		break;
-	case TOC_CHECKSUM_OFFSET:
-		if (strcmp(name, "offset") == 0)
-			xar->xmlsts = TOC_CHECKSUM;
-		break;
-	case TOC_CHECKSUM_SIZE:
-		if (strcmp(name, "size") == 0)
-			xar->xmlsts = TOC_CHECKSUM;
-		break;
-	case TOC_FILE:
-		if (strcmp(name, "file") == 0) {
-			if (xar->file->parent != NULL &&
-			    ((xar->file->mode & AE_IFMT) == AE_IFDIR))
-				xar->file->parent->subdirs++;
-			xar->file = xar->file->parent;
-			if (xar->file == NULL)
-				xar->xmlsts = TOC;
-		}
-		break;
-	case FILE_DATA:
-		if (strcmp(name, "data") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_DATA_LENGTH:
-		if (strcmp(name, "length") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_OFFSET:
-		if (strcmp(name, "offset") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_SIZE:
-		if (strcmp(name, "size") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_ENCODING:
-		if (strcmp(name, "encoding") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_A_CHECKSUM:
-		if (strcmp(name, "archived-checksum") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_E_CHECKSUM:
-		if (strcmp(name, "extracted-checksum") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_DATA_CONTENT:
-		if (strcmp(name, "content") == 0)
-			xar->xmlsts = FILE_DATA;
-		break;
-	case FILE_EA:
-		if (strcmp(name, "ea") == 0) {
-			xar->xmlsts = TOC_FILE;
-			xar->xattr = NULL;
-		}
-		break;
-	case FILE_EA_LENGTH:
-		if (strcmp(name, "length") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_OFFSET:
-		if (strcmp(name, "offset") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_SIZE:
-		if (strcmp(name, "size") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_ENCODING:
-		if (strcmp(name, "encoding") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_A_CHECKSUM:
-		if (strcmp(name, "archived-checksum") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_E_CHECKSUM:
-		if (strcmp(name, "extracted-checksum") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_NAME:
-		if (strcmp(name, "name") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_EA_FSTYPE:
-		if (strcmp(name, "fstype") == 0)
-			xar->xmlsts = FILE_EA;
-		break;
-	case FILE_CTIME:
-		if (strcmp(name, "ctime") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_MTIME:
-		if (strcmp(name, "mtime") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_ATIME:
-		if (strcmp(name, "atime") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_GROUP:
-		if (strcmp(name, "group") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_GID:
-		if (strcmp(name, "gid") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_USER:
-		if (strcmp(name, "user") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_UID:
-		if (strcmp(name, "uid") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_MODE:
-		if (strcmp(name, "mode") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_DEVICE:
-		if (strcmp(name, "device") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_DEVICE_MAJOR:
-		if (strcmp(name, "major") == 0)
-			xar->xmlsts = FILE_DEVICE;
-		break;
-	case FILE_DEVICE_MINOR:
-		if (strcmp(name, "minor") == 0)
-			xar->xmlsts = FILE_DEVICE;
-		break;
-	case FILE_DEVICENO:
-		if (strcmp(name, "deviceno") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_INODE:
-		if (strcmp(name, "inode") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_LINK:
-		if (strcmp(name, "link") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_TYPE:
-		if (strcmp(name, "type") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_NAME:
-		if (strcmp(name, "name") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_ACL:
-		if (strcmp(name, "acl") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_ACL_DEFAULT:
-		if (strcmp(name, "default") == 0)
-			xar->xmlsts = FILE_ACL;
-		break;
-	case FILE_ACL_ACCESS:
-		if (strcmp(name, "access") == 0)
-			xar->xmlsts = FILE_ACL;
-		break;
-	case FILE_ACL_APPLEEXTENDED:
-		if (strcmp(name, "appleextended") == 0)
-			xar->xmlsts = FILE_ACL;
-		break;
-	case FILE_FLAGS:
-		if (strcmp(name, "flags") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_FLAGS_USER_NODUMP:
-		if (strcmp(name, "UserNoDump") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_USER_IMMUTABLE:
-		if (strcmp(name, "UserImmutable") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_USER_APPEND:
-		if (strcmp(name, "UserAppend") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_USER_OPAQUE:
-		if (strcmp(name, "UserOpaque") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_USER_NOUNLINK:
-		if (strcmp(name, "UserNoUnlink") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_SYS_ARCHIVED:
-		if (strcmp(name, "SystemArchived") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_SYS_IMMUTABLE:
-		if (strcmp(name, "SystemImmutable") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_SYS_APPEND:
-		if (strcmp(name, "SystemAppend") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_SYS_NOUNLINK:
-		if (strcmp(name, "SystemNoUnlink") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_FLAGS_SYS_SNAPSHOT:
-		if (strcmp(name, "SystemSnapshot") == 0)
-			xar->xmlsts = FILE_FLAGS;
-		break;
-	case FILE_EXT2:
-		if (strcmp(name, "ext2") == 0)
-			xar->xmlsts = TOC_FILE;
-		break;
-	case FILE_EXT2_SecureDeletion:
-		if (strcmp(name, "SecureDeletion") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Undelete:
-		if (strcmp(name, "Undelete") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Compress:
-		if (strcmp(name, "Compress") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Synchronous:
-		if (strcmp(name, "Synchronous") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Immutable:
-		if (strcmp(name, "Immutable") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_AppendOnly:
-		if (strcmp(name, "AppendOnly") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_NoDump:
-		if (strcmp(name, "NoDump") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_NoAtime:
-		if (strcmp(name, "NoAtime") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_CompDirty:
-		if (strcmp(name, "CompDirty") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_CompBlock:
-		if (strcmp(name, "CompBlock") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_NoCompBlock:
-		if (strcmp(name, "NoCompBlock") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_CompError:
-		if (strcmp(name, "CompError") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_BTree:
-		if (strcmp(name, "BTree") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_HashIndexed:
-		if (strcmp(name, "HashIndexed") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_iMagic:
-		if (strcmp(name, "iMagic") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Journaled:
-		if (strcmp(name, "Journaled") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_NoTail:
-		if (strcmp(name, "NoTail") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_DirSync:
-		if (strcmp(name, "DirSync") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_TopDir:
-		if (strcmp(name, "TopDir") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case FILE_EXT2_Reserved:
-		if (strcmp(name, "Reserved") == 0)
-			xar->xmlsts = FILE_EXT2;
-		break;
-	case UNKNOWN:
-		unknowntag_end(xar, name);
-		break;
-	}
-}
-
-static const int base64[256] = {
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0F */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1F */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, 62, -1, -1, -1, 63, /* 20 - 2F */
-	52, 53, 54, 55, 56, 57, 58, 59,
-	60, 61, -1, -1, -1, -1, -1, -1, /* 30 - 3F */
-	-1,  0,  1,  2,  3,  4,  5,  6,
-	 7,  8,  9, 10, 11, 12, 13, 14, /* 40 - 4F */
-	15, 16, 17, 18, 19, 20, 21, 22,
-	23, 24, 25, -1, -1, -1, -1, -1, /* 50 - 5F */
-	-1, 26, 27, 28, 29, 30, 31, 32,
-	33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */
-	41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, -1, -1, -1, -1, -1, /* 70 - 7F */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8F */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9F */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* A0 - AF */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* B0 - BF */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* C0 - CF */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* D0 - DF */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* E0 - EF */
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, /* F0 - FF */
-};
-
-static void
-strappend_base64(struct xar *xar,
-    struct archive_string *as, const char *s, size_t l)
-{
-	unsigned char buff[256];
-	unsigned char *out;
-	const unsigned char *b;
-	size_t len;
-
-	(void)xar; /* UNUSED */
-	len = 0;
-	out = buff;
-	b = (const unsigned char *)s;
-	while (l > 0) {
-		int n = 0;
-
-		if (base64[b[0]] < 0 || base64[b[1]] < 0)
-			break;
-		n = base64[*b++] << 18;
-		n |= base64[*b++] << 12;
-		*out++ = n >> 16;
-		len++;
-		l -= 2;
-
-		if (l > 0) {
-			if (base64[*b] < 0)
-				break;
-			n |= base64[*b++] << 6;
-			*out++ = (n >> 8) & 0xFF;
-			len++;
-			--l;
-		}
-		if (l > 0) {
-			if (base64[*b] < 0)
-				break;
-			n |= base64[*b++];
-			*out++ = n & 0xFF;
-			len++;
-			--l;
-		}
-		if (len+3 >= sizeof(buff)) {
-			archive_strncat(as, (const char *)buff, len);
-			len = 0;
-			out = buff;
-		}
-	}
-	if (len > 0)
-		archive_strncat(as, (const char *)buff, len);
-}
-
-static int
-is_string(const char *known, const char *data, size_t len)
-{
-	if (strlen(known) != len)
-		return -1;
-	return memcmp(data, known, len);
-}
-
-static void
-xml_data(void *userData, const char *s, int len)
-{
-	struct archive_read *a;
-	struct xar *xar;
-
-	a = (struct archive_read *)userData;
-	xar = (struct xar *)(a->format->data);
-
-#if DEBUG
-	{
-		char buff[1024];
-		if (len > (int)(sizeof(buff)-1))
-			len = (int)(sizeof(buff)-1);
-		strncpy(buff, s, len);
-		buff[len] = 0;
-		fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff);
-	}
-#endif
-	switch (xar->xmlsts) {
-	case TOC_CHECKSUM_OFFSET:
-		xar->toc_chksum_offset = atol10(s, len);
-		break;
-	case TOC_CHECKSUM_SIZE:
-		xar->toc_chksum_size = atol10(s, len);
-		break;
-	default:
-		break;
-	}
-	if (xar->file == NULL)
-		return;
-
-	switch (xar->xmlsts) {
-	case FILE_NAME:
-		if (xar->file->parent != NULL) {
-			archive_string_concat(&(xar->file->pathname),
-			    &(xar->file->parent->pathname));
-			archive_strappend_char(&(xar->file->pathname), '/');
-		}
-		xar->file->has |= HAS_PATHNAME;
-		if (xar->base64text) {
-			strappend_base64(xar,
-			    &(xar->file->pathname), s, len);
-		} else
-			archive_strncat(&(xar->file->pathname), s, len);
-		break;
-	case FILE_LINK:
-		xar->file->has |= HAS_SYMLINK;
-		archive_strncpy(&(xar->file->symlink), s, len);
-		break;
-	case FILE_TYPE:
-		if (is_string("file", s, len) == 0 ||
-		    is_string("hardlink", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFREG;
-		if (is_string("directory", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFDIR;
-		if (is_string("symlink", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFLNK;
-		if (is_string("character special", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFCHR;
-		if (is_string("block special", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFBLK;
-		if (is_string("socket", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFSOCK;
-		if (is_string("fifo", s, len) == 0)
-			xar->file->mode =
-			    (xar->file->mode & ~AE_IFMT) | AE_IFIFO;
-		xar->file->has |= HAS_TYPE;
-		break;
-	case FILE_INODE:
-		xar->file->has |= HAS_INO;
-		xar->file->ino64 = atol10(s, len);
-		break;
-	case FILE_DEVICE_MAJOR:
-		xar->file->has |= HAS_DEVMAJOR;
-		xar->file->devmajor = (dev_t)atol10(s, len);
-		break;
-	case FILE_DEVICE_MINOR:
-		xar->file->has |= HAS_DEVMINOR;
-		xar->file->devminor = (dev_t)atol10(s, len);
-		break;
-	case FILE_DEVICENO:
-		xar->file->has |= HAS_DEV;
-		xar->file->dev = (dev_t)atol10(s, len);
-		break;
-	case FILE_MODE:
-		xar->file->has |= HAS_MODE;
-		xar->file->mode =
-		    (xar->file->mode & AE_IFMT) |
-		    ((mode_t)(atol8(s, len)) & ~AE_IFMT);
-		break;
-	case FILE_GROUP:
-		xar->file->has |= HAS_GID;
-		archive_strncpy(&(xar->file->gname), s, len);
-		break;
-	case FILE_GID:
-		xar->file->has |= HAS_GID;
-		xar->file->gid = atol10(s, len);
-		break;
-	case FILE_USER:
-		xar->file->has |= HAS_UID;
-		archive_strncpy(&(xar->file->uname), s, len);
-		break;
-	case FILE_UID:
-		xar->file->has |= HAS_UID;
-		xar->file->uid = atol10(s, len);
-		break;
-	case FILE_CTIME:
-		xar->file->has |= HAS_TIME | HAS_CTIME;
-		xar->file->ctime = parse_time(s, len);
-		break;
-	case FILE_MTIME:
-		xar->file->has |= HAS_TIME | HAS_MTIME;
-		xar->file->mtime = parse_time(s, len);
-		break;
-	case FILE_ATIME:
-		xar->file->has |= HAS_TIME | HAS_ATIME;
-		xar->file->atime = parse_time(s, len);
-		break;
-	case FILE_DATA_LENGTH:
-		xar->file->has |= HAS_DATA;
-		xar->file->length = atol10(s, len);
-		break;
-	case FILE_DATA_OFFSET:
-		xar->file->has |= HAS_DATA;
-		xar->file->offset = atol10(s, len);
-		break;
-	case FILE_DATA_SIZE:
-		xar->file->has |= HAS_DATA;
-		xar->file->size = atol10(s, len);
-		break;
-	case FILE_DATA_A_CHECKSUM:
-		xar->file->a_sum.len = atohex(xar->file->a_sum.val,
-		    sizeof(xar->file->a_sum.val), s, len);
-		break;
-	case FILE_DATA_E_CHECKSUM:
-		xar->file->e_sum.len = atohex(xar->file->e_sum.val,
-		    sizeof(xar->file->e_sum.val), s, len);
-		break;
-	case FILE_EA_LENGTH:
-		xar->file->has |= HAS_XATTR;
-		xar->xattr->length = atol10(s, len);
-		break;
-	case FILE_EA_OFFSET:
-		xar->file->has |= HAS_XATTR;
-		xar->xattr->offset = atol10(s, len);
-		break;
-	case FILE_EA_SIZE:
-		xar->file->has |= HAS_XATTR;
-		xar->xattr->size = atol10(s, len);
-		break;
-	case FILE_EA_A_CHECKSUM:
-		xar->file->has |= HAS_XATTR;
-		xar->xattr->a_sum.len = atohex(xar->xattr->a_sum.val,
-		    sizeof(xar->xattr->a_sum.val), s, len);
-		break;
-	case FILE_EA_E_CHECKSUM:
-		xar->file->has |= HAS_XATTR;
-		xar->xattr->e_sum.len = atohex(xar->xattr->e_sum.val,
-		    sizeof(xar->xattr->e_sum.val), s, len);
-		break;
-	case FILE_EA_NAME:
-		xar->file->has |= HAS_XATTR;
-		archive_strncpy(&(xar->xattr->name), s, len);
-		break;
-	case FILE_EA_FSTYPE:
-		xar->file->has |= HAS_XATTR;
-		archive_strncpy(&(xar->xattr->fstype), s, len);
-		break;
-		break;
-	case FILE_ACL_DEFAULT:
-	case FILE_ACL_ACCESS:
-	case FILE_ACL_APPLEEXTENDED:
-		xar->file->has |= HAS_ACL;
-		/* TODO */
-		break;
-	case INIT:
-	case XAR:
-	case TOC:
-	case TOC_CREATION_TIME:
-	case TOC_CHECKSUM:
-	case TOC_CHECKSUM_OFFSET:
-	case TOC_CHECKSUM_SIZE:
-	case TOC_FILE:
-	case FILE_DATA:
-	case FILE_DATA_ENCODING:
-	case FILE_DATA_CONTENT:
-	case FILE_DEVICE:
-	case FILE_EA:
-	case FILE_EA_ENCODING:
-	case FILE_ACL:
-	case FILE_FLAGS:
-	case FILE_FLAGS_USER_NODUMP:
-	case FILE_FLAGS_USER_IMMUTABLE:
-	case FILE_FLAGS_USER_APPEND:
-	case FILE_FLAGS_USER_OPAQUE:
-	case FILE_FLAGS_USER_NOUNLINK:
-	case FILE_FLAGS_SYS_ARCHIVED:
-	case FILE_FLAGS_SYS_IMMUTABLE:
-	case FILE_FLAGS_SYS_APPEND:
-	case FILE_FLAGS_SYS_NOUNLINK:
-	case FILE_FLAGS_SYS_SNAPSHOT:
-	case FILE_EXT2:
-	case FILE_EXT2_SecureDeletion:
-	case FILE_EXT2_Undelete:
-	case FILE_EXT2_Compress:
-	case FILE_EXT2_Synchronous:
-	case FILE_EXT2_Immutable:
-	case FILE_EXT2_AppendOnly:
-	case FILE_EXT2_NoDump:
-	case FILE_EXT2_NoAtime:
-	case FILE_EXT2_CompDirty:
-	case FILE_EXT2_CompBlock:
-	case FILE_EXT2_NoCompBlock:
-	case FILE_EXT2_CompError:
-	case FILE_EXT2_BTree:
-	case FILE_EXT2_HashIndexed:
-	case FILE_EXT2_iMagic:
-	case FILE_EXT2_Journaled:
-	case FILE_EXT2_NoTail:
-	case FILE_EXT2_DirSync:
-	case FILE_EXT2_TopDir:
-	case FILE_EXT2_Reserved:
-	case UNKNOWN:
-		break;
-	}
-}
-
-/*
- * BSD file flags.
- */
-static int
-xml_parse_file_flags(struct xar *xar, const char *name)
-{
-	const char *flag = NULL;
-
-	if (strcmp(name, "UserNoDump") == 0) {
-		xar->xmlsts = FILE_FLAGS_USER_NODUMP;
-		flag = "nodump";
-	}
-	else if (strcmp(name, "UserImmutable") == 0) {
-		xar->xmlsts = FILE_FLAGS_USER_IMMUTABLE;
-		flag = "uimmutable";
-	}
-	else if (strcmp(name, "UserAppend") == 0) {
-		xar->xmlsts = FILE_FLAGS_USER_APPEND;
-		flag = "uappend";
-	}
-	else if (strcmp(name, "UserOpaque") == 0) {
-		xar->xmlsts = FILE_FLAGS_USER_OPAQUE;
-		flag = "opaque";
-	}
-	else if (strcmp(name, "UserNoUnlink") == 0) {
-		xar->xmlsts = FILE_FLAGS_USER_NOUNLINK;
-		flag = "nouunlink";
-	}
-	else if (strcmp(name, "SystemArchived") == 0) {
-		xar->xmlsts = FILE_FLAGS_SYS_ARCHIVED;
-		flag = "archived";
-	}
-	else if (strcmp(name, "SystemImmutable") == 0) {
-		xar->xmlsts = FILE_FLAGS_SYS_IMMUTABLE;
-		flag = "simmutable";
-	}
-	else if (strcmp(name, "SystemAppend") == 0) {
-		xar->xmlsts = FILE_FLAGS_SYS_APPEND;
-		flag = "sappend";
-	}
-	else if (strcmp(name, "SystemNoUnlink") == 0) {
-		xar->xmlsts = FILE_FLAGS_SYS_NOUNLINK;
-		flag = "nosunlink";
-	}
-	else if (strcmp(name, "SystemSnapshot") == 0) {
-		xar->xmlsts = FILE_FLAGS_SYS_SNAPSHOT;
-		flag = "snapshot";
-	}
-
-	if (flag == NULL)
-		return (0);
-	xar->file->has |= HAS_FFLAGS;
-	if (archive_strlen(&(xar->file->fflags_text)) > 0)
-		archive_strappend_char(&(xar->file->fflags_text), ',');
-	archive_strcat(&(xar->file->fflags_text), flag);
-	return (1);
-}
-
-/*
- * Linux file flags.
- */
-static int
-xml_parse_file_ext2(struct xar *xar, const char *name)
-{
-	const char *flag = NULL;
-
-	if (strcmp(name, "SecureDeletion") == 0) {
-		xar->xmlsts = FILE_EXT2_SecureDeletion;
-		flag = "securedeletion";
-	}
-	else if (strcmp(name, "Undelete") == 0) {
-		xar->xmlsts = FILE_EXT2_Undelete;
-		flag = "nouunlink";
-	}
-	else if (strcmp(name, "Compress") == 0) {
-		xar->xmlsts = FILE_EXT2_Compress;
-		flag = "compress";
-	}
-	else if (strcmp(name, "Synchronous") == 0) {
-		xar->xmlsts = FILE_EXT2_Synchronous;
-		flag = "sync";
-	}
-	else if (strcmp(name, "Immutable") == 0) {
-		xar->xmlsts = FILE_EXT2_Immutable;
-		flag = "simmutable";
-	}
-	else if (strcmp(name, "AppendOnly") == 0) {
-		xar->xmlsts = FILE_EXT2_AppendOnly;
-		flag = "sappend";
-	}
-	else if (strcmp(name, "NoDump") == 0) {
-		xar->xmlsts = FILE_EXT2_NoDump;
-		flag = "nodump";
-	}
-	else if (strcmp(name, "NoAtime") == 0) {
-		xar->xmlsts = FILE_EXT2_NoAtime;
-		flag = "noatime";
-	}
-	else if (strcmp(name, "CompDirty") == 0) {
-		xar->xmlsts = FILE_EXT2_CompDirty;
-		flag = "compdirty";
-	}
-	else if (strcmp(name, "CompBlock") == 0) {
-		xar->xmlsts = FILE_EXT2_CompBlock;
-		flag = "comprblk";
-	}
-	else if (strcmp(name, "NoCompBlock") == 0) {
-		xar->xmlsts = FILE_EXT2_NoCompBlock;
-		flag = "nocomprblk";
-	}
-	else if (strcmp(name, "CompError") == 0) {
-		xar->xmlsts = FILE_EXT2_CompError;
-		flag = "comperr";
-	}
-	else if (strcmp(name, "BTree") == 0) {
-		xar->xmlsts = FILE_EXT2_BTree;
-		flag = "btree";
-	}
-	else if (strcmp(name, "HashIndexed") == 0) {
-		xar->xmlsts = FILE_EXT2_HashIndexed;
-		flag = "hashidx";
-	}
-	else if (strcmp(name, "iMagic") == 0) {
-		xar->xmlsts = FILE_EXT2_iMagic;
-		flag = "imagic";
-	}
-	else if (strcmp(name, "Journaled") == 0) {
-		xar->xmlsts = FILE_EXT2_Journaled;
-		flag = "journal";
-	}
-	else if (strcmp(name, "NoTail") == 0) {
-		xar->xmlsts = FILE_EXT2_NoTail;
-		flag = "notail";
-	}
-	else if (strcmp(name, "DirSync") == 0) {
-		xar->xmlsts = FILE_EXT2_DirSync;
-		flag = "dirsync";
-	}
-	else if (strcmp(name, "TopDir") == 0) {
-		xar->xmlsts = FILE_EXT2_TopDir;
-		flag = "topdir";
-	}
-	else if (strcmp(name, "Reserved") == 0) {
-		xar->xmlsts = FILE_EXT2_Reserved;
-		flag = "reserved";
-	}
-
-	if (flag == NULL)
-		return (0);
-	if (archive_strlen(&(xar->file->fflags_text)) > 0)
-		archive_strappend_char(&(xar->file->fflags_text), ',');
-	archive_strcat(&(xar->file->fflags_text), flag);
-	return (1);
-}
-
-#ifdef HAVE_LIBXML_XMLREADER_H
-
-static int
-xml2_xmlattr_setup(struct archive_read *a,
-    struct xmlattr_list *list, xmlTextReaderPtr reader)
-{
-	struct xmlattr *attr;
-	int r;
-
-	list->first = NULL;
-	list->last = &(list->first);
-	r = xmlTextReaderMoveToFirstAttribute(reader);
-	while (r == 1) {
-		attr = malloc(sizeof*(attr));
-		if (attr == NULL) {
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		attr->name = strdup(
-		    (const char *)xmlTextReaderConstLocalName(reader));
-		if (attr->name == NULL) {
-			free(attr);
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		attr->value = strdup(
-		    (const char *)xmlTextReaderConstValue(reader));
-		if (attr->value == NULL) {
-			free(attr->name);
-			free(attr);
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			return (ARCHIVE_FATAL);
-		}
-		attr->next = NULL;
-		*list->last = attr;
-		list->last = &(attr->next);
-		r = xmlTextReaderMoveToNextAttribute(reader);
-	}
-	return (r);
-}
-
-static int
-xml2_read_cb(void *context, char *buffer, int len)
-{
-	struct archive_read *a;
-	struct xar *xar;
-	const void *d;
-	size_t outbytes;
-	size_t used = 0;
-	int r;
-
-	a = (struct archive_read *)context;
-	xar = (struct xar *)(a->format->data);
-
-	if (xar->toc_remaining <= 0)
-		return (0);
-	d = buffer;
-	outbytes = len;
-	r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining);
-	if (r != ARCHIVE_OK)
-		return (r);
-	__archive_read_consume(a, used);
-	xar->toc_remaining -= used;
-	xar->offset += used;
-	xar->toc_total += outbytes;
-	PRINT_TOC(buffer, len);
-
-	return ((int)outbytes);
-}
-
-static int
-xml2_close_cb(void *context)
-{
-
-	(void)context; /* UNUSED */
-	return (0);
-}
-
-static void
-xml2_error_hdr(void *arg, const char *msg, xmlParserSeverities severity,
-    xmlTextReaderLocatorPtr locator)
-{
-	struct archive_read *a;
-
-	(void)locator; /* UNUSED */
-	a = (struct archive_read *)arg;
-	switch (severity) {
-	case XML_PARSER_SEVERITY_VALIDITY_WARNING:
-	case XML_PARSER_SEVERITY_WARNING:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "XML Parsing error: %s", msg);
-		break;
-	case XML_PARSER_SEVERITY_VALIDITY_ERROR:
-	case XML_PARSER_SEVERITY_ERROR:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "XML Parsing error: %s", msg);
-		break;
-	}
-}
-
-static int
-xml2_read_toc(struct archive_read *a)
-{
-	xmlTextReaderPtr reader;
-	struct xmlattr_list list;
-	int r;
-
-	reader = xmlReaderForIO(xml2_read_cb, xml2_close_cb, a, NULL, NULL, 0);
-	if (reader == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Couldn't allocate memory for xml parser");
-		return (ARCHIVE_FATAL);
-	}
-	xmlTextReaderSetErrorHandler(reader, xml2_error_hdr, a);
-
-	while ((r = xmlTextReaderRead(reader)) == 1) {
-		const char *name, *value;
-		int type, empty;
-
-		type = xmlTextReaderNodeType(reader);
-		name = (const char *)xmlTextReaderConstLocalName(reader);
-		switch (type) {
-		case XML_READER_TYPE_ELEMENT:
-			empty = xmlTextReaderIsEmptyElement(reader);
-			r = xml2_xmlattr_setup(a, &list, reader);
-			if (r == ARCHIVE_OK)
-				r = xml_start(a, name, &list);
-			xmlattr_cleanup(&list);
-			if (r != ARCHIVE_OK)
-				return (r);
-			if (empty)
-				xml_end(a, name);
-			break;
-		case XML_READER_TYPE_END_ELEMENT:
-			xml_end(a, name);
-			break;
-		case XML_READER_TYPE_TEXT:
-			value = (const char *)xmlTextReaderConstValue(reader);
-			xml_data(a, value, strlen(value));
-			break;
-		case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
-		default:
-			break;
-		}
-		if (r < 0)
-			break;
-	}
-	xmlFreeTextReader(reader);
-	xmlCleanupParser();
-
-	return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL);
-}
-
-#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
-
-static int
-expat_xmlattr_setup(struct archive_read *a,
-    struct xmlattr_list *list, const XML_Char **atts)
-{
-	struct xmlattr *attr;
-	char *name, *value;
-
-	list->first = NULL;
-	list->last = &(list->first);
-	if (atts == NULL)
-		return (ARCHIVE_OK);
-	while (atts[0] != NULL && atts[1] != NULL) {
-		attr = malloc(sizeof*(attr));
-		name = strdup(atts[0]);
-		value = strdup(atts[1]);
-		if (attr == NULL || name == NULL || value == NULL) {
-			archive_set_error(&a->archive, ENOMEM, "Out of memory");
-			free(attr);
-			free(name);
-			free(value);
-			return (ARCHIVE_FATAL);
-		}
-		attr->name = name;
-		attr->value = value;
-		attr->next = NULL;
-		*list->last = attr;
-		list->last = &(attr->next);
-		atts += 2;
-	}
-	return (ARCHIVE_OK);
-}
-
-static void
-expat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts)
-{
-	struct expat_userData *ud = (struct expat_userData *)userData;
-	struct archive_read *a = ud->archive;
-	struct xmlattr_list list;
-	int r;
-
-	r = expat_xmlattr_setup(a, &list, atts);
-	if (r == ARCHIVE_OK)
-		r = xml_start(a, (const char *)name, &list);
-	xmlattr_cleanup(&list);
-	ud->state = r;
-}
-
-static void
-expat_end_cb(void *userData, const XML_Char *name)
-{
-	struct expat_userData *ud = (struct expat_userData *)userData;
-
-	xml_end(ud->archive, (const char *)name);
-}
-
-static void
-expat_data_cb(void *userData, const XML_Char *s, int len)
-{
-	struct expat_userData *ud = (struct expat_userData *)userData;
-
-	xml_data(ud->archive, s, len);
-}
-
-static int
-expat_read_toc(struct archive_read *a)
-{
-	struct xar *xar;
-	XML_Parser parser;
-	struct expat_userData ud;
-
-	ud.state = ARCHIVE_OK;
-	ud.archive = a;
-
-	xar = (struct xar *)(a->format->data);
-
-	/* Initialize XML Parser library. */
-	parser = XML_ParserCreate(NULL);
-	if (parser == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Couldn't allocate memory for xml parser");
-		return (ARCHIVE_FATAL);
-	}
-	XML_SetUserData(parser, &ud);
-	XML_SetElementHandler(parser, expat_start_cb, expat_end_cb);
-	XML_SetCharacterDataHandler(parser, expat_data_cb);
-	xar->xmlsts = INIT;
-
-	while (xar->toc_remaining && ud.state == ARCHIVE_OK) {
-		enum XML_Status xr;
-		const void *d;
-		size_t outbytes;
-		size_t used;
-		int r;
-
-		d = NULL;
-		r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining);
-		if (r != ARCHIVE_OK)
-			return (r);
-		xar->toc_remaining -= used;
-		xar->offset += used;
-		xar->toc_total += outbytes;
-		PRINT_TOC(d, outbytes);
-
-		xr = XML_Parse(parser, d, outbytes, xar->toc_remaining == 0);
-		__archive_read_consume(a, used);
-		if (xr == XML_STATUS_ERROR) {
-			XML_ParserFree(parser);
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "XML Parsing failed");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	XML_ParserFree(parser);
-	return (ud.state);
-}
-#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */
-
-#endif /* Support xar format */
diff --git a/c/archive_read_support_format_zip.c b/c/archive_read_support_format_zip.c
deleted file mode 100644
--- a/c/archive_read_support_format_zip.c
+++ /dev/null
@@ -1,4270 +0,0 @@
-/*-
- * Copyright (c) 2004-2013 Tim Kientzle
- * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA
- * Copyright (c) 2013 Konrad Kleine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 2009-12-28 03:11:36Z kientzle $");
-
-/*
- * The definitive documentation of the Zip file format is:
- *   http://www.pkware.com/documents/casestudies/APPNOTE.TXT
- *
- * The Info-Zip project has pioneered various extensions to better
- * support Zip on Unix, including the 0x5455 "UT", 0x5855 "UX", 0x7855
- * "Ux", and 0x7875 "ux" extensions for time and ownership
- * information.
- *
- * History of this code: The streaming Zip reader was first added to
- * libarchive in January 2005.  Support for seekable input sources was
- * added in Nov 2011.  Zip64 support (including a significant code
- * refactoring) was added in 2014.
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_ZSTD_H
-#include <zstd.h>
-#endif
-
-#include "archive.h"
-#include "archive_digest_private.h"
-#include "archive_cryptor_private.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_hmac_private.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_read_private.h"
-#include "archive_ppmd8_private.h"
-
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-
-struct zip_entry {
-	struct archive_rb_node	node;
-	struct zip_entry	*next;
-	int64_t			local_header_offset;
-	int64_t			compressed_size;
-	int64_t			uncompressed_size;
-	int64_t			gid;
-	int64_t			uid;
-	struct archive_string	rsrcname;
-	time_t			mtime;
-	time_t			atime;
-	time_t			ctime;
-	uint32_t		crc32;
-	uint16_t		mode;
-	uint16_t		zip_flags; /* From GP Flags Field */
-	unsigned char		compression;
-	unsigned char		system; /* From "version written by" */
-	unsigned char		flags; /* Our extra markers. */
-	unsigned char		decdat;/* Used for Decryption check */
-
-	/* WinZip AES encryption extra field should be available
-	 * when compression is 99. */
-	struct {
-		/* Vendor version: AE-1 - 0x0001, AE-2 - 0x0002 */
-		unsigned	vendor;
-#define AES_VENDOR_AE_1	0x0001
-#define AES_VENDOR_AE_2	0x0002
-		/* AES encryption strength:
-		 * 1 - 128 bits, 2 - 192 bits, 2 - 256 bits. */
-		unsigned	strength;
-		/* Actual compression method. */
-		unsigned char	compression;
-	}			aes_extra;
-};
-
-struct trad_enc_ctx {
-	uint32_t	keys[3];
-};
-
-/* Bits used in zip_flags. */
-#define ZIP_ENCRYPTED	(1 << 0)
-#define ZIP_LENGTH_AT_END	(1 << 3)
-#define ZIP_STRONG_ENCRYPTED	(1 << 6)
-#define ZIP_UTF8_NAME	(1 << 11)
-/* See "7.2 Single Password Symmetric Encryption Method"
-   in http://www.pkware.com/documents/casestudies/APPNOTE.TXT */
-#define ZIP_CENTRAL_DIRECTORY_ENCRYPTED	(1 << 13)
-
-/* Bits used in flags. */
-#define LA_USED_ZIP64	(1 << 0)
-#define LA_FROM_CENTRAL_DIRECTORY (1 << 1)
-
-/*
- * See "WinZip - AES Encryption Information"
- *     http://www.winzip.com/aes_info.htm
- */
-/* Value used in compression method. */
-#define WINZIP_AES_ENCRYPTION	99
-/* Authentication code size. */
-#define AUTH_CODE_SIZE	10
-/**/
-#define MAX_DERIVED_KEY_BUF_SIZE	(AES_MAX_KEY_SIZE * 2 + 2)
-
-struct zip {
-	/* Structural information about the archive. */
-	struct archive_string	format_name;
-	int64_t			central_directory_offset;
-	int64_t			central_directory_offset_adjusted;
-	size_t			central_directory_entries_total;
-	size_t			central_directory_entries_on_this_disk;
-	int			has_encrypted_entries;
-
-	/* List of entries (seekable Zip only) */
-	struct zip_entry	*zip_entries;
-	struct archive_rb_tree	tree;
-	struct archive_rb_tree	tree_rsrc;
-
-	/* Bytes read but not yet consumed via __archive_read_consume() */
-	size_t			unconsumed;
-
-	/* Information about entry we're currently reading. */
-	struct zip_entry	*entry;
-	int64_t			entry_bytes_remaining;
-
-	/* These count the number of bytes actually read for the entry. */
-	int64_t			entry_compressed_bytes_read;
-	int64_t			entry_uncompressed_bytes_read;
-
-	/* Running CRC32 of the decompressed data */
-	unsigned long		entry_crc32;
-	unsigned long		(*crc32func)(unsigned long, const void *,
-				    size_t);
-	char			ignore_crc32;
-
-	/* Flags to mark progress of decompression. */
-	char			decompress_init;
-	char			end_of_entry;
-
-	unsigned char 		*uncompressed_buffer;
-	size_t 			uncompressed_buffer_size;
-
-#ifdef HAVE_ZLIB_H
-	z_stream		stream;
-	char			stream_valid;
-#endif
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	lzma_stream		zipx_lzma_stream;
-	char            zipx_lzma_valid;
-#endif
-
-#ifdef HAVE_BZLIB_H
-	bz_stream		bzstream;
-	char            bzstream_valid;
-#endif
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-	ZSTD_DStream	*zstdstream;
-	char            zstdstream_valid;
-#endif
-
-	IByteIn			zipx_ppmd_stream;
-	ssize_t			zipx_ppmd_read_compressed;
-	CPpmd8			ppmd8;
-	char			ppmd8_valid;
-	char			ppmd8_stream_failed;
-
-	struct archive_string_conv *sconv;
-	struct archive_string_conv *sconv_default;
-	struct archive_string_conv *sconv_utf8;
-	int			init_default_conversion;
-	int			process_mac_extensions;
-
-	char			init_decryption;
-
-	/* Decryption buffer. */
-	/*
-	 * The decrypted data starts at decrypted_ptr and
-	 * extends for decrypted_bytes_remaining.  Decryption
-	 * adds new data to the end of this block, data is returned
-	 * to clients from the beginning.  When the block hits the
-	 * end of decrypted_buffer, it has to be shuffled back to
-	 * the beginning of the buffer.
-	 */
-	unsigned char 		*decrypted_buffer;
-	unsigned char 		*decrypted_ptr;
-	size_t 			decrypted_buffer_size;
-	size_t 			decrypted_bytes_remaining;
-	size_t 			decrypted_unconsumed_bytes;
-
-	/* Traditional PKWARE decryption. */
-	struct trad_enc_ctx	tctx;
-	char			tctx_valid;
-
-	/* WinZip AES decryption. */
-	/* Contexts used for AES decryption. */
-	archive_crypto_ctx	cctx;
-	char			cctx_valid;
-	archive_hmac_sha1_ctx	hctx;
-	char			hctx_valid;
-
-	/* Strong encryption's decryption header information. */
-	unsigned		iv_size;
-	unsigned		alg_id;
-	unsigned		bit_len;
-	unsigned		flags;
-	unsigned		erd_size;
-	unsigned		v_size;
-	unsigned		v_crc32;
-	uint8_t			*iv;
-	uint8_t			*erd;
-	uint8_t			*v_data;
-};
-
-/* Many systems define min or MIN, but not all. */
-#define	zipmin(a,b) ((a) < (b) ? (a) : (b))
-
-#ifdef HAVE_ZLIB_H
-static int
-zip_read_data_deflate(struct archive_read *a, const void **buff,
-	size_t *size, int64_t *offset);
-#endif
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-static int
-zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
-	size_t *size, int64_t *offset);
-#endif
-
-/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
- * streams inside ZIP files. It has 2 purposes: one is to fetch the next
- * compressed byte from the stream, second one is to increase the counter how
- * many compressed bytes were read. */
-static Byte
-ppmd_read(void* p) {
-	/* Get the handle to current decompression context. */
-	struct archive_read *a = ((IByteIn*)p)->a;
-	struct zip *zip = (struct zip*) a->format->data;
-	ssize_t bytes_avail = 0;
-
-	/* Fetch next byte. */
-	const uint8_t* data = __archive_read_ahead(a, 1, &bytes_avail);
-	if(bytes_avail < 1) {
-		zip->ppmd8_stream_failed = 1;
-		return 0;
-	}
-
-	__archive_read_consume(a, 1);
-
-	/* Increment the counter. */
-	++zip->zipx_ppmd_read_compressed;
-
-	/* Return the next compressed byte. */
-	return data[0];
-}
-
-/* ------------------------------------------------------------------------ */
-
-/*
-  Traditional PKWARE Decryption functions.
- */
-
-static void
-trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
-{
-	uint8_t t;
-#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL)
-
-	ctx->keys[0] = CRC32(ctx->keys[0], c);
-	ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1;
-	t = (ctx->keys[1] >> 24) & 0xff;
-	ctx->keys[2] = CRC32(ctx->keys[2], t);
-#undef CRC32
-}
-
-static uint8_t
-trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
-{
-	unsigned temp = ctx->keys[2] | 2;
-	return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
-}
-
-static void
-trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
-    size_t in_len, uint8_t *out, size_t out_len)
-{
-	unsigned i, max;
-
-	max = (unsigned)((in_len < out_len)? in_len: out_len);
-
-	for (i = 0; i < max; i++) {
-		uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
-		out[i] = t;
-		trad_enc_update_keys(ctx, t);
-	}
-}
-
-static int
-trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len,
-    const uint8_t *key, size_t key_len, uint8_t *crcchk)
-{
-	uint8_t header[12];
-
-	if (key_len < 12) {
-		*crcchk = 0xff;
-		return -1;
-	}
-
-	ctx->keys[0] = 305419896L;
-	ctx->keys[1] = 591751049L;
-	ctx->keys[2] = 878082192L;
-
-	for (;pw_len; --pw_len)
-		trad_enc_update_keys(ctx, *pw++);
-
-	trad_enc_decrypt_update(ctx, key, 12, header, 12);
-	/* Return the last byte for CRC check. */
-	*crcchk = header[11];
-	return 0;
-}
-
-#if 0
-static void
-crypt_derive_key_sha1(const void *p, int size, unsigned char *key,
-    int key_size)
-{
-#define MD_SIZE 20
-	archive_sha1_ctx ctx;
-	unsigned char md1[MD_SIZE];
-	unsigned char md2[MD_SIZE * 2];
-	unsigned char mkb[64];
-	int i;
-
-	archive_sha1_init(&ctx);
-	archive_sha1_update(&ctx, p, size);
-	archive_sha1_final(&ctx, md1);
-
-	memset(mkb, 0x36, sizeof(mkb));
-	for (i = 0; i < MD_SIZE; i++)
-		mkb[i] ^= md1[i];
-	archive_sha1_init(&ctx);
-	archive_sha1_update(&ctx, mkb, sizeof(mkb));
-	archive_sha1_final(&ctx, md2);
-
-	memset(mkb, 0x5C, sizeof(mkb));
-	for (i = 0; i < MD_SIZE; i++)
-		mkb[i] ^= md1[i];
-	archive_sha1_init(&ctx);
-	archive_sha1_update(&ctx, mkb, sizeof(mkb));
-	archive_sha1_final(&ctx, md2 + MD_SIZE);
-
-	if (key_size > 32)
-		key_size = 32;
-	memcpy(key, md2, key_size);
-#undef MD_SIZE
-}
-#endif
-
-/*
- * Common code for streaming or seeking modes.
- *
- * Includes code to read local file headers, decompress data
- * from entry bodies, and common API.
- */
-
-static unsigned long
-real_crc32(unsigned long crc, const void *buff, size_t len)
-{
-	return crc32(crc, buff, (unsigned int)len);
-}
-
-/* Used by "ignorecrc32" option to speed up tests. */
-static unsigned long
-fake_crc32(unsigned long crc, const void *buff, size_t len)
-{
-	(void)crc; /* UNUSED */
-	(void)buff; /* UNUSED */
-	(void)len; /* UNUSED */
-	return 0;
-}
-
-static const struct {
-	int id;
-	const char * name;
-} compression_methods[] = {
-	{0, "uncompressed"}, /* The file is stored (no compression) */
-	{1, "shrinking"}, /* The file is Shrunk */
-	{2, "reduced-1"}, /* The file is Reduced with compression factor 1 */
-	{3, "reduced-2"}, /* The file is Reduced with compression factor 2 */
-	{4, "reduced-3"}, /* The file is Reduced with compression factor 3 */
-	{5, "reduced-4"}, /* The file is Reduced with compression factor 4 */
-	{6, "imploded"},  /* The file is Imploded */
-	{7, "reserved"},  /* Reserved for Tokenizing compression algorithm */
-	{8, "deflation"}, /* The file is Deflated */
-	{9, "deflation-64-bit"}, /* Enhanced Deflating using Deflate64(tm) */
-	{10, "ibm-terse"},/* PKWARE Data Compression Library Imploding
-			   * (old IBM TERSE) */
-	{11, "reserved"}, /* Reserved by PKWARE */
-	{12, "bzip"},     /* File is compressed using BZIP2 algorithm */
-	{13, "reserved"}, /* Reserved by PKWARE */
-	{14, "lzma"},     /* LZMA (EFS) */
-	{15, "reserved"}, /* Reserved by PKWARE */
-	{16, "reserved"}, /* Reserved by PKWARE */
-	{17, "reserved"}, /* Reserved by PKWARE */
-	{18, "ibm-terse-new"}, /* File is compressed using IBM TERSE (new) */
-	{19, "ibm-lz777"},/* IBM LZ77 z Architecture (PFS) */
-	{93, "zstd"},     /*  Zstandard (zstd) Compression */
-	{95, "xz"},       /* XZ compressed data */
-	{96, "jpeg"},     /* JPEG compressed data */
-	{97, "wav-pack"}, /* WavPack compressed data */
-	{98, "ppmd-1"},   /* PPMd version I, Rev 1 */
-	{99, "aes"}       /* WinZip AES encryption  */
-};
-
-static const char *
-compression_name(const int compression)
-{
-	static const int num_compression_methods =
-		sizeof(compression_methods)/sizeof(compression_methods[0]);
-	int i=0;
-
-	while(compression >= 0 && i < num_compression_methods) {
-		if (compression_methods[i].id == compression)
-			return compression_methods[i].name;
-		i++;
-	}
-	return "??";
-}
-
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-zip_time(const char *p)
-{
-	int msTime, msDate;
-	struct tm ts;
-
-	msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
-	msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
-
-	memset(&ts, 0, sizeof(ts));
-	ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
-	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
-	ts.tm_mday = msDate & 0x1f; /* Day of month. */
-	ts.tm_hour = (msTime >> 11) & 0x1f;
-	ts.tm_min = (msTime >> 5) & 0x3f;
-	ts.tm_sec = (msTime << 1) & 0x3e;
-	ts.tm_isdst = -1;
-	return mktime(&ts);
-}
-
-/*
- * The extra data is stored as a list of
- *	id1+size1+data1 + id2+size2+data2 ...
- *  triplets.  id and size are 2 bytes each.
- */
-static int
-process_extra(struct archive_read *a, struct archive_entry *entry,
-     const char *p, size_t extra_length, struct zip_entry* zip_entry)
-{
-	unsigned offset = 0;
-	struct zip *zip = (struct zip *)(a->format->data);
-
-	if (extra_length == 0) {
-		return ARCHIVE_OK;
-	}
-
-	if (extra_length < 4) {
-		size_t i = 0;
-		/* Some ZIP files may have trailing 0 bytes. Let's check they
-		 * are all 0 and ignore them instead of returning an error.
-		 *
-		 * This is not technically correct, but some ZIP files look
-		 * like this and other tools support those files - so let's
-		 * also  support them.
-		 */
-		for (; i < extra_length; i++) {
-			if (p[i] != 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Too-small extra data: "
-				    "Need at least 4 bytes, "
-				    "but only found %d bytes",
-				    (int)extra_length);
-				return ARCHIVE_FAILED;
-			}
-		}
-
-		return ARCHIVE_OK;
-	}
-
-	while (offset <= extra_length - 4) {
-		unsigned short headerid = archive_le16dec(p + offset);
-		unsigned short datasize = archive_le16dec(p + offset + 2);
-
-		offset += 4;
-		if (offset + datasize > extra_length) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT, "Extra data overflow: "
-			    "Need %d bytes but only found %d bytes",
-			    (int)datasize, (int)(extra_length - offset));
-			return ARCHIVE_FAILED;
-		}
-#ifdef DEBUG
-		fprintf(stderr, "Header id 0x%04x, length %d\n",
-		    headerid, datasize);
-#endif
-		switch (headerid) {
-		case 0x0001:
-			/* Zip64 extended information extra field. */
-			zip_entry->flags |= LA_USED_ZIP64;
-			if (zip_entry->uncompressed_size == 0xffffffff) {
-				uint64_t t = 0;
-				if (datasize < 8
-				    || (t = archive_le64dec(p + offset)) >
-				    INT64_MAX) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_FILE_FORMAT,
-					    "Malformed 64-bit "
-					    "uncompressed size");
-					return ARCHIVE_FAILED;
-				}
-				zip_entry->uncompressed_size = t;
-				offset += 8;
-				datasize -= 8;
-			}
-			if (zip_entry->compressed_size == 0xffffffff) {
-				uint64_t t = 0;
-				if (datasize < 8
-				    || (t = archive_le64dec(p + offset)) >
-				    INT64_MAX) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_FILE_FORMAT,
-					    "Malformed 64-bit "
-					    "compressed size");
-					return ARCHIVE_FAILED;
-				}
-				zip_entry->compressed_size = t;
-				offset += 8;
-				datasize -= 8;
-			}
-			if (zip_entry->local_header_offset == 0xffffffff) {
-				uint64_t t = 0;
-				if (datasize < 8
-				    || (t = archive_le64dec(p + offset)) >
-				    INT64_MAX) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_FILE_FORMAT,
-					    "Malformed 64-bit "
-					    "local header offset");
-					return ARCHIVE_FAILED;
-				}
-				zip_entry->local_header_offset = t;
-				offset += 8;
-				datasize -= 8;
-			}
-			/* archive_le32dec(p + offset) gives disk
-			 * on which file starts, but we don't handle
-			 * multi-volume Zip files. */
-			break;
-#ifdef DEBUG
-		case 0x0017:
-		{
-			/* Strong encryption field. */
-			if (archive_le16dec(p + offset) == 2) {
-				unsigned algId =
-					archive_le16dec(p + offset + 2);
-				unsigned bitLen =
-					archive_le16dec(p + offset + 4);
-				int	 flags =
-					archive_le16dec(p + offset + 6);
-				fprintf(stderr, "algId=0x%04x, bitLen=%u, "
-				    "flgas=%d\n", algId, bitLen,flags);
-			}
-			break;
-		}
-#endif
-		case 0x5455:
-		{
-			/* Extended time field "UT". */
-			int flags;
-			if (datasize == 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Incomplete extended time field");
-				return ARCHIVE_FAILED;
-			}
-			flags = p[offset];
-			offset++;
-			datasize--;
-			/* Flag bits indicate which dates are present. */
-			if (flags & 0x01)
-			{
-#ifdef DEBUG
-				fprintf(stderr, "mtime: %lld -> %d\n",
-				    (long long)zip_entry->mtime,
-				    archive_le32dec(p + offset));
-#endif
-				if (datasize < 4)
-					break;
-				zip_entry->mtime = archive_le32dec(p + offset);
-				offset += 4;
-				datasize -= 4;
-			}
-			if (flags & 0x02)
-			{
-				if (datasize < 4)
-					break;
-				zip_entry->atime = archive_le32dec(p + offset);
-				offset += 4;
-				datasize -= 4;
-			}
-			if (flags & 0x04)
-			{
-				if (datasize < 4)
-					break;
-				zip_entry->ctime = archive_le32dec(p + offset);
-				offset += 4;
-				datasize -= 4;
-			}
-			break;
-		}
-		case 0x5855:
-		{
-			/* Info-ZIP Unix Extra Field (old version) "UX". */
-			if (datasize >= 8) {
-				zip_entry->atime = archive_le32dec(p + offset);
-				zip_entry->mtime =
-				    archive_le32dec(p + offset + 4);
-			}
-			if (datasize >= 12) {
-				zip_entry->uid =
-				    archive_le16dec(p + offset + 8);
-				zip_entry->gid =
-				    archive_le16dec(p + offset + 10);
-			}
-			break;
-		}
-		case 0x6c78:
-		{
-			/* Experimental 'xl' field */
-			/*
-			 * Introduced Dec 2013 to provide a way to
-			 * include external file attributes (and other
-			 * fields that ordinarily appear only in
-			 * central directory) in local file header.
-			 * This provides file type and permission
-			 * information necessary to support full
-			 * streaming extraction.  Currently being
-			 * discussed with other Zip developers
-			 * ... subject to change.
-			 *
-			 * Format:
-			 *  The field starts with a bitmap that specifies
-			 *  which additional fields are included.  The
-			 *  bitmap is variable length and can be extended in
-			 *  the future.
-			 *
-			 *  n bytes - feature bitmap: first byte has low-order
-			 *    7 bits.  If high-order bit is set, a subsequent
-			 *    byte holds the next 7 bits, etc.
-			 *
-			 *  if bitmap & 1, 2 byte "version made by"
-			 *  if bitmap & 2, 2 byte "internal file attributes"
-			 *  if bitmap & 4, 4 byte "external file attributes"
-			 *  if bitmap & 8, 2 byte comment length + n byte
-			 *  comment
-			 */
-			int bitmap, bitmap_last;
-
-			if (datasize < 1)
-				break;
-			bitmap_last = bitmap = 0xff & p[offset];
-			offset += 1;
-			datasize -= 1;
-
-			/* We only support first 7 bits of bitmap; skip rest. */
-			while ((bitmap_last & 0x80) != 0
-			    && datasize >= 1) {
-				bitmap_last = p[offset];
-				offset += 1;
-				datasize -= 1;
-			}
-
-			if (bitmap & 1) {
-				/* 2 byte "version made by" */
-				if (datasize < 2)
-					break;
-				zip_entry->system
-				    = archive_le16dec(p + offset) >> 8;
-				offset += 2;
-				datasize -= 2;
-			}
-			if (bitmap & 2) {
-				/* 2 byte "internal file attributes" */
-				uint32_t internal_attributes;
-				if (datasize < 2)
-					break;
-				internal_attributes
-				    = archive_le16dec(p + offset);
-				/* Not used by libarchive at present. */
-				(void)internal_attributes; /* UNUSED */
-				offset += 2;
-				datasize -= 2;
-			}
-			if (bitmap & 4) {
-				/* 4 byte "external file attributes" */
-				uint32_t external_attributes;
-				if (datasize < 4)
-					break;
-				external_attributes
-				    = archive_le32dec(p + offset);
-				if (zip_entry->system == 3) {
-					zip_entry->mode
-					    = external_attributes >> 16;
-				} else if (zip_entry->system == 0) {
-					// Interpret MSDOS directory bit
-					if (0x10 == (external_attributes &
-					    0x10)) {
-						zip_entry->mode =
-						    AE_IFDIR | 0775;
-					} else {
-						zip_entry->mode =
-						    AE_IFREG | 0664;
-					}
-					if (0x01 == (external_attributes &
-					    0x01)) {
-						/* Read-only bit;
-						 * strip write permissions */
-						zip_entry->mode &= 0555;
-					}
-				} else {
-					zip_entry->mode = 0;
-				}
-				offset += 4;
-				datasize -= 4;
-			}
-			if (bitmap & 8) {
-				/* 2 byte comment length + comment */
-				uint32_t comment_length;
-				if (datasize < 2)
-					break;
-				comment_length
-				    = archive_le16dec(p + offset);
-				offset += 2;
-				datasize -= 2;
-
-				if (datasize < comment_length)
-					break;
-				/* Comment is not supported by libarchive */
-				offset += comment_length;
-				datasize -= comment_length;
-			}
-			break;
-		}
-		case 0x7075:
-		{
-			/* Info-ZIP Unicode Path Extra Field. */
-			if (datasize < 5 || entry == NULL)
-				break;
-			offset += 5;
-			datasize -= 5;
-
-			/* The path name in this field is always encoded
-			 * in UTF-8. */
-			if (zip->sconv_utf8 == NULL) {
-				zip->sconv_utf8 =
-					archive_string_conversion_from_charset(
-					&a->archive, "UTF-8", 1);
-				/* If the converter from UTF-8 is not
-				 * available, then the path name from the main
-				 * field will more likely be correct. */
-				if (zip->sconv_utf8 == NULL)
-					break;
-			}
-
-			/* Make sure the CRC32 of the filename matches. */
-			if (!zip->ignore_crc32) {
-				const char *cp = archive_entry_pathname(entry);
-				if (cp) {
-					unsigned long file_crc =
-					    zip->crc32func(0, cp, strlen(cp));
-					unsigned long utf_crc =
-					    archive_le32dec(p + offset - 4);
-					if (file_crc != utf_crc) {
-#ifdef DEBUG
-						fprintf(stderr,
-						    "CRC filename mismatch; "
-						    "CDE is %lx, but UTF8 "
-						    "is outdated with %lx\n",
-						    file_crc, utf_crc);
-#endif
-						break;
-					}
-				}
-			}
-
-			if (archive_entry_copy_pathname_l(entry,
-			    p + offset, datasize, zip->sconv_utf8) != 0) {
-				/* Ignore the error, and fallback to the path
-				 * name from the main field. */
-#ifdef DEBUG
-				fprintf(stderr, "Failed to read the ZIP "
-				    "0x7075 extra field path.\n");
-#endif
-			}
-			break;
-		}
-		case 0x7855:
-			/* Info-ZIP Unix Extra Field (type 2) "Ux". */
-#ifdef DEBUG
-			fprintf(stderr, "uid %d gid %d\n",
-			    archive_le16dec(p + offset),
-			    archive_le16dec(p + offset + 2));
-#endif
-			if (datasize >= 2)
-				zip_entry->uid = archive_le16dec(p + offset);
-			if (datasize >= 4)
-				zip_entry->gid =
-				    archive_le16dec(p + offset + 2);
-			break;
-		case 0x7875:
-		{
-			/* Info-Zip Unix Extra Field (type 3) "ux". */
-			int uidsize = 0, gidsize = 0;
-
-			/* TODO: support arbitrary uidsize/gidsize. */
-			if (datasize >= 1 && p[offset] == 1) {/* version=1 */
-				if (datasize >= 4) {
-					/* get a uid size. */
-					uidsize = 0xff & (int)p[offset+1];
-					if (uidsize == 2)
-						zip_entry->uid =
-						    archive_le16dec(
-						        p + offset + 2);
-					else if (uidsize == 4 && datasize >= 6)
-						zip_entry->uid =
-						    archive_le32dec(
-						        p + offset + 2);
-				}
-				if (datasize >= (2 + uidsize + 3)) {
-					/* get a gid size. */
-					gidsize = 0xff &
-					    (int)p[offset+2+uidsize];
-					if (gidsize == 2)
-						zip_entry->gid =
-						    archive_le16dec(
-						        p+offset+2+uidsize+1);
-					else if (gidsize == 4 &&
-					    datasize >= (2 + uidsize + 5))
-						zip_entry->gid =
-						    archive_le32dec(
-						        p+offset+2+uidsize+1);
-				}
-			}
-			break;
-		}
-		case 0x9901:
-			/* WinZip AES extra data field. */
-			if (datasize < 6) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Incomplete AES field");
-				return ARCHIVE_FAILED;
-			}
-			if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
-				/* Vendor version. */
-				zip_entry->aes_extra.vendor =
-				    archive_le16dec(p + offset);
-				/* AES encryption strength. */
-				zip_entry->aes_extra.strength = p[offset + 4];
-				/* Actual compression method. */
-				zip_entry->aes_extra.compression =
-				    p[offset + 5];
-			}
-			break;
-		default:
-			break;
-		}
-		offset += datasize;
-	}
-	return ARCHIVE_OK;
-}
-
-/*
- * Assumes file pointer is at beginning of local file header.
- */
-static int
-zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
-    struct zip *zip)
-{
-	const char *p;
-	const void *h;
-	const wchar_t *wp;
-	const char *cp;
-	size_t len, filename_length, extra_length;
-	struct archive_string_conv *sconv;
-	struct zip_entry *zip_entry = zip->entry;
-	struct zip_entry zip_entry_central_dir;
-	int ret = ARCHIVE_OK;
-	char version;
-
-	/* Save a copy of the original for consistency checks. */
-	zip_entry_central_dir = *zip_entry;
-
-	zip->decompress_init = 0;
-	zip->end_of_entry = 0;
-	zip->entry_uncompressed_bytes_read = 0;
-	zip->entry_compressed_bytes_read = 0;
-	zip->entry_crc32 = zip->crc32func(0, NULL, 0);
-
-	/* Setup default conversion. */
-	if (zip->sconv == NULL && !zip->init_default_conversion) {
-		zip->sconv_default =
-		    archive_string_default_conversion_for_read(&(a->archive));
-		zip->init_default_conversion = 1;
-	}
-
-	if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file header");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (memcmp(p, "PK\003\004", 4) != 0) {
-		archive_set_error(&a->archive, -1, "Damaged Zip archive");
-		return ARCHIVE_FATAL;
-	}
-	version = p[4];
-	zip_entry->system = p[5];
-	zip_entry->zip_flags = archive_le16dec(p + 6);
-	if (zip_entry->zip_flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) {
-		zip->has_encrypted_entries = 1;
-		archive_entry_set_is_data_encrypted(entry, 1);
-		if (zip_entry->zip_flags & ZIP_CENTRAL_DIRECTORY_ENCRYPTED &&
-			zip_entry->zip_flags & ZIP_ENCRYPTED &&
-			zip_entry->zip_flags & ZIP_STRONG_ENCRYPTED) {
-			archive_entry_set_is_metadata_encrypted(entry, 1);
-			return ARCHIVE_FATAL;
-		}
-	}
-	zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
-	zip_entry->compression = (char)archive_le16dec(p + 8);
-	zip_entry->mtime = zip_time(p + 10);
-	zip_entry->crc32 = archive_le32dec(p + 14);
-	if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
-		zip_entry->decdat = p[11];
-	else
-		zip_entry->decdat = p[17];
-	zip_entry->compressed_size = archive_le32dec(p + 18);
-	zip_entry->uncompressed_size = archive_le32dec(p + 22);
-	filename_length = archive_le16dec(p + 26);
-	extra_length = archive_le16dec(p + 28);
-
-	__archive_read_consume(a, 30);
-
-	/* Read the filename. */
-	if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file header");
-		return (ARCHIVE_FATAL);
-	}
-	if (zip_entry->zip_flags & ZIP_UTF8_NAME) {
-		/* The filename is stored to be UTF-8. */
-		if (zip->sconv_utf8 == NULL) {
-			zip->sconv_utf8 =
-			    archive_string_conversion_from_charset(
-				&a->archive, "UTF-8", 1);
-			if (zip->sconv_utf8 == NULL)
-				return (ARCHIVE_FATAL);
-		}
-		sconv = zip->sconv_utf8;
-	} else if (zip->sconv != NULL)
-		sconv = zip->sconv;
-	else
-		sconv = zip->sconv_default;
-
-	if (archive_entry_copy_pathname_l(entry,
-	    h, filename_length, sconv) != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Pathname cannot be converted "
-		    "from %s to current locale.",
-		    archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	__archive_read_consume(a, filename_length);
-
-	/* Read the extra data. */
-	if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file header");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (ARCHIVE_OK != process_extra(a, entry, h, extra_length,
-	    zip_entry)) {
-		return ARCHIVE_FATAL;
-	}
-	__archive_read_consume(a, extra_length);
-
-	/* Work around a bug in Info-Zip: When reading from a pipe, it
-	 * stats the pipe instead of synthesizing a file entry. */
-	if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) {
-		zip_entry->mode &= ~ AE_IFMT;
-		zip_entry->mode |= AE_IFREG;
-	}
-
-	/* If the mode is totally empty, set some sane default. */
-	if (zip_entry->mode == 0) {
-		zip_entry->mode |= 0664;
-	}
-
-	/* Windows archivers sometimes use backslash as the directory
-	 * separator. Normalize to slash. */
-	if (zip_entry->system == 0 &&
-	    (wp = archive_entry_pathname_w(entry)) != NULL) {
-		if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
-			size_t i;
-			struct archive_wstring s;
-			archive_string_init(&s);
-			archive_wstrcpy(&s, wp);
-			for (i = 0; i < archive_strlen(&s); i++) {
-				if (s.s[i] == '\\')
-					s.s[i] = '/';
-			}
-			archive_entry_copy_pathname_w(entry, s.s);
-			archive_wstring_free(&s);
-		}
-	}
-
-	/* Make sure that entries with a trailing '/' are marked as directories
-	 * even if the External File Attributes contains bogus values.  If this
-	 * is not a directory and there is no type, assume a regular file. */
-	if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
-		int has_slash;
-
-		wp = archive_entry_pathname_w(entry);
-		if (wp != NULL) {
-			len = wcslen(wp);
-			has_slash = len > 0 && wp[len - 1] == L'/';
-		} else {
-			cp = archive_entry_pathname(entry);
-			len = (cp != NULL)?strlen(cp):0;
-			has_slash = len > 0 && cp[len - 1] == '/';
-		}
-		/* Correct file type as needed. */
-		if (has_slash) {
-			zip_entry->mode &= ~AE_IFMT;
-			zip_entry->mode |= AE_IFDIR;
-			zip_entry->mode |= 0111;
-		} else if ((zip_entry->mode & AE_IFMT) == 0) {
-			zip_entry->mode |= AE_IFREG;
-		}
-	}
-
-	/* Make sure directories end in '/' */
-	if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) {
-		wp = archive_entry_pathname_w(entry);
-		if (wp != NULL) {
-			len = wcslen(wp);
-			if (len > 0 && wp[len - 1] != L'/') {
-				struct archive_wstring s;
-				archive_string_init(&s);
-				archive_wstrcat(&s, wp);
-				archive_wstrappend_wchar(&s, L'/');
-				archive_entry_copy_pathname_w(entry, s.s);
-				archive_wstring_free(&s);
-			}
-		} else {
-			cp = archive_entry_pathname(entry);
-			len = (cp != NULL)?strlen(cp):0;
-			if (len > 0 && cp[len - 1] != '/') {
-				struct archive_string s;
-				archive_string_init(&s);
-				archive_strcat(&s, cp);
-				archive_strappend_char(&s, '/');
-				archive_entry_set_pathname(entry, s.s);
-				archive_string_free(&s);
-			}
-		}
-	}
-
-	if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) {
-		/* If this came from the central dir, its size info
-		 * is definitive, so ignore the length-at-end flag. */
-		zip_entry->zip_flags &= ~ZIP_LENGTH_AT_END;
-		/* If local header is missing a value, use the one from
-		   the central directory.  If both have it, warn about
-		   mismatches. */
-		if (zip_entry->crc32 == 0) {
-			zip_entry->crc32 = zip_entry_central_dir.crc32;
-		} else if (!zip->ignore_crc32
-		    && zip_entry->crc32 != zip_entry_central_dir.crc32) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Inconsistent CRC32 values");
-			ret = ARCHIVE_WARN;
-		}
-		if (zip_entry->compressed_size == 0) {
-			zip_entry->compressed_size
-			    = zip_entry_central_dir.compressed_size;
-		} else if (zip_entry->compressed_size
-		    != zip_entry_central_dir.compressed_size) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Inconsistent compressed size: "
-			    "%jd in central directory, %jd in local header",
-			    (intmax_t)zip_entry_central_dir.compressed_size,
-			    (intmax_t)zip_entry->compressed_size);
-			ret = ARCHIVE_WARN;
-		}
-		if (zip_entry->uncompressed_size == 0 ||
-			zip_entry->uncompressed_size == 0xffffffff) {
-			zip_entry->uncompressed_size
-			    = zip_entry_central_dir.uncompressed_size;
-		} else if (zip_entry->uncompressed_size
-		    != zip_entry_central_dir.uncompressed_size) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Inconsistent uncompressed size: "
-			    "%jd in central directory, %jd in local header",
-			    (intmax_t)zip_entry_central_dir.uncompressed_size,
-			    (intmax_t)zip_entry->uncompressed_size);
-			ret = ARCHIVE_WARN;
-		}
-	}
-
-	/* Populate some additional entry fields: */
-	archive_entry_set_mode(entry, zip_entry->mode);
-	archive_entry_set_uid(entry, zip_entry->uid);
-	archive_entry_set_gid(entry, zip_entry->gid);
-	archive_entry_set_mtime(entry, zip_entry->mtime, 0);
-	archive_entry_set_ctime(entry, zip_entry->ctime, 0);
-	archive_entry_set_atime(entry, zip_entry->atime, 0);
-
-	if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) {
-		size_t linkname_length;
-
-		if (zip_entry->compressed_size > 64 * 1024) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Zip file with oversized link entry");
-			return ARCHIVE_FATAL;
-		}
-
-		linkname_length = (size_t)zip_entry->compressed_size;
-
-		archive_entry_set_size(entry, 0);
-
-		// take into account link compression if any
-		size_t linkname_full_length = linkname_length;
-		if (zip->entry->compression != 0)
-		{
-			// symlink target string appeared to be compressed
-			int status = ARCHIVE_FATAL;
-			const void *uncompressed_buffer = NULL;
-
-			switch (zip->entry->compression)
-			{
-#if HAVE_ZLIB_H
-				case 8: /* Deflate compression. */
-					zip->entry_bytes_remaining = zip_entry->compressed_size;
-					status = zip_read_data_deflate(a, &uncompressed_buffer,
-						&linkname_full_length, NULL);
-					break;
-#endif
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-				case 14: /* ZIPx LZMA compression. */
-					/*(see zip file format specification, section 4.4.5)*/
-					zip->entry_bytes_remaining = zip_entry->compressed_size;
-					status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
-						&linkname_full_length, NULL);
-					break;
-#endif
-				default: /* Unsupported compression. */
-					break;
-			}
-			if (status == ARCHIVE_OK)
-			{
-				p = uncompressed_buffer;
-			}
-			else
-			{
-				archive_set_error(&a->archive,
-					ARCHIVE_ERRNO_FILE_FORMAT,
-					"Unsupported ZIP compression method "
-					"during decompression of link entry (%d: %s)",
-					zip->entry->compression,
-					compression_name(zip->entry->compression));
-				return ARCHIVE_FAILED;
-			}
-		}
-		else
-		{
-			p = __archive_read_ahead(a, linkname_length, NULL);
-		}
-
-		if (p == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Truncated Zip file");
-			return ARCHIVE_FATAL;
-		}
-
-		sconv = zip->sconv;
-		if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
-			sconv = zip->sconv_utf8;
-		if (sconv == NULL)
-			sconv = zip->sconv_default;
-		if (archive_entry_copy_symlink_l(entry, p, linkname_full_length,
-		    sconv) != 0) {
-			if (errno != ENOMEM && sconv == zip->sconv_utf8 &&
-			    (zip->entry->zip_flags & ZIP_UTF8_NAME))
-			    archive_entry_copy_symlink_l(entry, p,
-				linkname_full_length, NULL);
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Symlink");
-				return (ARCHIVE_FATAL);
-			}
-			/*
-			 * Since there is no character-set regulation for
-			 * symlink name, do not report the conversion error
-			 * in an automatic conversion.
-			 */
-			if (sconv != zip->sconv_utf8 ||
-			    (zip->entry->zip_flags & ZIP_UTF8_NAME) == 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Symlink cannot be converted "
-				    "from %s to current locale.",
-				    archive_string_conversion_charset_name(
-					sconv));
-				ret = ARCHIVE_WARN;
-			}
-		}
-		zip_entry->uncompressed_size = zip_entry->compressed_size = 0;
-
-		if (__archive_read_consume(a, linkname_length) < 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Read error skipping symlink target name");
-			return ARCHIVE_FATAL;
-		}
-	} else if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
-	    || zip_entry->uncompressed_size > 0) {
-		/* Set the size only if it's meaningful. */
-		archive_entry_set_size(entry, zip_entry->uncompressed_size);
-	}
-	zip->entry_bytes_remaining = zip_entry->compressed_size;
-
-	/* If there's no body, force read_data() to return EOF immediately. */
-	if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
-	    && zip->entry_bytes_remaining < 1)
-		zip->end_of_entry = 1;
-
-	/* Set up a more descriptive format name. */
-        archive_string_empty(&zip->format_name);
-	archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)",
-	    version / 10, version % 10,
-	    compression_name(zip->entry->compression));
-	a->archive.archive_format_name = zip->format_name.s;
-
-	return (ret);
-}
-
-static int
-check_authentication_code(struct archive_read *a, const void *_p)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-
-	/* Check authentication code. */
-	if (zip->hctx_valid) {
-		const void *p;
-		uint8_t hmac[20];
-		size_t hmac_len = 20;
-		int cmp;
-
-		archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len);
-		if (_p == NULL) {
-			/* Read authentication code. */
-			p = __archive_read_ahead(a, AUTH_CODE_SIZE, NULL);
-			if (p == NULL) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Truncated ZIP file data");
-				return (ARCHIVE_FATAL);
-			}
-		} else {
-			p = _p;
-		}
-		cmp = memcmp(hmac, p, AUTH_CODE_SIZE);
-		__archive_read_consume(a, AUTH_CODE_SIZE);
-		if (cmp != 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "ZIP bad Authentication code");
-			return (ARCHIVE_WARN);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Read "uncompressed" data.  There are three cases:
- *  1) We know the size of the data.  This is always true for the
- * seeking reader (we've examined the Central Directory already).
- *  2) ZIP_LENGTH_AT_END was set, but only the CRC was deferred.
- * Info-ZIP seems to do this; we know the size but have to grab
- * the CRC from the data descriptor afterwards.
- *  3) We're streaming and ZIP_LENGTH_AT_END was specified and
- * we have no size information.  In this case, we can do pretty
- * well by watching for the data descriptor record.  The data
- * descriptor is 16 bytes and includes a computed CRC that should
- * provide a strong check.
- *
- * TODO: Technically, the PK\007\010 signature is optional.
- * In the original spec, the data descriptor contained CRC
- * and size fields but had no leading signature.  In practice,
- * newer writers seem to provide the signature pretty consistently.
- *
- * For uncompressed data, the PK\007\010 marker seems essential
- * to be sure we've actually seen the end of the entry.
- *
- * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
- * zip->end_of_entry if it consumes all of the data.
- */
-static int
-zip_read_data_none(struct archive_read *a, const void **_buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip *zip;
-	const char *buff;
-	ssize_t bytes_avail;
-	int r;
-
-	(void)offset; /* UNUSED */
-
-	zip = (struct zip *)(a->format->data);
-
-	if (zip->entry->zip_flags & ZIP_LENGTH_AT_END) {
-		const char *p;
-		ssize_t grabbing_bytes = 24;
-
-		if (zip->hctx_valid)
-			grabbing_bytes += AUTH_CODE_SIZE;
-		/* Grab at least 24 bytes. */
-		buff = __archive_read_ahead(a, grabbing_bytes, &bytes_avail);
-		if (bytes_avail < grabbing_bytes) {
-			/* Zip archives have end-of-archive markers
-			   that are longer than this, so a failure to get at
-			   least 24 bytes really does indicate a truncated
-			   file. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated ZIP file data");
-			return (ARCHIVE_FATAL);
-		}
-		/* Check for a complete PK\007\010 signature, followed
-		 * by the correct 4-byte CRC. */
-		p = buff;
-		if (zip->hctx_valid)
-			p += AUTH_CODE_SIZE;
-		if (p[0] == 'P' && p[1] == 'K'
-		    && p[2] == '\007' && p[3] == '\010'
-		    && (archive_le32dec(p + 4) == zip->entry_crc32
-			|| zip->ignore_crc32
-			|| (zip->hctx_valid
-			 && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
-			if (zip->entry->flags & LA_USED_ZIP64) {
-				uint64_t compressed, uncompressed;
-				zip->entry->crc32 = archive_le32dec(p + 4);
-				compressed = archive_le64dec(p + 8);
-				uncompressed = archive_le64dec(p + 16);
-				if (compressed > INT64_MAX || uncompressed >
-				    INT64_MAX) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_FILE_FORMAT,
-					    "Overflow of 64-bit file sizes");
-					return ARCHIVE_FAILED;
-				}
-				zip->entry->compressed_size = compressed;
-				zip->entry->uncompressed_size = uncompressed;
-				zip->unconsumed = 24;
-			} else {
-				zip->entry->crc32 = archive_le32dec(p + 4);
-				zip->entry->compressed_size =
-					archive_le32dec(p + 8);
-				zip->entry->uncompressed_size =
-					archive_le32dec(p + 12);
-				zip->unconsumed = 16;
-			}
-			if (zip->hctx_valid) {
-				r = check_authentication_code(a, buff);
-				if (r != ARCHIVE_OK)
-					return (r);
-			}
-			zip->end_of_entry = 1;
-			return (ARCHIVE_OK);
-		}
-		/* If not at EOF, ensure we consume at least one byte. */
-		++p;
-
-		/* Scan forward until we see where a PK\007\010 signature
-		 * might be. */
-		/* Return bytes up until that point.  On the next call,
-		 * the code above will verify the data descriptor. */
-		while (p < buff + bytes_avail - 4) {
-			if (p[3] == 'P') { p += 3; }
-			else if (p[3] == 'K') { p += 2; }
-			else if (p[3] == '\007') { p += 1; }
-			else if (p[3] == '\010' && p[2] == '\007'
-			    && p[1] == 'K' && p[0] == 'P') {
-				if (zip->hctx_valid)
-					p -= AUTH_CODE_SIZE;
-				break;
-			} else { p += 4; }
-		}
-		bytes_avail = p - buff;
-	} else {
-		if (zip->entry_bytes_remaining == 0) {
-			zip->end_of_entry = 1;
-			if (zip->hctx_valid) {
-				r = check_authentication_code(a, NULL);
-				if (r != ARCHIVE_OK)
-					return (r);
-			}
-			return (ARCHIVE_OK);
-		}
-		/* Grab a bunch of bytes. */
-		buff = __archive_read_ahead(a, 1, &bytes_avail);
-		if (bytes_avail <= 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated ZIP file data");
-			return (ARCHIVE_FATAL);
-		}
-		if (bytes_avail > zip->entry_bytes_remaining)
-			bytes_avail = (ssize_t)zip->entry_bytes_remaining;
-	}
-	if (zip->tctx_valid || zip->cctx_valid) {
-		size_t dec_size = bytes_avail;
-
-		if (dec_size > zip->decrypted_buffer_size)
-			dec_size = zip->decrypted_buffer_size;
-		if (zip->tctx_valid) {
-			trad_enc_decrypt_update(&zip->tctx,
-			    (const uint8_t *)buff, dec_size,
-			    zip->decrypted_buffer, dec_size);
-		} else {
-			size_t dsize = dec_size;
-			archive_hmac_sha1_update(&zip->hctx,
-			    (const uint8_t *)buff, dec_size);
-			archive_decrypto_aes_ctr_update(&zip->cctx,
-			    (const uint8_t *)buff, dec_size,
-			    zip->decrypted_buffer, &dsize);
-		}
-		bytes_avail = dec_size;
-		buff = (const char *)zip->decrypted_buffer;
-	}
-	*size = bytes_avail;
-	zip->entry_bytes_remaining -= bytes_avail;
-	zip->entry_uncompressed_bytes_read += bytes_avail;
-	zip->entry_compressed_bytes_read += bytes_avail;
-	zip->unconsumed += bytes_avail;
-	*_buff = buff;
-	return (ARCHIVE_OK);
-}
-
-static int
-consume_optional_marker(struct archive_read *a, struct zip *zip)
-{
-	if (zip->end_of_entry && (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) {
-		const char *p;
-
-		if (NULL == (p = __archive_read_ahead(a, 24, NULL))) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated ZIP end-of-file record");
-			return (ARCHIVE_FATAL);
-		}
-		/* Consume the optional PK\007\010 marker. */
-		if (p[0] == 'P' && p[1] == 'K' &&
-		    p[2] == '\007' && p[3] == '\010') {
-			p += 4;
-			zip->unconsumed = 4;
-		}
-		if (zip->entry->flags & LA_USED_ZIP64) {
-			uint64_t compressed, uncompressed;
-			zip->entry->crc32 = archive_le32dec(p);
-			compressed = archive_le64dec(p + 4);
-			uncompressed = archive_le64dec(p + 12);
-			if (compressed > INT64_MAX ||
-			    uncompressed > INT64_MAX) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Overflow of 64-bit file sizes");
-				return ARCHIVE_FAILED;
-			}
-			zip->entry->compressed_size = compressed;
-			zip->entry->uncompressed_size = uncompressed;
-			zip->unconsumed += 20;
-		} else {
-			zip->entry->crc32 = archive_le32dec(p);
-			zip->entry->compressed_size = archive_le32dec(p + 4);
-			zip->entry->uncompressed_size = archive_le32dec(p + 8);
-			zip->unconsumed += 12;
-		}
-	}
-
-    return (ARCHIVE_OK);
-}
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-static int
-zipx_xz_init(struct archive_read *a, struct zip *zip)
-{
-	lzma_ret r;
-
-	if(zip->zipx_lzma_valid) {
-		lzma_end(&zip->zipx_lzma_stream);
-		zip->zipx_lzma_valid = 0;
-	}
-
-	memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
-	r = lzma_stream_decoder(&zip->zipx_lzma_stream, UINT64_MAX, 0);
-	if (r != LZMA_OK) {
-		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-		    "xz initialization failed(%d)",
-		    r);
-
-		return (ARCHIVE_FAILED);
-	}
-
-	zip->zipx_lzma_valid = 1;
-
-	free(zip->uncompressed_buffer);
-
-	zip->uncompressed_buffer_size = 256 * 1024;
-	zip->uncompressed_buffer =
-	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
-	if (zip->uncompressed_buffer == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for xz decompression");
-		    return (ARCHIVE_FATAL);
-	}
-
-	zip->decompress_init = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
-{
-	lzma_ret r;
-	const uint8_t* p;
-
-#pragma pack(push)
-#pragma pack(1)
-	struct _alone_header {
-	    uint8_t bytes[5];
-	    uint64_t uncompressed_size;
-	} alone_header;
-#pragma pack(pop)
-
-	if(zip->zipx_lzma_valid) {
-		lzma_end(&zip->zipx_lzma_stream);
-		zip->zipx_lzma_valid = 0;
-	}
-
-	/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
-	 * that is a part of XZ Utils. The stream format stored inside ZIPX
-	 * file is a modified "lzma alone" file format, that was used by the
-	 * `lzma` utility which was later deprecated in favour of `xz` utility.
- 	 * Since those formats are nearly the same, we can use a standard
-	 * "lzma alone" decoder from XZ Utils. */
-
-	memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
-	r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX);
-	if (r != LZMA_OK) {
-		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-		    "lzma initialization failed(%d)", r);
-
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Flag the cleanup function that we want our lzma-related structures
-	 * to be freed later. */
-	zip->zipx_lzma_valid = 1;
-
-	/* The "lzma alone" file format and the stream format inside ZIPx are
-	 * almost the same. Here's an example of a structure of "lzma alone"
-	 * format:
-	 *
-	 * $ cat /bin/ls | lzma | xxd | head -n 1
-	 * 00000000: 5d00 0080 00ff ffff ffff ffff ff00 2814
-	 *
-	 *    5 bytes        8 bytes        n bytes
-	 * <lzma_params><uncompressed_size><data...>
-	 *
-	 * lzma_params is a 5-byte blob that has to be decoded to extract
-	 * parameters of this LZMA stream. The uncompressed_size field is an
-	 * uint64_t value that contains information about the size of the
-	 * uncompressed file, or UINT64_MAX if this value is unknown.
-	 * The <data...> part is the actual lzma-compressed data stream.
-	 *
-	 * Now here's the structure of the stream inside the ZIPX file:
-	 *
-	 * $ cat stream_inside_zipx | xxd | head -n 1
-	 * 00000000: 0914 0500 5d00 8000 0000 2814 .... ....
-	 *
-	 *  2byte   2byte    5 bytes     n bytes
-	 * <magic1><magic2><lzma_params><data...>
-	 *
-	 * This means that the ZIPX file contains an additional magic1 and
-	 * magic2 headers, the lzma_params field contains the same parameter
-	 * set as in the "lzma alone" format, and the <data...> field is the
-	 * same as in the "lzma alone" format as well. Note that also the zipx
-	 * format is missing the uncompressed_size field.
-	 *
-	 * So, in order to use the "lzma alone" decoder for the zipx lzma
-	 * stream, we simply need to shuffle around some fields, prepare a new
-	 * lzma alone header, feed it into lzma alone decoder so it will
-	 * initialize itself properly, and then we can start feeding normal
-	 * zipx lzma stream into the decoder.
-	 */
-
-	/* Read magic1,magic2,lzma_params from the ZIPX stream. */
-	if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated lzma data");
-		return (ARCHIVE_FATAL);
-	}
-
-	if(p[2] != 0x05 || p[3] != 0x00) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid lzma data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Prepare an lzma alone header: copy the lzma_params blob into
-	 * a proper place into the lzma alone header. */
-	memcpy(&alone_header.bytes[0], p + 4, 5);
-
-	/* Initialize the 'uncompressed size' field to unknown; we'll manually
-	 * monitor how many bytes there are still to be uncompressed. */
-	alone_header.uncompressed_size = UINT64_MAX;
-
-	if(!zip->uncompressed_buffer) {
-		zip->uncompressed_buffer_size = 256 * 1024;
-		zip->uncompressed_buffer =
-			(uint8_t*) malloc(zip->uncompressed_buffer_size);
-
-		if (zip->uncompressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for lzma decompression");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	zip->zipx_lzma_stream.next_in = (void*) &alone_header;
-	zip->zipx_lzma_stream.avail_in = sizeof(alone_header);
-	zip->zipx_lzma_stream.total_in = 0;
-	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
-	zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
-	zip->zipx_lzma_stream.total_out = 0;
-
-	/* Feed only the header into the lzma alone decoder. This will
-	 * effectively initialize the decoder, and will not produce any
-	 * output bytes yet. */
-	r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
-	if (r != LZMA_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "lzma stream initialization error");
-		return ARCHIVE_FATAL;
-	}
-
-	/* We've already consumed some bytes, so take this into account. */
-	__archive_read_consume(a, 9);
-	zip->entry_bytes_remaining -= 9;
-	zip->entry_compressed_bytes_read += 9;
-
-	zip->decompress_init = 1;
-	return (ARCHIVE_OK);
-}
-
-static int
-zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
-	size_t *size, int64_t *offset)
-{
-	struct zip* zip = (struct zip *)(a->format->data);
-	int ret;
-	lzma_ret lz_ret;
-	const void* compressed_buf;
-	ssize_t bytes_avail, in_bytes, to_consume = 0;
-
-	(void) offset; /* UNUSED */
-
-	/* Initialize decompressor if not yet initialized. */
-	if (!zip->decompress_init) {
-		ret = zipx_xz_init(a, zip);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-	}
-
-	compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
-	if (bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated xz file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
-	zip->zipx_lzma_stream.next_in = compressed_buf;
-	zip->zipx_lzma_stream.avail_in = in_bytes;
-	zip->zipx_lzma_stream.total_in = 0;
-	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
-	zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
-	zip->zipx_lzma_stream.total_out = 0;
-
-	/* Perform the decompression. */
-	lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
-	switch(lz_ret) {
-		case LZMA_DATA_ERROR:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "xz data error (error %d)", (int) lz_ret);
-			return (ARCHIVE_FATAL);
-
-		case LZMA_NO_CHECK:
-		case LZMA_OK:
-			break;
-
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "xz unknown error %d", (int) lz_ret);
-			return (ARCHIVE_FATAL);
-
-		case LZMA_STREAM_END:
-			lzma_end(&zip->zipx_lzma_stream);
-			zip->zipx_lzma_valid = 0;
-
-			if((int64_t) zip->zipx_lzma_stream.total_in !=
-			    zip->entry_bytes_remaining)
-			{
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "xz premature end of stream");
-				return (ARCHIVE_FATAL);
-			}
-
-			zip->end_of_entry = 1;
-			break;
-	}
-
-	to_consume = zip->zipx_lzma_stream.total_in;
-
-	__archive_read_consume(a, to_consume);
-	zip->entry_bytes_remaining -= to_consume;
-	zip->entry_compressed_bytes_read += to_consume;
-	zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out;
-
-	*size = zip->zipx_lzma_stream.total_out;
-	*buff = zip->uncompressed_buffer;
-
-	ret = consume_optional_marker(a, zip);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip* zip = (struct zip *)(a->format->data);
-	int ret;
-	lzma_ret lz_ret;
-	const void* compressed_buf;
-	ssize_t bytes_avail, in_bytes, to_consume;
-
-	(void) offset; /* UNUSED */
-
-	/* Initialize decompressor if not yet initialized. */
-	if (!zip->decompress_init) {
-		ret = zipx_lzma_alone_init(a, zip);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-	}
-
-	/* Fetch more compressed data. The same note as in deflate handler
-	 * applies here as well:
-	 *
-	 * Note: '1' here is a performance optimization. Recall that the
-	 * decompression layer returns a count of available bytes; asking for
-	 * more than that forces the decompressor to combine reads by copying
-	 * data.
-	 */
-	compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
-	if (bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated lzma file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Set decompressor parameters. */
-	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
-
-	zip->zipx_lzma_stream.next_in = compressed_buf;
-	zip->zipx_lzma_stream.avail_in = in_bytes;
-	zip->zipx_lzma_stream.total_in = 0;
-	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
-	zip->zipx_lzma_stream.avail_out =
-		/* These lzma_alone streams lack end of stream marker, so let's
-		 * make sure the unpacker won't try to unpack more than it's
-		 * supposed to. */
-		zipmin((int64_t) zip->uncompressed_buffer_size,
-		    zip->entry->uncompressed_size -
-		    zip->entry_uncompressed_bytes_read);
-	zip->zipx_lzma_stream.total_out = 0;
-
-	/* Perform the decompression. */
-	lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
-	switch(lz_ret) {
-		case LZMA_DATA_ERROR:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "lzma data error (error %d)", (int) lz_ret);
-			return (ARCHIVE_FATAL);
-
-		/* This case is optional in lzma alone format. It can happen,
-		 * but most of the files don't have it. (GitHub #1257) */
-		case LZMA_STREAM_END:
-			lzma_end(&zip->zipx_lzma_stream);
-			zip->zipx_lzma_valid = 0;
-			if((int64_t) zip->zipx_lzma_stream.total_in !=
-			    zip->entry_bytes_remaining)
-			{
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "lzma alone premature end of stream");
-				return (ARCHIVE_FATAL);
-			}
-
-			zip->end_of_entry = 1;
-			break;
-
-		case LZMA_OK:
-			break;
-
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "lzma unknown error %d", (int) lz_ret);
-			return (ARCHIVE_FATAL);
-	}
-
-	to_consume = zip->zipx_lzma_stream.total_in;
-
-	/* Update pointers. */
-	__archive_read_consume(a, to_consume);
-	zip->entry_bytes_remaining -= to_consume;
-	zip->entry_compressed_bytes_read += to_consume;
-	zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out;
-
-	if(zip->entry_bytes_remaining == 0) {
-		zip->end_of_entry = 1;
-	}
-
-	/* Return values. */
-	*size = zip->zipx_lzma_stream.total_out;
-	*buff = zip->uncompressed_buffer;
-
-	/* Behave the same way as during deflate decompression. */
-	ret = consume_optional_marker(a, zip);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	/* Free lzma decoder handle because we'll no longer need it. */
-	if(zip->end_of_entry) {
-		lzma_end(&zip->zipx_lzma_stream);
-		zip->zipx_lzma_valid = 0;
-	}
-
-	/* If we're here, then we're good! */
-	return (ARCHIVE_OK);
-}
-#endif /* HAVE_LZMA_H && HAVE_LIBLZMA */
-
-static int
-zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
-{
-	const void* p;
-	uint32_t val;
-	uint32_t order;
-	uint32_t mem;
-	uint32_t restore_method;
-
-	/* Remove previous decompression context if it exists. */
-	if(zip->ppmd8_valid) {
-		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
-		zip->ppmd8_valid = 0;
-	}
-
-	/* Create a new decompression context. */
-	__archive_ppmd8_functions.Ppmd8_Construct(&zip->ppmd8);
-	zip->ppmd8_stream_failed = 0;
-
-	/* Setup function pointers required by Ppmd8 decompressor. The
-	 * 'ppmd_read' function will feed new bytes to the decompressor,
-	 * and will increment the 'zip->zipx_ppmd_read_compressed' counter. */
-	zip->ppmd8.Stream.In = &zip->zipx_ppmd_stream;
-	zip->zipx_ppmd_stream.a = a;
-	zip->zipx_ppmd_stream.Read = &ppmd_read;
-
-	/* Reset number of read bytes to 0. */
-	zip->zipx_ppmd_read_compressed = 0;
-
-	/* Read Ppmd8 header (2 bytes). */
-	p = __archive_read_ahead(a, 2, NULL);
-	if(!p) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated file data in PPMd8 stream");
-		return (ARCHIVE_FATAL);
-	}
-	__archive_read_consume(a, 2);
-
-	/* Decode the stream's compression parameters. */
-	val = archive_le16dec(p);
-	order = (val & 15) + 1;
-	mem = ((val >> 4) & 0xff) + 1;
-	restore_method = (val >> 12);
-
-	if(order < 2 || restore_method > 2) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Invalid parameter set in PPMd8 stream (order=%" PRId32 ", "
-		    "restore=%" PRId32 ")", order, restore_method);
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Allocate the memory needed to properly decompress the file. */
-	if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes",
-		    mem << 20);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Signal the cleanup function to release Ppmd8 context in the
-	 * cleanup phase. */
-	zip->ppmd8_valid = 1;
-
-	/* Perform further Ppmd8 initialization. */
-	if(!__archive_ppmd8_functions.Ppmd8_RangeDec_Init(&zip->ppmd8)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "PPMd8 stream range decoder initialization error");
-		return (ARCHIVE_FATAL);
-	}
-
-	__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order,
-	    restore_method);
-
-	/* Allocate the buffer that will hold uncompressed data. */
-	free(zip->uncompressed_buffer);
-
-	zip->uncompressed_buffer_size = 256 * 1024;
-	zip->uncompressed_buffer =
-	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
-
-	if(zip->uncompressed_buffer == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for PPMd8 decompression");
-		return ARCHIVE_FATAL;
-	}
-
-	/* Ppmd8 initialization is done. */
-	zip->decompress_init = 1;
-
-	/* We've already read 2 bytes in the output stream. Additionally,
-	 * Ppmd8 initialization code could read some data as well. So we
-	 * are advancing the stream by 2 bytes plus whatever number of
-	 * bytes Ppmd8 init function used. */
-	zip->entry_compressed_bytes_read += 2 + zip->zipx_ppmd_read_compressed;
-
-	return ARCHIVE_OK;
-}
-
-static int
-zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip* zip = (struct zip *)(a->format->data);
-	int ret;
-	size_t consumed_bytes = 0;
-	ssize_t bytes_avail = 0;
-
-	(void) offset; /* UNUSED */
-
-	/* If we're here for the first time, initialize Ppmd8 decompression
-	 * context first. */
-	if(!zip->decompress_init) {
-		ret = zipx_ppmd8_init(a, zip);
-		if(ret != ARCHIVE_OK)
-			return ret;
-	}
-
-	/* Fetch for more data. We're reading 1 byte here, but libarchive
-	 * should prefetch more bytes. */
-	(void) __archive_read_ahead(a, 1, &bytes_avail);
-	if(bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated PPMd8 file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* This counter will be updated inside ppmd_read(), which at one
-	 * point will be called by Ppmd8_DecodeSymbol. */
-	zip->zipx_ppmd_read_compressed = 0;
-
-	/* Decompression loop. */
-	do {
-		int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(
-		    &zip->ppmd8);
-		if(sym < 0) {
-			zip->end_of_entry = 1;
-			break;
-		}
-
-		/* This field is set by ppmd_read() when there was no more data
-		 * to be read. */
-		if(zip->ppmd8_stream_failed) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated PPMd8 file body");
-			return (ARCHIVE_FATAL);
-		}
-
-		zip->uncompressed_buffer[consumed_bytes] = (uint8_t) sym;
-		++consumed_bytes;
-	} while(consumed_bytes < zip->uncompressed_buffer_size);
-
-	/* Update pointers for libarchive. */
-	*buff = zip->uncompressed_buffer;
-	*size = consumed_bytes;
-
-	/* Update pointers so we can continue decompression in another call. */
-	zip->entry_bytes_remaining -= zip->zipx_ppmd_read_compressed;
-	zip->entry_compressed_bytes_read += zip->zipx_ppmd_read_compressed;
-	zip->entry_uncompressed_bytes_read += consumed_bytes;
-
-	/* If we're at the end of stream, deinitialize Ppmd8 context. */
-	if(zip->end_of_entry) {
-		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
-		zip->ppmd8_valid = 0;
-	}
-
-	/* Seek for optional marker, same way as in each zip entry. */
-	ret = consume_optional_marker(a, zip);
-	if (ret != ARCHIVE_OK)
-		return ret;
-
-	return ARCHIVE_OK;
-}
-
-#ifdef HAVE_BZLIB_H
-static int
-zipx_bzip2_init(struct archive_read *a, struct zip *zip)
-{
-	int r;
-
-	/* Deallocate already existing BZ2 decompression context if it
-	 * exists. */
-	if(zip->bzstream_valid) {
-		BZ2_bzDecompressEnd(&zip->bzstream);
-		zip->bzstream_valid = 0;
-	}
-
-	/* Allocate a new BZ2 decompression context. */
-	memset(&zip->bzstream, 0, sizeof(bz_stream));
-	r = BZ2_bzDecompressInit(&zip->bzstream, 0, 1);
-	if(r != BZ_OK) {
-		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
-		    "bzip2 initialization failed(%d)",
-		    r);
-
-		return ARCHIVE_FAILED;
-	}
-
-	/* Mark the bzstream field to be released in cleanup phase. */
-	zip->bzstream_valid = 1;
-
-	/* (Re)allocate the buffer that will contain decompressed bytes. */
-	free(zip->uncompressed_buffer);
-
-	zip->uncompressed_buffer_size = 256 * 1024;
-	zip->uncompressed_buffer =
-	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
-	if (zip->uncompressed_buffer == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for bzip2 decompression");
-		    return ARCHIVE_FATAL;
-	}
-
-	/* Initialization done. */
-	zip->decompress_init = 1;
-	return ARCHIVE_OK;
-}
-
-static int
-zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	ssize_t bytes_avail = 0, in_bytes, to_consume;
-	const void *compressed_buff;
-	int r;
-	uint64_t total_out;
-
-	(void) offset; /* UNUSED */
-
-	/* Initialize decompression context if we're here for the first time. */
-	if(!zip->decompress_init) {
-		r = zipx_bzip2_init(a, zip);
-		if(r != ARCHIVE_OK)
-			return r;
-	}
-
-	/* Fetch more compressed bytes. */
-	compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
-	if(bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated bzip2 file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
-	if(in_bytes < 1) {
-		/* libbz2 doesn't complain when caller feeds avail_in == 0.
-		 * It will actually return success in this case, which is
-		 * undesirable. This is why we need to make this check
-		 * manually. */
-
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated bzip2 file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Setup buffer boundaries. */
-	zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff;
-	zip->bzstream.avail_in = (uint32_t)in_bytes;
-	zip->bzstream.total_in_hi32 = 0;
-	zip->bzstream.total_in_lo32 = 0;
-	zip->bzstream.next_out = (char*) zip->uncompressed_buffer;
-	zip->bzstream.avail_out = (uint32_t)zip->uncompressed_buffer_size;
-	zip->bzstream.total_out_hi32 = 0;
-	zip->bzstream.total_out_lo32 = 0;
-
-	/* Perform the decompression. */
-	r = BZ2_bzDecompress(&zip->bzstream);
-	switch(r) {
-		case BZ_STREAM_END:
-			/* If we're at the end of the stream, deinitialize the
-			 * decompression context now. */
-			switch(BZ2_bzDecompressEnd(&zip->bzstream)) {
-				case BZ_OK:
-					break;
-				default:
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "Failed to clean up bzip2 "
-					    "decompressor");
-					return ARCHIVE_FATAL;
-			}
-
-			zip->end_of_entry = 1;
-			break;
-		case BZ_OK:
-			/* The decompressor has successfully decoded this
-			 * chunk of data, but more data is still in queue. */
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "bzip2 decompression failed");
-			return ARCHIVE_FATAL;
-	}
-
-	/* Update the pointers so decompressor can continue decoding. */
-	to_consume = zip->bzstream.total_in_lo32;
-	__archive_read_consume(a, to_consume);
-
-	total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) |
-	    zip->bzstream.total_out_lo32;
-
-	zip->entry_bytes_remaining -= to_consume;
-	zip->entry_compressed_bytes_read += to_consume;
-	zip->entry_uncompressed_bytes_read += total_out;
-
-	/* Give libarchive its due. */
-	*size = total_out;
-	*buff = zip->uncompressed_buffer;
-
-	/* Seek for optional marker, like in other entries. */
-	r = consume_optional_marker(a, zip);
-	if(r != ARCHIVE_OK)
-		return r;
-
-	return ARCHIVE_OK;
-}
-
-#endif
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-static int
-zipx_zstd_init(struct archive_read *a, struct zip *zip)
-{
-	size_t r;
-
-	/* Deallocate already existing Zstd decompression context if it
-	 * exists. */
-	if(zip->zstdstream_valid) {
-		ZSTD_freeDStream(zip->zstdstream);
-		zip->zstdstream_valid = 0;
-	}
-
-	/* Allocate a new Zstd decompression context. */
-	zip->zstdstream = ZSTD_createDStream();
-
-	r = ZSTD_initDStream(zip->zstdstream);
-	if (ZSTD_isError(r)) {
-		 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"Error initializing zstd decompressor: %s",
-			ZSTD_getErrorName(r));
-
-		return ARCHIVE_FAILED;
-	}
-
-	/* Mark the zstdstream field to be released in cleanup phase. */
-	zip->zstdstream_valid = 1;
-
-	/* (Re)allocate the buffer that will contain decompressed bytes. */
-	free(zip->uncompressed_buffer);
-
-	zip->uncompressed_buffer_size = ZSTD_DStreamOutSize();
-	zip->uncompressed_buffer =
-	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
-	if (zip->uncompressed_buffer == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-			"No memory for Zstd decompression");
-
-		return ARCHIVE_FATAL;
-	}
-
-	/* Initialization done. */
-	zip->decompress_init = 1;
-	return ARCHIVE_OK;
-}
-
-static int
-zip_read_data_zipx_zstd(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	ssize_t bytes_avail = 0, in_bytes, to_consume;
-	const void *compressed_buff;
-	int r;
-	size_t ret;
-	uint64_t total_out;
-	ZSTD_outBuffer out;
-	ZSTD_inBuffer in;
-
-	(void) offset; /* UNUSED */
-
-	/* Initialize decompression context if we're here for the first time. */
-	if(!zip->decompress_init) {
-		r = zipx_zstd_init(a, zip);
-		if(r != ARCHIVE_OK)
-			return r;
-	}
-
-	/* Fetch more compressed bytes */
-	compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
-	if(bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated zstd file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
-	if(in_bytes < 1) {
-		/* zstd doesn't complain when caller feeds avail_in == 0.
-		 * It will actually return success in this case, which is
-		 * undesirable. This is why we need to make this check
-		 * manually. */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated zstd file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Setup buffer boundaries */
-	in.src = compressed_buff;
-	in.size = in_bytes;
-	in.pos = 0;
-	out = (ZSTD_outBuffer) { zip->uncompressed_buffer, zip->uncompressed_buffer_size, 0 };
-
-	/* Perform the decompression. */
-	ret = ZSTD_decompressStream(zip->zstdstream, &out, &in);
-	if (ZSTD_isError(ret)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"Error during zstd decompression: %s",
-			ZSTD_getErrorName(ret));
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Check end of the stream. */
-	if (ret == 0) {
-		if ((in.pos == in.size) && (out.pos < out.size)) {
-			zip->end_of_entry = 1;
-			ZSTD_freeDStream(zip->zstdstream);
-			zip->zstdstream_valid = 0;
-		}
-	}
-
-	/* Update the pointers so decompressor can continue decoding. */
-	to_consume = in.pos;
-	__archive_read_consume(a, to_consume);
-
-	total_out = out.pos;
-
-	zip->entry_bytes_remaining -= to_consume;
-	zip->entry_compressed_bytes_read += to_consume;
-	zip->entry_uncompressed_bytes_read += total_out;
-
-	/* Give libarchive its due. */
-	*size = total_out;
-	*buff = zip->uncompressed_buffer;
-
-	/* Seek for optional marker, like in other entries. */
-	r = consume_optional_marker(a, zip);
-	if(r != ARCHIVE_OK)
-		return r;
-
-	return ARCHIVE_OK;
-}
-#endif
-
-#ifdef HAVE_ZLIB_H
-static int
-zip_deflate_init(struct archive_read *a, struct zip *zip)
-{
-	int r;
-
-	/* If we haven't yet read any data, initialize the decompressor. */
-	if (!zip->decompress_init) {
-		if (zip->stream_valid)
-			r = inflateReset(&zip->stream);
-		else
-			r = inflateInit2(&zip->stream,
-			    -15 /* Don't check for zlib header */);
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't initialize ZIP decompression.");
-			return (ARCHIVE_FATAL);
-		}
-		/* Stream structure has been set up. */
-		zip->stream_valid = 1;
-		/* We've initialized decompression for this stream. */
-		zip->decompress_init = 1;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-zip_read_data_deflate(struct archive_read *a, const void **buff,
-    size_t *size, int64_t *offset)
-{
-	struct zip *zip;
-	ssize_t bytes_avail;
-	const void *compressed_buff, *sp;
-	int r;
-
-	(void)offset; /* UNUSED */
-
-	zip = (struct zip *)(a->format->data);
-
-	/* If the buffer hasn't been allocated, allocate it now. */
-	if (zip->uncompressed_buffer == NULL) {
-		zip->uncompressed_buffer_size = 256 * 1024;
-		zip->uncompressed_buffer
-		    = (unsigned char *)malloc(zip->uncompressed_buffer_size);
-		if (zip->uncompressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for ZIP decompression");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	r = zip_deflate_init(a, zip);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	/*
-	 * Note: '1' here is a performance optimization.
-	 * Recall that the decompression layer returns a count of
-	 * available bytes; asking for more than that forces the
-	 * decompressor to combine reads by copying data.
-	 */
-	compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail);
-	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
-	    && bytes_avail > zip->entry_bytes_remaining) {
-		bytes_avail = (ssize_t)zip->entry_bytes_remaining;
-	}
-	if (bytes_avail < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file body");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (zip->tctx_valid || zip->cctx_valid) {
-		if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) {
-			size_t buff_remaining =
-			    (zip->decrypted_buffer +
-			    zip->decrypted_buffer_size)
-			    - (zip->decrypted_ptr +
-			    zip->decrypted_bytes_remaining);
-
-			if (buff_remaining > (size_t)bytes_avail)
-				buff_remaining = (size_t)bytes_avail;
-
-			if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) &&
-			      zip->entry_bytes_remaining > 0) {
-				if ((int64_t)(zip->decrypted_bytes_remaining
-				    + buff_remaining)
-				      > zip->entry_bytes_remaining) {
-					if (zip->entry_bytes_remaining <
-					    (int64_t)zip->decrypted_bytes_remaining)
-						buff_remaining = 0;
-					else
-						buff_remaining =
-						    (size_t)zip->entry_bytes_remaining
-						    - zip->decrypted_bytes_remaining;
-				}
-			}
-			if (buff_remaining > 0) {
-				if (zip->tctx_valid) {
-					trad_enc_decrypt_update(&zip->tctx,
-					    compressed_buff, buff_remaining,
-					    zip->decrypted_ptr
-					      + zip->decrypted_bytes_remaining,
-					    buff_remaining);
-				} else {
-					size_t dsize = buff_remaining;
-					archive_decrypto_aes_ctr_update(
-					    &zip->cctx,
-					    compressed_buff, buff_remaining,
-					    zip->decrypted_ptr
-					      + zip->decrypted_bytes_remaining,
-					    &dsize);
-				}
-				zip->decrypted_bytes_remaining +=
-				    buff_remaining;
-			}
-		}
-		bytes_avail = zip->decrypted_bytes_remaining;
-		compressed_buff = (const char *)zip->decrypted_ptr;
-	}
-
-	/*
-	 * A bug in zlib.h: stream.next_in should be marked 'const'
-	 * but isn't (the library never alters data through the
-	 * next_in pointer, only reads it).  The result: this ugly
-	 * cast to remove 'const'.
-	 */
-	zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
-	zip->stream.avail_in = (uInt)bytes_avail;
-	zip->stream.total_in = 0;
-	zip->stream.next_out = zip->uncompressed_buffer;
-	zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
-	zip->stream.total_out = 0;
-
-	r = inflate(&zip->stream, 0);
-	switch (r) {
-	case Z_OK:
-		break;
-	case Z_STREAM_END:
-		zip->end_of_entry = 1;
-		break;
-	case Z_MEM_ERROR:
-		archive_set_error(&a->archive, ENOMEM,
-		    "Out of memory for ZIP decompression");
-		return (ARCHIVE_FATAL);
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "ZIP decompression failed (%d)", r);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Consume as much as the compressor actually used. */
-	bytes_avail = zip->stream.total_in;
-	if (zip->tctx_valid || zip->cctx_valid) {
-		zip->decrypted_bytes_remaining -= bytes_avail;
-		if (zip->decrypted_bytes_remaining == 0)
-			zip->decrypted_ptr = zip->decrypted_buffer;
-		else
-			zip->decrypted_ptr += bytes_avail;
-	}
-	/* Calculate compressed data as much as we used.*/
-	if (zip->hctx_valid)
-		archive_hmac_sha1_update(&zip->hctx, sp, bytes_avail);
-	__archive_read_consume(a, bytes_avail);
-	zip->entry_bytes_remaining -= bytes_avail;
-	zip->entry_compressed_bytes_read += bytes_avail;
-
-	*size = zip->stream.total_out;
-	zip->entry_uncompressed_bytes_read += zip->stream.total_out;
-	*buff = zip->uncompressed_buffer;
-
-	if (zip->end_of_entry && zip->hctx_valid) {
-		r = check_authentication_code(a, NULL);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	r = consume_optional_marker(a, zip);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	return (ARCHIVE_OK);
-}
-#endif
-
-static int
-read_decryption_header(struct archive_read *a)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	const char *p;
-	unsigned int remaining_size;
-	unsigned int ts;
-
-	/*
-	 * Read an initialization vector data field.
-	 */
-	p = __archive_read_ahead(a, 2, NULL);
-	if (p == NULL)
-		goto truncated;
-	ts = zip->iv_size;
-	zip->iv_size = archive_le16dec(p);
-	__archive_read_consume(a, 2);
-	if (ts < zip->iv_size) {
-		free(zip->iv);
-		zip->iv = NULL;
-	}
-	p = __archive_read_ahead(a, zip->iv_size, NULL);
-	if (p == NULL)
-		goto truncated;
-	if (zip->iv == NULL) {
-		zip->iv = malloc(zip->iv_size);
-		if (zip->iv == NULL)
-			goto nomem;
-	}
-	memcpy(zip->iv, p, zip->iv_size);
-	__archive_read_consume(a, zip->iv_size);
-
-	/*
-	 * Read a size of remaining decryption header field.
-	 */
-	p = __archive_read_ahead(a, 14, NULL);
-	if (p == NULL)
-		goto truncated;
-	remaining_size = archive_le32dec(p);
-	if (remaining_size < 16 || remaining_size > (1 << 18))
-		goto corrupted;
-
-	/* Check if format version is supported. */
-	if (archive_le16dec(p+4) != 3) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported encryption format version: %u",
-		    archive_le16dec(p+4));
-		return (ARCHIVE_FAILED);
-	}
-
-	/*
-	 * Read an encryption algorithm field.
-	 */
-	zip->alg_id = archive_le16dec(p+6);
-	switch (zip->alg_id) {
-	case 0x6601:/* DES */
-	case 0x6602:/* RC2 */
-	case 0x6603:/* 3DES 168 */
-	case 0x6609:/* 3DES 112 */
-	case 0x660E:/* AES 128 */
-	case 0x660F:/* AES 192 */
-	case 0x6610:/* AES 256 */
-	case 0x6702:/* RC2 (version >= 5.2) */
-	case 0x6720:/* Blowfish */
-	case 0x6721:/* Twofish */
-	case 0x6801:/* RC4 */
-		/* Supported encryption algorithm. */
-		break;
-	default:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unknown encryption algorithm: %u", zip->alg_id);
-		return (ARCHIVE_FAILED);
-	}
-
-	/*
-	 * Read a bit length field.
-	 */
-	zip->bit_len = archive_le16dec(p+8);
-
-	/*
-	 * Read a flags field.
-	 */
-	zip->flags = archive_le16dec(p+10);
-	switch (zip->flags & 0xf000) {
-	case 0x0001: /* Password is required to decrypt. */
-	case 0x0002: /* Certificates only. */
-	case 0x0003: /* Password or certificate required to decrypt. */
-		break;
-	default:
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unknown encryption flag: %u", zip->flags);
-		return (ARCHIVE_FAILED);
-	}
-	if ((zip->flags & 0xf000) == 0 ||
-	    (zip->flags & 0xf000) == 0x4000) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unknown encryption flag: %u", zip->flags);
-		return (ARCHIVE_FAILED);
-	}
-
-	/*
-	 * Read an encrypted random data field.
-	 */
-	ts = zip->erd_size;
-	zip->erd_size = archive_le16dec(p+12);
-	__archive_read_consume(a, 14);
-	if ((zip->erd_size & 0xf) != 0 ||
-	    (zip->erd_size + 16) > remaining_size ||
-	    (zip->erd_size + 16) < zip->erd_size)
-		goto corrupted;
-
-	if (ts < zip->erd_size) {
-		free(zip->erd);
-		zip->erd = NULL;
-	}
-	p = __archive_read_ahead(a, zip->erd_size, NULL);
-	if (p == NULL)
-		goto truncated;
-	if (zip->erd == NULL) {
-		zip->erd = malloc(zip->erd_size);
-		if (zip->erd == NULL)
-			goto nomem;
-	}
-	memcpy(zip->erd, p, zip->erd_size);
-	__archive_read_consume(a, zip->erd_size);
-
-	/*
-	 * Read a reserved data field.
-	 */
-	p = __archive_read_ahead(a, 4, NULL);
-	if (p == NULL)
-		goto truncated;
-	/* Reserved data size should be zero. */
-	if (archive_le32dec(p) != 0)
-		goto corrupted;
-	__archive_read_consume(a, 4);
-
-	/*
-	 * Read a password validation data field.
-	 */
-	p = __archive_read_ahead(a, 2, NULL);
-	if (p == NULL)
-		goto truncated;
-	ts = zip->v_size;
-	zip->v_size = archive_le16dec(p);
-	__archive_read_consume(a, 2);
-	if ((zip->v_size & 0x0f) != 0 ||
-	    (zip->erd_size + zip->v_size + 16) > remaining_size ||
-	    (zip->erd_size + zip->v_size + 16) < (zip->erd_size + zip->v_size))
-		goto corrupted;
-	if (ts < zip->v_size) {
-		free(zip->v_data);
-		zip->v_data = NULL;
-	}
-	p = __archive_read_ahead(a, zip->v_size, NULL);
-	if (p == NULL)
-		goto truncated;
-	if (zip->v_data == NULL) {
-		zip->v_data = malloc(zip->v_size);
-		if (zip->v_data == NULL)
-			goto nomem;
-	}
-	memcpy(zip->v_data, p, zip->v_size);
-	__archive_read_consume(a, zip->v_size);
-
-	p = __archive_read_ahead(a, 4, NULL);
-	if (p == NULL)
-		goto truncated;
-	zip->v_crc32 = archive_le32dec(p);
-	__archive_read_consume(a, 4);
-
-	/*return (ARCHIVE_OK);
-	 * This is not fully implemented yet.*/
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Encrypted file is unsupported");
-	return (ARCHIVE_FAILED);
-truncated:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Truncated ZIP file data");
-	return (ARCHIVE_FATAL);
-corrupted:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Corrupted ZIP file data");
-	return (ARCHIVE_FATAL);
-nomem:
-	archive_set_error(&a->archive, ENOMEM,
-	    "No memory for ZIP decryption");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-zip_alloc_decryption_buffer(struct archive_read *a)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	size_t bs = 256 * 1024;
-
-	if (zip->decrypted_buffer == NULL) {
-		zip->decrypted_buffer_size = bs;
-		zip->decrypted_buffer = malloc(bs);
-		if (zip->decrypted_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for ZIP decryption");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	zip->decrypted_ptr = zip->decrypted_buffer;
-	return (ARCHIVE_OK);
-}
-
-static int
-init_traditional_PKWARE_decryption(struct archive_read *a)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	const void *p;
-	int retry;
-	int r;
-
-	if (zip->tctx_valid)
-		return (ARCHIVE_OK);
-
-	/*
-	   Read the 12 bytes encryption header stored at
-	   the start of the data area.
-	 */
-#define ENC_HEADER_SIZE	12
-	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
-	    && zip->entry_bytes_remaining < ENC_HEADER_SIZE) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated Zip encrypted body: only %jd bytes available",
-		    (intmax_t)zip->entry_bytes_remaining);
-		return (ARCHIVE_FATAL);
-	}
-
-	p = __archive_read_ahead(a, ENC_HEADER_SIZE, NULL);
-	if (p == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file data");
-		return (ARCHIVE_FATAL);
-	}
-
-	for (retry = 0;; retry++) {
-		const char *passphrase;
-		uint8_t crcchk;
-
-		passphrase = __archive_read_next_passphrase(a);
-		if (passphrase == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    (retry > 0)?
-				"Incorrect passphrase":
-				"Passphrase required for this entry");
-			return (ARCHIVE_FAILED);
-		}
-
-		/*
-		 * Initialize ctx for Traditional PKWARE Decryption.
-		 */
-		r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
-			p, ENC_HEADER_SIZE, &crcchk);
-		if (r == 0 && crcchk == zip->entry->decdat)
-			break;/* The passphrase is OK. */
-		if (retry > 10000) {
-			/* Avoid infinity loop. */
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Too many incorrect passphrases");
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	__archive_read_consume(a, ENC_HEADER_SIZE);
-	zip->tctx_valid = 1;
-	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) {
-	    zip->entry_bytes_remaining -= ENC_HEADER_SIZE;
-	}
-	/*zip->entry_uncompressed_bytes_read += ENC_HEADER_SIZE;*/
-	zip->entry_compressed_bytes_read += ENC_HEADER_SIZE;
-	zip->decrypted_bytes_remaining = 0;
-
-	return (zip_alloc_decryption_buffer(a));
-#undef ENC_HEADER_SIZE
-}
-
-static int
-init_WinZip_AES_decryption(struct archive_read *a)
-{
-	struct zip *zip = (struct zip *)(a->format->data);
-	const void *p;
-	const uint8_t *pv;
-	size_t key_len, salt_len;
-	uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE];
-	int retry;
-	int r;
-
-	if (zip->cctx_valid || zip->hctx_valid)
-		return (ARCHIVE_OK);
-
-	switch (zip->entry->aes_extra.strength) {
-	case 1: salt_len = 8;  key_len = 16; break;
-	case 2: salt_len = 12; key_len = 24; break;
-	case 3: salt_len = 16; key_len = 32; break;
-	default: goto corrupted;
-	}
-	p = __archive_read_ahead(a, salt_len + 2, NULL);
-	if (p == NULL)
-		goto truncated;
-
-	for (retry = 0;; retry++) {
-		const char *passphrase;
-
-		passphrase = __archive_read_next_passphrase(a);
-		if (passphrase == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    (retry > 0)?
-				"Incorrect passphrase":
-				"Passphrase required for this entry");
-			return (ARCHIVE_FAILED);
-		}
-		memset(derived_key, 0, sizeof(derived_key));
-		r = archive_pbkdf2_sha1(passphrase, strlen(passphrase),
-		    p, salt_len, 1000, derived_key, key_len * 2 + 2);
-		if (r != 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Decryption is unsupported due to lack of "
-			    "crypto library");
-			return (ARCHIVE_FAILED);
-		}
-
-		/* Check password verification value. */
-		pv = ((const uint8_t *)p) + salt_len;
-		if (derived_key[key_len * 2] == pv[0] &&
-		    derived_key[key_len * 2 + 1] == pv[1])
-			break;/* The passphrase is OK. */
-		if (retry > 10000) {
-			/* Avoid infinity loop. */
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Too many incorrect passphrases");
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	r = archive_decrypto_aes_ctr_init(&zip->cctx, derived_key, key_len);
-	if (r != 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Decryption is unsupported due to lack of crypto library");
-		return (ARCHIVE_FAILED);
-	}
-	r = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, key_len);
-	if (r != 0) {
-		archive_decrypto_aes_ctr_release(&zip->cctx);
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to initialize HMAC-SHA1");
-		return (ARCHIVE_FAILED);
-	}
-	zip->cctx_valid = zip->hctx_valid = 1;
-	__archive_read_consume(a, salt_len + 2);
-	zip->entry_bytes_remaining -= salt_len + 2 + AUTH_CODE_SIZE;
-	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
-	    && zip->entry_bytes_remaining < 0)
-		goto corrupted;
-	zip->entry_compressed_bytes_read += salt_len + 2 + AUTH_CODE_SIZE;
-	zip->decrypted_bytes_remaining = 0;
-
-	zip->entry->compression = zip->entry->aes_extra.compression;
-	return (zip_alloc_decryption_buffer(a));
-
-truncated:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Truncated ZIP file data");
-	return (ARCHIVE_FATAL);
-corrupted:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-	    "Corrupted ZIP file data");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-archive_read_format_zip_read_data(struct archive_read *a,
-    const void **buff, size_t *size, int64_t *offset)
-{
-	int r;
-	struct zip *zip = (struct zip *)(a->format->data);
-
-	if (zip->has_encrypted_entries ==
-			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-		zip->has_encrypted_entries = 0;
-	}
-
-	*offset = zip->entry_uncompressed_bytes_read;
-	*size = 0;
-	*buff = NULL;
-
-	/* If we hit end-of-entry last time, return ARCHIVE_EOF. */
-	if (zip->end_of_entry)
-		return (ARCHIVE_EOF);
-
-	/* Return EOF immediately if this is a non-regular file. */
-	if (AE_IFREG != (zip->entry->mode & AE_IFMT))
-		return (ARCHIVE_EOF);
-
-	__archive_read_consume(a, zip->unconsumed);
-	zip->unconsumed = 0;
-
-	if (zip->init_decryption) {
-		zip->has_encrypted_entries = 1;
-		if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED)
-			r = read_decryption_header(a);
-		else if (zip->entry->compression == WINZIP_AES_ENCRYPTION)
-			r = init_WinZip_AES_decryption(a);
-		else
-			r = init_traditional_PKWARE_decryption(a);
-		if (r != ARCHIVE_OK)
-			return (r);
-		zip->init_decryption = 0;
-	}
-
-	switch(zip->entry->compression) {
-	case 0:  /* No compression. */
-		r =  zip_read_data_none(a, buff, size, offset);
-		break;
-#ifdef HAVE_BZLIB_H
-	case 12: /* ZIPx bzip2 compression. */
-		r = zip_read_data_zipx_bzip2(a, buff, size, offset);
-		break;
-#endif
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-	case 14: /* ZIPx LZMA compression. */
-		r = zip_read_data_zipx_lzma_alone(a, buff, size, offset);
-		break;
-	case 95: /* ZIPx XZ compression. */
-		r = zip_read_data_zipx_xz(a, buff, size, offset);
-		break;
-#endif
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-	case 93: /* ZIPx Zstd compression. */
-		r = zip_read_data_zipx_zstd(a, buff, size, offset);
-		break;
-#endif
-	/* PPMd support is built-in, so we don't need any #if guards. */
-	case 98: /* ZIPx PPMd compression. */
-		r = zip_read_data_zipx_ppmd(a, buff, size, offset);
-		break;
-
-#ifdef HAVE_ZLIB_H
-	case 8: /* Deflate compression. */
-		r =  zip_read_data_deflate(a, buff, size, offset);
-		break;
-#endif
-	default: /* Unsupported compression. */
-		/* Return a warning. */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported ZIP compression method (%d: %s)",
-		    zip->entry->compression, compression_name(zip->entry->compression));
-		/* We can't decompress this entry, but we will
-		 * be able to skip() it and try the next entry. */
-		return (ARCHIVE_FAILED);
-		break;
-	}
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Update checksum */
-	if (*size)
-		zip->entry_crc32 = zip->crc32func(zip->entry_crc32, *buff,
-		    (unsigned)*size);
-	/* If we hit the end, swallow any end-of-data marker. */
-	if (zip->end_of_entry) {
-		/* Check file size, CRC against these values. */
-		if (zip->entry->compressed_size !=
-		    zip->entry_compressed_bytes_read) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "ZIP compressed data is wrong size "
-			    "(read %jd, expected %jd)",
-			    (intmax_t)zip->entry_compressed_bytes_read,
-			    (intmax_t)zip->entry->compressed_size);
-			return (ARCHIVE_WARN);
-		}
-		/* Size field only stores the lower 32 bits of the actual
-		 * size. */
-		if ((zip->entry->uncompressed_size & UINT32_MAX)
-		    != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "ZIP uncompressed data is wrong size "
-			    "(read %jd, expected %jd)\n",
-			    (intmax_t)zip->entry_uncompressed_bytes_read,
-			    (intmax_t)zip->entry->uncompressed_size);
-			return (ARCHIVE_WARN);
-		}
-		/* Check computed CRC against header */
-		if ((!zip->hctx_valid ||
-		      zip->entry->aes_extra.vendor != AES_VENDOR_AE_2) &&
-		   zip->entry->crc32 != zip->entry_crc32
-		    && !zip->ignore_crc32) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "ZIP bad CRC: 0x%lx should be 0x%lx",
-			    (unsigned long)zip->entry_crc32,
-			    (unsigned long)zip->entry->crc32);
-			return (ARCHIVE_WARN);
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_zip_cleanup(struct archive_read *a)
-{
-	struct zip *zip;
-	struct zip_entry *zip_entry, *next_zip_entry;
-
-	zip = (struct zip *)(a->format->data);
-
-#ifdef HAVE_ZLIB_H
-	if (zip->stream_valid)
-		inflateEnd(&zip->stream);
-#endif
-
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-    if (zip->zipx_lzma_valid) {
-		lzma_end(&zip->zipx_lzma_stream);
-	}
-#endif
-
-#ifdef HAVE_BZLIB_H
-	if (zip->bzstream_valid) {
-		BZ2_bzDecompressEnd(&zip->bzstream);
-	}
-#endif
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-	if (zip->zstdstream_valid) {
-		ZSTD_freeDStream(zip->zstdstream);
-	}
-#endif
-
-	free(zip->uncompressed_buffer);
-
-	if (zip->ppmd8_valid)
-		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
-
-	if (zip->zip_entries) {
-		zip_entry = zip->zip_entries;
-		while (zip_entry != NULL) {
-			next_zip_entry = zip_entry->next;
-			archive_string_free(&zip_entry->rsrcname);
-			free(zip_entry);
-			zip_entry = next_zip_entry;
-		}
-	}
-	free(zip->decrypted_buffer);
-	if (zip->cctx_valid)
-		archive_decrypto_aes_ctr_release(&zip->cctx);
-	if (zip->hctx_valid)
-		archive_hmac_sha1_cleanup(&zip->hctx);
-	free(zip->iv);
-	free(zip->erd);
-	free(zip->v_data);
-	archive_string_free(&zip->format_name);
-	free(zip);
-	(a->format->data) = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_read_format_zip_has_encrypted_entries(struct archive_read *_a)
-{
-	if (_a && _a->format) {
-		struct zip * zip = (struct zip *)_a->format->data;
-		if (zip) {
-			return zip->has_encrypted_entries;
-		}
-	}
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-}
-
-static int
-archive_read_format_zip_options(struct archive_read *a,
-    const char *key, const char *val)
-{
-	struct zip *zip;
-	int ret = ARCHIVE_FAILED;
-
-	zip = (struct zip *)(a->format->data);
-	if (strcmp(key, "compat-2x")  == 0) {
-		/* Handle filenames as libarchive 2.x */
-		zip->init_default_conversion = (val != NULL) ? 1 : 0;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "zip: hdrcharset option needs a character-set name"
-			);
-		else {
-			zip->sconv = archive_string_conversion_from_charset(
-			    &a->archive, val, 0);
-			if (zip->sconv != NULL) {
-				if (strcmp(val, "UTF-8") == 0)
-					zip->sconv_utf8 = zip->sconv;
-				ret = ARCHIVE_OK;
-			} else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	} else if (strcmp(key, "ignorecrc32") == 0) {
-		/* Mostly useful for testing. */
-		if (val == NULL || val[0] == 0) {
-			zip->crc32func = real_crc32;
-			zip->ignore_crc32 = 0;
-		} else {
-			zip->crc32func = fake_crc32;
-			zip->ignore_crc32 = 1;
-		}
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "mac-ext") == 0) {
-		zip->process_mac_extensions = (val != NULL && val[0] != 0);
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-int
-archive_read_support_format_zip(struct archive *a)
-{
-	int r;
-	r = archive_read_support_format_zip_streamable(a);
-	if (r != ARCHIVE_OK)
-		return r;
-	return (archive_read_support_format_zip_seekable(a));
-}
-
-/* ------------------------------------------------------------------------ */
-
-/*
- * Streaming-mode support
- */
-
-
-static int
-archive_read_support_format_zip_capabilities_streamable(struct archive_read * a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
-		ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
-}
-
-static int
-archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
-{
-	const char *p;
-
-	(void)best_bid; /* UNUSED */
-
-	if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
-		return (-1);
-
-	/*
-	 * Bid of 29 here comes from:
-	 *  + 16 bits for "PK",
-	 *  + next 16-bit field has 6 options so contributes
-	 *    about 16 - log_2(6) ~= 16 - 2.6 ~= 13 bits
-	 *
-	 * So we've effectively verified ~29 total bits of check data.
-	 */
-	if (p[0] == 'P' && p[1] == 'K') {
-		if ((p[2] == '\001' && p[3] == '\002')
-		    || (p[2] == '\003' && p[3] == '\004')
-		    || (p[2] == '\005' && p[3] == '\006')
-		    || (p[2] == '\006' && p[3] == '\006')
-		    || (p[2] == '\007' && p[3] == '\010')
-		    || (p[2] == '0' && p[3] == '0'))
-			return (29);
-	}
-
-	/* TODO: It's worth looking ahead a little bit for a valid
-	 * PK signature.  In particular, that would make it possible
-	 * to read some UUEncoded SFX files or SFX files coming from
-	 * a network socket. */
-
-	return (0);
-}
-
-static int
-archive_read_format_zip_streamable_read_header(struct archive_read *a,
-    struct archive_entry *entry)
-{
-	struct zip *zip;
-
-	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
-	if (a->archive.archive_format_name == NULL)
-		a->archive.archive_format_name = "ZIP";
-
-	zip = (struct zip *)(a->format->data);
-
-	/*
-	 * It should be sufficient to call archive_read_next_header() for
-	 * a reader to determine if an entry is encrypted or not. If the
-	 * encryption of an entry is only detectable when calling
-	 * archive_read_data(), so be it. We'll do the same check there
-	 * as well.
-	 */
-	if (zip->has_encrypted_entries ==
-			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW)
-		zip->has_encrypted_entries = 0;
-
-	/* Make sure we have a zip_entry structure to use. */
-	if (zip->zip_entries == NULL) {
-		zip->zip_entries = malloc(sizeof(struct zip_entry));
-		if (zip->zip_entries == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Out  of memory");
-			return ARCHIVE_FATAL;
-		}
-	}
-	zip->entry = zip->zip_entries;
-	memset(zip->entry, 0, sizeof(struct zip_entry));
-
-	if (zip->cctx_valid)
-		archive_decrypto_aes_ctr_release(&zip->cctx);
-	if (zip->hctx_valid)
-		archive_hmac_sha1_cleanup(&zip->hctx);
-	zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0;
-	__archive_read_reset_passphrase(a);
-
-	/* Search ahead for the next local file header. */
-	__archive_read_consume(a, zip->unconsumed);
-	zip->unconsumed = 0;
-	for (;;) {
-		int64_t skipped = 0;
-		const char *p, *end;
-		ssize_t bytes;
-
-		p = __archive_read_ahead(a, 4, &bytes);
-		if (p == NULL)
-			return (ARCHIVE_FATAL);
-		end = p + bytes;
-
-		while (p + 4 <= end) {
-			if (p[0] == 'P' && p[1] == 'K') {
-				if (p[2] == '\003' && p[3] == '\004') {
-					/* Regular file entry. */
-					__archive_read_consume(a, skipped);
-					return zip_read_local_file_header(a,
-					    entry, zip);
-				}
-
-                              /*
-                               * TODO: We cannot restore permissions
-                               * based only on the local file headers.
-                               * Consider scanning the central
-                               * directory and returning additional
-                               * entries for at least directories.
-                               * This would allow us to properly set
-                               * directory permissions.
-			       *
-			       * This won't help us fix symlinks
-			       * and may not help with regular file
-			       * permissions, either.  <sigh>
-                               */
-                              if (p[2] == '\001' && p[3] == '\002') {
-                                      return (ARCHIVE_EOF);
-                              }
-
-                              /* End of central directory?  Must be an
-                               * empty archive. */
-                              if ((p[2] == '\005' && p[3] == '\006')
-                                  || (p[2] == '\006' && p[3] == '\006'))
-                                      return (ARCHIVE_EOF);
-			}
-			++p;
-			++skipped;
-		}
-		__archive_read_consume(a, skipped);
-	}
-}
-
-static int
-archive_read_format_zip_read_data_skip_streamable(struct archive_read *a)
-{
-	struct zip *zip;
-	int64_t bytes_skipped;
-
-	zip = (struct zip *)(a->format->data);
-	bytes_skipped = __archive_read_consume(a, zip->unconsumed);
-	zip->unconsumed = 0;
-	if (bytes_skipped < 0)
-		return (ARCHIVE_FATAL);
-
-	/* If we've already read to end of data, we're done. */
-	if (zip->end_of_entry)
-		return (ARCHIVE_OK);
-
-	/* So we know we're streaming... */
-	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
-	    || zip->entry->compressed_size > 0) {
-		/* We know the compressed length, so we can just skip. */
-		bytes_skipped = __archive_read_consume(a,
-					zip->entry_bytes_remaining);
-		if (bytes_skipped < 0)
-			return (ARCHIVE_FATAL);
-		return (ARCHIVE_OK);
-	}
-
-	if (zip->init_decryption) {
-		int r;
-
-		zip->has_encrypted_entries = 1;
-		if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED)
-			r = read_decryption_header(a);
-		else if (zip->entry->compression == WINZIP_AES_ENCRYPTION)
-			r = init_WinZip_AES_decryption(a);
-		else
-			r = init_traditional_PKWARE_decryption(a);
-		if (r != ARCHIVE_OK)
-			return (r);
-		zip->init_decryption = 0;
-	}
-
-	/* We're streaming and we don't know the length. */
-	/* If the body is compressed and we know the format, we can
-	 * find an exact end-of-entry by decompressing it. */
-	switch (zip->entry->compression) {
-#ifdef HAVE_ZLIB_H
-	case 8: /* Deflate compression. */
-		while (!zip->end_of_entry) {
-			int64_t offset = 0;
-			const void *buff = NULL;
-			size_t size = 0;
-			int r;
-			r =  zip_read_data_deflate(a, &buff, &size, &offset);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-		return ARCHIVE_OK;
-#endif
-	default: /* Uncompressed or unknown. */
-		/* Scan for a PK\007\010 signature. */
-		for (;;) {
-			const char *p, *buff;
-			ssize_t bytes_avail;
-			buff = __archive_read_ahead(a, 16, &bytes_avail);
-			if (bytes_avail < 16) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_FILE_FORMAT,
-				    "Truncated ZIP file data");
-				return (ARCHIVE_FATAL);
-			}
-			p = buff;
-			while (p <= buff + bytes_avail - 16) {
-				if (p[3] == 'P') { p += 3; }
-				else if (p[3] == 'K') { p += 2; }
-				else if (p[3] == '\007') { p += 1; }
-				else if (p[3] == '\010' && p[2] == '\007'
-				    && p[1] == 'K' && p[0] == 'P') {
-					if (zip->entry->flags & LA_USED_ZIP64)
-						__archive_read_consume(a,
-						    p - buff + 24);
-					else
-						__archive_read_consume(a,
-						    p - buff + 16);
-					return ARCHIVE_OK;
-				} else { p += 4; }
-			}
-			__archive_read_consume(a, p - buff);
-		}
-	}
-}
-
-int
-archive_read_support_format_zip_streamable(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct zip *zip;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip");
-
-	zip = (struct zip *)calloc(1, sizeof(*zip));
-	if (zip == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate zip data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Streamable reader doesn't support mac extensions. */
-	zip->process_mac_extensions = 0;
-
-	/*
-	 * Until enough data has been read, we cannot tell about
-	 * any encrypted entries yet.
-	 */
-	zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-	zip->crc32func = real_crc32;
-
-	r = __archive_read_register_format(a,
-	    zip,
-	    "zip",
-	    archive_read_format_zip_streamable_bid,
-	    archive_read_format_zip_options,
-	    archive_read_format_zip_streamable_read_header,
-	    archive_read_format_zip_read_data,
-	    archive_read_format_zip_read_data_skip_streamable,
-	    NULL,
-	    archive_read_format_zip_cleanup,
-	    archive_read_support_format_zip_capabilities_streamable,
-	    archive_read_format_zip_has_encrypted_entries);
-
-	if (r != ARCHIVE_OK)
-		free(zip);
-	return (ARCHIVE_OK);
-}
-
-/* ------------------------------------------------------------------------ */
-
-/*
- * Seeking-mode support
- */
-
-static int
-archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
-		ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
-}
-
-/*
- * TODO: This is a performance sink because it forces the read core to
- * drop buffered data from the start of file, which will then have to
- * be re-read again if this bidder loses.
- *
- * We workaround this a little by passing in the best bid so far so
- * that later bidders can do nothing if they know they'll never
- * outbid.  But we can certainly do better...
- */
-static int
-read_eocd(struct zip *zip, const char *p, int64_t current_offset)
-{
-	uint16_t disk_num;
-	uint32_t cd_size, cd_offset;
-	
-	disk_num = archive_le16dec(p + 4);
-	cd_size = archive_le32dec(p + 12);
-	cd_offset = archive_le32dec(p + 16);
-
-	/* Sanity-check the EOCD we've found. */
-
-	/* This must be the first volume. */
-	if (disk_num != 0)
-		return 0;
-	/* Central directory must be on this volume. */
-	if (disk_num != archive_le16dec(p + 6))
-		return 0;
-	/* All central directory entries must be on this volume. */
-	if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
-		return 0;
-	/* Central directory can't extend beyond start of EOCD record. */
-	if (cd_offset + cd_size > current_offset)
-		return 0;
-
-	/* Save the central directory location for later use. */
-	zip->central_directory_offset = cd_offset;
-	zip->central_directory_offset_adjusted = current_offset - cd_size;
-
-	/* This is just a tiny bit higher than the maximum
-	   returned by the streaming Zip bidder.  This ensures
-	   that the more accurate seeking Zip parser wins
-	   whenever seek is available. */
-	return 32;
-}
-
-/*
- * Examine Zip64 EOCD locator:  If it's valid, store the information
- * from it.
- */
-static int
-read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
-{
-	int64_t eocd64_offset;
-	int64_t eocd64_size;
-
-	/* Sanity-check the locator record. */
-
-	/* Central dir must be on first volume. */
-	if (archive_le32dec(p + 4) != 0)
-		return 0;
-	/* Must be only a single volume. */
-	if (archive_le32dec(p + 16) != 1)
-		return 0;
-
-	/* Find the Zip64 EOCD record. */
-	eocd64_offset = archive_le64dec(p + 8);
-	if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
-		return 0;
-	if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
-		return 0;
-	/* Make sure we can read all of it. */
-	eocd64_size = archive_le64dec(p + 4) + 12;
-	if (eocd64_size < 56 || eocd64_size > 16384)
-		return 0;
-	if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
-		return 0;
-
-	/* Sanity-check the EOCD64 */
-	if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
-		return 0;
-	if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
-		return 0;
-	/* CD can't be split. */
-	if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
-		return 0;
-
-	/* Save the central directory offset for later use. */
-	zip->central_directory_offset = archive_le64dec(p + 48);
-	/* TODO: Needs scanning backwards to find the eocd64 instead of assuming */
-	zip->central_directory_offset_adjusted = zip->central_directory_offset;
-
-	return 32;
-}
-
-static int
-archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
-{
-	struct zip *zip = (struct zip *)a->format->data;
-	int64_t file_size, current_offset;
-	const char *p;
-	int i, tail;
-
-	/* If someone has already bid more than 32, then avoid
-	   trashing the look-ahead buffers with a seek. */
-	if (best_bid > 32)
-		return (-1);
-
-	file_size = __archive_read_seek(a, 0, SEEK_END);
-	if (file_size <= 0)
-		return 0;
-
-	/* Search last 16k of file for end-of-central-directory
-	 * record (which starts with PK\005\006) */
-	tail = (int)zipmin(1024 * 16, file_size);
-	current_offset = __archive_read_seek(a, -tail, SEEK_END);
-	if (current_offset < 0)
-		return 0;
-	if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
-		return 0;
-	/* Boyer-Moore search backwards from the end, since we want
-	 * to match the last EOCD in the file (there can be more than
-	 * one if there is an uncompressed Zip archive as a member
-	 * within this Zip archive). */
-	for (i = tail - 22; i > 0;) {
-		switch (p[i]) {
-		case 'P':
-			if (memcmp(p + i, "PK\005\006", 4) == 0) {
-				int ret = read_eocd(zip, p + i,
-				    current_offset + i);
-				/* Zip64 EOCD locator precedes
-				 * regular EOCD if present. */
-				if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
-					int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
-					if (ret_zip64 > ret)
-						ret = ret_zip64;
-				}
-				return (ret);
-			}
-			i -= 4;
-			break;
-		case 'K': i -= 1; break;
-		case 005: i -= 2; break;
-		case 006: i -= 3; break;
-		default: i -= 4; break;
-		}
-	}
-	return 0;
-}
-
-/* The red-black trees are only used in seeking mode to manage
- * the in-memory copy of the central directory. */
-
-static int
-cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2)
-{
-	const struct zip_entry *e1 = (const struct zip_entry *)n1;
-	const struct zip_entry *e2 = (const struct zip_entry *)n2;
-
-	if (e1->local_header_offset > e2->local_header_offset)
-		return -1;
-	if (e1->local_header_offset < e2->local_header_offset)
-		return 1;
-	return 0;
-}
-
-static int
-cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	/* This function won't be called */
-	(void)n; /* UNUSED */
-	(void)key; /* UNUSED */
-	return 1;
-}
-
-static const struct archive_rb_tree_ops rb_ops = {
-	&cmp_node, &cmp_key
-};
-
-static int
-rsrc_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct zip_entry *e1 = (const struct zip_entry *)n1;
-	const struct zip_entry *e2 = (const struct zip_entry *)n2;
-
-	return (strcmp(e2->rsrcname.s, e1->rsrcname.s));
-}
-
-static int
-rsrc_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct zip_entry *e = (const struct zip_entry *)n;
-	return (strcmp((const char *)key, e->rsrcname.s));
-}
-
-static const struct archive_rb_tree_ops rb_rsrc_ops = {
-	&rsrc_cmp_node, &rsrc_cmp_key
-};
-
-static const char *
-rsrc_basename(const char *name, size_t name_length)
-{
-	const char *s, *r;
-
-	r = s = name;
-	for (;;) {
-		s = memchr(s, '/', name_length - (s - name));
-		if (s == NULL)
-			break;
-		r = ++s;
-	}
-	return (r);
-}
-
-static void
-expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
-{
-	struct archive_string str;
-	struct zip_entry *dir;
-	char *s;
-
-	archive_string_init(&str);
-	archive_strncpy(&str, name, name_length);
-	for (;;) {
-		s = strrchr(str.s, '/');
-		if (s == NULL)
-			break;
-		*s = '\0';
-		/* Transfer the parent directory from zip->tree_rsrc RB
-		 * tree to zip->tree RB tree to expose. */
-		dir = (struct zip_entry *)
-		    __archive_rb_tree_find_node(&zip->tree_rsrc, str.s);
-		if (dir == NULL)
-			break;
-		__archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node);
-		archive_string_free(&dir->rsrcname);
-		__archive_rb_tree_insert_node(&zip->tree, &dir->node);
-	}
-	archive_string_free(&str);
-}
-
-static int
-slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
-    struct zip *zip)
-{
-	ssize_t i;
-	unsigned found;
-	int64_t correction;
-	ssize_t bytes_avail;
-	const char *p;
-
-	/*
-	 * Find the start of the central directory.  The end-of-CD
-	 * record has our starting point, but there are lots of
-	 * Zip archives which have had other data prepended to the
-	 * file, which makes the recorded offsets all too small.
-	 * So we search forward from the specified offset until we
-	 * find the real start of the central directory.  Then we
-	 * know the correction we need to apply to account for leading
-	 * padding.
-	 */
-	if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
-		< 0)
-		return ARCHIVE_FATAL;
-
-	found = 0;
-	while (!found) {
-		if ((p = __archive_read_ahead(a, 20, &bytes_avail)) == NULL)
-			return ARCHIVE_FATAL;
-		for (found = 0, i = 0; !found && i < bytes_avail - 4;) {
-			switch (p[i + 3]) {
-			case 'P': i += 3; break;
-			case 'K': i += 2; break;
-			case 001: i += 1; break;
-			case 002:
-				if (memcmp(p + i, "PK\001\002", 4) == 0) {
-					p += i;
-					found = 1;
-				} else
-					i += 4;
-				break;
-			case 005: i += 1; break;
-			case 006:
-				if (memcmp(p + i, "PK\005\006", 4) == 0) {
-					p += i;
-					found = 1;
-				} else if (memcmp(p + i, "PK\006\006", 4) == 0) {
-					p += i;
-					found = 1;
-				} else
-					i += 1;
-				break;
-			default: i += 4; break;
-			}
-		}
-		__archive_read_consume(a, i);
-	}
-	correction = archive_filter_bytes(&a->archive, 0)
-			- zip->central_directory_offset;
-
-	__archive_rb_tree_init(&zip->tree, &rb_ops);
-	__archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);
-
-	zip->central_directory_entries_total = 0;
-	while (1) {
-		struct zip_entry *zip_entry;
-		size_t filename_length, extra_length, comment_length;
-		uint32_t external_attributes;
-		const char *name, *r;
-
-		if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
-			return ARCHIVE_FATAL;
-		if (memcmp(p, "PK\006\006", 4) == 0
-		    || memcmp(p, "PK\005\006", 4) == 0) {
-			break;
-		} else if (memcmp(p, "PK\001\002", 4) != 0) {
-			archive_set_error(&a->archive,
-			    -1, "Invalid central directory signature");
-			return ARCHIVE_FATAL;
-		}
-		if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
-			return ARCHIVE_FATAL;
-
-		zip_entry = calloc(1, sizeof(struct zip_entry));
-		if (zip_entry == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-				"Can't allocate zip entry");
-			return ARCHIVE_FATAL;
-		}
-		zip_entry->next = zip->zip_entries;
-		zip_entry->flags |= LA_FROM_CENTRAL_DIRECTORY;
-		zip->zip_entries = zip_entry;
-		zip->central_directory_entries_total++;
-
-		/* version = p[4]; */
-		zip_entry->system = p[5];
-		/* version_required = archive_le16dec(p + 6); */
-		zip_entry->zip_flags = archive_le16dec(p + 8);
-		if (zip_entry->zip_flags
-		      & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)){
-			zip->has_encrypted_entries = 1;
-		}
-		zip_entry->compression = (char)archive_le16dec(p + 10);
-		zip_entry->mtime = zip_time(p + 12);
-		zip_entry->crc32 = archive_le32dec(p + 16);
-		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
-			zip_entry->decdat = p[13];
-		else
-			zip_entry->decdat = p[19];
-		zip_entry->compressed_size = archive_le32dec(p + 20);
-		zip_entry->uncompressed_size = archive_le32dec(p + 24);
-		filename_length = archive_le16dec(p + 28);
-		extra_length = archive_le16dec(p + 30);
-		comment_length = archive_le16dec(p + 32);
-		/* disk_start = archive_le16dec(p + 34);
-		 *   Better be zero.
-		 * internal_attributes = archive_le16dec(p + 36);
-		 *   text bit */
-		external_attributes = archive_le32dec(p + 38);
-		zip_entry->local_header_offset =
-		    archive_le32dec(p + 42) + correction;
-
-		/* If we can't guess the mode, leave it zero here;
-		   when we read the local file header we might get
-		   more information. */
-		if (zip_entry->system == 3) {
-			zip_entry->mode = external_attributes >> 16;
-		} else if (zip_entry->system == 0) {
-			// Interpret MSDOS directory bit
-			if (0x10 == (external_attributes & 0x10)) {
-				zip_entry->mode = AE_IFDIR | 0775;
-			} else {
-				zip_entry->mode = AE_IFREG | 0664;
-			}
-			if (0x01 == (external_attributes & 0x01)) {
-				// Read-only bit; strip write permissions
-				zip_entry->mode &= 0555;
-			}
-		} else {
-			zip_entry->mode = 0;
-		}
-
-		/* We're done with the regular data; get the filename and
-		 * extra data. */
-		__archive_read_consume(a, 46);
-		p = __archive_read_ahead(a, filename_length + extra_length,
-			NULL);
-		if (p == NULL) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated ZIP file header");
-			return ARCHIVE_FATAL;
-		}
-		if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
-		    extra_length, zip_entry)) {
-			return ARCHIVE_FATAL;
-		}
-
-		/*
-		 * Mac resource fork files are stored under the
-		 * "__MACOSX/" directory, so we should check if
-		 * it is.
-		 */
-		if (!zip->process_mac_extensions) {
-			/* Treat every entry as a regular entry. */
-			__archive_rb_tree_insert_node(&zip->tree,
-			    &zip_entry->node);
-		} else {
-			name = p;
-			r = rsrc_basename(name, filename_length);
-			if (filename_length >= 9 &&
-			    strncmp("__MACOSX/", name, 9) == 0) {
-				/* If this file is not a resource fork nor
-				 * a directory. We should treat it as a non
-				 * resource fork file to expose it. */
-				if (name[filename_length-1] != '/' &&
-				    (r - name < 3 || r[0] != '.' ||
-				     r[1] != '_')) {
-					__archive_rb_tree_insert_node(
-					    &zip->tree, &zip_entry->node);
-					/* Expose its parent directories. */
-					expose_parent_dirs(zip, name,
-					    filename_length);
-				} else {
-					/* This file is a resource fork file or
-					 * a directory. */
-					archive_strncpy(&(zip_entry->rsrcname),
-					     name, filename_length);
-					__archive_rb_tree_insert_node(
-					    &zip->tree_rsrc, &zip_entry->node);
-				}
-			} else {
-				/* Generate resource fork name to find its
-				 * resource file at zip->tree_rsrc. */
-				archive_strcpy(&(zip_entry->rsrcname),
-				    "__MACOSX/");
-				archive_strncat(&(zip_entry->rsrcname),
-				    name, r - name);
-				archive_strcat(&(zip_entry->rsrcname), "._");
-				archive_strncat(&(zip_entry->rsrcname),
-				    name + (r - name),
-				    filename_length - (r - name));
-				/* Register an entry to RB tree to sort it by
-				 * file offset. */
-				__archive_rb_tree_insert_node(&zip->tree,
-				    &zip_entry->node);
-			}
-		}
-
-		/* Skip the comment too ... */
-		__archive_read_consume(a,
-		    filename_length + extra_length + comment_length);
-	}
-
-	return ARCHIVE_OK;
-}
-
-static ssize_t
-zip_get_local_file_header_size(struct archive_read *a, size_t extra)
-{
-	const char *p;
-	ssize_t filename_length, extra_length;
-
-	if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file header");
-		return (ARCHIVE_WARN);
-	}
-	p += extra;
-
-	if (memcmp(p, "PK\003\004", 4) != 0) {
-		archive_set_error(&a->archive, -1, "Damaged Zip archive");
-		return ARCHIVE_WARN;
-	}
-	filename_length = archive_le16dec(p + 26);
-	extra_length = archive_le16dec(p + 28);
-
-	return (30 + filename_length + extra_length);
-}
-
-static int
-zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
-    struct zip_entry *rsrc)
-{
-	struct zip *zip = (struct zip *)a->format->data;
-	unsigned char *metadata, *mp;
-	int64_t offset = archive_filter_bytes(&a->archive, 0);
-	size_t remaining_bytes, metadata_bytes;
-	ssize_t hsize;
-	int ret = ARCHIVE_OK, eof;
-
-	switch(rsrc->compression) {
-	case 0:  /* No compression. */
-		if (rsrc->uncompressed_size != rsrc->compressed_size) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Malformed OS X metadata entry: "
-			    "inconsistent size");
-			return (ARCHIVE_FATAL);
-		}
-#ifdef HAVE_ZLIB_H
-	case 8: /* Deflate compression. */
-#endif
-		break;
-	default: /* Unsupported compression. */
-		/* Return a warning. */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Unsupported ZIP compression method (%s)",
-		    compression_name(rsrc->compression));
-		/* We can't decompress this entry, but we will
-		 * be able to skip() it and try the next entry. */
-		return (ARCHIVE_WARN);
-	}
-
-	if (rsrc->uncompressed_size > (4 * 1024 * 1024)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Mac metadata is too large: %jd > 4M bytes",
-		    (intmax_t)rsrc->uncompressed_size);
-		return (ARCHIVE_WARN);
-	}
-	if (rsrc->compressed_size > (4 * 1024 * 1024)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Mac metadata is too large: %jd > 4M bytes",
-		    (intmax_t)rsrc->compressed_size);
-		return (ARCHIVE_WARN);
-	}
-
-	metadata = malloc((size_t)rsrc->uncompressed_size);
-	if (metadata == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for Mac metadata");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (offset < rsrc->local_header_offset)
-		__archive_read_consume(a, rsrc->local_header_offset - offset);
-	else if (offset != rsrc->local_header_offset) {
-		__archive_read_seek(a, rsrc->local_header_offset, SEEK_SET);
-	}
-
-	hsize = zip_get_local_file_header_size(a, 0);
-	__archive_read_consume(a, hsize);
-
-	remaining_bytes = (size_t)rsrc->compressed_size;
-	metadata_bytes = (size_t)rsrc->uncompressed_size;
-	mp = metadata;
-	eof = 0;
-	while (!eof && remaining_bytes) {
-		const unsigned char *p;
-		ssize_t bytes_avail;
-		size_t bytes_used;
-
-		p = __archive_read_ahead(a, 1, &bytes_avail);
-		if (p == NULL) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Truncated ZIP file header");
-			ret = ARCHIVE_WARN;
-			goto exit_mac_metadata;
-		}
-		if ((size_t)bytes_avail > remaining_bytes)
-			bytes_avail = remaining_bytes;
-		switch(rsrc->compression) {
-		case 0:  /* No compression. */
-			if ((size_t)bytes_avail > metadata_bytes)
-				bytes_avail = metadata_bytes;
-			memcpy(mp, p, bytes_avail);
-			bytes_used = (size_t)bytes_avail;
-			metadata_bytes -= bytes_used;
-			mp += bytes_used;
-			if (metadata_bytes == 0)
-				eof = 1;
-			break;
-#ifdef HAVE_ZLIB_H
-		case 8: /* Deflate compression. */
-		{
-			int r;
-
-			ret = zip_deflate_init(a, zip);
-			if (ret != ARCHIVE_OK)
-				goto exit_mac_metadata;
-			zip->stream.next_in =
-			    (Bytef *)(uintptr_t)(const void *)p;
-			zip->stream.avail_in = (uInt)bytes_avail;
-			zip->stream.total_in = 0;
-			zip->stream.next_out = mp;
-			zip->stream.avail_out = (uInt)metadata_bytes;
-			zip->stream.total_out = 0;
-
-			r = inflate(&zip->stream, 0);
-			switch (r) {
-			case Z_OK:
-				break;
-			case Z_STREAM_END:
-				eof = 1;
-				break;
-			case Z_MEM_ERROR:
-				archive_set_error(&a->archive, ENOMEM,
-				    "Out of memory for ZIP decompression");
-				ret = ARCHIVE_FATAL;
-				goto exit_mac_metadata;
-			default:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "ZIP decompression failed (%d)", r);
-				ret = ARCHIVE_FATAL;
-				goto exit_mac_metadata;
-			}
-			bytes_used = zip->stream.total_in;
-			metadata_bytes -= zip->stream.total_out;
-			mp += zip->stream.total_out;
-			break;
-		}
-#endif
-		default:
-			bytes_used = 0;
-			break;
-		}
-		__archive_read_consume(a, bytes_used);
-		remaining_bytes -= bytes_used;
-	}
-	archive_entry_copy_mac_metadata(entry, metadata,
-	    (size_t)rsrc->uncompressed_size - metadata_bytes);
-
-exit_mac_metadata:
-	__archive_read_seek(a, offset, SEEK_SET);
-	zip->decompress_init = 0;
-	free(metadata);
-	return (ret);
-}
-
-static int
-archive_read_format_zip_seekable_read_header(struct archive_read *a,
-	struct archive_entry *entry)
-{
-	struct zip *zip = (struct zip *)a->format->data;
-	struct zip_entry *rsrc;
-	int64_t offset;
-	int r, ret = ARCHIVE_OK;
-
-	/*
-	 * It should be sufficient to call archive_read_next_header() for
-	 * a reader to determine if an entry is encrypted or not. If the
-	 * encryption of an entry is only detectable when calling
-	 * archive_read_data(), so be it. We'll do the same check there
-	 * as well.
-	 */
-	if (zip->has_encrypted_entries ==
-			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW)
-		zip->has_encrypted_entries = 0;
-
-	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
-	if (a->archive.archive_format_name == NULL)
-		a->archive.archive_format_name = "ZIP";
-
-	if (zip->zip_entries == NULL) {
-		r = slurp_central_directory(a, entry, zip);
-		if (r != ARCHIVE_OK)
-			return r;
-		/* Get first entry whose local header offset is lower than
-		 * other entries in the archive file. */
-		zip->entry =
-		    (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree);
-	} else if (zip->entry != NULL) {
-		/* Get next entry in local header offset order. */
-		zip->entry = (struct zip_entry *)__archive_rb_tree_iterate(
-		    &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT);
-	}
-
-	if (zip->entry == NULL)
-		return ARCHIVE_EOF;
-
-	if (zip->entry->rsrcname.s)
-		rsrc = (struct zip_entry *)__archive_rb_tree_find_node(
-		    &zip->tree_rsrc, zip->entry->rsrcname.s);
-	else
-		rsrc = NULL;
-
-	if (zip->cctx_valid)
-		archive_decrypto_aes_ctr_release(&zip->cctx);
-	if (zip->hctx_valid)
-		archive_hmac_sha1_cleanup(&zip->hctx);
-	zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0;
-	__archive_read_reset_passphrase(a);
-
-	/* File entries are sorted by the header offset, we should mostly
-	 * use __archive_read_consume to advance a read point to avoid
-	 * redundant data reading.  */
-	offset = archive_filter_bytes(&a->archive, 0);
-	if (offset < zip->entry->local_header_offset)
-		__archive_read_consume(a,
-		    zip->entry->local_header_offset - offset);
-	else if (offset != zip->entry->local_header_offset) {
-		__archive_read_seek(a, zip->entry->local_header_offset,
-		    SEEK_SET);
-	}
-	zip->unconsumed = 0;
-	r = zip_read_local_file_header(a, entry, zip);
-	if (r != ARCHIVE_OK)
-		return r;
-	if (rsrc) {
-		int ret2 = zip_read_mac_metadata(a, entry, rsrc);
-		if (ret2 < ret)
-			ret = ret2;
-	}
-	return (ret);
-}
-
-/*
- * We're going to seek for the next header anyway, so we don't
- * need to bother doing anything here.
- */
-static int
-archive_read_format_zip_read_data_skip_seekable(struct archive_read *a)
-{
-	struct zip *zip;
-	zip = (struct zip *)(a->format->data);
-
-	zip->unconsumed = 0;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_read_support_format_zip_seekable(struct archive *_a)
-{
-	struct archive_read *a = (struct archive_read *)_a;
-	struct zip *zip;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip_seekable");
-
-	zip = (struct zip *)calloc(1, sizeof(*zip));
-	if (zip == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate zip data");
-		return (ARCHIVE_FATAL);
-	}
-
-#ifdef HAVE_COPYFILE_H
-	/* Set this by default on Mac OS. */
-	zip->process_mac_extensions = 1;
-#endif
-
-	/*
-	 * Until enough data has been read, we cannot tell about
-	 * any encrypted entries yet.
-	 */
-	zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
-	zip->crc32func = real_crc32;
-
-	r = __archive_read_register_format(a,
-	    zip,
-	    "zip",
-	    archive_read_format_zip_seekable_bid,
-	    archive_read_format_zip_options,
-	    archive_read_format_zip_seekable_read_header,
-	    archive_read_format_zip_read_data,
-	    archive_read_format_zip_read_data_skip_seekable,
-	    NULL,
-	    archive_read_format_zip_cleanup,
-	    archive_read_support_format_zip_capabilities_seekable,
-	    archive_read_format_zip_has_encrypted_entries);
-
-	if (r != ARCHIVE_OK)
-		free(zip);
-	return (ARCHIVE_OK);
-}
-
-/*# vim:set noet:*/
diff --git a/c/archive_string.c b/c/archive_string.c
deleted file mode 100644
--- a/c/archive_string.c
+++ /dev/null
@@ -1,4244 +0,0 @@
-/*-
- * Copyright (c) 2003-2011 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_string.c 201095 2009-12-28 02:33:22Z kientzle $");
-
-/*
- * Basic resizable string support, to simplify manipulating arbitrary-sized
- * strings while minimizing heap activity.
- *
- * In particular, the buffer used by a string object is only grown, it
- * never shrinks, so you can clear and reuse the same string object
- * without incurring additional memory allocations.
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-#ifdef HAVE_LOCALCHARSET_H
-#include <localcharset.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
-#include <locale.h>
-#endif
-
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_string_composition.h"
-
-#if !defined(HAVE_WMEMCPY) && !defined(wmemcpy)
-#define wmemcpy(a,b,i)  (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t))
-#endif
-
-#if !defined(HAVE_WMEMMOVE) && !defined(wmemmove)
-#define wmemmove(a,b,i)  (wchar_t *)memmove((a), (b), (i) * sizeof(wchar_t))
-#endif
-
-#undef max
-#define max(a, b)       ((a)>(b)?(a):(b))
-
-struct archive_string_conv {
-	struct archive_string_conv	*next;
-	char				*from_charset;
-	char				*to_charset;
-	unsigned			 from_cp;
-	unsigned			 to_cp;
-	/* Set 1 if from_charset and to_charset are the same. */
-	int				 same;
-	int				 flag;
-#define SCONV_TO_CHARSET	1	/* MBS is being converted to specified
-					 * charset. */
-#define SCONV_FROM_CHARSET	(1<<1)	/* MBS is being converted from
-					 * specified charset. */
-#define SCONV_BEST_EFFORT 	(1<<2)	/* Copy at least ASCII code. */
-#define SCONV_WIN_CP	 	(1<<3)	/* Use Windows API for converting
-					 * MBS. */
-#define SCONV_UTF8_LIBARCHIVE_2 (1<<4)	/* Incorrect UTF-8 made by libarchive
-					 * 2.x in the wrong assumption. */
-#define SCONV_NORMALIZATION_C	(1<<6)	/* Need normalization to be Form C.
-					 * Before UTF-8 characters are actually
-					 * processed. */
-#define SCONV_NORMALIZATION_D	(1<<7)	/* Need normalization to be Form D.
-					 * Before UTF-8 characters are actually
-					 * processed.
-					 * Currently this only for MAC OS X. */
-#define SCONV_TO_UTF8		(1<<8)	/* "to charset" side is UTF-8. */
-#define SCONV_FROM_UTF8		(1<<9)	/* "from charset" side is UTF-8. */
-#define SCONV_TO_UTF16BE 	(1<<10)	/* "to charset" side is UTF-16BE. */
-#define SCONV_FROM_UTF16BE 	(1<<11)	/* "from charset" side is UTF-16BE. */
-#define SCONV_TO_UTF16LE 	(1<<12)	/* "to charset" side is UTF-16LE. */
-#define SCONV_FROM_UTF16LE 	(1<<13)	/* "from charset" side is UTF-16LE. */
-#define SCONV_TO_UTF16		(SCONV_TO_UTF16BE | SCONV_TO_UTF16LE)
-#define SCONV_FROM_UTF16	(SCONV_FROM_UTF16BE | SCONV_FROM_UTF16LE)
-
-#if HAVE_ICONV
-	iconv_t				 cd;
-	iconv_t				 cd_w;/* Use at archive_mstring on
-				 	       * Windows. */
-#endif
-	/* A temporary buffer for normalization. */
-	struct archive_string		 utftmp;
-	int (*converter[2])(struct archive_string *, const void *, size_t,
-	    struct archive_string_conv *);
-	int				 nconverter;
-};
-
-#define CP_C_LOCALE	0	/* "C" locale only for this file. */
-#define CP_UTF16LE	1200
-#define CP_UTF16BE	1201
-
-#define IS_HIGH_SURROGATE_LA(uc) ((uc) >= 0xD800 && (uc) <= 0xDBFF)
-#define IS_LOW_SURROGATE_LA(uc)	 ((uc) >= 0xDC00 && (uc) <= 0xDFFF)
-#define IS_SURROGATE_PAIR_LA(uc) ((uc) >= 0xD800 && (uc) <= 0xDFFF)
-#define UNICODE_MAX		0x10FFFF
-#define UNICODE_R_CHAR		0xFFFD	/* Replacement character. */
-/* Set U+FFFD(Replacement character) in UTF-8. */
-static const char utf8_replacement_char[] = {0xef, 0xbf, 0xbd};
-
-static struct archive_string_conv *find_sconv_object(struct archive *,
-	const char *, const char *);
-static void add_sconv_object(struct archive *, struct archive_string_conv *);
-static struct archive_string_conv *create_sconv_object(const char *,
-	const char *, unsigned, int);
-static void free_sconv_object(struct archive_string_conv *);
-static struct archive_string_conv *get_sconv_object(struct archive *,
-	const char *, const char *, int);
-static unsigned make_codepage_from_charset(const char *);
-static unsigned get_current_codepage(void);
-static unsigned get_current_oemcp(void);
-static size_t mbsnbytes(const void *, size_t);
-static size_t utf16nbytes(const void *, size_t);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static int archive_wstring_append_from_mbs_in_codepage(
-    struct archive_wstring *, const char *, size_t,
-    struct archive_string_conv *);
-static int archive_string_append_from_wcs_in_codepage(struct archive_string *,
-    const wchar_t *, size_t, struct archive_string_conv *);
-static int is_big_endian(void);
-static int strncat_in_codepage(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int win_strncat_from_utf16be(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int win_strncat_from_utf16le(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int win_strncat_to_utf16be(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int win_strncat_to_utf16le(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-#endif
-static int best_effort_strncat_from_utf16be(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-static int best_effort_strncat_from_utf16le(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-static int best_effort_strncat_to_utf16be(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-static int best_effort_strncat_to_utf16le(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-#if defined(HAVE_ICONV)
-static int iconv_strncat_in_locale(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-#endif
-static int best_effort_strncat_in_locale(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-static int _utf8_to_unicode(uint32_t *, const char *, size_t);
-static int utf8_to_unicode(uint32_t *, const char *, size_t);
-static inline uint32_t combine_surrogate_pair(uint32_t, uint32_t);
-static int cesu8_to_unicode(uint32_t *, const char *, size_t);
-static size_t unicode_to_utf8(char *, size_t, uint32_t);
-static int utf16_to_unicode(uint32_t *, const char *, size_t, int);
-static size_t unicode_to_utf16be(char *, size_t, uint32_t);
-static size_t unicode_to_utf16le(char *, size_t, uint32_t);
-static int strncat_from_utf8_libarchive2(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-static int strncat_from_utf8_to_utf8(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int archive_string_normalize_C(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int archive_string_normalize_D(struct archive_string *, const void *,
-    size_t, struct archive_string_conv *);
-static int archive_string_append_unicode(struct archive_string *,
-    const void *, size_t, struct archive_string_conv *);
-
-static struct archive_string *
-archive_string_append(struct archive_string *as, const char *p, size_t s)
-{
-	if (archive_string_ensure(as, as->length + s + 1) == NULL)
-		return (NULL);
-	if (s)
-		memmove(as->s + as->length, p, s);
-	as->length += s;
-	as->s[as->length] = 0;
-	return (as);
-}
-
-static struct archive_wstring *
-archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
-{
-	if (archive_wstring_ensure(as, as->length + s + 1) == NULL)
-		return (NULL);
-	if (s)
-		wmemmove(as->s + as->length, p, s);
-	as->length += s;
-	as->s[as->length] = 0;
-	return (as);
-}
-
-struct archive_string *
-archive_array_append(struct archive_string *as, const char *p, size_t s)
-{
-	return archive_string_append(as, p, s);
-}
-
-void
-archive_string_concat(struct archive_string *dest, struct archive_string *src)
-{
-	if (archive_string_append(dest, src->s, src->length) == NULL)
-		__archive_errx(1, "Out of memory");
-}
-
-void
-archive_wstring_concat(struct archive_wstring *dest,
-    struct archive_wstring *src)
-{
-	if (archive_wstring_append(dest, src->s, src->length) == NULL)
-		__archive_errx(1, "Out of memory");
-}
-
-void
-archive_string_free(struct archive_string *as)
-{
-	as->length = 0;
-	as->buffer_length = 0;
-	free(as->s);
-	as->s = NULL;
-}
-
-void
-archive_wstring_free(struct archive_wstring *as)
-{
-	as->length = 0;
-	as->buffer_length = 0;
-	free(as->s);
-	as->s = NULL;
-}
-
-struct archive_wstring *
-archive_wstring_ensure(struct archive_wstring *as, size_t s)
-{
-	return (struct archive_wstring *)
-		archive_string_ensure((struct archive_string *)as,
-					s * sizeof(wchar_t));
-}
-
-/* Returns NULL on any allocation failure. */
-struct archive_string *
-archive_string_ensure(struct archive_string *as, size_t s)
-{
-	char *p;
-	size_t new_length;
-
-	/* If buffer is already big enough, don't reallocate. */
-	if (as->s && (s <= as->buffer_length))
-		return (as);
-
-	/*
-	 * Growing the buffer at least exponentially ensures that
-	 * append operations are always linear in the number of
-	 * characters appended.  Using a smaller growth rate for
-	 * larger buffers reduces memory waste somewhat at the cost of
-	 * a larger constant factor.
-	 */
-	if (as->buffer_length < 32)
-		/* Start with a minimum 32-character buffer. */
-		new_length = 32;
-	else if (as->buffer_length < 8192)
-		/* Buffers under 8k are doubled for speed. */
-		new_length = as->buffer_length + as->buffer_length;
-	else {
-		/* Buffers 8k and over grow by at least 25% each time. */
-		new_length = as->buffer_length + as->buffer_length / 4;
-		/* Be safe: If size wraps, fail. */
-		if (new_length < as->buffer_length) {
-			/* On failure, wipe the string and return NULL. */
-			archive_string_free(as);
-			errno = ENOMEM;/* Make sure errno has ENOMEM. */
-			return (NULL);
-		}
-	}
-	/*
-	 * The computation above is a lower limit to how much we'll
-	 * grow the buffer.  In any case, we have to grow it enough to
-	 * hold the request.
-	 */
-	if (new_length < s)
-		new_length = s;
-	/* Now we can reallocate the buffer. */
-	p = (char *)realloc(as->s, new_length);
-	if (p == NULL) {
-		/* On failure, wipe the string and return NULL. */
-		archive_string_free(as);
-		errno = ENOMEM;/* Make sure errno has ENOMEM. */
-		return (NULL);
-	}
-
-	as->s = p;
-	as->buffer_length = new_length;
-	return (as);
-}
-
-/*
- * TODO: See if there's a way to avoid scanning
- * the source string twice.  Then test to see
- * if it actually helps (remember that we're almost
- * always called with pretty short arguments, so
- * such an optimization might not help).
- */
-struct archive_string *
-archive_strncat(struct archive_string *as, const void *_p, size_t n)
-{
-	size_t s;
-	const char *p, *pp;
-
-	p = (const char *)_p;
-
-	/* Like strlen(p), except won't examine positions beyond p[n]. */
-	s = 0;
-	pp = p;
-	while (s < n && *pp) {
-		pp++;
-		s++;
-	}
-	if ((as = archive_string_append(as, p, s)) == NULL)
-		__archive_errx(1, "Out of memory");
-	return (as);
-}
-
-struct archive_wstring *
-archive_wstrncat(struct archive_wstring *as, const wchar_t *p, size_t n)
-{
-	size_t s;
-	const wchar_t *pp;
-
-	/* Like strlen(p), except won't examine positions beyond p[n]. */
-	s = 0;
-	pp = p;
-	while (s < n && *pp) {
-		pp++;
-		s++;
-	}
-	if ((as = archive_wstring_append(as, p, s)) == NULL)
-		__archive_errx(1, "Out of memory");
-	return (as);
-}
-
-struct archive_string *
-archive_strcat(struct archive_string *as, const void *p)
-{
-	/* strcat is just strncat without an effective limit. 
-	 * Assert that we'll never get called with a source
-	 * string over 16MB.
-	 * TODO: Review all uses of strcat in the source
-	 * and try to replace them with strncat().
-	 */
-	return archive_strncat(as, p, 0x1000000);
-}
-
-struct archive_wstring *
-archive_wstrcat(struct archive_wstring *as, const wchar_t *p)
-{
-	/* Ditto. */
-	return archive_wstrncat(as, p, 0x1000000);
-}
-
-struct archive_string *
-archive_strappend_char(struct archive_string *as, char c)
-{
-	if ((as = archive_string_append(as, &c, 1)) == NULL)
-		__archive_errx(1, "Out of memory");
-	return (as);
-}
-
-struct archive_wstring *
-archive_wstrappend_wchar(struct archive_wstring *as, wchar_t c)
-{
-	if ((as = archive_wstring_append(as, &c, 1)) == NULL)
-		__archive_errx(1, "Out of memory");
-	return (as);
-}
-
-/*
- * Get the "current character set" name to use with iconv.
- * On FreeBSD, the empty character set name "" chooses
- * the correct character encoding for the current locale,
- * so this isn't necessary.
- * But iconv on Mac OS 10.6 doesn't seem to handle this correctly;
- * on that system, we have to explicitly call nl_langinfo()
- * to get the right name.  Not sure about other platforms.
- *
- * NOTE: GNU libiconv does not recognize the character-set name
- * which some platform nl_langinfo(CODESET) returns, so we should
- * use locale_charset() instead of nl_langinfo(CODESET) for GNU libiconv.
- */
-static const char *
-default_iconv_charset(const char *charset) {
-	if (charset != NULL && charset[0] != '\0')
-		return charset;
-#if HAVE_LOCALE_CHARSET && !defined(__APPLE__)
-	/* locale_charset() is broken on Mac OS */
-	return locale_charset();
-#elif HAVE_NL_LANGINFO
-	return nl_langinfo(CODESET);
-#else
-	return "";
-#endif
-}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-/*
- * Convert MBS to WCS.
- * Note: returns -1 if conversion fails.
- */
-int
-archive_wstring_append_from_mbs(struct archive_wstring *dest,
-    const char *p, size_t len)
-{
-	return archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL);
-}
-
-static int
-archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
-    const char *s, size_t length, struct archive_string_conv *sc)
-{
-	int count, ret = 0;
-	UINT from_cp;
-
-	if (sc != NULL)
-		from_cp = sc->from_cp;
-	else
-		from_cp = get_current_codepage();
-
-	if (from_cp == CP_C_LOCALE) {
-		/*
-		 * "C" locale special processing.
-		 */
-		wchar_t *ws;
-		const unsigned char *mp;
-
-		if (NULL == archive_wstring_ensure(dest,
-		    dest->length + length + 1))
-			return (-1);
-
-		ws = dest->s + dest->length;
-		mp = (const unsigned char *)s;
-		count = 0;
-		while (count < (int)length && *mp) {
-			*ws++ = (wchar_t)*mp++;
-			count++;
-		}
-	} else if (sc != NULL &&
-	    (sc->flag & (SCONV_NORMALIZATION_C | SCONV_NORMALIZATION_D))) {
-		/*
-		 * Normalize UTF-8 and UTF-16BE and convert it directly
-		 * to UTF-16 as wchar_t.
-		 */
-		struct archive_string u16;
-		int saved_flag = sc->flag;/* save current flag. */
-
-		if (is_big_endian())
-			sc->flag |= SCONV_TO_UTF16BE;
-		else
-			sc->flag |= SCONV_TO_UTF16LE;
-
-		if (sc->flag & SCONV_FROM_UTF16) {
-			/*
-			 *  UTF-16BE/LE NFD ===> UTF-16 NFC
-			 *  UTF-16BE/LE NFC ===> UTF-16 NFD
-			 */
-			count = (int)utf16nbytes(s, length);
-		} else {
-			/*
-			 *  UTF-8 NFD ===> UTF-16 NFC
-			 *  UTF-8 NFC ===> UTF-16 NFD
-			 */
-			count = (int)mbsnbytes(s, length);
-		}
-		u16.s = (char *)dest->s;
-		u16.length = dest->length << 1;;
-		u16.buffer_length = dest->buffer_length;
-		if (sc->flag & SCONV_NORMALIZATION_C)
-			ret = archive_string_normalize_C(&u16, s, count, sc);
-		else
-			ret = archive_string_normalize_D(&u16, s, count, sc);
-		dest->s = (wchar_t *)u16.s;
-		dest->length = u16.length >> 1;
-		dest->buffer_length = u16.buffer_length;
-		sc->flag = saved_flag;/* restore the saved flag. */
-		return (ret);
-	} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
-		count = (int)utf16nbytes(s, length);
-		count >>= 1; /* to be WCS length */
-		/* Allocate memory for WCS. */
-		if (NULL == archive_wstring_ensure(dest,
-		    dest->length + count + 1))
-			return (-1);
-		wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
-		if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) {
-			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
-			for (b = 0; b < count; b++) {
-				uint16_t val = archive_le16dec(u16+b);
-				archive_be16enc(u16+b, val);
-			}
-		} else if ((sc->flag & SCONV_FROM_UTF16LE) && is_big_endian()) {
-			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
-			for (b = 0; b < count; b++) {
-				uint16_t val = archive_be16dec(u16+b);
-				archive_le16enc(u16+b, val);
-			}
-		}
-	} else {
-		DWORD mbflag;
-		size_t buffsize;
-
-		if (sc == NULL)
-			mbflag = 0;
-		else if (sc->flag & SCONV_FROM_CHARSET) {
-			/* Do not trust the length which comes from
-			 * an archive file. */
-			length = mbsnbytes(s, length);
-			mbflag = 0;
-		} else
-			mbflag = MB_PRECOMPOSED;
-
-		buffsize = dest->length + length + 1;
-		do {
-			/* Allocate memory for WCS. */
-			if (NULL == archive_wstring_ensure(dest, buffsize))
-				return (-1);
-			/* Convert MBS to WCS. */
-			count = MultiByteToWideChar(from_cp,
-			    mbflag, s, (int)length, dest->s + dest->length,
-			    (int)(dest->buffer_length >> 1) -1);
-			if (count == 0 &&
-			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-				/* Expand the WCS buffer. */
-				buffsize = dest->buffer_length << 1;
-				continue;
-			}
-			if (count == 0 && length != 0)
-				ret = -1;
-			break;
-		} while (1);
-	}
-	dest->length += count;
-	dest->s[dest->length] = L'\0';
-	return (ret);
-}
-
-#else
-
-/*
- * Convert MBS to WCS.
- * Note: returns -1 if conversion fails.
- */
-int
-archive_wstring_append_from_mbs(struct archive_wstring *dest,
-    const char *p, size_t len)
-{
-	size_t r;
-	int ret_val = 0;
-	/*
-	 * No single byte will be more than one wide character,
-	 * so this length estimate will always be big enough.
-	 */
-	// size_t wcs_length = len;
-	size_t mbs_length = len;
-	const char *mbs = p;
-	wchar_t *wcs;
-#if HAVE_MBRTOWC
-	mbstate_t shift_state;
-
-	memset(&shift_state, 0, sizeof(shift_state));
-#endif
-	/*
-	 * As we decided to have wcs_length == mbs_length == len
-	 * we can use len here instead of wcs_length
-	 */
-	if (NULL == archive_wstring_ensure(dest, dest->length + len + 1))
-		return (-1);
-	wcs = dest->s + dest->length;
-	/*
-	 * We cannot use mbsrtowcs/mbstowcs here because those may convert
-	 * extra MBS when strlen(p) > len and one wide character consists of
-	 * multi bytes.
-	 */
-	while (*mbs && mbs_length > 0) {
-		/*
-		 * The buffer we allocated is always big enough.
-		 * Keep this code path in a comment if we decide to choose
-		 * smaller wcs_length in the future
-		 */
-/*
-		if (wcs_length == 0) {
-			dest->length = wcs - dest->s;
-			dest->s[dest->length] = L'\0';
-			wcs_length = mbs_length;
-			if (NULL == archive_wstring_ensure(dest,
-			    dest->length + wcs_length + 1))
-				return (-1);
-			wcs = dest->s + dest->length;
-		}
-*/
-#if HAVE_MBRTOWC
-		r = mbrtowc(wcs, mbs, mbs_length, &shift_state);
-#else
-		r = mbtowc(wcs, mbs, mbs_length);
-#endif
-		if (r == (size_t)-1 || r == (size_t)-2) {
-			ret_val = -1;
-			break;
-		}
-		if (r == 0 || r > mbs_length)
-			break;
-		wcs++;
-		// wcs_length--;
-		mbs += r;
-		mbs_length -= r;
-	}
-	dest->length = wcs - dest->s;
-	dest->s[dest->length] = L'\0';
-	return (ret_val);
-}
-
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-/*
- * WCS ==> MBS.
- * Note: returns -1 if conversion fails.
- *
- * Win32 builds use WideCharToMultiByte from the Windows API.
- * (Maybe Cygwin should too?  WideCharToMultiByte will know a
- * lot more about local character encodings than the wcrtomb()
- * wrapper is going to know.)
- */
-int
-archive_string_append_from_wcs(struct archive_string *as,
-    const wchar_t *w, size_t len)
-{
-	return archive_string_append_from_wcs_in_codepage(as, w, len, NULL);
-}
-
-static int
-archive_string_append_from_wcs_in_codepage(struct archive_string *as,
-    const wchar_t *ws, size_t len, struct archive_string_conv *sc)
-{
-	BOOL defchar_used, *dp;
-	int count, ret = 0;
-	UINT to_cp;
-	int wslen = (int)len;
-
-	if (sc != NULL)
-		to_cp = sc->to_cp;
-	else
-		to_cp = get_current_codepage();
-
-	if (to_cp == CP_C_LOCALE) {
-		/*
-		 * "C" locale special processing.
-		 */
-		const wchar_t *wp = ws;
-		char *p;
-
-		if (NULL == archive_string_ensure(as,
-		    as->length + wslen +1))
-			return (-1);
-		p = as->s + as->length;
-		count = 0;
-		defchar_used = 0;
-		while (count < wslen && *wp) {
-			if (*wp > 255) {
-				*p++ = '?';
-				wp++;
-				defchar_used = 1;
-			} else
-				*p++ = (char)*wp++;
-			count++;
-		}
-	} else if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) {
-		uint16_t *u16;
-
-		if (NULL ==
-		    archive_string_ensure(as, as->length + len * 2 + 2))
-			return (-1);
-		u16 = (uint16_t *)(as->s + as->length);
-		count = 0;
-		defchar_used = 0;
-		if (sc->flag & SCONV_TO_UTF16BE) {
-			while (count < (int)len && *ws) {
-				archive_be16enc(u16+count, *ws);
-				ws++;
-				count++;
-			}
-		} else {
-			while (count < (int)len && *ws) {
-				archive_le16enc(u16+count, *ws);
-				ws++;
-				count++;
-			}
-		}
-		count <<= 1; /* to be byte size */
-	} else {
-		/* Make sure the MBS buffer has plenty to set. */
-		if (NULL ==
-		    archive_string_ensure(as, as->length + len * 2 + 1))
-			return (-1);
-		do {
-			defchar_used = 0;
-			if (to_cp == CP_UTF8 || sc == NULL)
-				dp = NULL;
-			else
-				dp = &defchar_used;
-			count = WideCharToMultiByte(to_cp, 0, ws, wslen,
-			    as->s + as->length,
-			    (int)as->buffer_length - (int)as->length - 1, NULL, dp);
-			if (count == 0 &&
-			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-				/* Expand the MBS buffer and retry. */
-				if (NULL == archive_string_ensure(as,
-					as->buffer_length + len))
-					return (-1);
-				continue;
-			}
-			if (count == 0)
-				ret = -1;
-			break;
-		} while (1);
-	}
-	as->length += count;
-	as->s[as->length] = '\0';
-	return (defchar_used?-1:ret);
-}
-
-#elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB)
-
-/*
- * Translates a wide character string into current locale character set
- * and appends to the archive_string.  Note: returns -1 if conversion
- * fails.
- */
-int
-archive_string_append_from_wcs(struct archive_string *as,
-    const wchar_t *w, size_t len)
-{
-	/* We cannot use the standard wcstombs() here because it
-	 * cannot tell us how big the output buffer should be.  So
-	 * I've built a loop around wcrtomb() or wctomb() that
-	 * converts a character at a time and resizes the string as
-	 * needed.  We prefer wcrtomb() when it's available because
-	 * it's thread-safe. */
-	int n, ret_val = 0;
-	char *p;
-	char *end;
-#if HAVE_WCRTOMB
-	mbstate_t shift_state;
-
-	memset(&shift_state, 0, sizeof(shift_state));
-#else
-	/* Clear the shift state before starting. */
-	wctomb(NULL, L'\0');
-#endif
-	/*
-	 * Allocate buffer for MBS.
-	 * We need this allocation here since it is possible that
-	 * as->s is still NULL.
-	 */
-	if (archive_string_ensure(as, as->length + len + 1) == NULL)
-		return (-1);
-
-	p = as->s + as->length;
-	end = as->s + as->buffer_length - MB_CUR_MAX -1;
-	while (*w != L'\0' && len > 0) {
-		if (p >= end) {
-			as->length = p - as->s;
-			as->s[as->length] = '\0';
-			/* Re-allocate buffer for MBS. */
-			if (archive_string_ensure(as,
-			    as->length + max(len * 2,
-			    (size_t)MB_CUR_MAX) + 1) == NULL)
-				return (-1);
-			p = as->s + as->length;
-			end = as->s + as->buffer_length - MB_CUR_MAX -1;
-		}
-#if HAVE_WCRTOMB
-		n = wcrtomb(p, *w++, &shift_state);
-#else
-		n = wctomb(p, *w++);
-#endif
-		if (n == -1) {
-			if (errno == EILSEQ) {
-				/* Skip an illegal wide char. */
-				*p++ = '?';
-				ret_val = -1;
-			} else {
-				ret_val = -1;
-				break;
-			}
-		} else
-			p += n;
-		len--;
-	}
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	return (ret_val);
-}
-
-#else /* HAVE_WCTOMB || HAVE_WCRTOMB */
-
-/*
- * TODO: Test if __STDC_ISO_10646__ is defined.
- * Non-Windows uses ISO C wcrtomb() or wctomb() to perform the conversion
- * one character at a time.  If a non-Windows platform doesn't have
- * either of these, fall back to the built-in UTF8 conversion.
- */
-int
-archive_string_append_from_wcs(struct archive_string *as,
-    const wchar_t *w, size_t len)
-{
-	(void)as;/* UNUSED */
-	(void)w;/* UNUSED */
-	(void)len;/* UNUSED */
-	errno = ENOSYS;
-	return (-1);
-}
-
-#endif /* HAVE_WCTOMB || HAVE_WCRTOMB */
-
-/*
- * Find a string conversion object by a pair of 'from' charset name
- * and 'to' charset name from an archive object.
- * Return NULL if not found.
- */
-static struct archive_string_conv *
-find_sconv_object(struct archive *a, const char *fc, const char *tc)
-{
-	struct archive_string_conv *sc; 
-
-	if (a == NULL)
-		return (NULL);
-
-	for (sc = a->sconv; sc != NULL; sc = sc->next) {
-		if (strcmp(sc->from_charset, fc) == 0 &&
-		    strcmp(sc->to_charset, tc) == 0)
-			break;
-	}
-	return (sc);
-}
-
-/*
- * Register a string object to an archive object.
- */
-static void
-add_sconv_object(struct archive *a, struct archive_string_conv *sc)
-{
-	struct archive_string_conv **psc; 
-
-	/* Add a new sconv to sconv list. */
-	psc = &(a->sconv);
-	while (*psc != NULL)
-		psc = &((*psc)->next);
-	*psc = sc;
-}
-
-static void
-add_converter(struct archive_string_conv *sc, int (*converter)
-    (struct archive_string *, const void *, size_t,
-     struct archive_string_conv *))
-{
-	if (sc == NULL || sc->nconverter >= 2)
-		__archive_errx(1, "Programming error");
-	sc->converter[sc->nconverter++] = converter;
-}
-
-static void
-setup_converter(struct archive_string_conv *sc)
-{
-
-	/* Reset. */
-	sc->nconverter = 0;
-
-	/*
-	 * Perform special sequence for the incorrect UTF-8 filenames
-	 * made by libarchive2.x.
-	 */
-	if (sc->flag & SCONV_UTF8_LIBARCHIVE_2) {
-		add_converter(sc, strncat_from_utf8_libarchive2);
-		return;
-	}
-
-	/*
-	 * Convert a string to UTF-16BE/LE.
-	 */
-	if (sc->flag & SCONV_TO_UTF16) {
-		/*
-		 * If the current locale is UTF-8, we can translate
-		 * a UTF-8 string into a UTF-16BE string.
-		 */
-		if (sc->flag & SCONV_FROM_UTF8) {
-			add_converter(sc, archive_string_append_unicode);
-			return;
-		}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		if (sc->flag & SCONV_WIN_CP) {
-			if (sc->flag & SCONV_TO_UTF16BE)
-				add_converter(sc, win_strncat_to_utf16be);
-			else
-				add_converter(sc, win_strncat_to_utf16le);
-			return;
-		}
-#endif
-
-#if defined(HAVE_ICONV)
-		if (sc->cd != (iconv_t)-1) {
-			add_converter(sc, iconv_strncat_in_locale);
-			return;
-		}
-#endif
-
-		if (sc->flag & SCONV_BEST_EFFORT) {
-			if (sc->flag & SCONV_TO_UTF16BE)
-				add_converter(sc,
-					best_effort_strncat_to_utf16be);
-			else
-				add_converter(sc,
-					best_effort_strncat_to_utf16le);
-		} else
-			/* Make sure we have no converter. */
-			sc->nconverter = 0;
-		return;
-	}
-
-	/*
-	 * Convert a string from UTF-16BE/LE.
-	 */
-	if (sc->flag & SCONV_FROM_UTF16) {
-		/*
-		 * At least we should normalize a UTF-16BE string.
-		 */
-		if (sc->flag & SCONV_NORMALIZATION_D)
-			add_converter(sc,archive_string_normalize_D);
-		else if (sc->flag & SCONV_NORMALIZATION_C)
-			add_converter(sc, archive_string_normalize_C);
-
-		if (sc->flag & SCONV_TO_UTF8) {
-			/*
-			 * If the current locale is UTF-8, we can translate
-			 * a UTF-16BE/LE string into a UTF-8 string directly.
-			 */
-			if (!(sc->flag &
-			    (SCONV_NORMALIZATION_D |SCONV_NORMALIZATION_C)))
-				add_converter(sc,
-				    archive_string_append_unicode);
-			return;
-		}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		if (sc->flag & SCONV_WIN_CP) {
-			if (sc->flag & SCONV_FROM_UTF16BE)
-				add_converter(sc, win_strncat_from_utf16be);
-			else
-				add_converter(sc, win_strncat_from_utf16le);
-			return;
-		}
-#endif
-
-#if defined(HAVE_ICONV)
-		if (sc->cd != (iconv_t)-1) {
-			add_converter(sc, iconv_strncat_in_locale);
-			return;
-		}
-#endif
-
-		if ((sc->flag & (SCONV_BEST_EFFORT | SCONV_FROM_UTF16BE))
-		    == (SCONV_BEST_EFFORT | SCONV_FROM_UTF16BE))
-			add_converter(sc, best_effort_strncat_from_utf16be);
-		else if ((sc->flag & (SCONV_BEST_EFFORT | SCONV_FROM_UTF16LE))
-		    == (SCONV_BEST_EFFORT | SCONV_FROM_UTF16LE))
-			add_converter(sc, best_effort_strncat_from_utf16le);
-		else
-			/* Make sure we have no converter. */
-			sc->nconverter = 0;
-		return;
-	}
-
-	if (sc->flag & SCONV_FROM_UTF8) {
-		/*
-		 * At least we should normalize a UTF-8 string.
-		 */
-		if (sc->flag & SCONV_NORMALIZATION_D)
-			add_converter(sc,archive_string_normalize_D);
-		else if (sc->flag & SCONV_NORMALIZATION_C)
-			add_converter(sc, archive_string_normalize_C);
-
-		/*
-		 * Copy UTF-8 string with a check of CESU-8.
-		 * Apparently, iconv does not check surrogate pairs in UTF-8
-		 * when both from-charset and to-charset are UTF-8, and then
-		 * we use our UTF-8 copy code.
-		 */
-		if (sc->flag & SCONV_TO_UTF8) {
-			/*
-			 * If the current locale is UTF-8, we can translate
-			 * a UTF-16BE string into a UTF-8 string directly.
-			 */
-			if (!(sc->flag &
-			    (SCONV_NORMALIZATION_D |SCONV_NORMALIZATION_C)))
-				add_converter(sc, strncat_from_utf8_to_utf8);
-			return;
-		}
-	}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/*
-	 * On Windows we can use Windows API for a string conversion.
-	 */
-	if (sc->flag & SCONV_WIN_CP) {
-		add_converter(sc, strncat_in_codepage);
-		return;
-	}
-#endif
-
-#if HAVE_ICONV
-	if (sc->cd != (iconv_t)-1) {
-		add_converter(sc, iconv_strncat_in_locale);
-		/*
-		 * iconv generally does not support UTF-8-MAC and so
-		 * we have to the output of iconv from NFC to NFD if
-		 * need.
-		 */
-		if ((sc->flag & SCONV_FROM_CHARSET) &&
-		    (sc->flag & SCONV_TO_UTF8)) {
-			if (sc->flag & SCONV_NORMALIZATION_D)
-				add_converter(sc, archive_string_normalize_D);
-		}
-		return;
-	}
-#endif
-
-	/*
-	 * Try conversion in the best effort or no conversion.
-	 */
-	if ((sc->flag & SCONV_BEST_EFFORT) || sc->same)
-		add_converter(sc, best_effort_strncat_in_locale);
-	else
-		/* Make sure we have no converter. */
-		sc->nconverter = 0;
-}
-
-/*
- * Return canonicalized charset-name but this supports just UTF-8, UTF-16BE
- * and CP932 which are referenced in create_sconv_object().
- */
-static const char *
-canonical_charset_name(const char *charset)
-{
-	char cs[16];
-	char *p;
-	const char *s;
-
-	if (charset == NULL || charset[0] == '\0'
-	    || strlen(charset) > 15)
-		return (charset);
-
-	/* Copy name to uppercase. */
-	p = cs;
-	s = charset;
-	while (*s) {
-		char c = *s++;
-		if (c >= 'a' && c <= 'z')
-			c -= 'a' - 'A';
-		*p++ = c;
-	}
-	*p++ = '\0';
-
-	if (strcmp(cs, "UTF-8") == 0 ||
-	    strcmp(cs, "UTF8") == 0)
-		return ("UTF-8");
-	if (strcmp(cs, "UTF-16BE") == 0 ||
-	    strcmp(cs, "UTF16BE") == 0)
-		return ("UTF-16BE");
-	if (strcmp(cs, "UTF-16LE") == 0 ||
-	    strcmp(cs, "UTF16LE") == 0)
-		return ("UTF-16LE");
-	if (strcmp(cs, "CP932") == 0)
-		return ("CP932");
-	return (charset);
-}
-
-/*
- * Create a string conversion object.
- */
-static struct archive_string_conv *
-create_sconv_object(const char *fc, const char *tc,
-    unsigned current_codepage, int flag)
-{
-	struct archive_string_conv *sc; 
-
-	sc = calloc(1, sizeof(*sc));
-	if (sc == NULL)
-		return (NULL);
-	sc->next = NULL;
-	sc->from_charset = strdup(fc);
-	if (sc->from_charset == NULL) {
-		free(sc);
-		return (NULL);
-	}
-	sc->to_charset = strdup(tc);
-	if (sc->to_charset == NULL) {
-		free(sc->from_charset);
-		free(sc);
-		return (NULL);
-	}
-	archive_string_init(&sc->utftmp);
-
-	if (flag & SCONV_TO_CHARSET) {
-		/*
-		 * Convert characters from the current locale charset to
-		 * a specified charset.
-		 */
-		sc->from_cp = current_codepage;
-		sc->to_cp = make_codepage_from_charset(tc);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		if (IsValidCodePage(sc->to_cp))
-			flag |= SCONV_WIN_CP;
-#endif
-	} else if (flag & SCONV_FROM_CHARSET) {
-		/*
-		 * Convert characters from a specified charset to
-		 * the current locale charset.
-		 */
-		sc->to_cp = current_codepage;
-		sc->from_cp = make_codepage_from_charset(fc);
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		if (IsValidCodePage(sc->from_cp))
-			flag |= SCONV_WIN_CP;
-#endif
-	}
-
-	/*
-	 * Check if "from charset" and "to charset" are the same.
-	 */
-	if (strcmp(fc, tc) == 0 ||
-	    (sc->from_cp != (unsigned)-1 && sc->from_cp == sc->to_cp))
-		sc->same = 1;
-	else
-		sc->same = 0;
-
-	/*
-	 * Mark if "from charset" or "to charset" are UTF-8 or UTF-16BE/LE.
-	 */
-	if (strcmp(tc, "UTF-8") == 0)
-		flag |= SCONV_TO_UTF8;
-	else if (strcmp(tc, "UTF-16BE") == 0)
-		flag |= SCONV_TO_UTF16BE;
-	else if (strcmp(tc, "UTF-16LE") == 0)
-		flag |= SCONV_TO_UTF16LE;
-	if (strcmp(fc, "UTF-8") == 0)
-		flag |= SCONV_FROM_UTF8;
-	else if (strcmp(fc, "UTF-16BE") == 0)
-		flag |= SCONV_FROM_UTF16BE;
-	else if (strcmp(fc, "UTF-16LE") == 0)
-		flag |= SCONV_FROM_UTF16LE;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	if (sc->to_cp == CP_UTF8)
-		flag |= SCONV_TO_UTF8;
-	else if (sc->to_cp == CP_UTF16BE)
-		flag |= SCONV_TO_UTF16BE | SCONV_WIN_CP;
-	else if (sc->to_cp == CP_UTF16LE)
-		flag |= SCONV_TO_UTF16LE | SCONV_WIN_CP;
-	if (sc->from_cp == CP_UTF8)
-		flag |= SCONV_FROM_UTF8;
-	else if (sc->from_cp == CP_UTF16BE)
-		flag |= SCONV_FROM_UTF16BE | SCONV_WIN_CP;
-	else if (sc->from_cp == CP_UTF16LE)
-		flag |= SCONV_FROM_UTF16LE | SCONV_WIN_CP;
-#endif
-
-	/*
-	 * Set a flag for Unicode NFD. Usually iconv cannot correctly
-	 * handle it. So we have to translate NFD characters to NFC ones
-	 * ourselves before iconv handles. Another reason is to prevent
-	 * that the same sight of two filenames, one is NFC and other
-	 * is NFD, would be in its directory.
-	 * On Mac OS X, although its filesystem layer automatically
-	 * convert filenames to NFD, it would be useful for filename
-	 * comparing to find out the same filenames that we normalize
-	 * that to be NFD ourselves.
-	 */
-	if ((flag & SCONV_FROM_CHARSET) &&
-	    (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8))) {
-#if defined(__APPLE__)
-		if (flag & SCONV_TO_UTF8)
-			flag |= SCONV_NORMALIZATION_D;
-		else
-#endif
-			flag |= SCONV_NORMALIZATION_C;
-	}
-#if defined(__APPLE__)
-	/*
-	 * In case writing an archive file, make sure that a filename
-	 * going to be passed to iconv is a Unicode NFC string since
-	 * a filename in HFS Plus filesystem is a Unicode NFD one and
-	 * iconv cannot handle it with "UTF-8" charset. It is simpler
-	 * than a use of "UTF-8-MAC" charset.
-	 */
-	if ((flag & SCONV_TO_CHARSET) &&
-	    (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
-	    !(flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8)))
-		flag |= SCONV_NORMALIZATION_C;
-	/*
-	 * In case reading an archive file. make sure that a filename
-	 * will be passed to users is a Unicode NFD string in order to
-	 * correctly compare the filename with other one which comes
-	 * from HFS Plus filesystem.
-	 */
-	if ((flag & SCONV_FROM_CHARSET) &&
-	   !(flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
-	    (flag & SCONV_TO_UTF8))
-		flag |= SCONV_NORMALIZATION_D;
-#endif
-
-#if defined(HAVE_ICONV)
-	sc->cd_w = (iconv_t)-1;
-	/*
-	 * Create an iconv object.
-	 */
-	if (((flag & (SCONV_TO_UTF8 | SCONV_TO_UTF16)) &&
-	    (flag & (SCONV_FROM_UTF8 | SCONV_FROM_UTF16))) ||
-	    (flag & SCONV_WIN_CP)) {
-		/* This case we won't use iconv. */
-		sc->cd = (iconv_t)-1;
-	} else {
-		sc->cd = iconv_open(tc, fc);
-		if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
-			/*
-			 * Unfortunately, all of iconv implements do support
-			 * "CP932" character-set, so we should use "SJIS"
-			 * instead if iconv_open failed.
-			 */
-			if (strcmp(tc, "CP932") == 0)
-				sc->cd = iconv_open("SJIS", fc);
-			else if (strcmp(fc, "CP932") == 0)
-				sc->cd = iconv_open(tc, "SJIS");
-		}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		/*
-		 * archive_mstring on Windows directly convert multi-bytes
-		 * into archive_wstring in order not to depend on locale
-		 * so that you can do a I18N programming. This will be
-		 * used only in archive_mstring_copy_mbs_len_l so far.
-		 */
-		if (flag & SCONV_FROM_CHARSET) {
-			sc->cd_w = iconv_open("UTF-8", fc);
-			if (sc->cd_w == (iconv_t)-1 &&
-			    (sc->flag & SCONV_BEST_EFFORT)) {
-				if (strcmp(fc, "CP932") == 0)
-					sc->cd_w = iconv_open("UTF-8", "SJIS");
-			}
-		}
-#endif /* _WIN32 && !__CYGWIN__ */
-	}
-#endif	/* HAVE_ICONV */
-
-	sc->flag = flag;
-
-	/*
-	 * Set up converters.
-	 */
-	setup_converter(sc);
-
-	return (sc);
-}
-
-/*
- * Free a string conversion object.
- */
-static void
-free_sconv_object(struct archive_string_conv *sc)
-{
-	free(sc->from_charset);
-	free(sc->to_charset);
-	archive_string_free(&sc->utftmp);
-#if HAVE_ICONV
-	if (sc->cd != (iconv_t)-1)
-		iconv_close(sc->cd);
-	if (sc->cd_w != (iconv_t)-1)
-		iconv_close(sc->cd_w);
-#endif
-	free(sc);
-}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-#  define GetOEMCP() CP_OEMCP
-# endif
-
-static unsigned
-my_atoi(const char *p)
-{
-	unsigned cp;
-
-	cp = 0;
-	while (*p) {
-		if (*p >= '0' && *p <= '9')
-			cp = cp * 10 + (*p - '0');
-		else
-			return (-1);
-		p++;
-	}
-	return (cp);
-}
-
-/*
- * Translate Charset name (as used by iconv) into CodePage (as used by Windows)
- * Return -1 if failed.
- *
- * Note: This translation code may be insufficient.
- */
-static struct charset {
-	const char *name;
-	unsigned cp;
-} charsets[] = {
-	/* MUST BE SORTED! */
-	{"ASCII", 1252},
-	{"ASMO-708", 708},
-	{"BIG5", 950},
-	{"CHINESE", 936},
-	{"CP367", 1252},
-	{"CP819", 1252},
-	{"CP1025", 21025},
-	{"DOS-720", 720},
-	{"DOS-862", 862},
-	{"EUC-CN", 51936},
-	{"EUC-JP", 51932},
-	{"EUC-KR", 949},
-	{"EUCCN", 51936},
-	{"EUCJP", 51932},
-	{"EUCKR", 949},
-	{"GB18030", 54936},
-	{"GB2312", 936},
-	{"HEBREW", 1255},
-	{"HZ-GB-2312", 52936},
-	{"IBM273", 20273},
-	{"IBM277", 20277},
-	{"IBM278", 20278},
-	{"IBM280", 20280},
-	{"IBM284", 20284},
-	{"IBM285", 20285},
-	{"IBM290", 20290},
-	{"IBM297", 20297},
-	{"IBM367", 1252},
-	{"IBM420", 20420},
-	{"IBM423", 20423},
-	{"IBM424", 20424},
-	{"IBM819", 1252},
-	{"IBM871", 20871},
-	{"IBM880", 20880},
-	{"IBM905", 20905},
-	{"IBM924", 20924},
-	{"ISO-8859-1", 28591},
-	{"ISO-8859-13", 28603},
-	{"ISO-8859-15", 28605},
-	{"ISO-8859-2", 28592},
-	{"ISO-8859-3", 28593},
-	{"ISO-8859-4", 28594},
-	{"ISO-8859-5", 28595},
-	{"ISO-8859-6", 28596},
-	{"ISO-8859-7", 28597},
-	{"ISO-8859-8", 28598},
-	{"ISO-8859-9", 28599},
-	{"ISO8859-1", 28591},
-	{"ISO8859-13", 28603},
-	{"ISO8859-15", 28605},
-	{"ISO8859-2", 28592},
-	{"ISO8859-3", 28593},
-	{"ISO8859-4", 28594},
-	{"ISO8859-5", 28595},
-	{"ISO8859-6", 28596},
-	{"ISO8859-7", 28597},
-	{"ISO8859-8", 28598},
-	{"ISO8859-9", 28599},
-	{"JOHAB", 1361},
-	{"KOI8-R", 20866},
-	{"KOI8-U", 21866},
-	{"KS_C_5601-1987", 949},
-	{"LATIN1", 1252},
-	{"LATIN2", 28592},
-	{"MACINTOSH", 10000},
-	{"SHIFT-JIS", 932},
-	{"SHIFT_JIS", 932},
-	{"SJIS", 932},
-	{"US", 1252},
-	{"US-ASCII", 1252},
-	{"UTF-16", 1200},
-	{"UTF-16BE", 1201},
-	{"UTF-16LE", 1200},
-	{"UTF-8", CP_UTF8},
-	{"X-EUROPA", 29001},
-	{"X-MAC-ARABIC", 10004},
-	{"X-MAC-CE", 10029},
-	{"X-MAC-CHINESEIMP", 10008},
-	{"X-MAC-CHINESETRAD", 10002},
-	{"X-MAC-CROATIAN", 10082},
-	{"X-MAC-CYRILLIC", 10007},
-	{"X-MAC-GREEK", 10006},
-	{"X-MAC-HEBREW", 10005},
-	{"X-MAC-ICELANDIC", 10079},
-	{"X-MAC-JAPANESE", 10001},
-	{"X-MAC-KOREAN", 10003},
-	{"X-MAC-ROMANIAN", 10010},
-	{"X-MAC-THAI", 10021},
-	{"X-MAC-TURKISH", 10081},
-	{"X-MAC-UKRAINIAN", 10017},
-};
-static unsigned
-make_codepage_from_charset(const char *charset)
-{
-	char cs[16];
-	char *p;
-	unsigned cp;
-	int a, b;
-
-	if (charset == NULL || strlen(charset) > 15)
-		return -1;
-
-	/* Copy name to uppercase. */
-	p = cs;
-	while (*charset) {
-		char c = *charset++;
-		if (c >= 'a' && c <= 'z')
-			c -= 'a' - 'A';
-		*p++ = c;
-	}
-	*p++ = '\0';
-	cp = -1;
-
-	/* Look it up in the table first, so that we can easily
-	 * override CP367, which we map to 1252 instead of 367. */
-	a = 0;
-	b = sizeof(charsets)/sizeof(charsets[0]);
-	while (b > a) {
-		int c = (b + a) / 2;
-		int r = strcmp(charsets[c].name, cs);
-		if (r < 0)
-			a = c + 1;
-		else if (r > 0)
-			b = c;
-		else
-			return charsets[c].cp;
-	}
-
-	/* If it's not in the table, try to parse it. */
-	switch (*cs) {
-	case 'C':
-		if (cs[1] == 'P' && cs[2] >= '0' && cs[2] <= '9') {
-			cp = my_atoi(cs + 2);
-		} else if (strcmp(cs, "CP_ACP") == 0)
-			cp = get_current_codepage();
-		else if (strcmp(cs, "CP_OEMCP") == 0)
-			cp = get_current_oemcp();
-		break;
-	case 'I':
-		if (cs[1] == 'B' && cs[2] == 'M' &&
-		    cs[3] >= '0' && cs[3] <= '9') {
-			cp = my_atoi(cs + 3);
-		}
-		break;
-	case 'W':
-		if (strncmp(cs, "WINDOWS-", 8) == 0) {
-			cp = my_atoi(cs + 8);
-			if (cp != 874 && (cp < 1250 || cp > 1258))
-				cp = -1;/* This may invalid code. */
-		}
-		break;
-	}
-	return (cp);
-}
-
-/*
- * Return ANSI Code Page of current locale set by setlocale().
- */
-static unsigned
-get_current_codepage(void)
-{
-	char *locale, *p;
-	unsigned cp;
-
-	locale = setlocale(LC_CTYPE, NULL);
-	if (locale == NULL)
-		return (GetACP());
-	if (locale[0] == 'C' && locale[1] == '\0')
-		return (CP_C_LOCALE);
-	p = strrchr(locale, '.');
-	if (p == NULL)
-		return (GetACP());
-	if (strcmp(p+1, "utf8") == 0)
-		return CP_UTF8;
-	cp = my_atoi(p+1);
-	if ((int)cp <= 0)
-		return (GetACP());
-	return (cp);
-}
-
-/*
- * Translation table between Locale Name and ACP/OEMCP.
- */
-static struct {
-	unsigned acp;
-	unsigned ocp;
-	const char *locale;
-} acp_ocp_map[] = {
-	{  950,  950, "Chinese_Taiwan" },
-	{  936,  936, "Chinese_People's Republic of China" },
-	{  950,  950, "Chinese_Taiwan" },
-	{ 1250,  852, "Czech_Czech Republic" },
-	{ 1252,  850, "Danish_Denmark" },
-	{ 1252,  850, "Dutch_Netherlands" },
-	{ 1252,  850, "Dutch_Belgium" },
-	{ 1252,  437, "English_United States" },
-	{ 1252,  850, "English_Australia" },
-	{ 1252,  850, "English_Canada" },
-	{ 1252,  850, "English_New Zealand" },
-	{ 1252,  850, "English_United Kingdom" },
-	{ 1252,  437, "English_United States" },
-	{ 1252,  850, "Finnish_Finland" },
-	{ 1252,  850, "French_France" },
-	{ 1252,  850, "French_Belgium" },
-	{ 1252,  850, "French_Canada" },
-	{ 1252,  850, "French_Switzerland" },
-	{ 1252,  850, "German_Germany" },
-	{ 1252,  850, "German_Austria" },
-	{ 1252,  850, "German_Switzerland" },
-	{ 1253,  737, "Greek_Greece" },
-	{ 1250,  852, "Hungarian_Hungary" },
-	{ 1252,  850, "Icelandic_Iceland" },
-	{ 1252,  850, "Italian_Italy" },
-	{ 1252,  850, "Italian_Switzerland" },
-	{  932,  932, "Japanese_Japan" },
-	{  949,  949, "Korean_Korea" },
-	{ 1252,  850, "Norwegian (BokmOl)_Norway" },
-	{ 1252,  850, "Norwegian (BokmOl)_Norway" },
-	{ 1252,  850, "Norwegian-Nynorsk_Norway" },
-	{ 1250,  852, "Polish_Poland" },
-	{ 1252,  850, "Portuguese_Portugal" },
-	{ 1252,  850, "Portuguese_Brazil" },
-	{ 1251,  866, "Russian_Russia" },
-	{ 1250,  852, "Slovak_Slovakia" },
-	{ 1252,  850, "Spanish_Spain" },
-	{ 1252,  850, "Spanish_Mexico" },
-	{ 1252,  850, "Spanish_Spain" },
-	{ 1252,  850, "Swedish_Sweden" },
-	{ 1254,  857, "Turkish_Turkey" },
-	{ 0, 0, NULL}
-};
-
-/*
- * Return OEM Code Page of current locale set by setlocale().
- */
-static unsigned
-get_current_oemcp(void)
-{
-	int i;
-	char *locale, *p;
-	size_t len;
-
-	locale = setlocale(LC_CTYPE, NULL);
-	if (locale == NULL)
-		return (GetOEMCP());
-	if (locale[0] == 'C' && locale[1] == '\0')
-		return (CP_C_LOCALE);
-
-	p = strrchr(locale, '.');
-	if (p == NULL)
-		return (GetOEMCP());
-	len = p - locale;
-	for (i = 0; acp_ocp_map[i].acp; i++) {
-		if (strncmp(acp_ocp_map[i].locale, locale, len) == 0)
-			return (acp_ocp_map[i].ocp);
-	}
-	return (GetOEMCP());
-}
-#else
-
-/*
- * POSIX platform does not use CodePage.
- */
-
-static unsigned
-get_current_codepage(void)
-{
-	return (-1);/* Unknown */
-}
-static unsigned
-make_codepage_from_charset(const char *charset)
-{
-	(void)charset; /* UNUSED */
-	return (-1);/* Unknown */
-}
-static unsigned
-get_current_oemcp(void)
-{
-	return (-1);/* Unknown */
-}
-
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-
-/*
- * Return a string conversion object.
- */
-static struct archive_string_conv *
-get_sconv_object(struct archive *a, const char *fc, const char *tc, int flag)
-{
-	struct archive_string_conv *sc;
-	unsigned current_codepage;
-
-	/* Check if we have made the sconv object. */
-	sc = find_sconv_object(a, fc, tc);
-	if (sc != NULL)
-		return (sc);
-
-	if (a == NULL)
-		current_codepage = get_current_codepage();
-	else
-		current_codepage = a->current_codepage;
-
-	sc = create_sconv_object(canonical_charset_name(fc),
-	    canonical_charset_name(tc), current_codepage, flag);
-	if (sc == NULL) {
-		if (a != NULL)
-			archive_set_error(a, ENOMEM,
-			    "Could not allocate memory for "
-			    "a string conversion object");
-		return (NULL);
-	}
-
-	/*
-	 * If there is no converter for current string conversion object,
-	 * we cannot handle this conversion.
-	 */
-	if (sc->nconverter == 0) {
-		if (a != NULL) {
-#if HAVE_ICONV
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "iconv_open failed : Cannot handle ``%s''",
-			    (flag & SCONV_TO_CHARSET)?tc:fc);
-#else
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "A character-set conversion not fully supported "
-			    "on this platform");
-#endif
-		}
-		/* Failed; free a sconv object. */
-		free_sconv_object(sc);
-		return (NULL);
-	}
-
-	/*
-	 * Success!
-	 */
-	if (a != NULL)
-		add_sconv_object(a, sc);
-	return (sc);
-}
-
-static const char *
-get_current_charset(struct archive *a)
-{
-	const char *cur_charset;
-
-	if (a == NULL)
-		cur_charset = default_iconv_charset("");
-	else {
-		cur_charset = default_iconv_charset(a->current_code);
-		if (a->current_code == NULL) {
-			a->current_code = strdup(cur_charset);
-			a->current_codepage = get_current_codepage();
-			a->current_oemcp = get_current_oemcp();
-		}
-	}
-	return (cur_charset);
-}
-
-/*
- * Make and Return a string conversion object.
- * Return NULL if the platform does not support the specified conversion
- * and best_effort is 0.
- * If best_effort is set, A string conversion object must be returned
- * unless memory allocation for the object fails, but the conversion
- * might fail when non-ASCII code is found.
- */
-struct archive_string_conv *
-archive_string_conversion_to_charset(struct archive *a, const char *charset,
-    int best_effort)
-{
-	int flag = SCONV_TO_CHARSET;
-
-	if (best_effort)
-		flag |= SCONV_BEST_EFFORT;
-	return (get_sconv_object(a, get_current_charset(a), charset, flag));
-}
-
-struct archive_string_conv *
-archive_string_conversion_from_charset(struct archive *a, const char *charset,
-    int best_effort)
-{
-	int flag = SCONV_FROM_CHARSET;
-
-	if (best_effort)
-		flag |= SCONV_BEST_EFFORT;
-	return (get_sconv_object(a, charset, get_current_charset(a), flag));
-}
-
-/*
- * archive_string_default_conversion_*_archive() are provided for Windows
- * platform because other archiver application use CP_OEMCP for
- * MultiByteToWideChar() and WideCharToMultiByte() for the filenames
- * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
- * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
- * So we should make a string conversion between CP_ACP and CP_OEMCP
- * for compatibility.
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-struct archive_string_conv *
-archive_string_default_conversion_for_read(struct archive *a)
-{
-	const char *cur_charset = get_current_charset(a);
-	char oemcp[16];
-
-	/* NOTE: a check of cur_charset is unneeded but we need
-	 * that get_current_charset() has been surely called at
-	 * this time whatever C compiler optimized. */
-	if (cur_charset != NULL &&
-	    (a->current_codepage == CP_C_LOCALE ||
-	     a->current_codepage == a->current_oemcp))
-		return (NULL);/* no conversion. */
-
-	_snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp);
-	/* Make sure a null termination must be set. */
-	oemcp[sizeof(oemcp)-1] = '\0';
-	return (get_sconv_object(a, oemcp, cur_charset,
-	    SCONV_FROM_CHARSET));
-}
-
-struct archive_string_conv *
-archive_string_default_conversion_for_write(struct archive *a)
-{
-	const char *cur_charset = get_current_charset(a);
-	char oemcp[16];
-
-	/* NOTE: a check of cur_charset is unneeded but we need
-	 * that get_current_charset() has been surely called at
-	 * this time whatever C compiler optimized. */
-	if (cur_charset != NULL &&
-	    (a->current_codepage == CP_C_LOCALE ||
-	     a->current_codepage == a->current_oemcp))
-		return (NULL);/* no conversion. */
-
-	_snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp);
-	/* Make sure a null termination must be set. */
-	oemcp[sizeof(oemcp)-1] = '\0';
-	return (get_sconv_object(a, cur_charset, oemcp,
-	    SCONV_TO_CHARSET));
-}
-#else
-struct archive_string_conv *
-archive_string_default_conversion_for_read(struct archive *a)
-{
-	(void)a; /* UNUSED */
-	return (NULL);
-}
-
-struct archive_string_conv *
-archive_string_default_conversion_for_write(struct archive *a)
-{
-	(void)a; /* UNUSED */
-	return (NULL);
-}
-#endif
-
-/*
- * Dispose of all character conversion objects in the archive object.
- */
-void
-archive_string_conversion_free(struct archive *a)
-{
-	struct archive_string_conv *sc; 
-	struct archive_string_conv *sc_next; 
-
-	for (sc = a->sconv; sc != NULL; sc = sc_next) {
-		sc_next = sc->next;
-		free_sconv_object(sc);
-	}
-	a->sconv = NULL;
-	free(a->current_code);
-	a->current_code = NULL;
-}
-
-/*
- * Return a conversion charset name.
- */
-const char *
-archive_string_conversion_charset_name(struct archive_string_conv *sc)
-{
-	if (sc->flag & SCONV_TO_CHARSET)
-		return (sc->to_charset);
-	else
-		return (sc->from_charset);
-}
-
-/*
- * Change the behavior of a string conversion.
- */
-void
-archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
-{
-	switch (opt) {
-	/*
-	 * A filename in UTF-8 was made with libarchive 2.x in a wrong
-	 * assumption that wchar_t was Unicode.
-	 * This option enables simulating the assumption in order to read
-	 * that filename correctly.
-	 */
-	case SCONV_SET_OPT_UTF8_LIBARCHIVE2X:
-#if (defined(_WIN32) && !defined(__CYGWIN__)) \
-	 || defined(__STDC_ISO_10646__) || defined(__APPLE__)
-		/*
-		 * Nothing to do for it since wchar_t on these platforms
-		 * is really Unicode.
-		 */
-		(void)sc; /* UNUSED */
-#else
-		if ((sc->flag & SCONV_UTF8_LIBARCHIVE_2) == 0) {
-			sc->flag |= SCONV_UTF8_LIBARCHIVE_2;
-			/* Set up string converters. */
-			setup_converter(sc);
-		}
-#endif
-		break;
-	case SCONV_SET_OPT_NORMALIZATION_C:
-		if ((sc->flag & SCONV_NORMALIZATION_C) == 0) {
-			sc->flag |= SCONV_NORMALIZATION_C;
-			sc->flag &= ~SCONV_NORMALIZATION_D;
-			/* Set up string converters. */
-			setup_converter(sc);
-		}
-		break;
-	case SCONV_SET_OPT_NORMALIZATION_D:
-#if defined(HAVE_ICONV)
-		/*
-		 * If iconv will take the string, do not change the
-		 * setting of the normalization.
-		 */
-		if (!(sc->flag & SCONV_WIN_CP) &&
-		     (sc->flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
-		    !(sc->flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8)))
-			break;
-#endif
-		if ((sc->flag & SCONV_NORMALIZATION_D) == 0) {
-			sc->flag |= SCONV_NORMALIZATION_D;
-			sc->flag &= ~SCONV_NORMALIZATION_C;
-			/* Set up string converters. */
-			setup_converter(sc);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- *
- * Copy one archive_string to another in locale conversion.
- *
- *	archive_strncat_l();
- *	archive_strncpy_l();
- *
- */
-
-static size_t
-mbsnbytes(const void *_p, size_t n)
-{
-	size_t s;
-	const char *p, *pp;
-
-	if (_p == NULL)
-		return (0);
-	p = (const char *)_p;
-
-	/* Like strlen(p), except won't examine positions beyond p[n]. */
-	s = 0;
-	pp = p;
-	while (s < n && *pp) {
-		pp++;
-		s++;
-	}
-	return (s);
-}
-
-static size_t
-utf16nbytes(const void *_p, size_t n)
-{
-	size_t s;
-	const char *p, *pp;
-
-	if (_p == NULL)
-		return (0);
-	p = (const char *)_p;
-
-	/* Like strlen(p), except won't examine positions beyond p[n]. */
-	s = 0;
-	pp = p;
-	n >>= 1;
-	while (s < n && (pp[0] || pp[1])) {
-		pp += 2;
-		s++;
-	}
-	return (s<<1);
-}
-
-int
-archive_strncpy_l(struct archive_string *as, const void *_p, size_t n,
-    struct archive_string_conv *sc)
-{
-	as->length = 0;
-	return (archive_strncat_l(as, _p, n, sc));
-}
-
-int
-archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
-    struct archive_string_conv *sc)
-{
-	const void *s;
-	size_t length = 0;
-	int i, r = 0, r2;
-
-	if (_p != NULL && n > 0) {
-		if (sc != NULL && (sc->flag & SCONV_FROM_UTF16))
-			length = utf16nbytes(_p, n);
-		else
-			length = mbsnbytes(_p, n);
-	}
-
-	/* We must allocate memory even if there is no data for conversion
-	 * or copy. This simulates archive_string_append behavior. */
-	if (length == 0) {
-		int tn = 1;
-		if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
-			tn = 2;
-		if (archive_string_ensure(as, as->length + tn) == NULL)
-			return (-1);
-		as->s[as->length] = 0;
-		if (tn == 2)
-			as->s[as->length+1] = 0;
-		return (0);
-	}
-
-	/*
-	 * If sc is NULL, we just make a copy.
-	 */
-	if (sc == NULL) {
-		if (archive_string_append(as, _p, length) == NULL)
-			return (-1);/* No memory */
-		return (0);
-	}
-
-	s = _p;
-	i = 0;
-	if (sc->nconverter > 1) {
-		sc->utftmp.length = 0;
-		r2 = sc->converter[0](&(sc->utftmp), s, length, sc);
-		if (r2 != 0 && errno == ENOMEM)
-			return (r2);
-		if (r > r2)
-			r = r2;
-		s = sc->utftmp.s;
-		length = sc->utftmp.length;
-		++i;
-	}
-	r2 = sc->converter[i](as, s, length, sc);
-	if (r > r2)
-		r = r2;
-	return (r);
-}
-
-#if HAVE_ICONV
-
-/*
- * Return -1 if conversion fails.
- */
-static int
-iconv_strncat_in_locale(struct archive_string *as, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	ICONV_CONST char *itp;
-	size_t remaining;
-	iconv_t cd;
-	char *outp;
-	size_t avail, bs;
-	int return_value = 0; /* success */
-	int to_size, from_size;
-
-	if (sc->flag & SCONV_TO_UTF16)
-		to_size = 2;
-	else
-		to_size = 1;
-	if (sc->flag & SCONV_FROM_UTF16)
-		from_size = 2;
-	else
-		from_size = 1;
-
-	if (archive_string_ensure(as, as->length + length*2+to_size) == NULL)
-		return (-1);
-
-	cd = sc->cd;
-	itp = (char *)(uintptr_t)_p;
-	remaining = length;
-	outp = as->s + as->length;
-	avail = as->buffer_length - as->length - to_size;
-	while (remaining >= (size_t)from_size) {
-		size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
-
-		if (result != (size_t)-1)
-			break; /* Conversion completed. */
-
-		if (errno == EILSEQ || errno == EINVAL) {
-			/*
-		 	 * If an output charset is UTF-8 or UTF-16BE/LE,
-			 * unknown character should be U+FFFD
-			 * (replacement character).
-			 */
-			if (sc->flag & (SCONV_TO_UTF8 | SCONV_TO_UTF16)) {
-				size_t rbytes;
-				if (sc->flag & SCONV_TO_UTF8)
-					rbytes = sizeof(utf8_replacement_char);
-				else
-					rbytes = 2;
-
-				if (avail < rbytes) {
-					as->length = outp - as->s;
-					bs = as->buffer_length +
-					    (remaining * to_size) + rbytes;
-					if (NULL ==
-					    archive_string_ensure(as, bs))
-						return (-1);
-					outp = as->s + as->length;
-					avail = as->buffer_length
-					    - as->length - to_size;
-				}
-				if (sc->flag & SCONV_TO_UTF8)
-					memcpy(outp, utf8_replacement_char, sizeof(utf8_replacement_char));
-				else if (sc->flag & SCONV_TO_UTF16BE)
-					archive_be16enc(outp, UNICODE_R_CHAR);
-				else
-					archive_le16enc(outp, UNICODE_R_CHAR);
-				outp += rbytes;
-				avail -= rbytes;
-			} else {
-				/* Skip the illegal input bytes. */
-				*outp++ = '?';
-				avail--;
-			}
-			itp += from_size;
-			remaining -= from_size;
-			return_value = -1; /* failure */
-		} else {
-			/* E2BIG no output buffer,
-			 * Increase an output buffer.  */
-			as->length = outp - as->s;
-			bs = as->buffer_length + remaining * 2;
-			if (NULL == archive_string_ensure(as, bs))
-				return (-1);
-			outp = as->s + as->length;
-			avail = as->buffer_length - as->length - to_size;
-		}
-	}
-	as->length = outp - as->s;
-	as->s[as->length] = 0;
-	if (to_size == 2)
-		as->s[as->length+1] = 0;
-	return (return_value);
-}
-
-#endif /* HAVE_ICONV */
-
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-/*
- * Translate a string from a some CodePage to an another CodePage by
- * Windows APIs, and copy the result. Return -1 if conversion fails.
- */
-static int
-strncat_in_codepage(struct archive_string *as,
-    const void *_p, size_t length, struct archive_string_conv *sc)
-{
-	const char *s = (const char *)_p;
-	struct archive_wstring aws;
-	size_t l;
-	int r, saved_flag;
-
-	archive_string_init(&aws);
-	saved_flag = sc->flag;
-	sc->flag &= ~(SCONV_NORMALIZATION_D | SCONV_NORMALIZATION_C);
-	r = archive_wstring_append_from_mbs_in_codepage(&aws, s, length, sc);
-	sc->flag = saved_flag;
-	if (r != 0) {
-		archive_wstring_free(&aws);
-		if (errno != ENOMEM)
-			archive_string_append(as, s, length);
-		return (-1);
-	}
-
-	l = as->length;
-	r = archive_string_append_from_wcs_in_codepage(
-	    as, aws.s, aws.length, sc);
-	if (r != 0 && errno != ENOMEM && l == as->length)
-		archive_string_append(as, s, length);
-	archive_wstring_free(&aws);
-	return (r);
-}
-
-/*
- * Test whether MBS ==> WCS is okay.
- */
-static int
-invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
-{
-	const char *p = (const char *)_p;
-	unsigned codepage;
-	DWORD mbflag = MB_ERR_INVALID_CHARS;
-
-	if (sc->flag & SCONV_FROM_CHARSET)
-		codepage = sc->to_cp;
-	else
-		codepage = sc->from_cp;
-
-	if (codepage == CP_C_LOCALE)
-		return (0);
-	if (codepage != CP_UTF8)
-		mbflag |= MB_PRECOMPOSED;
-
-	if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
-		return (-1); /* Invalid */
-	return (0); /* Okay */
-}
-
-#else
-
-/*
- * Test whether MBS ==> WCS is okay.
- */
-static int
-invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
-{
-	const char *p = (const char *)_p;
-	size_t r;
-
-#if HAVE_MBRTOWC
-	mbstate_t shift_state;
-
-	memset(&shift_state, 0, sizeof(shift_state));
-#else
-	/* Clear the shift state before starting. */
-	mbtowc(NULL, NULL, 0);
-#endif
-	while (n) {
-		wchar_t wc;
-
-#if HAVE_MBRTOWC
-		r = mbrtowc(&wc, p, n, &shift_state);
-#else
-		r = mbtowc(&wc, p, n);
-#endif
-		if (r == (size_t)-1 || r == (size_t)-2)
-			return (-1);/* Invalid. */
-		if (r == 0)
-			break;
-		p += r;
-		n -= r;
-	}
-	(void)sc; /* UNUSED */
-	return (0); /* All Okey. */
-}
-
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-
-/*
- * Basically returns -1 because we cannot make a conversion of charset
- * without iconv but in some cases this would return 0.
- * Returns 0 if all copied characters are ASCII.
- * Returns 0 if both from-locale and to-locale are the same and those
- * can be WCS with no error.
- */
-static int
-best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	size_t remaining;
-	const uint8_t *itp;
-	int return_value = 0; /* success */
-
-	/*
-	 * If both from-locale and to-locale is the same, this makes a copy.
-	 * And then this checks all copied MBS can be WCS if so returns 0.
-	 */
-	if (sc->same) {
-		if (archive_string_append(as, _p, length) == NULL)
-			return (-1);/* No memory */
-		return (invalid_mbs(_p, length, sc));
-	}
-
-	/*
-	 * If a character is ASCII, this just copies it. If not, this
-	 * assigns '?' character instead but in UTF-8 locale this assigns
-	 * byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD,
-	 * a Replacement Character in Unicode.
-	 */
-
-	remaining = length;
-	itp = (const uint8_t *)_p;
-	while (*itp && remaining > 0) {
-		if (*itp > 127) {
-			// Non-ASCII: Substitute with suitable replacement
-			if (sc->flag & SCONV_TO_UTF8) {
-				if (archive_string_append(as, utf8_replacement_char, sizeof(utf8_replacement_char)) == NULL) {
-					__archive_errx(1, "Out of memory");
-				}
-			} else {
-				archive_strappend_char(as, '?');
-			}
-			return_value = -1;
-		} else {
-			archive_strappend_char(as, *itp);
-		}
-		++itp;
-	}
-	return (return_value);
-}
-
-
-/*
- * Unicode conversion functions.
- *   - UTF-8 <===> UTF-8 in removing surrogate pairs.
- *   - UTF-8 NFD ===> UTF-8 NFC in removing surrogate pairs.
- *   - UTF-8 made by libarchive 2.x ===> UTF-8.
- *   - UTF-16BE <===> UTF-8.
- *
- */
-
-/*
- * Utility to convert a single UTF-8 sequence.
- *
- * Usually return used bytes, return used byte in negative value when
- * a unicode character is replaced with U+FFFD.
- * See also http://unicode.org/review/pr-121.html Public Review Issue #121
- * Recommended Practice for Replacement Characters.
- */
-static int
-_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
-	static const char utf8_count[256] = {
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
-		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
-		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
-		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
-		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
-		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
-		 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
-		 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
-		 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
-		 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
-	};
-	int ch, i;
-	int cnt;
-	uint32_t wc;
-
-	/* Sanity check. */
-	if (n == 0)
-		return (0);
-	/*
-	 * Decode 1-4 bytes depending on the value of the first byte.
-	 */
-	ch = (unsigned char)*s;
-	if (ch == 0)
-		return (0); /* Standard:  return 0 for end-of-string. */
-	cnt = utf8_count[ch];
-
-	/* Invalid sequence or there are not plenty bytes. */
-	if ((int)n < cnt) {
-		cnt = (int)n;
-		for (i = 1; i < cnt; i++) {
-			if ((s[i] & 0xc0) != 0x80) {
-				cnt = i;
-				break;
-			}
-		}
-		goto invalid_sequence;
-	}
-
-	/* Make a Unicode code point from a single UTF-8 sequence. */
-	switch (cnt) {
-	case 1:	/* 1 byte sequence. */
-		*pwc = ch & 0x7f;
-		return (cnt);
-	case 2:	/* 2 bytes sequence. */
-		if ((s[1] & 0xc0) != 0x80) {
-			cnt = 1;
-			goto invalid_sequence;
-		}
-		*pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
-		return (cnt);
-	case 3:	/* 3 bytes sequence. */
-		if ((s[1] & 0xc0) != 0x80) {
-			cnt = 1;
-			goto invalid_sequence;
-		}
-		if ((s[2] & 0xc0) != 0x80) {
-			cnt = 2;
-			goto invalid_sequence;
-		}
-		wc = ((ch & 0x0f) << 12)
-		    | ((s[1] & 0x3f) << 6)
-		    | (s[2] & 0x3f);
-		if (wc < 0x800)
-			goto invalid_sequence;/* Overlong sequence. */
-		break;
-	case 4:	/* 4 bytes sequence. */
-		if ((s[1] & 0xc0) != 0x80) {
-			cnt = 1;
-			goto invalid_sequence;
-		}
-		if ((s[2] & 0xc0) != 0x80) {
-			cnt = 2;
-			goto invalid_sequence;
-		}
-		if ((s[3] & 0xc0) != 0x80) {
-			cnt = 3;
-			goto invalid_sequence;
-		}
-		wc = ((ch & 0x07) << 18)
-		    | ((s[1] & 0x3f) << 12)
-		    | ((s[2] & 0x3f) << 6)
-		    | (s[3] & 0x3f);
-		if (wc < 0x10000)
-			goto invalid_sequence;/* Overlong sequence. */
-		break;
-	default: /* Others are all invalid sequence. */
-		if (ch == 0xc0 || ch == 0xc1)
-			cnt = 2;
-		else if (ch >= 0xf5 && ch <= 0xf7)
-			cnt = 4;
-		else if (ch >= 0xf8 && ch <= 0xfb)
-			cnt = 5;
-		else if (ch == 0xfc || ch == 0xfd)
-			cnt = 6;
-		else
-			cnt = 1;
-		if ((int)n < cnt)
-			cnt = (int)n;
-		for (i = 1; i < cnt; i++) {
-			if ((s[i] & 0xc0) != 0x80) {
-				cnt = i;
-				break;
-			}
-		}
-		goto invalid_sequence;
-	}
-
-	/* The code point larger than 0x10FFFF is not legal
-	 * Unicode values. */
-	if (wc > UNICODE_MAX)
-		goto invalid_sequence;
-	/* Correctly gets a Unicode, returns used bytes. */
-	*pwc = wc;
-	return (cnt);
-invalid_sequence:
-	*pwc = UNICODE_R_CHAR;/* set the Replacement Character instead. */
-	return (cnt * -1);
-}
-
-static int
-utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
-	int cnt;
-
-	cnt = _utf8_to_unicode(pwc, s, n);
-	/* Any of Surrogate pair is not legal Unicode values. */
-	if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
-		return (-3);
-	return (cnt);
-}
-
-static inline uint32_t
-combine_surrogate_pair(uint32_t uc, uint32_t uc2)
-{
-	uc -= 0xD800;
-	uc *= 0x400;
-	uc += uc2 - 0xDC00;
-	uc += 0x10000;
-	return (uc);
-}
-
-/*
- * Convert a single UTF-8/CESU-8 sequence to a Unicode code point in
- * removing surrogate pairs.
- *
- * CESU-8: The Compatibility Encoding Scheme for UTF-16.
- *
- * Usually return used bytes, return used byte in negative value when
- * a unicode character is replaced with U+FFFD.
- */
-static int
-cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
-	uint32_t wc = 0;
-	int cnt;
-
-	cnt = _utf8_to_unicode(&wc, s, n);
-	if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) {
-		uint32_t wc2 = 0;
-		if (n - 3 < 3) {
-			/* Invalid byte sequence. */
-			goto invalid_sequence;
-		}
-		cnt = _utf8_to_unicode(&wc2, s+3, n-3);
-		if (cnt != 3 || !IS_LOW_SURROGATE_LA(wc2)) {
-			/* Invalid byte sequence. */
-			goto invalid_sequence;
-		}
-		wc = combine_surrogate_pair(wc, wc2);
-		cnt = 6;
-	} else if (cnt == 3 && IS_LOW_SURROGATE_LA(wc)) {
-		/* Invalid byte sequence. */
-		goto invalid_sequence;
-	}
-	*pwc = wc;
-	return (cnt);
-invalid_sequence:
-	*pwc = UNICODE_R_CHAR;/* set the Replacement Character instead. */
-	if (cnt > 0)
-		cnt *= -1;
-	return (cnt);
-}
-
-/*
- * Convert a Unicode code point to a single UTF-8 sequence.
- *
- * NOTE:This function does not check if the Unicode is legal or not.
- * Please you definitely check it before calling this.
- */
-static size_t
-unicode_to_utf8(char *p, size_t remaining, uint32_t uc)
-{
-	char *_p = p;
-
-	/* Invalid Unicode char maps to Replacement character */
-	if (uc > UNICODE_MAX)
-		uc = UNICODE_R_CHAR;
-	/* Translate code point to UTF8 */
-	if (uc <= 0x7f) {
-		if (remaining == 0)
-			return (0);
-		*p++ = (char)uc;
-	} else if (uc <= 0x7ff) {
-		if (remaining < 2)
-			return (0);
-		*p++ = 0xc0 | ((uc >> 6) & 0x1f);
-		*p++ = 0x80 | (uc & 0x3f);
-	} else if (uc <= 0xffff) {
-		if (remaining < 3)
-			return (0);
-		*p++ = 0xe0 | ((uc >> 12) & 0x0f);
-		*p++ = 0x80 | ((uc >> 6) & 0x3f);
-		*p++ = 0x80 | (uc & 0x3f);
-	} else {
-		if (remaining < 4)
-			return (0);
-		*p++ = 0xf0 | ((uc >> 18) & 0x07);
-		*p++ = 0x80 | ((uc >> 12) & 0x3f);
-		*p++ = 0x80 | ((uc >> 6) & 0x3f);
-		*p++ = 0x80 | (uc & 0x3f);
-	}
-	return (p - _p);
-}
-
-static int
-utf16be_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
-	return (utf16_to_unicode(pwc, s, n, 1));
-}
-
-static int
-utf16le_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
-	return (utf16_to_unicode(pwc, s, n, 0));
-}
-
-static int
-utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
-{
-	const char *utf16 = s;
-	unsigned uc;
-
-	if (n == 0)
-		return (0);
-	if (n == 1) {
-		/* set the Replacement Character instead. */
-		*pwc = UNICODE_R_CHAR;
-		return (-1);
-	}
-
-	if (be)
-		uc = archive_be16dec(utf16);
-	else
-		uc = archive_le16dec(utf16);
-	utf16 += 2;
-		
-	/* If this is a surrogate pair, assemble the full code point.*/
-	if (IS_HIGH_SURROGATE_LA(uc)) {
-		unsigned uc2;
-
-		if (n >= 4) {
-			if (be)
-				uc2 = archive_be16dec(utf16);
-			else
-				uc2 = archive_le16dec(utf16);
-		} else
-			uc2 = 0;
-		if (IS_LOW_SURROGATE_LA(uc2)) {
-			uc = combine_surrogate_pair(uc, uc2);
-			utf16 += 2;
-		} else {
-	 		/* Undescribed code point should be U+FFFD
-		 	* (replacement character). */
-			*pwc = UNICODE_R_CHAR;
-			return (-2);
-		}
-	}
-
-	/*
-	 * Surrogate pair values(0xd800 through 0xdfff) are only
-	 * used by UTF-16, so, after above calculation, the code
-	 * must not be surrogate values, and Unicode has no codes
-	 * larger than 0x10ffff. Thus, those are not legal Unicode
-	 * values.
-	 */
-	if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {
-	 	/* Undescribed code point should be U+FFFD
-	 	* (replacement character). */
-		*pwc = UNICODE_R_CHAR;
-		return (((int)(utf16 - s)) * -1);
-	}
-	*pwc = uc;
-	return ((int)(utf16 - s));
-}
-
-static size_t
-unicode_to_utf16be(char *p, size_t remaining, uint32_t uc)
-{
-	char *utf16 = p;
-
-	if (uc > 0xffff) {
-		/* We have a code point that won't fit into a
-		 * wchar_t; convert it to a surrogate pair. */
-		if (remaining < 4)
-			return (0);
-		uc -= 0x10000;
-		archive_be16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800);
-		archive_be16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
-		return (4);
-	} else {
-		if (remaining < 2)
-			return (0);
-		archive_be16enc(utf16, uc);
-		return (2);
-	}
-}
-
-static size_t
-unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
-{
-	char *utf16 = p;
-
-	if (uc > 0xffff) {
-		/* We have a code point that won't fit into a
-		 * wchar_t; convert it to a surrogate pair. */
-		if (remaining < 4)
-			return (0);
-		uc -= 0x10000;
-		archive_le16enc(utf16, ((uc >> 10) & 0x3ff) + 0xD800);
-		archive_le16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
-		return (4);
-	} else {
-		if (remaining < 2)
-			return (0);
-		archive_le16enc(utf16, uc);
-		return (2);
-	}
-}
-
-/*
- * Copy UTF-8 string in checking surrogate pair.
- * If any surrogate pair are found, it would be canonicalized.
- */
-static int
-strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p,
-    size_t len, struct archive_string_conv *sc)
-{
-	const char *s;
-	char *p, *endp;
-	int n, ret = 0;
-
-	(void)sc; /* UNUSED */
-
-	if (archive_string_ensure(as, as->length + len + 1) == NULL)
-		return (-1);
-
-	s = (const char *)_p;
-	p = as->s + as->length;
-	endp = as->s + as->buffer_length -1;
-	do {
-		uint32_t uc;
-		const char *ss = s;
-		size_t w;
-
-		/*
-		 * Forward byte sequence until a conversion of that is needed.
-		 */
-		while ((n = utf8_to_unicode(&uc, s, len)) > 0) {
-			s += n;
-			len -= n;
-		}
-		if (ss < s) {
-			if (p + (s - ss) > endp) {
-				as->length = p - as->s;
-				if (archive_string_ensure(as,
-				    as->buffer_length + len + 1) == NULL)
-					return (-1);
-				p = as->s + as->length;
-				endp = as->s + as->buffer_length -1;
-			}
-
-			memcpy(p, ss, s - ss);
-			p += s - ss;
-		}
-
-		/*
-		 * If n is negative, current byte sequence needs a replacement.
-		 */
-		if (n < 0) {
-			if (n == -3 && IS_SURROGATE_PAIR_LA(uc)) {
-				/* Current byte sequence may be CESU-8. */
-				n = cesu8_to_unicode(&uc, s, len);
-			}
-			if (n < 0) {
-				ret = -1;
-				n *= -1;/* Use a replaced unicode character. */
-			}
-
-			/* Rebuild UTF-8 byte sequence. */
-			while ((w = unicode_to_utf8(p, endp - p, uc)) == 0) {
-				as->length = p - as->s;
-				if (archive_string_ensure(as,
-				    as->buffer_length + len + 1) == NULL)
-					return (-1);
-				p = as->s + as->length;
-				endp = as->s + as->buffer_length -1;
-			}
-			p += w;
-			s += n;
-			len -= n;
-		}
-	} while (n > 0);
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	return (ret);
-}
-
-static int
-archive_string_append_unicode(struct archive_string *as, const void *_p,
-    size_t len, struct archive_string_conv *sc)
-{
-	const char *s;
-	char *p, *endp;
-	uint32_t uc;
-	size_t w;
-	int n, ret = 0, ts, tm;
-	int (*parse)(uint32_t *, const char *, size_t);
-	size_t (*unparse)(char *, size_t, uint32_t);
-
-	if (sc->flag & SCONV_TO_UTF16BE) {
-		unparse = unicode_to_utf16be;
-		ts = 2;
-	} else if (sc->flag & SCONV_TO_UTF16LE) {
-		unparse = unicode_to_utf16le;
-		ts = 2;
-	} else if (sc->flag & SCONV_TO_UTF8) {
-		unparse = unicode_to_utf8;
-		ts = 1;
-	} else {
-		/*
-		 * This case is going to be converted to another
-		 * character-set through iconv.
-		 */
-		if (sc->flag & SCONV_FROM_UTF16BE) {
-			unparse = unicode_to_utf16be;
-			ts = 2;
-		} else if (sc->flag & SCONV_FROM_UTF16LE) {
-			unparse = unicode_to_utf16le;
-			ts = 2;
-		} else {
-			unparse = unicode_to_utf8;
-			ts = 1;
-		}
-	}
-
-	if (sc->flag & SCONV_FROM_UTF16BE) {
-		parse = utf16be_to_unicode;
-		tm = 1;
-	} else if (sc->flag & SCONV_FROM_UTF16LE) {
-		parse = utf16le_to_unicode;
-		tm = 1;
-	} else {
-		parse = cesu8_to_unicode;
-		tm = ts;
-	}
-
-	if (archive_string_ensure(as, as->length + len * tm + ts) == NULL)
-		return (-1);
-
-	s = (const char *)_p;
-	p = as->s + as->length;
-	endp = as->s + as->buffer_length - ts;
-	while ((n = parse(&uc, s, len)) != 0) {
-		if (n < 0) {
-			/* Use a replaced unicode character. */
-			n *= -1;
-			ret = -1;
-		}
-		s += n;
-		len -= n;
-		while ((w = unparse(p, endp - p, uc)) == 0) {
-			/* There is not enough output buffer so
-			 * we have to expand it. */
-			as->length = p - as->s;
-			if (archive_string_ensure(as,
-			    as->buffer_length + len * tm + ts) == NULL)
-				return (-1);
-			p = as->s + as->length;
-			endp = as->s + as->buffer_length - ts;
-		}
-		p += w;
-	}
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	if (ts == 2)
-		as->s[as->length+1] = '\0';
-	return (ret);
-}
-
-/*
- * Following Constants for Hangul compositions this information comes from
- * Unicode Standard Annex #15  http://unicode.org/reports/tr15/
- */
-#define HC_SBASE	0xAC00
-#define HC_LBASE	0x1100
-#define HC_VBASE	0x1161
-#define HC_TBASE	0x11A7
-#define HC_LCOUNT	19
-#define HC_VCOUNT	21
-#define HC_TCOUNT	28
-#define HC_NCOUNT	(HC_VCOUNT * HC_TCOUNT)
-#define HC_SCOUNT	(HC_LCOUNT * HC_NCOUNT)
-
-static uint32_t
-get_nfc(uint32_t uc, uint32_t uc2)
-{
-	int t, b;
-
-	t = 0;
-	b = sizeof(u_composition_table)/sizeof(u_composition_table[0]) -1;
-	while (b >= t) {
-		int m = (t + b) / 2;
-		if (u_composition_table[m].cp1 < uc)
-			t = m + 1;
-		else if (u_composition_table[m].cp1 > uc)
-			b = m - 1;
-		else if (u_composition_table[m].cp2 < uc2)
-			t = m + 1;
-		else if (u_composition_table[m].cp2 > uc2)
-			b = m - 1;
-		else
-			return (u_composition_table[m].nfc);
-	}
-	return (0);
-}
-
-#define FDC_MAX 10	/* The maximum number of Following Decomposable
-			 * Characters. */
-
-/*
- * Update first code point.
- */
-#define UPDATE_UC(new_uc)	do {		\
-	uc = new_uc;				\
-	ucptr = NULL;				\
-} while (0)
-
-/*
- * Replace first code point with second code point.
- */
-#define REPLACE_UC_WITH_UC2() do {		\
-	uc = uc2;				\
-	ucptr = uc2ptr;				\
-	n = n2;					\
-} while (0)
-
-#define EXPAND_BUFFER() do {			\
-	as->length = p - as->s;			\
-	if (archive_string_ensure(as,		\
-	    as->buffer_length + len * tm + ts) == NULL)\
-		return (-1);			\
-	p = as->s + as->length;			\
-	endp = as->s + as->buffer_length - ts;	\
-} while (0)
-
-#define UNPARSE(p, endp, uc)	do {		\
-	while ((w = unparse(p, (endp) - (p), uc)) == 0) {\
-		EXPAND_BUFFER();		\
-	}					\
-	p += w;					\
-} while (0)
-
-/*
- * Write first code point.
- * If the code point has not be changed from its original code,
- * this just copies it from its original buffer pointer.
- * If not, this converts it to UTF-8 byte sequence and copies it.
- */
-#define WRITE_UC()	do {			\
-	if (ucptr) {				\
-		if (p + n > endp)		\
-			EXPAND_BUFFER();	\
-		switch (n) {			\
-		case 4:				\
-			*p++ = *ucptr++;	\
-			/* FALL THROUGH */	\
-		case 3:				\
-			*p++ = *ucptr++;	\
-			/* FALL THROUGH */	\
-		case 2:				\
-			*p++ = *ucptr++;	\
-			/* FALL THROUGH */	\
-		case 1:				\
-			*p++ = *ucptr;		\
-			break;			\
-		}				\
-		ucptr = NULL;			\
-	} else {				\
-		UNPARSE(p, endp, uc);		\
-	}					\
-} while (0)
-
-/*
- * Collect following decomposable code points.
- */
-#define COLLECT_CPS(start)	do {		\
-	int _i;					\
-	for (_i = start; _i < FDC_MAX ; _i++) {	\
-		nx = parse(&ucx[_i], s, len);	\
-		if (nx <= 0)			\
-			break;			\
-		cx = CCC(ucx[_i]);		\
-		if (cl >= cx && cl != 228 && cx != 228)\
-			break;			\
-		s += nx;			\
-		len -= nx;			\
-		cl = cx;			\
-		ccx[_i] = cx;			\
-	}					\
-	if (_i >= FDC_MAX) {			\
-		ret = -1;			\
-		ucx_size = FDC_MAX;		\
-	} else					\
-		ucx_size = _i;			\
-} while (0)
-
-/*
- * Normalize UTF-8/UTF-16BE characters to Form C and copy the result.
- *
- * TODO: Convert composition exclusions, which are never converted
- * from NFC,NFD,NFKC and NFKD, to Form C.
- */
-static int
-archive_string_normalize_C(struct archive_string *as, const void *_p,
-    size_t len, struct archive_string_conv *sc)
-{
-	const char *s = (const char *)_p;
-	char *p, *endp;
-	uint32_t uc, uc2;
-	size_t w;
-	int always_replace, n, n2, ret = 0, spair, ts, tm;
-	int (*parse)(uint32_t *, const char *, size_t);
-	size_t (*unparse)(char *, size_t, uint32_t);
-
-	always_replace = 1;
-	ts = 1;/* text size. */
-	if (sc->flag & SCONV_TO_UTF16BE) {
-		unparse = unicode_to_utf16be;
-		ts = 2;
-		if (sc->flag & SCONV_FROM_UTF16BE)
-			always_replace = 0;
-	} else if (sc->flag & SCONV_TO_UTF16LE) {
-		unparse = unicode_to_utf16le;
-		ts = 2;
-		if (sc->flag & SCONV_FROM_UTF16LE)
-			always_replace = 0;
-	} else if (sc->flag & SCONV_TO_UTF8) {
-		unparse = unicode_to_utf8;
-		if (sc->flag & SCONV_FROM_UTF8)
-			always_replace = 0;
-	} else {
-		/*
-		 * This case is going to be converted to another
-		 * character-set through iconv.
-		 */
-		always_replace = 0;
-		if (sc->flag & SCONV_FROM_UTF16BE) {
-			unparse = unicode_to_utf16be;
-			ts = 2;
-		} else if (sc->flag & SCONV_FROM_UTF16LE) {
-			unparse = unicode_to_utf16le;
-			ts = 2;
-		} else {
-			unparse = unicode_to_utf8;
-		}
-	}
-
-	if (sc->flag & SCONV_FROM_UTF16BE) {
-		parse = utf16be_to_unicode;
-		tm = 1;
-		spair = 4;/* surrogate pair size in UTF-16. */
-	} else if (sc->flag & SCONV_FROM_UTF16LE) {
-		parse = utf16le_to_unicode;
-		tm = 1;
-		spair = 4;/* surrogate pair size in UTF-16. */
-	} else {
-		parse = cesu8_to_unicode;
-		tm = ts;
-		spair = 6;/* surrogate pair size in UTF-8. */
-	}
-
-	if (archive_string_ensure(as, as->length + len * tm + ts) == NULL)
-		return (-1);
-
-	p = as->s + as->length;
-	endp = as->s + as->buffer_length - ts;
-	while ((n = parse(&uc, s, len)) != 0) {
-		const char *ucptr, *uc2ptr;
-
-		if (n < 0) {
-			/* Use a replaced unicode character. */
-			UNPARSE(p, endp, uc);
-			s += n*-1;
-			len -= n*-1;
-			ret = -1;
-			continue;
-		} else if (n == spair || always_replace)
-			/* uc is converted from a surrogate pair.
-			 * this should be treated as a changed code. */
-			ucptr = NULL;
-		else
-			ucptr = s;
-		s += n;
-		len -= n;
-
-		/* Read second code point. */
-		while ((n2 = parse(&uc2, s, len)) > 0) {
-			uint32_t ucx[FDC_MAX];
-			int ccx[FDC_MAX];
-			int cl, cx, i, nx, ucx_size;
-			int LIndex,SIndex;
-			uint32_t nfc;
-
-			if (n2 == spair || always_replace)
-				/* uc2 is converted from a surrogate pair.
-			 	 * this should be treated as a changed code. */
-				uc2ptr = NULL;
-			else
-				uc2ptr = s;
-			s += n2;
-			len -= n2;
-
-			/*
-			 * If current second code point is out of decomposable
-			 * code points, finding compositions is unneeded.
-			 */
-			if (!IS_DECOMPOSABLE_BLOCK(uc2)) {
-				WRITE_UC();
-				REPLACE_UC_WITH_UC2();
-				continue;
-			}
-
-			/*
-			 * Try to combine current code points.
-			 */
-			/*
-			 * We have to combine Hangul characters according to
-			 * http://uniicode.org/reports/tr15/#Hangul
-			 */
-			if (0 <= (LIndex = uc - HC_LBASE) &&
-			    LIndex < HC_LCOUNT) {
-				/*
-				 * Hangul Composition.
-				 * 1. Two current code points are L and V.
-				 */
-				int VIndex = uc2 - HC_VBASE;
-				if (0 <= VIndex && VIndex < HC_VCOUNT) {
-					/* Make syllable of form LV. */
-					UPDATE_UC(HC_SBASE +
-					    (LIndex * HC_VCOUNT + VIndex) *
-					     HC_TCOUNT);
-				} else {
-					WRITE_UC();
-					REPLACE_UC_WITH_UC2();
-				}
-				continue;
-			} else if (0 <= (SIndex = uc - HC_SBASE) &&
-			    SIndex < HC_SCOUNT && (SIndex % HC_TCOUNT) == 0) {
-				/*
-				 * Hangul Composition.
-				 * 2. Two current code points are LV and T.
-				 */
-				int TIndex = uc2 - HC_TBASE;
-				if (0 < TIndex && TIndex < HC_TCOUNT) {
-					/* Make syllable of form LVT. */
-					UPDATE_UC(uc + TIndex);
-				} else {
-					WRITE_UC();
-					REPLACE_UC_WITH_UC2();
-				}
-				continue;
-			} else if ((nfc = get_nfc(uc, uc2)) != 0) {
-				/* A composition to current code points
-				 * is found. */
-				UPDATE_UC(nfc);
-				continue;
-			} else if ((cl = CCC(uc2)) == 0) {
-				/* Clearly 'uc2' the second code point is not
-				 * a decomposable code. */
-				WRITE_UC();
-				REPLACE_UC_WITH_UC2();
-				continue;
-			}
-
-			/*
-			 * Collect following decomposable code points.
-			 */
-			cx = 0;
-			ucx[0] = uc2;
-			ccx[0] = cl;
-			COLLECT_CPS(1);
-
-			/*
-			 * Find a composed code in the collected code points.
-			 */
-			i = 1;
-			while (i < ucx_size) {
-				int j;
-
-				if ((nfc = get_nfc(uc, ucx[i])) == 0) {
-					i++;
-					continue;
-				}
-
-				/*
-				 * nfc is composed of uc and ucx[i].
-				 */
-				UPDATE_UC(nfc);
-
-				/*
-				 * Remove ucx[i] by shifting
-				 * following code points.
-				 */
-				for (j = i; j+1 < ucx_size; j++) {
-					ucx[j] = ucx[j+1];
-					ccx[j] = ccx[j+1];
-				}
-				ucx_size --;
-
-				/*
-				 * Collect following code points blocked
-				 * by ucx[i] the removed code point.
-				 */
-				if (ucx_size > 0 && i == ucx_size &&
-				    nx > 0 && cx == cl) {
-					cl =  ccx[ucx_size-1];
-					COLLECT_CPS(ucx_size);
-				}
-				/*
-				 * Restart finding a composed code with
-				 * the updated uc from the top of the
-				 * collected code points.
-				 */
-				i = 0;
-			}
-
-			/*
-			 * Apparently the current code points are not
-			 * decomposed characters or already composed.
-			 */
-			WRITE_UC();
-			for (i = 0; i < ucx_size; i++)
-				UNPARSE(p, endp, ucx[i]);
-
-			/*
-			 * Flush out remaining canonical combining characters.
-			 */
-			if (nx > 0 && cx == cl && len > 0) {
-				while ((nx = parse(&ucx[0], s, len))
-				    > 0) {
-					cx = CCC(ucx[0]);
-					if (cl > cx)
-						break;
-					s += nx;
-					len -= nx;
-					cl = cx;
-					UNPARSE(p, endp, ucx[0]);
-				}
-			}
-			break;
-		}
-		if (n2 < 0) {
-			WRITE_UC();
-			/* Use a replaced unicode character. */
-			UNPARSE(p, endp, uc2);
-			s += n2*-1;
-			len -= n2*-1;
-			ret = -1;
-			continue;
-		} else if (n2 == 0) {
-			WRITE_UC();
-			break;
-		}
-	}
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	if (ts == 2)
-		as->s[as->length+1] = '\0';
-	return (ret);
-}
-
-static int
-get_nfd(uint32_t *cp1, uint32_t *cp2, uint32_t uc)
-{
-	int t, b;
-
-	/*
-	 * These are not converted to NFD on Mac OS.
-	 */
-	if ((uc >= 0x2000 && uc <= 0x2FFF) ||
-	    (uc >= 0xF900 && uc <= 0xFAFF) ||
-	    (uc >= 0x2F800 && uc <= 0x2FAFF))
-		return (0);
-	/*
-	 * Those code points are not converted to NFD on Mac OS.
-	 * I do not know the reason because it is undocumented.
-	 *   NFC        NFD
-	 *   1109A  ==> 11099 110BA
-	 *   1109C  ==> 1109B 110BA
-	 *   110AB  ==> 110A5 110BA
-	 */
-	if (uc == 0x1109A || uc == 0x1109C || uc == 0x110AB)
-		return (0);
-
-	t = 0;
-	b = sizeof(u_decomposition_table)/sizeof(u_decomposition_table[0]) -1;
-	while (b >= t) {
-		int m = (t + b) / 2;
-		if (u_decomposition_table[m].nfc < uc)
-			t = m + 1;
-		else if (u_decomposition_table[m].nfc > uc)
-			b = m - 1;
-		else {
-			*cp1 = u_decomposition_table[m].cp1;
-			*cp2 = u_decomposition_table[m].cp2;
-			return (1);
-		}
-	}
-	return (0);
-}
-
-#define REPLACE_UC_WITH(cp) do {		\
-	uc = cp;				\
-	ucptr = NULL;				\
-} while (0)
-
-/*
- * Normalize UTF-8 characters to Form D and copy the result.
- */
-static int
-archive_string_normalize_D(struct archive_string *as, const void *_p,
-    size_t len, struct archive_string_conv *sc)
-{
-	const char *s = (const char *)_p;
-	char *p, *endp;
-	uint32_t uc, uc2;
-	size_t w;
-	int always_replace, n, n2, ret = 0, spair, ts, tm;
-	int (*parse)(uint32_t *, const char *, size_t);
-	size_t (*unparse)(char *, size_t, uint32_t);
-
-	always_replace = 1;
-	ts = 1;/* text size. */
-	if (sc->flag & SCONV_TO_UTF16BE) {
-		unparse = unicode_to_utf16be;
-		ts = 2;
-		if (sc->flag & SCONV_FROM_UTF16BE)
-			always_replace = 0;
-	} else if (sc->flag & SCONV_TO_UTF16LE) {
-		unparse = unicode_to_utf16le;
-		ts = 2;
-		if (sc->flag & SCONV_FROM_UTF16LE)
-			always_replace = 0;
-	} else if (sc->flag & SCONV_TO_UTF8) {
-		unparse = unicode_to_utf8;
-		if (sc->flag & SCONV_FROM_UTF8)
-			always_replace = 0;
-	} else {
-		/*
-		 * This case is going to be converted to another
-		 * character-set through iconv.
-		 */
-		always_replace = 0;
-		if (sc->flag & SCONV_FROM_UTF16BE) {
-			unparse = unicode_to_utf16be;
-			ts = 2;
-		} else if (sc->flag & SCONV_FROM_UTF16LE) {
-			unparse = unicode_to_utf16le;
-			ts = 2;
-		} else {
-			unparse = unicode_to_utf8;
-		}
-	}
-
-	if (sc->flag & SCONV_FROM_UTF16BE) {
-		parse = utf16be_to_unicode;
-		tm = 1;
-		spair = 4;/* surrogate pair size in UTF-16. */
-	} else if (sc->flag & SCONV_FROM_UTF16LE) {
-		parse = utf16le_to_unicode;
-		tm = 1;
-		spair = 4;/* surrogate pair size in UTF-16. */
-	} else {
-		parse = cesu8_to_unicode;
-		tm = ts;
-		spair = 6;/* surrogate pair size in UTF-8. */
-	}
-
-	if (archive_string_ensure(as, as->length + len * tm + ts) == NULL)
-		return (-1);
-
-	p = as->s + as->length;
-	endp = as->s + as->buffer_length - ts;
-	while ((n = parse(&uc, s, len)) != 0) {
-		const char *ucptr;
-		uint32_t cp1, cp2;
-		int SIndex;
-		struct {
-			uint32_t uc;
-			int ccc;
-		} fdc[FDC_MAX];
-		int fdi, fdj;
-		int ccc;
-
-check_first_code:
-		if (n < 0) {
-			/* Use a replaced unicode character. */
-			UNPARSE(p, endp, uc);
-			s += n*-1;
-			len -= n*-1;
-			ret = -1;
-			continue;
-		} else if (n == spair || always_replace)
-			/* uc is converted from a surrogate pair.
-			 * this should be treated as a changed code. */
-			ucptr = NULL;
-		else
-			ucptr = s;
-		s += n;
-		len -= n;
-
-		/* Hangul Decomposition. */
-		if ((SIndex = uc - HC_SBASE) >= 0 && SIndex < HC_SCOUNT) {
-			int L = HC_LBASE + SIndex / HC_NCOUNT;
-			int V = HC_VBASE + (SIndex % HC_NCOUNT) / HC_TCOUNT;
-			int T = HC_TBASE + SIndex % HC_TCOUNT;
-
-			REPLACE_UC_WITH(L);
-			WRITE_UC();
-			REPLACE_UC_WITH(V);
-			WRITE_UC();
-			if (T != HC_TBASE) {
-				REPLACE_UC_WITH(T);
-				WRITE_UC();
-			}
-			continue;
-		}
-		if (IS_DECOMPOSABLE_BLOCK(uc) && CCC(uc) != 0) {
-			WRITE_UC();
-			continue;
-		}
-
-		fdi = 0;
-		while (get_nfd(&cp1, &cp2, uc) && fdi < FDC_MAX) {
-			int k;
-
-			for (k = fdi; k > 0; k--)
-				fdc[k] = fdc[k-1];
-			fdc[0].ccc = CCC(cp2);
-			fdc[0].uc = cp2;
-			fdi++;
-			REPLACE_UC_WITH(cp1);
-		}
-
-		/* Read following code points. */
-		while ((n2 = parse(&uc2, s, len)) > 0 &&
-		    (ccc = CCC(uc2)) != 0 && fdi < FDC_MAX) {
-			int j, k;
-
-			s += n2;
-			len -= n2;
-			for (j = 0; j < fdi; j++) {
-				if (fdc[j].ccc > ccc)
-					break;
-			}
-			if (j < fdi) {
-				for (k = fdi; k > j; k--)
-					fdc[k] = fdc[k-1];
-				fdc[j].ccc = ccc;
-				fdc[j].uc = uc2;
-			} else {
-				fdc[fdi].ccc = ccc;
-				fdc[fdi].uc = uc2;
-			}
-			fdi++;
-		}
-
-		WRITE_UC();
-		for (fdj = 0; fdj < fdi; fdj++) {
-			REPLACE_UC_WITH(fdc[fdj].uc);
-			WRITE_UC();
-		}
-
-		if (n2 == 0)
-			break;
-		REPLACE_UC_WITH(uc2);
-		n = n2;
-		goto check_first_code;
-	}
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	if (ts == 2)
-		as->s[as->length+1] = '\0';
-	return (ret);
-}
-
-/*
- * libarchive 2.x made incorrect UTF-8 strings in the wrong assumption
- * that WCS is Unicode. It is true for several platforms but some are false.
- * And then people who did not use UTF-8 locale on the non Unicode WCS
- * platform and made a tar file with libarchive(mostly bsdtar) 2.x. Those
- * now cannot get right filename from libarchive 3.x and later since we
- * fixed the wrong assumption and it is incompatible to older its versions.
- * So we provide special option, "compat-2x.x", for resolving it.
- * That option enable the string conversion of libarchive 2.x.
- *
- * Translates the wrong UTF-8 string made by libarchive 2.x into current
- * locale character set and appends to the archive_string.
- * Note: returns -1 if conversion fails.
- */
-static int
-strncat_from_utf8_libarchive2(struct archive_string *as,
-    const void *_p, size_t len, struct archive_string_conv *sc)
-{
-	const char *s;
-	int n;
-	char *p;
-	char *end;
-	uint32_t unicode;
-#if HAVE_WCRTOMB
-	mbstate_t shift_state;
-
-	memset(&shift_state, 0, sizeof(shift_state));
-#else
-	/* Clear the shift state before starting. */
-	wctomb(NULL, L'\0');
-#endif
-	(void)sc; /* UNUSED */
-	/*
-	 * Allocate buffer for MBS.
-	 * We need this allocation here since it is possible that
-	 * as->s is still NULL.
-	 */
-	if (archive_string_ensure(as, as->length + len + 1) == NULL)
-		return (-1);
-
-	s = (const char *)_p;
-	p = as->s + as->length;
-	end = as->s + as->buffer_length - MB_CUR_MAX -1;
-	while ((n = _utf8_to_unicode(&unicode, s, len)) != 0) {
-		wchar_t wc;
-
-		if (p >= end) {
-			as->length = p - as->s;
-			/* Re-allocate buffer for MBS. */
-			if (archive_string_ensure(as,
-			    as->length + max(len * 2,
-			    (size_t)MB_CUR_MAX) + 1) == NULL)
-				return (-1);
-			p = as->s + as->length;
-			end = as->s + as->buffer_length - MB_CUR_MAX -1;
-		}
-
-		/*
-		 * As libarchive 2.x, translates the UTF-8 characters into
-		 * wide-characters in the assumption that WCS is Unicode.
-		 */
-		if (n < 0) {
-			n *= -1;
-			wc = L'?';
-		} else
-			wc = (wchar_t)unicode;
-
-		s += n;
-		len -= n;
-		/*
-		 * Translates the wide-character into the current locale MBS.
-		 */
-#if HAVE_WCRTOMB
-		n = (int)wcrtomb(p, wc, &shift_state);
-#else
-		n = (int)wctomb(p, wc);
-#endif
-		if (n == -1)
-			return (-1);
-		p += n;
-	}
-	as->length = p - as->s;
-	as->s[as->length] = '\0';
-	return (0);
-}
-
-
-/*
- * Conversion functions between current locale dependent MBS and UTF-16BE.
- *   strncat_from_utf16be() : UTF-16BE --> MBS
- *   strncat_to_utf16be()   : MBS --> UTF16BE
- */
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-/*
- * Convert a UTF-16BE/LE string to current locale and copy the result.
- * Return -1 if conversion fails.
- */
-static int
-win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
-    struct archive_string_conv *sc, int be)
-{
-	struct archive_string tmp;
-	const char *u16;
-	int ll;
-	BOOL defchar;
-	char *mbs;
-	size_t mbs_size, b;
-	int ret = 0;
-
-	bytes &= ~1;
-	if (archive_string_ensure(as, as->length + bytes +1) == NULL)
-		return (-1);
-
-	mbs = as->s + as->length;
-	mbs_size = as->buffer_length - as->length -1;
-
-	if (sc->to_cp == CP_C_LOCALE) {
-		/*
-		 * "C" locale special process.
-		 */
-		u16 = _p;
-		ll = 0;
-		for (b = 0; b < bytes; b += 2) {
-			uint16_t val;
-			if (be)
-				val = archive_be16dec(u16+b);
-			else
-				val = archive_le16dec(u16+b);
-			if (val > 255) {
-				*mbs++ = '?';
-				ret = -1;
-			} else
-				*mbs++ = (char)(val&0xff);
-			ll++;
-		}
-		as->length += ll;
-		as->s[as->length] = '\0';
-		return (ret);
-	}
-
-	archive_string_init(&tmp);
-	if (be) {
-		if (is_big_endian()) {
-			u16 = _p;
-		} else {
-			if (archive_string_ensure(&tmp, bytes+2) == NULL)
-				return (-1);
-			memcpy(tmp.s, _p, bytes);
-			for (b = 0; b < bytes; b += 2) {
-				uint16_t val = archive_be16dec(tmp.s+b);
-				archive_le16enc(tmp.s+b, val);
-			}
-			u16 = tmp.s;
-		}
-	} else {
-		if (!is_big_endian()) {
-			u16 = _p;
-		} else {
-			if (archive_string_ensure(&tmp, bytes+2) == NULL)
-				return (-1);
-			memcpy(tmp.s, _p, bytes);
-			for (b = 0; b < bytes; b += 2) {
-				uint16_t val = archive_le16dec(tmp.s+b);
-				archive_be16enc(tmp.s+b, val);
-			}
-			u16 = tmp.s;
-		}
-	}
-
-	do {
-		defchar = 0;
-		ll = WideCharToMultiByte(sc->to_cp, 0,
-		    (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
-			NULL, &defchar);
-		/* Exit loop if we succeeded */
-		if (ll != 0 ||
-		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			break;
-		}
-		/* Else expand buffer and loop to try again. */
-		ll = WideCharToMultiByte(sc->to_cp, 0,
-		    (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
-		if (archive_string_ensure(as, ll +1) == NULL)
-			return (-1);
-		mbs = as->s + as->length;
-		mbs_size = as->buffer_length - as->length -1;
-	} while (1);
-	archive_string_free(&tmp);
-	as->length += ll;
-	as->s[as->length] = '\0';
-	if (ll == 0 || defchar)
-		ret = -1;
-	return (ret);
-}
-
-static int
-win_strncat_from_utf16be(struct archive_string *as, const void *_p,
-    size_t bytes, struct archive_string_conv *sc)
-{
-	return (win_strncat_from_utf16(as, _p, bytes, sc, 1));
-}
-
-static int
-win_strncat_from_utf16le(struct archive_string *as, const void *_p,
-    size_t bytes, struct archive_string_conv *sc)
-{
-	return (win_strncat_from_utf16(as, _p, bytes, sc, 0));
-}
-
-static int
-is_big_endian(void)
-{
-	uint16_t d = 1;
-
-	return (archive_be16dec(&d) == 1);
-}
-
-/*
- * Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion fails.
- */
-static int
-win_strncat_to_utf16(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc, int bigendian)
-{
-	const char *s = (const char *)_p;
-	char *u16;
-	size_t count, avail;
-
-	if (archive_string_ensure(as16,
-	    as16->length + (length + 1) * 2) == NULL)
-		return (-1);
-
-	u16 = as16->s + as16->length;
-	avail = as16->buffer_length - 2;
-	if (sc->from_cp == CP_C_LOCALE) {
-		/*
-		 * "C" locale special process.
-		 */
-		count = 0;
-		while (count < length && *s) {
-			if (bigendian)
-				archive_be16enc(u16, *s);
-			else
-				archive_le16enc(u16, *s);
-			u16 += 2;
-			s++;
-			count++;
-		}
-		as16->length += count << 1;
-		as16->s[as16->length] = 0;
-		as16->s[as16->length+1] = 0;
-		return (0);
-	}
-	do {
-		count = MultiByteToWideChar(sc->from_cp,
-		    MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
-		/* Exit loop if we succeeded */
-		if (count != 0 ||
-		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			break;
-		}
-		/* Expand buffer and try again */
-		count = MultiByteToWideChar(sc->from_cp,
-		    MB_PRECOMPOSED, s, (int)length, NULL, 0);
-		if (archive_string_ensure(as16, (count +1) * 2)
-		    == NULL)
-			return (-1);
-		u16 = as16->s + as16->length;
-		avail = as16->buffer_length - 2;
-	} while (1);
-	as16->length += count * 2;
-	as16->s[as16->length] = 0;
-	as16->s[as16->length+1] = 0;
-	if (count == 0)
-		return (-1);
-
-	if (is_big_endian()) {
-		if (!bigendian) {
-			while (count > 0) {
-				uint16_t v = archive_be16dec(u16);
-				archive_le16enc(u16, v);
-				u16 += 2;
-				count--;
-			}
-		}
-	} else {
-		if (bigendian) {
-			while (count > 0) {
-				uint16_t v = archive_le16dec(u16);
-				archive_be16enc(u16, v);
-				u16 += 2;
-				count--;
-			}
-		}
-	}
-	return (0);
-}
-
-static int
-win_strncat_to_utf16be(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	return (win_strncat_to_utf16(as16, _p, length, sc, 1));
-}
-
-static int
-win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	return (win_strncat_to_utf16(as16, _p, length, sc, 0));
-}
-
-#endif /* _WIN32 && !__CYGWIN__ */
-
-/*
- * Do the best effort for conversions.
- * We cannot handle UTF-16BE character-set without such iconv,
- * but there is a chance if a string consists just ASCII code or
- * a current locale is UTF-8.
- */
-
-/*
- * Convert a UTF-16BE string to current locale and copy the result.
- * Return -1 if conversion fails.
- */
-static int
-best_effort_strncat_from_utf16(struct archive_string *as, const void *_p,
-    size_t bytes, struct archive_string_conv *sc, int be)
-{
-	const char *utf16 = (const char *)_p;
-	char *mbs;
-	uint32_t uc;
-	int n, ret;
-
-	(void)sc; /* UNUSED */
-	/*
-	 * Other case, we should do the best effort.
-	 * If all character are ASCII(<0x7f), we can convert it.
-	 * if not , we set a alternative character and return -1.
-	 */
-	ret = 0;
-	if (archive_string_ensure(as, as->length + bytes +1) == NULL)
-		return (-1);
-	mbs = as->s + as->length;
-
-	while ((n = utf16_to_unicode(&uc, utf16, bytes, be)) != 0) {
-		if (n < 0) {
-			n *= -1;
-			ret =  -1;
-		}
-		bytes -= n;
-		utf16 += n;
-
-		if (uc > 127) {
-			/* We cannot handle it. */
-			*mbs++ = '?';
-			ret =  -1;
-		} else
-			*mbs++ = (char)uc;
-	}
-	as->length = mbs - as->s;
-	as->s[as->length] = '\0';
-	return (ret);
-}
-
-static int
-best_effort_strncat_from_utf16be(struct archive_string *as, const void *_p,
-    size_t bytes, struct archive_string_conv *sc)
-{
-	return (best_effort_strncat_from_utf16(as, _p, bytes, sc, 1));
-}
-
-static int
-best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p,
-    size_t bytes, struct archive_string_conv *sc)
-{
-	return (best_effort_strncat_from_utf16(as, _p, bytes, sc, 0));
-}
-
-/*
- * Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion fails.
- */
-static int
-best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc, int bigendian)
-{
-	const char *s = (const char *)_p;
-	char *utf16;
-	size_t remaining;
-	int ret;
-
-	(void)sc; /* UNUSED */
-	/*
-	 * Other case, we should do the best effort.
-	 * If all character are ASCII(<0x7f), we can convert it.
-	 * if not , we set a alternative character and return -1.
-	 */
-	ret = 0;
-	remaining = length;
-
-	if (archive_string_ensure(as16,
-	    as16->length + (length + 1) * 2) == NULL)
-		return (-1);
-
-	utf16 = as16->s + as16->length;
-	while (remaining--) {
-		unsigned c = *s++;
-		if (c > 127) {
-			/* We cannot handle it. */
-			c = UNICODE_R_CHAR;
-			ret = -1;
-		}
-		if (bigendian)
-			archive_be16enc(utf16, c);
-		else
-			archive_le16enc(utf16, c);
-		utf16 += 2;
-	}
-	as16->length = utf16 - as16->s;
-	as16->s[as16->length] = 0;
-	as16->s[as16->length+1] = 0;
-	return (ret);
-}
-
-static int
-best_effort_strncat_to_utf16be(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	return (best_effort_strncat_to_utf16(as16, _p, length, sc, 1));
-}
-
-static int
-best_effort_strncat_to_utf16le(struct archive_string *as16, const void *_p,
-    size_t length, struct archive_string_conv *sc)
-{
-	return (best_effort_strncat_to_utf16(as16, _p, length, sc, 0));
-}
-
-
-/*
- * Multistring operations.
- */
-
-void
-archive_mstring_clean(struct archive_mstring *aes)
-{
-	archive_wstring_free(&(aes->aes_wcs));
-	archive_string_free(&(aes->aes_mbs));
-	archive_string_free(&(aes->aes_utf8));
-	archive_string_free(&(aes->aes_mbs_in_locale));
-	aes->aes_set = 0;
-}
-
-void
-archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring *src)
-{
-	dest->aes_set = src->aes_set;
-	archive_string_copy(&(dest->aes_mbs), &(src->aes_mbs));
-	archive_string_copy(&(dest->aes_utf8), &(src->aes_utf8));
-	archive_wstring_copy(&(dest->aes_wcs), &(src->aes_wcs));
-}
-
-int
-archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes,
-  const char **p)
-{
-	struct archive_string_conv *sc;
-	int r;
-
-	/* If we already have a UTF8 form, return that immediately. */
-	if (aes->aes_set & AES_SET_UTF8) {
-		*p = aes->aes_utf8.s;
-		return (0);
-	}
-
-	*p = NULL;
-	/* Try converting WCS to MBS first if MBS does not exist yet. */
-	if ((aes->aes_set & AES_SET_MBS) == 0) {
-		const char *pm; /* unused */
-		archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */
-	}
-	if (aes->aes_set & AES_SET_MBS) {
-		sc = archive_string_conversion_to_charset(a, "UTF-8", 1);
-		if (sc == NULL)
-			return (-1);/* Couldn't allocate memory for sc. */
-		r = archive_strncpy_l(&(aes->aes_utf8), aes->aes_mbs.s,
-		    aes->aes_mbs.length, sc);
-		if (a == NULL)
-			free_sconv_object(sc);
-		if (r == 0) {
-			aes->aes_set |= AES_SET_UTF8;
-			*p = aes->aes_utf8.s;
-			return (0);/* success. */
-		} else
-			return (-1);/* failure. */
-	}
-	return (0);/* success. */
-}
-
-int
-archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes,
-    const char **p)
-{
-	struct archive_string_conv *sc;
-	int r, ret = 0;
-
-	/* If we already have an MBS form, return that immediately. */
-	if (aes->aes_set & AES_SET_MBS) {
-		*p = aes->aes_mbs.s;
-		return (ret);
-	}
-
-	*p = NULL;
-	/* If there's a WCS form, try converting with the native locale. */
-	if (aes->aes_set & AES_SET_WCS) {
-		archive_string_empty(&(aes->aes_mbs));
-		r = archive_string_append_from_wcs(&(aes->aes_mbs),
-		    aes->aes_wcs.s, aes->aes_wcs.length);
-		*p = aes->aes_mbs.s;
-		if (r == 0) {
-			aes->aes_set |= AES_SET_MBS;
-			return (ret);
-		} else
-			ret = -1;
-	}
-
-	/* If there's a UTF-8 form, try converting with the native locale. */
-	if (aes->aes_set & AES_SET_UTF8) {
-		archive_string_empty(&(aes->aes_mbs));
-		sc = archive_string_conversion_from_charset(a, "UTF-8", 1);
-		if (sc == NULL)
-			return (-1);/* Couldn't allocate memory for sc. */
-		r = archive_strncpy_l(&(aes->aes_mbs),
-			aes->aes_utf8.s, aes->aes_utf8.length, sc);
-		if (a == NULL)
-			free_sconv_object(sc);
-		*p = aes->aes_mbs.s;
-		if (r == 0) {
-			aes->aes_set |= AES_SET_MBS;
-			ret = 0;/* success; overwrite previous error. */
-		} else
-			ret = -1;/* failure. */
-	}
-	return (ret);
-}
-
-int
-archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes,
-    const wchar_t **wp)
-{
-	int r, ret = 0;
-
-	(void)a;/* UNUSED */
-	/* Return WCS form if we already have it. */
-	if (aes->aes_set & AES_SET_WCS) {
-		*wp = aes->aes_wcs.s;
-		return (ret);
-	}
-
-	*wp = NULL;
-	/* Try converting UTF8 to MBS first if MBS does not exist yet. */
-	if ((aes->aes_set & AES_SET_MBS) == 0) {
-		const char *p; /* unused */
-		archive_mstring_get_mbs(a, aes, &p); /* ignore errors, we'll handle it later */
-	}
-	/* Try converting MBS to WCS using native locale. */
-	if (aes->aes_set & AES_SET_MBS) {
-		archive_wstring_empty(&(aes->aes_wcs));
-		r = archive_wstring_append_from_mbs(&(aes->aes_wcs),
-		    aes->aes_mbs.s, aes->aes_mbs.length);
-		if (r == 0) {
-			aes->aes_set |= AES_SET_WCS;
-			*wp = aes->aes_wcs.s;
-		} else
-			ret = -1;/* failure. */
-	}
-	return (ret);
-}
-
-int
-archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
-    const char **p, size_t *length, struct archive_string_conv *sc)
-{
-	int ret = 0;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	int r;
-
-	/*
-	 * Internationalization programming on Windows must use Wide
-	 * characters because Windows platform cannot make locale UTF-8.
-	 */
-	if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) {
-		archive_string_empty(&(aes->aes_mbs_in_locale));
-		r = archive_string_append_from_wcs_in_codepage(
-		    &(aes->aes_mbs_in_locale), aes->aes_wcs.s,
-		    aes->aes_wcs.length, sc);
-		if (r == 0) {
-			*p = aes->aes_mbs_in_locale.s;
-			if (length != NULL)
-				*length = aes->aes_mbs_in_locale.length;
-			return (0);
-		} else if (errno == ENOMEM)
-			return (-1);
-		else
-			ret = -1;
-	}
-#endif
-
-	/* If there is not an MBS form but there is a WCS or UTF8 form, try converting
-	 * with the native locale to be used for translating it to specified
-	 * character-set. */
-	if ((aes->aes_set & AES_SET_MBS) == 0) {
-		const char *pm; /* unused */
-		archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */
-	}
-	/* If we already have an MBS form, use it to be translated to
-	 * specified character-set. */
-	if (aes->aes_set & AES_SET_MBS) {
-		if (sc == NULL) {
-			/* Conversion is unneeded. */
-			*p = aes->aes_mbs.s;
-			if (length != NULL)
-				*length = aes->aes_mbs.length;
-			return (0);
-		}
-		ret = archive_strncpy_l(&(aes->aes_mbs_in_locale),
-		    aes->aes_mbs.s, aes->aes_mbs.length, sc);
-		*p = aes->aes_mbs_in_locale.s;
-		if (length != NULL)
-			*length = aes->aes_mbs_in_locale.length;
-	} else {
-		*p = NULL;
-		if (length != NULL)
-			*length = 0;
-	}
-	return (ret);
-}
-
-int
-archive_mstring_copy_mbs(struct archive_mstring *aes, const char *mbs)
-{
-	if (mbs == NULL) {
-		aes->aes_set = 0;
-		return (0);
-	}
-	return (archive_mstring_copy_mbs_len(aes, mbs, strlen(mbs)));
-}
-
-int
-archive_mstring_copy_mbs_len(struct archive_mstring *aes, const char *mbs,
-    size_t len)
-{
-	if (mbs == NULL) {
-		aes->aes_set = 0;
-		return (0);
-	}
-	aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */
-	archive_strncpy(&(aes->aes_mbs), mbs, len);
-	archive_string_empty(&(aes->aes_utf8));
-	archive_wstring_empty(&(aes->aes_wcs));
-	return (0);
-}
-
-int
-archive_mstring_copy_wcs(struct archive_mstring *aes, const wchar_t *wcs)
-{
-	return archive_mstring_copy_wcs_len(aes, wcs,
-				wcs == NULL ? 0 : wcslen(wcs));
-}
-
-int
-archive_mstring_copy_utf8(struct archive_mstring *aes, const char *utf8)
-{
-  if (utf8 == NULL) {
-    aes->aes_set = 0;
-    return (0);
-  }
-  aes->aes_set = AES_SET_UTF8;
-  archive_string_empty(&(aes->aes_mbs));
-  archive_string_empty(&(aes->aes_wcs));
-  archive_strncpy(&(aes->aes_utf8), utf8, strlen(utf8));
-  return (int)strlen(utf8);
-}
-
-int
-archive_mstring_copy_wcs_len(struct archive_mstring *aes, const wchar_t *wcs,
-    size_t len)
-{
-	if (wcs == NULL) {
-		aes->aes_set = 0;
-		return (0);
-	}
-	aes->aes_set = AES_SET_WCS; /* Only WCS form set. */
-	archive_string_empty(&(aes->aes_mbs));
-	archive_string_empty(&(aes->aes_utf8));
-	archive_wstrncpy(&(aes->aes_wcs), wcs, len);
-	return (0);
-}
-
-int
-archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
-    const char *mbs, size_t len, struct archive_string_conv *sc)
-{
-	int r;
-
-	if (mbs == NULL) {
-		aes->aes_set = 0;
-		return (0);
-	}
-	archive_string_empty(&(aes->aes_mbs));
-	archive_wstring_empty(&(aes->aes_wcs));
-	archive_string_empty(&(aes->aes_utf8));
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/*
-	 * Internationalization programming on Windows must use Wide
-	 * characters because Windows platform cannot make locale UTF-8.
-	 */
-	if (sc == NULL) {
-		if (archive_string_append(&(aes->aes_mbs),
-			mbs, mbsnbytes(mbs, len)) == NULL) {
-			aes->aes_set = 0;
-			r = -1;
-		} else {
-			aes->aes_set = AES_SET_MBS;
-			r = 0;
-		}
-#if defined(HAVE_ICONV)
-	} else if (sc != NULL && sc->cd_w != (iconv_t)-1) {
-		/*
-		 * This case happens only when MultiByteToWideChar() cannot
-		 * handle sc->from_cp, and we have to iconv in order to
-		 * translate character-set to wchar_t,UTF-16.
-		 */
-		iconv_t cd = sc->cd;
-		unsigned from_cp;
-		int flag;
-
-		/*
-		 * Translate multi-bytes from some character-set to UTF-8.
-		 */ 
-		sc->cd = sc->cd_w;
-		r = archive_strncpy_l(&(aes->aes_utf8), mbs, len, sc);
-		sc->cd = cd;
-		if (r != 0) {
-			aes->aes_set = 0;
-			return (r);
-		}
-		aes->aes_set = AES_SET_UTF8;
-
-		/*
-		 * Append the UTF-8 string into wstring.
-		 */ 
-		flag = sc->flag;
-		sc->flag &= ~(SCONV_NORMALIZATION_C
-				| SCONV_TO_UTF16| SCONV_FROM_UTF16);
-		from_cp = sc->from_cp;
-		sc->from_cp = CP_UTF8;
-		r = archive_wstring_append_from_mbs_in_codepage(&(aes->aes_wcs),
-			aes->aes_utf8.s, aes->aes_utf8.length, sc);
-		sc->flag = flag;
-		sc->from_cp = from_cp;
-		if (r == 0)
-			aes->aes_set |= AES_SET_WCS;
-#endif
-	} else {
-		r = archive_wstring_append_from_mbs_in_codepage(
-		    &(aes->aes_wcs), mbs, len, sc);
-		if (r == 0)
-			aes->aes_set = AES_SET_WCS;
-		else
-			aes->aes_set = 0;
-	}
-#else
-	r = archive_strncpy_l(&(aes->aes_mbs), mbs, len, sc);
-	if (r == 0)
-		aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */
-	else
-		aes->aes_set = 0;
-#endif
-	return (r);
-}
-
-/*
- * The 'update' form tries to proactively update all forms of
- * this string (WCS and MBS) and returns an error if any of
- * them fail.  This is used by the 'pax' handler, for instance,
- * to detect and report character-conversion failures early while
- * still allowing clients to get potentially useful values from
- * the more tolerant lazy conversions.  (get_mbs and get_wcs will
- * strive to give the user something useful, so you can get hopefully
- * usable values even if some of the character conversions are failing.)
- */
-int
-archive_mstring_update_utf8(struct archive *a, struct archive_mstring *aes,
-    const char *utf8)
-{
-	struct archive_string_conv *sc;
-	int r;
-
-	if (utf8 == NULL) {
-		aes->aes_set = 0;
-		return (0); /* Succeeded in clearing everything. */
-	}
-
-	/* Save the UTF8 string. */
-	archive_strcpy(&(aes->aes_utf8), utf8);
-
-	/* Empty the mbs and wcs strings. */
-	archive_string_empty(&(aes->aes_mbs));
-	archive_wstring_empty(&(aes->aes_wcs));
-
-	aes->aes_set = AES_SET_UTF8;	/* Only UTF8 is set now. */
-
-	/* Try converting UTF-8 to MBS, return false on failure. */
-	sc = archive_string_conversion_from_charset(a, "UTF-8", 1);
-	if (sc == NULL)
-		return (-1);/* Couldn't allocate memory for sc. */
-	r = archive_strcpy_l(&(aes->aes_mbs), utf8, sc);
-	if (a == NULL)
-		free_sconv_object(sc);
-	if (r != 0)
-		return (-1);
-	aes->aes_set = AES_SET_UTF8 | AES_SET_MBS; /* Both UTF8 and MBS set. */
-
-	/* Try converting MBS to WCS, return false on failure. */
-	if (archive_wstring_append_from_mbs(&(aes->aes_wcs), aes->aes_mbs.s,
-	    aes->aes_mbs.length))
-		return (-1);
-	aes->aes_set = AES_SET_UTF8 | AES_SET_WCS | AES_SET_MBS;
-
-	/* All conversions succeeded. */
-	return (0);
-}
diff --git a/c/archive_string.h b/c/archive_string.h
deleted file mode 100644
--- a/c/archive_string.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_string.h 201092 2009-12-28 02:26:06Z kientzle $
- *
- */
-
-#ifndef ARCHIVE_STRING_H_INCLUDED
-#define ARCHIVE_STRING_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-#include <stdarg.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>  /* required for wchar_t on some systems */
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#include "archive.h"
-
-/*
- * Basic resizable/reusable string support similar to Java's "StringBuffer."
- *
- * Unlike sbuf(9), the buffers here are fully reusable and track the
- * length throughout.
- */
-
-struct archive_string {
-	char	*s;  /* Pointer to the storage */
-	size_t	 length; /* Length of 's' in characters */
-	size_t	 buffer_length; /* Length of malloc-ed storage in bytes. */
-};
-
-struct archive_wstring {
-	wchar_t	*s;  /* Pointer to the storage */
-	size_t	 length; /* Length of 's' in characters */
-	size_t	 buffer_length; /* Length of malloc-ed storage in bytes. */
-};
-
-struct archive_string_conv;
-
-/* Initialize an archive_string object on the stack or elsewhere. */
-#define	archive_string_init(a)	\
-	do { (a)->s = NULL; (a)->length = 0; (a)->buffer_length = 0; } while(0)
-
-/* Append a C char to an archive_string, resizing as necessary. */
-struct archive_string *
-archive_strappend_char(struct archive_string *, char);
-
-/* Ditto for a wchar_t and an archive_wstring. */
-struct archive_wstring *
-archive_wstrappend_wchar(struct archive_wstring *, wchar_t);
-
-/* Append a raw array to an archive_string, resizing as necessary */
-struct archive_string *
-archive_array_append(struct archive_string *, const char *, size_t);
-
-/* Convert a Unicode string to current locale and append the result. */
-/* Returns -1 if conversion fails. */
-int
-archive_string_append_from_wcs(struct archive_string *, const wchar_t *, size_t);
-
-
-/* Create a string conversion object.
- * Return NULL and set a error message if the conversion is not supported
- * on the platform. */
-struct archive_string_conv *
-archive_string_conversion_to_charset(struct archive *, const char *, int);
-struct archive_string_conv *
-archive_string_conversion_from_charset(struct archive *, const char *, int);
-/* Create the default string conversion object for reading/writing an archive.
- * Return NULL if the conversion is unneeded.
- * Note: On non Windows platform this always returns NULL.
- */
-struct archive_string_conv *
-archive_string_default_conversion_for_read(struct archive *);
-struct archive_string_conv *
-archive_string_default_conversion_for_write(struct archive *);
-/* Dispose of a string conversion object. */
-void
-archive_string_conversion_free(struct archive *);
-const char *
-archive_string_conversion_charset_name(struct archive_string_conv *);
-void
-archive_string_conversion_set_opt(struct archive_string_conv *, int);
-#define SCONV_SET_OPT_UTF8_LIBARCHIVE2X	1
-#define SCONV_SET_OPT_NORMALIZATION_C	2
-#define SCONV_SET_OPT_NORMALIZATION_D	4
-
-
-/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion fails. */
-int
-archive_strncpy_l(struct archive_string *, const void *, size_t,
-    struct archive_string_conv *);
-
-/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion fails. */
-int
-archive_strncat_l(struct archive_string *, const void *, size_t,
-    struct archive_string_conv *);
-
-
-/* Copy one archive_string to another */
-#define	archive_string_copy(dest, src) \
-	((dest)->length = 0, archive_string_concat((dest), (src)))
-#define	archive_wstring_copy(dest, src) \
-	((dest)->length = 0, archive_wstring_concat((dest), (src)))
-
-/* Concatenate one archive_string to another */
-void archive_string_concat(struct archive_string *dest, struct archive_string *src);
-void archive_wstring_concat(struct archive_wstring *dest, struct archive_wstring *src);
-
-/* Ensure that the underlying buffer is at least as large as the request. */
-struct archive_string *
-archive_string_ensure(struct archive_string *, size_t);
-struct archive_wstring *
-archive_wstring_ensure(struct archive_wstring *, size_t);
-
-/* Append C string, which may lack trailing \0. */
-/* The source is declared void * here because this gets used with
- * "signed char *", "unsigned char *" and "char *" arguments.
- * Declaring it "char *" as with some of the other functions just
- * leads to a lot of extra casts. */
-struct archive_string *
-archive_strncat(struct archive_string *, const void *, size_t);
-struct archive_wstring *
-archive_wstrncat(struct archive_wstring *, const wchar_t *, size_t);
-
-/* Append a C string to an archive_string, resizing as necessary. */
-struct archive_string *
-archive_strcat(struct archive_string *, const void *);
-struct archive_wstring *
-archive_wstrcat(struct archive_wstring *, const wchar_t *);
-
-/* Copy a C string to an archive_string, resizing as necessary. */
-#define	archive_strcpy(as,p) \
-	archive_strncpy((as), (p), ((p) == NULL ? 0 : strlen(p)))
-#define	archive_wstrcpy(as,p) \
-	archive_wstrncpy((as), (p), ((p) == NULL ? 0 : wcslen(p)))
-#define	archive_strcpy_l(as,p,lo) \
-	archive_strncpy_l((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo))
-
-/* Copy a C string to an archive_string with limit, resizing as necessary. */
-#define	archive_strncpy(as,p,l) \
-	((as)->length=0, archive_strncat((as), (p), (l)))
-#define	archive_wstrncpy(as,p,l) \
-	((as)->length = 0, archive_wstrncat((as), (p), (l)))
-
-/* Return length of string. */
-#define	archive_strlen(a) ((a)->length)
-
-/* Set string length to zero. */
-#define	archive_string_empty(a) ((a)->length = 0)
-#define	archive_wstring_empty(a) ((a)->length = 0)
-
-/* Release any allocated storage resources. */
-void	archive_string_free(struct archive_string *);
-void	archive_wstring_free(struct archive_wstring *);
-
-/* Like 'vsprintf', but resizes the underlying string as necessary. */
-/* Note: This only implements a small subset of standard printf functionality. */
-void	archive_string_vsprintf(struct archive_string *, const char *,
-	    va_list) __LA_PRINTF(2, 0);
-void	archive_string_sprintf(struct archive_string *, const char *, ...)
-	    __LA_PRINTF(2, 3);
-
-/* Translates from MBS to Unicode. */
-/* Returns non-zero if conversion failed in any way. */
-int archive_wstring_append_from_mbs(struct archive_wstring *dest,
-    const char *, size_t);
-
-
-/* A "multistring" can hold Unicode, UTF8, or MBS versions of
- * the string.  If you set and read the same version, no translation
- * is done.  If you set and read different versions, the library
- * will attempt to transparently convert.
- */
-struct archive_mstring {
-	struct archive_string aes_mbs;
-	struct archive_string aes_utf8;
-	struct archive_wstring aes_wcs;
-	struct archive_string aes_mbs_in_locale;
-	/* Bitmap of which of the above are valid.  Because we're lazy
-	 * about malloc-ing and reusing the underlying storage, we
-	 * can't rely on NULL pointers to indicate whether a string
-	 * has been set. */
-	int aes_set;
-#define	AES_SET_MBS 1
-#define	AES_SET_UTF8 2
-#define	AES_SET_WCS 4
-};
-
-void	archive_mstring_clean(struct archive_mstring *);
-void	archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring *src);
-int archive_mstring_get_mbs(struct archive *, struct archive_mstring *, const char **);
-int archive_mstring_get_utf8(struct archive *, struct archive_mstring *, const char **);
-int archive_mstring_get_wcs(struct archive *, struct archive_mstring *, const wchar_t **);
-int	archive_mstring_get_mbs_l(struct archive *, struct archive_mstring *, const char **,
-	    size_t *, struct archive_string_conv *);
-int	archive_mstring_copy_mbs(struct archive_mstring *, const char *mbs);
-int	archive_mstring_copy_mbs_len(struct archive_mstring *, const char *mbs,
-	    size_t);
-int	archive_mstring_copy_utf8(struct archive_mstring *, const char *utf8);
-int	archive_mstring_copy_wcs(struct archive_mstring *, const wchar_t *wcs);
-int	archive_mstring_copy_wcs_len(struct archive_mstring *,
-	    const wchar_t *wcs, size_t);
-int	archive_mstring_copy_mbs_len_l(struct archive_mstring *,
-	    const char *mbs, size_t, struct archive_string_conv *);
-int     archive_mstring_update_utf8(struct archive *, struct archive_mstring *aes, const char *utf8);
-
-
-#endif
diff --git a/c/archive_string_composition.h b/c/archive_string_composition.h
deleted file mode 100644
--- a/c/archive_string_composition.h
+++ /dev/null
@@ -1,2292 +0,0 @@
-/*-
- * Copyright (c) 2011-2012 libarchive Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * ATTENTION!
- *  This file is generated by build/utils/gen_archive_string_composition_h.sh
- *  from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
- *
- *  See also http://unicode.org/report/tr15/
- */
-
-#ifndef ARCHIVE_STRING_COMPOSITION_H_INCLUDED
-#define ARCHIVE_STRING_COMPOSITION_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-struct unicode_composition_table {
-	uint32_t cp1;
-	uint32_t cp2;
-	uint32_t nfc;
-};
-
-static const struct unicode_composition_table u_composition_table[] = {
-	{ 0x0003C , 0x00338 , 0x0226E },
-	{ 0x0003D , 0x00338 , 0x02260 },
-	{ 0x0003E , 0x00338 , 0x0226F },
-	{ 0x00041 , 0x00300 , 0x000C0 },
-	{ 0x00041 , 0x00301 , 0x000C1 },
-	{ 0x00041 , 0x00302 , 0x000C2 },
-	{ 0x00041 , 0x00303 , 0x000C3 },
-	{ 0x00041 , 0x00304 , 0x00100 },
-	{ 0x00041 , 0x00306 , 0x00102 },
-	{ 0x00041 , 0x00307 , 0x00226 },
-	{ 0x00041 , 0x00308 , 0x000C4 },
-	{ 0x00041 , 0x00309 , 0x01EA2 },
-	{ 0x00041 , 0x0030A , 0x000C5 },
-	{ 0x00041 , 0x0030C , 0x001CD },
-	{ 0x00041 , 0x0030F , 0x00200 },
-	{ 0x00041 , 0x00311 , 0x00202 },
-	{ 0x00041 , 0x00323 , 0x01EA0 },
-	{ 0x00041 , 0x00325 , 0x01E00 },
-	{ 0x00041 , 0x00328 , 0x00104 },
-	{ 0x00042 , 0x00307 , 0x01E02 },
-	{ 0x00042 , 0x00323 , 0x01E04 },
-	{ 0x00042 , 0x00331 , 0x01E06 },
-	{ 0x00043 , 0x00301 , 0x00106 },
-	{ 0x00043 , 0x00302 , 0x00108 },
-	{ 0x00043 , 0x00307 , 0x0010A },
-	{ 0x00043 , 0x0030C , 0x0010C },
-	{ 0x00043 , 0x00327 , 0x000C7 },
-	{ 0x00044 , 0x00307 , 0x01E0A },
-	{ 0x00044 , 0x0030C , 0x0010E },
-	{ 0x00044 , 0x00323 , 0x01E0C },
-	{ 0x00044 , 0x00327 , 0x01E10 },
-	{ 0x00044 , 0x0032D , 0x01E12 },
-	{ 0x00044 , 0x00331 , 0x01E0E },
-	{ 0x00045 , 0x00300 , 0x000C8 },
-	{ 0x00045 , 0x00301 , 0x000C9 },
-	{ 0x00045 , 0x00302 , 0x000CA },
-	{ 0x00045 , 0x00303 , 0x01EBC },
-	{ 0x00045 , 0x00304 , 0x00112 },
-	{ 0x00045 , 0x00306 , 0x00114 },
-	{ 0x00045 , 0x00307 , 0x00116 },
-	{ 0x00045 , 0x00308 , 0x000CB },
-	{ 0x00045 , 0x00309 , 0x01EBA },
-	{ 0x00045 , 0x0030C , 0x0011A },
-	{ 0x00045 , 0x0030F , 0x00204 },
-	{ 0x00045 , 0x00311 , 0x00206 },
-	{ 0x00045 , 0x00323 , 0x01EB8 },
-	{ 0x00045 , 0x00327 , 0x00228 },
-	{ 0x00045 , 0x00328 , 0x00118 },
-	{ 0x00045 , 0x0032D , 0x01E18 },
-	{ 0x00045 , 0x00330 , 0x01E1A },
-	{ 0x00046 , 0x00307 , 0x01E1E },
-	{ 0x00047 , 0x00301 , 0x001F4 },
-	{ 0x00047 , 0x00302 , 0x0011C },
-	{ 0x00047 , 0x00304 , 0x01E20 },
-	{ 0x00047 , 0x00306 , 0x0011E },
-	{ 0x00047 , 0x00307 , 0x00120 },
-	{ 0x00047 , 0x0030C , 0x001E6 },
-	{ 0x00047 , 0x00327 , 0x00122 },
-	{ 0x00048 , 0x00302 , 0x00124 },
-	{ 0x00048 , 0x00307 , 0x01E22 },
-	{ 0x00048 , 0x00308 , 0x01E26 },
-	{ 0x00048 , 0x0030C , 0x0021E },
-	{ 0x00048 , 0x00323 , 0x01E24 },
-	{ 0x00048 , 0x00327 , 0x01E28 },
-	{ 0x00048 , 0x0032E , 0x01E2A },
-	{ 0x00049 , 0x00300 , 0x000CC },
-	{ 0x00049 , 0x00301 , 0x000CD },
-	{ 0x00049 , 0x00302 , 0x000CE },
-	{ 0x00049 , 0x00303 , 0x00128 },
-	{ 0x00049 , 0x00304 , 0x0012A },
-	{ 0x00049 , 0x00306 , 0x0012C },
-	{ 0x00049 , 0x00307 , 0x00130 },
-	{ 0x00049 , 0x00308 , 0x000CF },
-	{ 0x00049 , 0x00309 , 0x01EC8 },
-	{ 0x00049 , 0x0030C , 0x001CF },
-	{ 0x00049 , 0x0030F , 0x00208 },
-	{ 0x00049 , 0x00311 , 0x0020A },
-	{ 0x00049 , 0x00323 , 0x01ECA },
-	{ 0x00049 , 0x00328 , 0x0012E },
-	{ 0x00049 , 0x00330 , 0x01E2C },
-	{ 0x0004A , 0x00302 , 0x00134 },
-	{ 0x0004B , 0x00301 , 0x01E30 },
-	{ 0x0004B , 0x0030C , 0x001E8 },
-	{ 0x0004B , 0x00323 , 0x01E32 },
-	{ 0x0004B , 0x00327 , 0x00136 },
-	{ 0x0004B , 0x00331 , 0x01E34 },
-	{ 0x0004C , 0x00301 , 0x00139 },
-	{ 0x0004C , 0x0030C , 0x0013D },
-	{ 0x0004C , 0x00323 , 0x01E36 },
-	{ 0x0004C , 0x00327 , 0x0013B },
-	{ 0x0004C , 0x0032D , 0x01E3C },
-	{ 0x0004C , 0x00331 , 0x01E3A },
-	{ 0x0004D , 0x00301 , 0x01E3E },
-	{ 0x0004D , 0x00307 , 0x01E40 },
-	{ 0x0004D , 0x00323 , 0x01E42 },
-	{ 0x0004E , 0x00300 , 0x001F8 },
-	{ 0x0004E , 0x00301 , 0x00143 },
-	{ 0x0004E , 0x00303 , 0x000D1 },
-	{ 0x0004E , 0x00307 , 0x01E44 },
-	{ 0x0004E , 0x0030C , 0x00147 },
-	{ 0x0004E , 0x00323 , 0x01E46 },
-	{ 0x0004E , 0x00327 , 0x00145 },
-	{ 0x0004E , 0x0032D , 0x01E4A },
-	{ 0x0004E , 0x00331 , 0x01E48 },
-	{ 0x0004F , 0x00300 , 0x000D2 },
-	{ 0x0004F , 0x00301 , 0x000D3 },
-	{ 0x0004F , 0x00302 , 0x000D4 },
-	{ 0x0004F , 0x00303 , 0x000D5 },
-	{ 0x0004F , 0x00304 , 0x0014C },
-	{ 0x0004F , 0x00306 , 0x0014E },
-	{ 0x0004F , 0x00307 , 0x0022E },
-	{ 0x0004F , 0x00308 , 0x000D6 },
-	{ 0x0004F , 0x00309 , 0x01ECE },
-	{ 0x0004F , 0x0030B , 0x00150 },
-	{ 0x0004F , 0x0030C , 0x001D1 },
-	{ 0x0004F , 0x0030F , 0x0020C },
-	{ 0x0004F , 0x00311 , 0x0020E },
-	{ 0x0004F , 0x0031B , 0x001A0 },
-	{ 0x0004F , 0x00323 , 0x01ECC },
-	{ 0x0004F , 0x00328 , 0x001EA },
-	{ 0x00050 , 0x00301 , 0x01E54 },
-	{ 0x00050 , 0x00307 , 0x01E56 },
-	{ 0x00052 , 0x00301 , 0x00154 },
-	{ 0x00052 , 0x00307 , 0x01E58 },
-	{ 0x00052 , 0x0030C , 0x00158 },
-	{ 0x00052 , 0x0030F , 0x00210 },
-	{ 0x00052 , 0x00311 , 0x00212 },
-	{ 0x00052 , 0x00323 , 0x01E5A },
-	{ 0x00052 , 0x00327 , 0x00156 },
-	{ 0x00052 , 0x00331 , 0x01E5E },
-	{ 0x00053 , 0x00301 , 0x0015A },
-	{ 0x00053 , 0x00302 , 0x0015C },
-	{ 0x00053 , 0x00307 , 0x01E60 },
-	{ 0x00053 , 0x0030C , 0x00160 },
-	{ 0x00053 , 0x00323 , 0x01E62 },
-	{ 0x00053 , 0x00326 , 0x00218 },
-	{ 0x00053 , 0x00327 , 0x0015E },
-	{ 0x00054 , 0x00307 , 0x01E6A },
-	{ 0x00054 , 0x0030C , 0x00164 },
-	{ 0x00054 , 0x00323 , 0x01E6C },
-	{ 0x00054 , 0x00326 , 0x0021A },
-	{ 0x00054 , 0x00327 , 0x00162 },
-	{ 0x00054 , 0x0032D , 0x01E70 },
-	{ 0x00054 , 0x00331 , 0x01E6E },
-	{ 0x00055 , 0x00300 , 0x000D9 },
-	{ 0x00055 , 0x00301 , 0x000DA },
-	{ 0x00055 , 0x00302 , 0x000DB },
-	{ 0x00055 , 0x00303 , 0x00168 },
-	{ 0x00055 , 0x00304 , 0x0016A },
-	{ 0x00055 , 0x00306 , 0x0016C },
-	{ 0x00055 , 0x00308 , 0x000DC },
-	{ 0x00055 , 0x00309 , 0x01EE6 },
-	{ 0x00055 , 0x0030A , 0x0016E },
-	{ 0x00055 , 0x0030B , 0x00170 },
-	{ 0x00055 , 0x0030C , 0x001D3 },
-	{ 0x00055 , 0x0030F , 0x00214 },
-	{ 0x00055 , 0x00311 , 0x00216 },
-	{ 0x00055 , 0x0031B , 0x001AF },
-	{ 0x00055 , 0x00323 , 0x01EE4 },
-	{ 0x00055 , 0x00324 , 0x01E72 },
-	{ 0x00055 , 0x00328 , 0x00172 },
-	{ 0x00055 , 0x0032D , 0x01E76 },
-	{ 0x00055 , 0x00330 , 0x01E74 },
-	{ 0x00056 , 0x00303 , 0x01E7C },
-	{ 0x00056 , 0x00323 , 0x01E7E },
-	{ 0x00057 , 0x00300 , 0x01E80 },
-	{ 0x00057 , 0x00301 , 0x01E82 },
-	{ 0x00057 , 0x00302 , 0x00174 },
-	{ 0x00057 , 0x00307 , 0x01E86 },
-	{ 0x00057 , 0x00308 , 0x01E84 },
-	{ 0x00057 , 0x00323 , 0x01E88 },
-	{ 0x00058 , 0x00307 , 0x01E8A },
-	{ 0x00058 , 0x00308 , 0x01E8C },
-	{ 0x00059 , 0x00300 , 0x01EF2 },
-	{ 0x00059 , 0x00301 , 0x000DD },
-	{ 0x00059 , 0x00302 , 0x00176 },
-	{ 0x00059 , 0x00303 , 0x01EF8 },
-	{ 0x00059 , 0x00304 , 0x00232 },
-	{ 0x00059 , 0x00307 , 0x01E8E },
-	{ 0x00059 , 0x00308 , 0x00178 },
-	{ 0x00059 , 0x00309 , 0x01EF6 },
-	{ 0x00059 , 0x00323 , 0x01EF4 },
-	{ 0x0005A , 0x00301 , 0x00179 },
-	{ 0x0005A , 0x00302 , 0x01E90 },
-	{ 0x0005A , 0x00307 , 0x0017B },
-	{ 0x0005A , 0x0030C , 0x0017D },
-	{ 0x0005A , 0x00323 , 0x01E92 },
-	{ 0x0005A , 0x00331 , 0x01E94 },
-	{ 0x00061 , 0x00300 , 0x000E0 },
-	{ 0x00061 , 0x00301 , 0x000E1 },
-	{ 0x00061 , 0x00302 , 0x000E2 },
-	{ 0x00061 , 0x00303 , 0x000E3 },
-	{ 0x00061 , 0x00304 , 0x00101 },
-	{ 0x00061 , 0x00306 , 0x00103 },
-	{ 0x00061 , 0x00307 , 0x00227 },
-	{ 0x00061 , 0x00308 , 0x000E4 },
-	{ 0x00061 , 0x00309 , 0x01EA3 },
-	{ 0x00061 , 0x0030A , 0x000E5 },
-	{ 0x00061 , 0x0030C , 0x001CE },
-	{ 0x00061 , 0x0030F , 0x00201 },
-	{ 0x00061 , 0x00311 , 0x00203 },
-	{ 0x00061 , 0x00323 , 0x01EA1 },
-	{ 0x00061 , 0x00325 , 0x01E01 },
-	{ 0x00061 , 0x00328 , 0x00105 },
-	{ 0x00062 , 0x00307 , 0x01E03 },
-	{ 0x00062 , 0x00323 , 0x01E05 },
-	{ 0x00062 , 0x00331 , 0x01E07 },
-	{ 0x00063 , 0x00301 , 0x00107 },
-	{ 0x00063 , 0x00302 , 0x00109 },
-	{ 0x00063 , 0x00307 , 0x0010B },
-	{ 0x00063 , 0x0030C , 0x0010D },
-	{ 0x00063 , 0x00327 , 0x000E7 },
-	{ 0x00064 , 0x00307 , 0x01E0B },
-	{ 0x00064 , 0x0030C , 0x0010F },
-	{ 0x00064 , 0x00323 , 0x01E0D },
-	{ 0x00064 , 0x00327 , 0x01E11 },
-	{ 0x00064 , 0x0032D , 0x01E13 },
-	{ 0x00064 , 0x00331 , 0x01E0F },
-	{ 0x00065 , 0x00300 , 0x000E8 },
-	{ 0x00065 , 0x00301 , 0x000E9 },
-	{ 0x00065 , 0x00302 , 0x000EA },
-	{ 0x00065 , 0x00303 , 0x01EBD },
-	{ 0x00065 , 0x00304 , 0x00113 },
-	{ 0x00065 , 0x00306 , 0x00115 },
-	{ 0x00065 , 0x00307 , 0x00117 },
-	{ 0x00065 , 0x00308 , 0x000EB },
-	{ 0x00065 , 0x00309 , 0x01EBB },
-	{ 0x00065 , 0x0030C , 0x0011B },
-	{ 0x00065 , 0x0030F , 0x00205 },
-	{ 0x00065 , 0x00311 , 0x00207 },
-	{ 0x00065 , 0x00323 , 0x01EB9 },
-	{ 0x00065 , 0x00327 , 0x00229 },
-	{ 0x00065 , 0x00328 , 0x00119 },
-	{ 0x00065 , 0x0032D , 0x01E19 },
-	{ 0x00065 , 0x00330 , 0x01E1B },
-	{ 0x00066 , 0x00307 , 0x01E1F },
-	{ 0x00067 , 0x00301 , 0x001F5 },
-	{ 0x00067 , 0x00302 , 0x0011D },
-	{ 0x00067 , 0x00304 , 0x01E21 },
-	{ 0x00067 , 0x00306 , 0x0011F },
-	{ 0x00067 , 0x00307 , 0x00121 },
-	{ 0x00067 , 0x0030C , 0x001E7 },
-	{ 0x00067 , 0x00327 , 0x00123 },
-	{ 0x00068 , 0x00302 , 0x00125 },
-	{ 0x00068 , 0x00307 , 0x01E23 },
-	{ 0x00068 , 0x00308 , 0x01E27 },
-	{ 0x00068 , 0x0030C , 0x0021F },
-	{ 0x00068 , 0x00323 , 0x01E25 },
-	{ 0x00068 , 0x00327 , 0x01E29 },
-	{ 0x00068 , 0x0032E , 0x01E2B },
-	{ 0x00068 , 0x00331 , 0x01E96 },
-	{ 0x00069 , 0x00300 , 0x000EC },
-	{ 0x00069 , 0x00301 , 0x000ED },
-	{ 0x00069 , 0x00302 , 0x000EE },
-	{ 0x00069 , 0x00303 , 0x00129 },
-	{ 0x00069 , 0x00304 , 0x0012B },
-	{ 0x00069 , 0x00306 , 0x0012D },
-	{ 0x00069 , 0x00308 , 0x000EF },
-	{ 0x00069 , 0x00309 , 0x01EC9 },
-	{ 0x00069 , 0x0030C , 0x001D0 },
-	{ 0x00069 , 0x0030F , 0x00209 },
-	{ 0x00069 , 0x00311 , 0x0020B },
-	{ 0x00069 , 0x00323 , 0x01ECB },
-	{ 0x00069 , 0x00328 , 0x0012F },
-	{ 0x00069 , 0x00330 , 0x01E2D },
-	{ 0x0006A , 0x00302 , 0x00135 },
-	{ 0x0006A , 0x0030C , 0x001F0 },
-	{ 0x0006B , 0x00301 , 0x01E31 },
-	{ 0x0006B , 0x0030C , 0x001E9 },
-	{ 0x0006B , 0x00323 , 0x01E33 },
-	{ 0x0006B , 0x00327 , 0x00137 },
-	{ 0x0006B , 0x00331 , 0x01E35 },
-	{ 0x0006C , 0x00301 , 0x0013A },
-	{ 0x0006C , 0x0030C , 0x0013E },
-	{ 0x0006C , 0x00323 , 0x01E37 },
-	{ 0x0006C , 0x00327 , 0x0013C },
-	{ 0x0006C , 0x0032D , 0x01E3D },
-	{ 0x0006C , 0x00331 , 0x01E3B },
-	{ 0x0006D , 0x00301 , 0x01E3F },
-	{ 0x0006D , 0x00307 , 0x01E41 },
-	{ 0x0006D , 0x00323 , 0x01E43 },
-	{ 0x0006E , 0x00300 , 0x001F9 },
-	{ 0x0006E , 0x00301 , 0x00144 },
-	{ 0x0006E , 0x00303 , 0x000F1 },
-	{ 0x0006E , 0x00307 , 0x01E45 },
-	{ 0x0006E , 0x0030C , 0x00148 },
-	{ 0x0006E , 0x00323 , 0x01E47 },
-	{ 0x0006E , 0x00327 , 0x00146 },
-	{ 0x0006E , 0x0032D , 0x01E4B },
-	{ 0x0006E , 0x00331 , 0x01E49 },
-	{ 0x0006F , 0x00300 , 0x000F2 },
-	{ 0x0006F , 0x00301 , 0x000F3 },
-	{ 0x0006F , 0x00302 , 0x000F4 },
-	{ 0x0006F , 0x00303 , 0x000F5 },
-	{ 0x0006F , 0x00304 , 0x0014D },
-	{ 0x0006F , 0x00306 , 0x0014F },
-	{ 0x0006F , 0x00307 , 0x0022F },
-	{ 0x0006F , 0x00308 , 0x000F6 },
-	{ 0x0006F , 0x00309 , 0x01ECF },
-	{ 0x0006F , 0x0030B , 0x00151 },
-	{ 0x0006F , 0x0030C , 0x001D2 },
-	{ 0x0006F , 0x0030F , 0x0020D },
-	{ 0x0006F , 0x00311 , 0x0020F },
-	{ 0x0006F , 0x0031B , 0x001A1 },
-	{ 0x0006F , 0x00323 , 0x01ECD },
-	{ 0x0006F , 0x00328 , 0x001EB },
-	{ 0x00070 , 0x00301 , 0x01E55 },
-	{ 0x00070 , 0x00307 , 0x01E57 },
-	{ 0x00072 , 0x00301 , 0x00155 },
-	{ 0x00072 , 0x00307 , 0x01E59 },
-	{ 0x00072 , 0x0030C , 0x00159 },
-	{ 0x00072 , 0x0030F , 0x00211 },
-	{ 0x00072 , 0x00311 , 0x00213 },
-	{ 0x00072 , 0x00323 , 0x01E5B },
-	{ 0x00072 , 0x00327 , 0x00157 },
-	{ 0x00072 , 0x00331 , 0x01E5F },
-	{ 0x00073 , 0x00301 , 0x0015B },
-	{ 0x00073 , 0x00302 , 0x0015D },
-	{ 0x00073 , 0x00307 , 0x01E61 },
-	{ 0x00073 , 0x0030C , 0x00161 },
-	{ 0x00073 , 0x00323 , 0x01E63 },
-	{ 0x00073 , 0x00326 , 0x00219 },
-	{ 0x00073 , 0x00327 , 0x0015F },
-	{ 0x00074 , 0x00307 , 0x01E6B },
-	{ 0x00074 , 0x00308 , 0x01E97 },
-	{ 0x00074 , 0x0030C , 0x00165 },
-	{ 0x00074 , 0x00323 , 0x01E6D },
-	{ 0x00074 , 0x00326 , 0x0021B },
-	{ 0x00074 , 0x00327 , 0x00163 },
-	{ 0x00074 , 0x0032D , 0x01E71 },
-	{ 0x00074 , 0x00331 , 0x01E6F },
-	{ 0x00075 , 0x00300 , 0x000F9 },
-	{ 0x00075 , 0x00301 , 0x000FA },
-	{ 0x00075 , 0x00302 , 0x000FB },
-	{ 0x00075 , 0x00303 , 0x00169 },
-	{ 0x00075 , 0x00304 , 0x0016B },
-	{ 0x00075 , 0x00306 , 0x0016D },
-	{ 0x00075 , 0x00308 , 0x000FC },
-	{ 0x00075 , 0x00309 , 0x01EE7 },
-	{ 0x00075 , 0x0030A , 0x0016F },
-	{ 0x00075 , 0x0030B , 0x00171 },
-	{ 0x00075 , 0x0030C , 0x001D4 },
-	{ 0x00075 , 0x0030F , 0x00215 },
-	{ 0x00075 , 0x00311 , 0x00217 },
-	{ 0x00075 , 0x0031B , 0x001B0 },
-	{ 0x00075 , 0x00323 , 0x01EE5 },
-	{ 0x00075 , 0x00324 , 0x01E73 },
-	{ 0x00075 , 0x00328 , 0x00173 },
-	{ 0x00075 , 0x0032D , 0x01E77 },
-	{ 0x00075 , 0x00330 , 0x01E75 },
-	{ 0x00076 , 0x00303 , 0x01E7D },
-	{ 0x00076 , 0x00323 , 0x01E7F },
-	{ 0x00077 , 0x00300 , 0x01E81 },
-	{ 0x00077 , 0x00301 , 0x01E83 },
-	{ 0x00077 , 0x00302 , 0x00175 },
-	{ 0x00077 , 0x00307 , 0x01E87 },
-	{ 0x00077 , 0x00308 , 0x01E85 },
-	{ 0x00077 , 0x0030A , 0x01E98 },
-	{ 0x00077 , 0x00323 , 0x01E89 },
-	{ 0x00078 , 0x00307 , 0x01E8B },
-	{ 0x00078 , 0x00308 , 0x01E8D },
-	{ 0x00079 , 0x00300 , 0x01EF3 },
-	{ 0x00079 , 0x00301 , 0x000FD },
-	{ 0x00079 , 0x00302 , 0x00177 },
-	{ 0x00079 , 0x00303 , 0x01EF9 },
-	{ 0x00079 , 0x00304 , 0x00233 },
-	{ 0x00079 , 0x00307 , 0x01E8F },
-	{ 0x00079 , 0x00308 , 0x000FF },
-	{ 0x00079 , 0x00309 , 0x01EF7 },
-	{ 0x00079 , 0x0030A , 0x01E99 },
-	{ 0x00079 , 0x00323 , 0x01EF5 },
-	{ 0x0007A , 0x00301 , 0x0017A },
-	{ 0x0007A , 0x00302 , 0x01E91 },
-	{ 0x0007A , 0x00307 , 0x0017C },
-	{ 0x0007A , 0x0030C , 0x0017E },
-	{ 0x0007A , 0x00323 , 0x01E93 },
-	{ 0x0007A , 0x00331 , 0x01E95 },
-	{ 0x000A8 , 0x00300 , 0x01FED },
-	{ 0x000A8 , 0x00301 , 0x00385 },
-	{ 0x000A8 , 0x00342 , 0x01FC1 },
-	{ 0x000C2 , 0x00300 , 0x01EA6 },
-	{ 0x000C2 , 0x00301 , 0x01EA4 },
-	{ 0x000C2 , 0x00303 , 0x01EAA },
-	{ 0x000C2 , 0x00309 , 0x01EA8 },
-	{ 0x000C4 , 0x00304 , 0x001DE },
-	{ 0x000C5 , 0x00301 , 0x001FA },
-	{ 0x000C6 , 0x00301 , 0x001FC },
-	{ 0x000C6 , 0x00304 , 0x001E2 },
-	{ 0x000C7 , 0x00301 , 0x01E08 },
-	{ 0x000CA , 0x00300 , 0x01EC0 },
-	{ 0x000CA , 0x00301 , 0x01EBE },
-	{ 0x000CA , 0x00303 , 0x01EC4 },
-	{ 0x000CA , 0x00309 , 0x01EC2 },
-	{ 0x000CF , 0x00301 , 0x01E2E },
-	{ 0x000D4 , 0x00300 , 0x01ED2 },
-	{ 0x000D4 , 0x00301 , 0x01ED0 },
-	{ 0x000D4 , 0x00303 , 0x01ED6 },
-	{ 0x000D4 , 0x00309 , 0x01ED4 },
-	{ 0x000D5 , 0x00301 , 0x01E4C },
-	{ 0x000D5 , 0x00304 , 0x0022C },
-	{ 0x000D5 , 0x00308 , 0x01E4E },
-	{ 0x000D6 , 0x00304 , 0x0022A },
-	{ 0x000D8 , 0x00301 , 0x001FE },
-	{ 0x000DC , 0x00300 , 0x001DB },
-	{ 0x000DC , 0x00301 , 0x001D7 },
-	{ 0x000DC , 0x00304 , 0x001D5 },
-	{ 0x000DC , 0x0030C , 0x001D9 },
-	{ 0x000E2 , 0x00300 , 0x01EA7 },
-	{ 0x000E2 , 0x00301 , 0x01EA5 },
-	{ 0x000E2 , 0x00303 , 0x01EAB },
-	{ 0x000E2 , 0x00309 , 0x01EA9 },
-	{ 0x000E4 , 0x00304 , 0x001DF },
-	{ 0x000E5 , 0x00301 , 0x001FB },
-	{ 0x000E6 , 0x00301 , 0x001FD },
-	{ 0x000E6 , 0x00304 , 0x001E3 },
-	{ 0x000E7 , 0x00301 , 0x01E09 },
-	{ 0x000EA , 0x00300 , 0x01EC1 },
-	{ 0x000EA , 0x00301 , 0x01EBF },
-	{ 0x000EA , 0x00303 , 0x01EC5 },
-	{ 0x000EA , 0x00309 , 0x01EC3 },
-	{ 0x000EF , 0x00301 , 0x01E2F },
-	{ 0x000F4 , 0x00300 , 0x01ED3 },
-	{ 0x000F4 , 0x00301 , 0x01ED1 },
-	{ 0x000F4 , 0x00303 , 0x01ED7 },
-	{ 0x000F4 , 0x00309 , 0x01ED5 },
-	{ 0x000F5 , 0x00301 , 0x01E4D },
-	{ 0x000F5 , 0x00304 , 0x0022D },
-	{ 0x000F5 , 0x00308 , 0x01E4F },
-	{ 0x000F6 , 0x00304 , 0x0022B },
-	{ 0x000F8 , 0x00301 , 0x001FF },
-	{ 0x000FC , 0x00300 , 0x001DC },
-	{ 0x000FC , 0x00301 , 0x001D8 },
-	{ 0x000FC , 0x00304 , 0x001D6 },
-	{ 0x000FC , 0x0030C , 0x001DA },
-	{ 0x00102 , 0x00300 , 0x01EB0 },
-	{ 0x00102 , 0x00301 , 0x01EAE },
-	{ 0x00102 , 0x00303 , 0x01EB4 },
-	{ 0x00102 , 0x00309 , 0x01EB2 },
-	{ 0x00103 , 0x00300 , 0x01EB1 },
-	{ 0x00103 , 0x00301 , 0x01EAF },
-	{ 0x00103 , 0x00303 , 0x01EB5 },
-	{ 0x00103 , 0x00309 , 0x01EB3 },
-	{ 0x00112 , 0x00300 , 0x01E14 },
-	{ 0x00112 , 0x00301 , 0x01E16 },
-	{ 0x00113 , 0x00300 , 0x01E15 },
-	{ 0x00113 , 0x00301 , 0x01E17 },
-	{ 0x0014C , 0x00300 , 0x01E50 },
-	{ 0x0014C , 0x00301 , 0x01E52 },
-	{ 0x0014D , 0x00300 , 0x01E51 },
-	{ 0x0014D , 0x00301 , 0x01E53 },
-	{ 0x0015A , 0x00307 , 0x01E64 },
-	{ 0x0015B , 0x00307 , 0x01E65 },
-	{ 0x00160 , 0x00307 , 0x01E66 },
-	{ 0x00161 , 0x00307 , 0x01E67 },
-	{ 0x00168 , 0x00301 , 0x01E78 },
-	{ 0x00169 , 0x00301 , 0x01E79 },
-	{ 0x0016A , 0x00308 , 0x01E7A },
-	{ 0x0016B , 0x00308 , 0x01E7B },
-	{ 0x0017F , 0x00307 , 0x01E9B },
-	{ 0x001A0 , 0x00300 , 0x01EDC },
-	{ 0x001A0 , 0x00301 , 0x01EDA },
-	{ 0x001A0 , 0x00303 , 0x01EE0 },
-	{ 0x001A0 , 0x00309 , 0x01EDE },
-	{ 0x001A0 , 0x00323 , 0x01EE2 },
-	{ 0x001A1 , 0x00300 , 0x01EDD },
-	{ 0x001A1 , 0x00301 , 0x01EDB },
-	{ 0x001A1 , 0x00303 , 0x01EE1 },
-	{ 0x001A1 , 0x00309 , 0x01EDF },
-	{ 0x001A1 , 0x00323 , 0x01EE3 },
-	{ 0x001AF , 0x00300 , 0x01EEA },
-	{ 0x001AF , 0x00301 , 0x01EE8 },
-	{ 0x001AF , 0x00303 , 0x01EEE },
-	{ 0x001AF , 0x00309 , 0x01EEC },
-	{ 0x001AF , 0x00323 , 0x01EF0 },
-	{ 0x001B0 , 0x00300 , 0x01EEB },
-	{ 0x001B0 , 0x00301 , 0x01EE9 },
-	{ 0x001B0 , 0x00303 , 0x01EEF },
-	{ 0x001B0 , 0x00309 , 0x01EED },
-	{ 0x001B0 , 0x00323 , 0x01EF1 },
-	{ 0x001B7 , 0x0030C , 0x001EE },
-	{ 0x001EA , 0x00304 , 0x001EC },
-	{ 0x001EB , 0x00304 , 0x001ED },
-	{ 0x00226 , 0x00304 , 0x001E0 },
-	{ 0x00227 , 0x00304 , 0x001E1 },
-	{ 0x00228 , 0x00306 , 0x01E1C },
-	{ 0x00229 , 0x00306 , 0x01E1D },
-	{ 0x0022E , 0x00304 , 0x00230 },
-	{ 0x0022F , 0x00304 , 0x00231 },
-	{ 0x00292 , 0x0030C , 0x001EF },
-	{ 0x00391 , 0x00300 , 0x01FBA },
-	{ 0x00391 , 0x00301 , 0x00386 },
-	{ 0x00391 , 0x00304 , 0x01FB9 },
-	{ 0x00391 , 0x00306 , 0x01FB8 },
-	{ 0x00391 , 0x00313 , 0x01F08 },
-	{ 0x00391 , 0x00314 , 0x01F09 },
-	{ 0x00391 , 0x00345 , 0x01FBC },
-	{ 0x00395 , 0x00300 , 0x01FC8 },
-	{ 0x00395 , 0x00301 , 0x00388 },
-	{ 0x00395 , 0x00313 , 0x01F18 },
-	{ 0x00395 , 0x00314 , 0x01F19 },
-	{ 0x00397 , 0x00300 , 0x01FCA },
-	{ 0x00397 , 0x00301 , 0x00389 },
-	{ 0x00397 , 0x00313 , 0x01F28 },
-	{ 0x00397 , 0x00314 , 0x01F29 },
-	{ 0x00397 , 0x00345 , 0x01FCC },
-	{ 0x00399 , 0x00300 , 0x01FDA },
-	{ 0x00399 , 0x00301 , 0x0038A },
-	{ 0x00399 , 0x00304 , 0x01FD9 },
-	{ 0x00399 , 0x00306 , 0x01FD8 },
-	{ 0x00399 , 0x00308 , 0x003AA },
-	{ 0x00399 , 0x00313 , 0x01F38 },
-	{ 0x00399 , 0x00314 , 0x01F39 },
-	{ 0x0039F , 0x00300 , 0x01FF8 },
-	{ 0x0039F , 0x00301 , 0x0038C },
-	{ 0x0039F , 0x00313 , 0x01F48 },
-	{ 0x0039F , 0x00314 , 0x01F49 },
-	{ 0x003A1 , 0x00314 , 0x01FEC },
-	{ 0x003A5 , 0x00300 , 0x01FEA },
-	{ 0x003A5 , 0x00301 , 0x0038E },
-	{ 0x003A5 , 0x00304 , 0x01FE9 },
-	{ 0x003A5 , 0x00306 , 0x01FE8 },
-	{ 0x003A5 , 0x00308 , 0x003AB },
-	{ 0x003A5 , 0x00314 , 0x01F59 },
-	{ 0x003A9 , 0x00300 , 0x01FFA },
-	{ 0x003A9 , 0x00301 , 0x0038F },
-	{ 0x003A9 , 0x00313 , 0x01F68 },
-	{ 0x003A9 , 0x00314 , 0x01F69 },
-	{ 0x003A9 , 0x00345 , 0x01FFC },
-	{ 0x003AC , 0x00345 , 0x01FB4 },
-	{ 0x003AE , 0x00345 , 0x01FC4 },
-	{ 0x003B1 , 0x00300 , 0x01F70 },
-	{ 0x003B1 , 0x00301 , 0x003AC },
-	{ 0x003B1 , 0x00304 , 0x01FB1 },
-	{ 0x003B1 , 0x00306 , 0x01FB0 },
-	{ 0x003B1 , 0x00313 , 0x01F00 },
-	{ 0x003B1 , 0x00314 , 0x01F01 },
-	{ 0x003B1 , 0x00342 , 0x01FB6 },
-	{ 0x003B1 , 0x00345 , 0x01FB3 },
-	{ 0x003B5 , 0x00300 , 0x01F72 },
-	{ 0x003B5 , 0x00301 , 0x003AD },
-	{ 0x003B5 , 0x00313 , 0x01F10 },
-	{ 0x003B5 , 0x00314 , 0x01F11 },
-	{ 0x003B7 , 0x00300 , 0x01F74 },
-	{ 0x003B7 , 0x00301 , 0x003AE },
-	{ 0x003B7 , 0x00313 , 0x01F20 },
-	{ 0x003B7 , 0x00314 , 0x01F21 },
-	{ 0x003B7 , 0x00342 , 0x01FC6 },
-	{ 0x003B7 , 0x00345 , 0x01FC3 },
-	{ 0x003B9 , 0x00300 , 0x01F76 },
-	{ 0x003B9 , 0x00301 , 0x003AF },
-	{ 0x003B9 , 0x00304 , 0x01FD1 },
-	{ 0x003B9 , 0x00306 , 0x01FD0 },
-	{ 0x003B9 , 0x00308 , 0x003CA },
-	{ 0x003B9 , 0x00313 , 0x01F30 },
-	{ 0x003B9 , 0x00314 , 0x01F31 },
-	{ 0x003B9 , 0x00342 , 0x01FD6 },
-	{ 0x003BF , 0x00300 , 0x01F78 },
-	{ 0x003BF , 0x00301 , 0x003CC },
-	{ 0x003BF , 0x00313 , 0x01F40 },
-	{ 0x003BF , 0x00314 , 0x01F41 },
-	{ 0x003C1 , 0x00313 , 0x01FE4 },
-	{ 0x003C1 , 0x00314 , 0x01FE5 },
-	{ 0x003C5 , 0x00300 , 0x01F7A },
-	{ 0x003C5 , 0x00301 , 0x003CD },
-	{ 0x003C5 , 0x00304 , 0x01FE1 },
-	{ 0x003C5 , 0x00306 , 0x01FE0 },
-	{ 0x003C5 , 0x00308 , 0x003CB },
-	{ 0x003C5 , 0x00313 , 0x01F50 },
-	{ 0x003C5 , 0x00314 , 0x01F51 },
-	{ 0x003C5 , 0x00342 , 0x01FE6 },
-	{ 0x003C9 , 0x00300 , 0x01F7C },
-	{ 0x003C9 , 0x00301 , 0x003CE },
-	{ 0x003C9 , 0x00313 , 0x01F60 },
-	{ 0x003C9 , 0x00314 , 0x01F61 },
-	{ 0x003C9 , 0x00342 , 0x01FF6 },
-	{ 0x003C9 , 0x00345 , 0x01FF3 },
-	{ 0x003CA , 0x00300 , 0x01FD2 },
-	{ 0x003CA , 0x00301 , 0x00390 },
-	{ 0x003CA , 0x00342 , 0x01FD7 },
-	{ 0x003CB , 0x00300 , 0x01FE2 },
-	{ 0x003CB , 0x00301 , 0x003B0 },
-	{ 0x003CB , 0x00342 , 0x01FE7 },
-	{ 0x003CE , 0x00345 , 0x01FF4 },
-	{ 0x003D2 , 0x00301 , 0x003D3 },
-	{ 0x003D2 , 0x00308 , 0x003D4 },
-	{ 0x00406 , 0x00308 , 0x00407 },
-	{ 0x00410 , 0x00306 , 0x004D0 },
-	{ 0x00410 , 0x00308 , 0x004D2 },
-	{ 0x00413 , 0x00301 , 0x00403 },
-	{ 0x00415 , 0x00300 , 0x00400 },
-	{ 0x00415 , 0x00306 , 0x004D6 },
-	{ 0x00415 , 0x00308 , 0x00401 },
-	{ 0x00416 , 0x00306 , 0x004C1 },
-	{ 0x00416 , 0x00308 , 0x004DC },
-	{ 0x00417 , 0x00308 , 0x004DE },
-	{ 0x00418 , 0x00300 , 0x0040D },
-	{ 0x00418 , 0x00304 , 0x004E2 },
-	{ 0x00418 , 0x00306 , 0x00419 },
-	{ 0x00418 , 0x00308 , 0x004E4 },
-	{ 0x0041A , 0x00301 , 0x0040C },
-	{ 0x0041E , 0x00308 , 0x004E6 },
-	{ 0x00423 , 0x00304 , 0x004EE },
-	{ 0x00423 , 0x00306 , 0x0040E },
-	{ 0x00423 , 0x00308 , 0x004F0 },
-	{ 0x00423 , 0x0030B , 0x004F2 },
-	{ 0x00427 , 0x00308 , 0x004F4 },
-	{ 0x0042B , 0x00308 , 0x004F8 },
-	{ 0x0042D , 0x00308 , 0x004EC },
-	{ 0x00430 , 0x00306 , 0x004D1 },
-	{ 0x00430 , 0x00308 , 0x004D3 },
-	{ 0x00433 , 0x00301 , 0x00453 },
-	{ 0x00435 , 0x00300 , 0x00450 },
-	{ 0x00435 , 0x00306 , 0x004D7 },
-	{ 0x00435 , 0x00308 , 0x00451 },
-	{ 0x00436 , 0x00306 , 0x004C2 },
-	{ 0x00436 , 0x00308 , 0x004DD },
-	{ 0x00437 , 0x00308 , 0x004DF },
-	{ 0x00438 , 0x00300 , 0x0045D },
-	{ 0x00438 , 0x00304 , 0x004E3 },
-	{ 0x00438 , 0x00306 , 0x00439 },
-	{ 0x00438 , 0x00308 , 0x004E5 },
-	{ 0x0043A , 0x00301 , 0x0045C },
-	{ 0x0043E , 0x00308 , 0x004E7 },
-	{ 0x00443 , 0x00304 , 0x004EF },
-	{ 0x00443 , 0x00306 , 0x0045E },
-	{ 0x00443 , 0x00308 , 0x004F1 },
-	{ 0x00443 , 0x0030B , 0x004F3 },
-	{ 0x00447 , 0x00308 , 0x004F5 },
-	{ 0x0044B , 0x00308 , 0x004F9 },
-	{ 0x0044D , 0x00308 , 0x004ED },
-	{ 0x00456 , 0x00308 , 0x00457 },
-	{ 0x00474 , 0x0030F , 0x00476 },
-	{ 0x00475 , 0x0030F , 0x00477 },
-	{ 0x004D8 , 0x00308 , 0x004DA },
-	{ 0x004D9 , 0x00308 , 0x004DB },
-	{ 0x004E8 , 0x00308 , 0x004EA },
-	{ 0x004E9 , 0x00308 , 0x004EB },
-	{ 0x00627 , 0x00653 , 0x00622 },
-	{ 0x00627 , 0x00654 , 0x00623 },
-	{ 0x00627 , 0x00655 , 0x00625 },
-	{ 0x00648 , 0x00654 , 0x00624 },
-	{ 0x0064A , 0x00654 , 0x00626 },
-	{ 0x006C1 , 0x00654 , 0x006C2 },
-	{ 0x006D2 , 0x00654 , 0x006D3 },
-	{ 0x006D5 , 0x00654 , 0x006C0 },
-	{ 0x00928 , 0x0093C , 0x00929 },
-	{ 0x00930 , 0x0093C , 0x00931 },
-	{ 0x00933 , 0x0093C , 0x00934 },
-	{ 0x009C7 , 0x009BE , 0x009CB },
-	{ 0x009C7 , 0x009D7 , 0x009CC },
-	{ 0x00B47 , 0x00B3E , 0x00B4B },
-	{ 0x00B47 , 0x00B56 , 0x00B48 },
-	{ 0x00B47 , 0x00B57 , 0x00B4C },
-	{ 0x00B92 , 0x00BD7 , 0x00B94 },
-	{ 0x00BC6 , 0x00BBE , 0x00BCA },
-	{ 0x00BC6 , 0x00BD7 , 0x00BCC },
-	{ 0x00BC7 , 0x00BBE , 0x00BCB },
-	{ 0x00C46 , 0x00C56 , 0x00C48 },
-	{ 0x00CBF , 0x00CD5 , 0x00CC0 },
-	{ 0x00CC6 , 0x00CC2 , 0x00CCA },
-	{ 0x00CC6 , 0x00CD5 , 0x00CC7 },
-	{ 0x00CC6 , 0x00CD6 , 0x00CC8 },
-	{ 0x00CCA , 0x00CD5 , 0x00CCB },
-	{ 0x00D46 , 0x00D3E , 0x00D4A },
-	{ 0x00D46 , 0x00D57 , 0x00D4C },
-	{ 0x00D47 , 0x00D3E , 0x00D4B },
-	{ 0x00DD9 , 0x00DCA , 0x00DDA },
-	{ 0x00DD9 , 0x00DCF , 0x00DDC },
-	{ 0x00DD9 , 0x00DDF , 0x00DDE },
-	{ 0x00DDC , 0x00DCA , 0x00DDD },
-	{ 0x01025 , 0x0102E , 0x01026 },
-	{ 0x01B05 , 0x01B35 , 0x01B06 },
-	{ 0x01B07 , 0x01B35 , 0x01B08 },
-	{ 0x01B09 , 0x01B35 , 0x01B0A },
-	{ 0x01B0B , 0x01B35 , 0x01B0C },
-	{ 0x01B0D , 0x01B35 , 0x01B0E },
-	{ 0x01B11 , 0x01B35 , 0x01B12 },
-	{ 0x01B3A , 0x01B35 , 0x01B3B },
-	{ 0x01B3C , 0x01B35 , 0x01B3D },
-	{ 0x01B3E , 0x01B35 , 0x01B40 },
-	{ 0x01B3F , 0x01B35 , 0x01B41 },
-	{ 0x01B42 , 0x01B35 , 0x01B43 },
-	{ 0x01E36 , 0x00304 , 0x01E38 },
-	{ 0x01E37 , 0x00304 , 0x01E39 },
-	{ 0x01E5A , 0x00304 , 0x01E5C },
-	{ 0x01E5B , 0x00304 , 0x01E5D },
-	{ 0x01E62 , 0x00307 , 0x01E68 },
-	{ 0x01E63 , 0x00307 , 0x01E69 },
-	{ 0x01EA0 , 0x00302 , 0x01EAC },
-	{ 0x01EA0 , 0x00306 , 0x01EB6 },
-	{ 0x01EA1 , 0x00302 , 0x01EAD },
-	{ 0x01EA1 , 0x00306 , 0x01EB7 },
-	{ 0x01EB8 , 0x00302 , 0x01EC6 },
-	{ 0x01EB9 , 0x00302 , 0x01EC7 },
-	{ 0x01ECC , 0x00302 , 0x01ED8 },
-	{ 0x01ECD , 0x00302 , 0x01ED9 },
-	{ 0x01F00 , 0x00300 , 0x01F02 },
-	{ 0x01F00 , 0x00301 , 0x01F04 },
-	{ 0x01F00 , 0x00342 , 0x01F06 },
-	{ 0x01F00 , 0x00345 , 0x01F80 },
-	{ 0x01F01 , 0x00300 , 0x01F03 },
-	{ 0x01F01 , 0x00301 , 0x01F05 },
-	{ 0x01F01 , 0x00342 , 0x01F07 },
-	{ 0x01F01 , 0x00345 , 0x01F81 },
-	{ 0x01F02 , 0x00345 , 0x01F82 },
-	{ 0x01F03 , 0x00345 , 0x01F83 },
-	{ 0x01F04 , 0x00345 , 0x01F84 },
-	{ 0x01F05 , 0x00345 , 0x01F85 },
-	{ 0x01F06 , 0x00345 , 0x01F86 },
-	{ 0x01F07 , 0x00345 , 0x01F87 },
-	{ 0x01F08 , 0x00300 , 0x01F0A },
-	{ 0x01F08 , 0x00301 , 0x01F0C },
-	{ 0x01F08 , 0x00342 , 0x01F0E },
-	{ 0x01F08 , 0x00345 , 0x01F88 },
-	{ 0x01F09 , 0x00300 , 0x01F0B },
-	{ 0x01F09 , 0x00301 , 0x01F0D },
-	{ 0x01F09 , 0x00342 , 0x01F0F },
-	{ 0x01F09 , 0x00345 , 0x01F89 },
-	{ 0x01F0A , 0x00345 , 0x01F8A },
-	{ 0x01F0B , 0x00345 , 0x01F8B },
-	{ 0x01F0C , 0x00345 , 0x01F8C },
-	{ 0x01F0D , 0x00345 , 0x01F8D },
-	{ 0x01F0E , 0x00345 , 0x01F8E },
-	{ 0x01F0F , 0x00345 , 0x01F8F },
-	{ 0x01F10 , 0x00300 , 0x01F12 },
-	{ 0x01F10 , 0x00301 , 0x01F14 },
-	{ 0x01F11 , 0x00300 , 0x01F13 },
-	{ 0x01F11 , 0x00301 , 0x01F15 },
-	{ 0x01F18 , 0x00300 , 0x01F1A },
-	{ 0x01F18 , 0x00301 , 0x01F1C },
-	{ 0x01F19 , 0x00300 , 0x01F1B },
-	{ 0x01F19 , 0x00301 , 0x01F1D },
-	{ 0x01F20 , 0x00300 , 0x01F22 },
-	{ 0x01F20 , 0x00301 , 0x01F24 },
-	{ 0x01F20 , 0x00342 , 0x01F26 },
-	{ 0x01F20 , 0x00345 , 0x01F90 },
-	{ 0x01F21 , 0x00300 , 0x01F23 },
-	{ 0x01F21 , 0x00301 , 0x01F25 },
-	{ 0x01F21 , 0x00342 , 0x01F27 },
-	{ 0x01F21 , 0x00345 , 0x01F91 },
-	{ 0x01F22 , 0x00345 , 0x01F92 },
-	{ 0x01F23 , 0x00345 , 0x01F93 },
-	{ 0x01F24 , 0x00345 , 0x01F94 },
-	{ 0x01F25 , 0x00345 , 0x01F95 },
-	{ 0x01F26 , 0x00345 , 0x01F96 },
-	{ 0x01F27 , 0x00345 , 0x01F97 },
-	{ 0x01F28 , 0x00300 , 0x01F2A },
-	{ 0x01F28 , 0x00301 , 0x01F2C },
-	{ 0x01F28 , 0x00342 , 0x01F2E },
-	{ 0x01F28 , 0x00345 , 0x01F98 },
-	{ 0x01F29 , 0x00300 , 0x01F2B },
-	{ 0x01F29 , 0x00301 , 0x01F2D },
-	{ 0x01F29 , 0x00342 , 0x01F2F },
-	{ 0x01F29 , 0x00345 , 0x01F99 },
-	{ 0x01F2A , 0x00345 , 0x01F9A },
-	{ 0x01F2B , 0x00345 , 0x01F9B },
-	{ 0x01F2C , 0x00345 , 0x01F9C },
-	{ 0x01F2D , 0x00345 , 0x01F9D },
-	{ 0x01F2E , 0x00345 , 0x01F9E },
-	{ 0x01F2F , 0x00345 , 0x01F9F },
-	{ 0x01F30 , 0x00300 , 0x01F32 },
-	{ 0x01F30 , 0x00301 , 0x01F34 },
-	{ 0x01F30 , 0x00342 , 0x01F36 },
-	{ 0x01F31 , 0x00300 , 0x01F33 },
-	{ 0x01F31 , 0x00301 , 0x01F35 },
-	{ 0x01F31 , 0x00342 , 0x01F37 },
-	{ 0x01F38 , 0x00300 , 0x01F3A },
-	{ 0x01F38 , 0x00301 , 0x01F3C },
-	{ 0x01F38 , 0x00342 , 0x01F3E },
-	{ 0x01F39 , 0x00300 , 0x01F3B },
-	{ 0x01F39 , 0x00301 , 0x01F3D },
-	{ 0x01F39 , 0x00342 , 0x01F3F },
-	{ 0x01F40 , 0x00300 , 0x01F42 },
-	{ 0x01F40 , 0x00301 , 0x01F44 },
-	{ 0x01F41 , 0x00300 , 0x01F43 },
-	{ 0x01F41 , 0x00301 , 0x01F45 },
-	{ 0x01F48 , 0x00300 , 0x01F4A },
-	{ 0x01F48 , 0x00301 , 0x01F4C },
-	{ 0x01F49 , 0x00300 , 0x01F4B },
-	{ 0x01F49 , 0x00301 , 0x01F4D },
-	{ 0x01F50 , 0x00300 , 0x01F52 },
-	{ 0x01F50 , 0x00301 , 0x01F54 },
-	{ 0x01F50 , 0x00342 , 0x01F56 },
-	{ 0x01F51 , 0x00300 , 0x01F53 },
-	{ 0x01F51 , 0x00301 , 0x01F55 },
-	{ 0x01F51 , 0x00342 , 0x01F57 },
-	{ 0x01F59 , 0x00300 , 0x01F5B },
-	{ 0x01F59 , 0x00301 , 0x01F5D },
-	{ 0x01F59 , 0x00342 , 0x01F5F },
-	{ 0x01F60 , 0x00300 , 0x01F62 },
-	{ 0x01F60 , 0x00301 , 0x01F64 },
-	{ 0x01F60 , 0x00342 , 0x01F66 },
-	{ 0x01F60 , 0x00345 , 0x01FA0 },
-	{ 0x01F61 , 0x00300 , 0x01F63 },
-	{ 0x01F61 , 0x00301 , 0x01F65 },
-	{ 0x01F61 , 0x00342 , 0x01F67 },
-	{ 0x01F61 , 0x00345 , 0x01FA1 },
-	{ 0x01F62 , 0x00345 , 0x01FA2 },
-	{ 0x01F63 , 0x00345 , 0x01FA3 },
-	{ 0x01F64 , 0x00345 , 0x01FA4 },
-	{ 0x01F65 , 0x00345 , 0x01FA5 },
-	{ 0x01F66 , 0x00345 , 0x01FA6 },
-	{ 0x01F67 , 0x00345 , 0x01FA7 },
-	{ 0x01F68 , 0x00300 , 0x01F6A },
-	{ 0x01F68 , 0x00301 , 0x01F6C },
-	{ 0x01F68 , 0x00342 , 0x01F6E },
-	{ 0x01F68 , 0x00345 , 0x01FA8 },
-	{ 0x01F69 , 0x00300 , 0x01F6B },
-	{ 0x01F69 , 0x00301 , 0x01F6D },
-	{ 0x01F69 , 0x00342 , 0x01F6F },
-	{ 0x01F69 , 0x00345 , 0x01FA9 },
-	{ 0x01F6A , 0x00345 , 0x01FAA },
-	{ 0x01F6B , 0x00345 , 0x01FAB },
-	{ 0x01F6C , 0x00345 , 0x01FAC },
-	{ 0x01F6D , 0x00345 , 0x01FAD },
-	{ 0x01F6E , 0x00345 , 0x01FAE },
-	{ 0x01F6F , 0x00345 , 0x01FAF },
-	{ 0x01F70 , 0x00345 , 0x01FB2 },
-	{ 0x01F74 , 0x00345 , 0x01FC2 },
-	{ 0x01F7C , 0x00345 , 0x01FF2 },
-	{ 0x01FB6 , 0x00345 , 0x01FB7 },
-	{ 0x01FBF , 0x00300 , 0x01FCD },
-	{ 0x01FBF , 0x00301 , 0x01FCE },
-	{ 0x01FBF , 0x00342 , 0x01FCF },
-	{ 0x01FC6 , 0x00345 , 0x01FC7 },
-	{ 0x01FF6 , 0x00345 , 0x01FF7 },
-	{ 0x01FFE , 0x00300 , 0x01FDD },
-	{ 0x01FFE , 0x00301 , 0x01FDE },
-	{ 0x01FFE , 0x00342 , 0x01FDF },
-	{ 0x02190 , 0x00338 , 0x0219A },
-	{ 0x02192 , 0x00338 , 0x0219B },
-	{ 0x02194 , 0x00338 , 0x021AE },
-	{ 0x021D0 , 0x00338 , 0x021CD },
-	{ 0x021D2 , 0x00338 , 0x021CF },
-	{ 0x021D4 , 0x00338 , 0x021CE },
-	{ 0x02203 , 0x00338 , 0x02204 },
-	{ 0x02208 , 0x00338 , 0x02209 },
-	{ 0x0220B , 0x00338 , 0x0220C },
-	{ 0x02223 , 0x00338 , 0x02224 },
-	{ 0x02225 , 0x00338 , 0x02226 },
-	{ 0x0223C , 0x00338 , 0x02241 },
-	{ 0x02243 , 0x00338 , 0x02244 },
-	{ 0x02245 , 0x00338 , 0x02247 },
-	{ 0x02248 , 0x00338 , 0x02249 },
-	{ 0x0224D , 0x00338 , 0x0226D },
-	{ 0x02261 , 0x00338 , 0x02262 },
-	{ 0x02264 , 0x00338 , 0x02270 },
-	{ 0x02265 , 0x00338 , 0x02271 },
-	{ 0x02272 , 0x00338 , 0x02274 },
-	{ 0x02273 , 0x00338 , 0x02275 },
-	{ 0x02276 , 0x00338 , 0x02278 },
-	{ 0x02277 , 0x00338 , 0x02279 },
-	{ 0x0227A , 0x00338 , 0x02280 },
-	{ 0x0227B , 0x00338 , 0x02281 },
-	{ 0x0227C , 0x00338 , 0x022E0 },
-	{ 0x0227D , 0x00338 , 0x022E1 },
-	{ 0x02282 , 0x00338 , 0x02284 },
-	{ 0x02283 , 0x00338 , 0x02285 },
-	{ 0x02286 , 0x00338 , 0x02288 },
-	{ 0x02287 , 0x00338 , 0x02289 },
-	{ 0x02291 , 0x00338 , 0x022E2 },
-	{ 0x02292 , 0x00338 , 0x022E3 },
-	{ 0x022A2 , 0x00338 , 0x022AC },
-	{ 0x022A8 , 0x00338 , 0x022AD },
-	{ 0x022A9 , 0x00338 , 0x022AE },
-	{ 0x022AB , 0x00338 , 0x022AF },
-	{ 0x022B2 , 0x00338 , 0x022EA },
-	{ 0x022B3 , 0x00338 , 0x022EB },
-	{ 0x022B4 , 0x00338 , 0x022EC },
-	{ 0x022B5 , 0x00338 , 0x022ED },
-	{ 0x03046 , 0x03099 , 0x03094 },
-	{ 0x0304B , 0x03099 , 0x0304C },
-	{ 0x0304D , 0x03099 , 0x0304E },
-	{ 0x0304F , 0x03099 , 0x03050 },
-	{ 0x03051 , 0x03099 , 0x03052 },
-	{ 0x03053 , 0x03099 , 0x03054 },
-	{ 0x03055 , 0x03099 , 0x03056 },
-	{ 0x03057 , 0x03099 , 0x03058 },
-	{ 0x03059 , 0x03099 , 0x0305A },
-	{ 0x0305B , 0x03099 , 0x0305C },
-	{ 0x0305D , 0x03099 , 0x0305E },
-	{ 0x0305F , 0x03099 , 0x03060 },
-	{ 0x03061 , 0x03099 , 0x03062 },
-	{ 0x03064 , 0x03099 , 0x03065 },
-	{ 0x03066 , 0x03099 , 0x03067 },
-	{ 0x03068 , 0x03099 , 0x03069 },
-	{ 0x0306F , 0x03099 , 0x03070 },
-	{ 0x0306F , 0x0309A , 0x03071 },
-	{ 0x03072 , 0x03099 , 0x03073 },
-	{ 0x03072 , 0x0309A , 0x03074 },
-	{ 0x03075 , 0x03099 , 0x03076 },
-	{ 0x03075 , 0x0309A , 0x03077 },
-	{ 0x03078 , 0x03099 , 0x03079 },
-	{ 0x03078 , 0x0309A , 0x0307A },
-	{ 0x0307B , 0x03099 , 0x0307C },
-	{ 0x0307B , 0x0309A , 0x0307D },
-	{ 0x0309D , 0x03099 , 0x0309E },
-	{ 0x030A6 , 0x03099 , 0x030F4 },
-	{ 0x030AB , 0x03099 , 0x030AC },
-	{ 0x030AD , 0x03099 , 0x030AE },
-	{ 0x030AF , 0x03099 , 0x030B0 },
-	{ 0x030B1 , 0x03099 , 0x030B2 },
-	{ 0x030B3 , 0x03099 , 0x030B4 },
-	{ 0x030B5 , 0x03099 , 0x030B6 },
-	{ 0x030B7 , 0x03099 , 0x030B8 },
-	{ 0x030B9 , 0x03099 , 0x030BA },
-	{ 0x030BB , 0x03099 , 0x030BC },
-	{ 0x030BD , 0x03099 , 0x030BE },
-	{ 0x030BF , 0x03099 , 0x030C0 },
-	{ 0x030C1 , 0x03099 , 0x030C2 },
-	{ 0x030C4 , 0x03099 , 0x030C5 },
-	{ 0x030C6 , 0x03099 , 0x030C7 },
-	{ 0x030C8 , 0x03099 , 0x030C9 },
-	{ 0x030CF , 0x03099 , 0x030D0 },
-	{ 0x030CF , 0x0309A , 0x030D1 },
-	{ 0x030D2 , 0x03099 , 0x030D3 },
-	{ 0x030D2 , 0x0309A , 0x030D4 },
-	{ 0x030D5 , 0x03099 , 0x030D6 },
-	{ 0x030D5 , 0x0309A , 0x030D7 },
-	{ 0x030D8 , 0x03099 , 0x030D9 },
-	{ 0x030D8 , 0x0309A , 0x030DA },
-	{ 0x030DB , 0x03099 , 0x030DC },
-	{ 0x030DB , 0x0309A , 0x030DD },
-	{ 0x030EF , 0x03099 , 0x030F7 },
-	{ 0x030F0 , 0x03099 , 0x030F8 },
-	{ 0x030F1 , 0x03099 , 0x030F9 },
-	{ 0x030F2 , 0x03099 , 0x030FA },
-	{ 0x030FD , 0x03099 , 0x030FE },
-	{ 0x11099 , 0x110BA , 0x1109A },
-	{ 0x1109B , 0x110BA , 0x1109C },
-	{ 0x110A5 , 0x110BA , 0x110AB },
-};
-
-#define CANONICAL_CLASS_MIN	0x0300
-#define CANONICAL_CLASS_MAX	0x1D244
-
-#define IS_DECOMPOSABLE_BLOCK(uc)	\
-	(((uc)>>8) <= 0x1D2 && u_decomposable_blocks[(uc)>>8])
-static const char u_decomposable_blocks[0x1D2+1] = {
-	0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,1,1,1,1,0,0,
-	1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,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,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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,1,0,0,1,0,
-	0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
-};
-
-/* Get Canonical Combining Class(CCC). */
-#define CCC(uc)	\
-	(((uc) > 0x1D244)?0:\
-	ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F])
-
-/* The table of the value of Canonical Combining Class */
-static const unsigned char ccc_val[][16] = {
- /* idx=0: XXXX0 - XXXXF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=1: 00300 - 0030F */
- {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=2: 00310 - 0031F */
- {230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220, 220, 220 },
- /* idx=3: 00320 - 0032F */
- {220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 220, 220, 220 },
- /* idx=4: 00330 - 0033F */
- {220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, 230, 230, 230 },
- /* idx=5: 00340 - 0034F */
- {230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, 230, 230, 220, 220, 0 },
- /* idx=6: 00350 - 0035F */
- {230, 230, 230, 220, 220, 220, 220, 230, 232, 220, 220, 230, 233, 234, 234, 233 },
- /* idx=7: 00360 - 0036F */
- {234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=8: 00480 - 0048F */
- {0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=9: 00590 - 0059F */
- {0, 220, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 230 },
- /* idx=10: 005A0 - 005AF */
- {230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230 },
- /* idx=11: 005B0 - 005BF */
- {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23 },
- /* idx=12: 005C0 - 005CF */
- {0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=13: 00610 - 0061F */
- {230, 230, 230, 230, 230, 230, 230, 230, 30, 31, 32, 0, 0, 0, 0, 0 },
- /* idx=14: 00640 - 0064F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31 },
- /* idx=15: 00650 - 0065F */
- {32, 33, 34, 230, 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 220 },
- /* idx=16: 00670 - 0067F */
- {35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=17: 006D0 - 006DF */
- {0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230 },
- /* idx=18: 006E0 - 006EF */
- {230, 230, 230, 220, 230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0 },
- /* idx=19: 00710 - 0071F */
- {0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=20: 00730 - 0073F */
- {230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230 },
- /* idx=21: 00740 - 0074F */
- {230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 0, 0 },
- /* idx=22: 007E0 - 007EF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230 },
- /* idx=23: 007F0 - 007FF */
- {230, 230, 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=24: 00810 - 0081F */
- {0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 230, 230, 230, 230, 230 },
- /* idx=25: 00820 - 0082F */
- {230, 230, 230, 230, 0, 230, 230, 230, 0, 230, 230, 230, 230, 230, 0, 0 },
- /* idx=26: 00850 - 0085F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0 },
- /* idx=27: 00930 - 0093F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=28: 00940 - 0094F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=29: 00950 - 0095F */
- {0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=30: 009B0 - 009BF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=31: 009C0 - 009CF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=32: 00A30 - 00A3F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=33: 00A40 - 00A4F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=34: 00AB0 - 00ABF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=35: 00AC0 - 00ACF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=36: 00B30 - 00B3F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=37: 00B40 - 00B4F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=38: 00BC0 - 00BCF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=39: 00C40 - 00C4F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=40: 00C50 - 00C5F */
- {0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=41: 00CB0 - 00CBF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 },
- /* idx=42: 00CC0 - 00CCF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=43: 00D40 - 00D4F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=44: 00DC0 - 00DCF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0 },
- /* idx=45: 00E30 - 00E3F */
- {0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0 },
- /* idx=46: 00E40 - 00E4F */
- {0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 0, 0, 0, 0 },
- /* idx=47: 00EB0 - 00EBF */
- {0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, 0, 0, 0, 0, 0 },
- /* idx=48: 00EC0 - 00ECF */
- {0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0 },
- /* idx=49: 00F10 - 00F1F */
- {0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 0, 0, 0, 0, 0, 0 },
- /* idx=50: 00F30 - 00F3F */
- {0, 0, 0, 0, 0, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0 },
- /* idx=51: 00F70 - 00F7F */
- {0, 129, 130, 0, 132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0 },
- /* idx=52: 00F80 - 00F8F */
- {130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=53: 00FC0 - 00FCF */
- {0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=54: 01030 - 0103F */
- {0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0 },
- /* idx=55: 01080 - 0108F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0 },
- /* idx=56: 01350 - 0135F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230 },
- /* idx=57: 01710 - 0171F */
- {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=58: 01730 - 0173F */
- {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=59: 017D0 - 017DF */
- {0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0 },
- /* idx=60: 018A0 - 018AF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0 },
- /* idx=61: 01930 - 0193F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0 },
- /* idx=62: 01A10 - 01A1F */
- {0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=63: 01A60 - 01A6F */
- {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=64: 01A70 - 01A7F */
- {0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 220 },
- /* idx=65: 01B30 - 01B3F */
- {0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=66: 01B40 - 01B4F */
- {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=67: 01B60 - 01B6F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230 },
- /* idx=68: 01B70 - 01B7F */
- {230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=69: 01BA0 - 01BAF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0 },
- /* idx=70: 01BE0 - 01BEF */
- {0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=71: 01BF0 - 01BFF */
- {0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=72: 01C30 - 01C3F */
- {0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=73: 01CD0 - 01CDF */
- {230, 230, 230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220 },
- /* idx=74: 01CE0 - 01CEF */
- {230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 220, 0, 0 },
- /* idx=75: 01DC0 - 01DCF */
- {230, 230, 220, 230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220 },
- /* idx=76: 01DD0 - 01DDF */
- {202, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=77: 01DE0 - 01DEF */
- {230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=78: 01DF0 - 01DFF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 220, 230, 220 },
- /* idx=79: 020D0 - 020DF */
- {230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, 230, 0, 0, 0 },
- /* idx=80: 020E0 - 020EF */
- {0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, 1, 220, 220, 220, 220 },
- /* idx=81: 020F0 - 020FF */
- {230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=82: 02CE0 - 02CEF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 },
- /* idx=83: 02CF0 - 02CFF */
- {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=84: 02D70 - 02D7F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
- /* idx=85: 02DE0 - 02DEF */
- {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=86: 02DF0 - 02DFF */
- {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=87: 03020 - 0302F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 228, 232, 222, 224, 224 },
- /* idx=88: 03090 - 0309F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0 },
- /* idx=89: 0A660 - 0A66F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 },
- /* idx=90: 0A670 - 0A67F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 0, 0 },
- /* idx=91: 0A6F0 - 0A6FF */
- {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=92: 0A800 - 0A80F */
- {0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=93: 0A8C0 - 0A8CF */
- {0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=94: 0A8E0 - 0A8EF */
- {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230 },
- /* idx=95: 0A8F0 - 0A8FF */
- {230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=96: 0A920 - 0A92F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0 },
- /* idx=97: 0A950 - 0A95F */
- {0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=98: 0A9B0 - 0A9BF */
- {0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=99: 0A9C0 - 0A9CF */
- {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=100: 0AAB0 - 0AABF */
- {230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0, 230, 230 },
- /* idx=101: 0AAC0 - 0AACF */
- {0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=102: 0ABE0 - 0ABEF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0 },
- /* idx=103: 0FB10 - 0FB1F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0 },
- /* idx=104: 0FE20 - 0FE2F */
- {230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=105: 101F0 - 101FF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0 },
- /* idx=106: 10A00 - 10A0F */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 230 },
- /* idx=107: 10A30 - 10A3F */
- {0, 0, 0, 0, 0, 0, 0, 0, 230, 1, 220, 0, 0, 0, 0, 9 },
- /* idx=108: 11040 - 1104F */
- {0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=109: 110B0 - 110BF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0 },
- /* idx=110: 1D160 - 1D16F */
- {0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 0, 0, 0, 226, 216, 216 },
- /* idx=111: 1D170 - 1D17F */
- {216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220 },
- /* idx=112: 1D180 - 1D18F */
- {220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0, 0, 0, 0 },
- /* idx=113: 1D1A0 - 1D1AF */
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0 },
- /* idx=114: 1D240 - 1D24F */
- {0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-/* The index table to ccc_val[*][16] */
-static const unsigned char ccc_val_index[][16] = {
- /* idx=0: XXX00 - XXXFF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=1: 00300 - 003FF */
- { 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=2: 00400 - 004FF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=3: 00500 - 005FF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,10,11,12, 0, 0, 0 },
- /* idx=4: 00600 - 006FF */
- { 0,13, 0, 0,14,15, 0,16, 0, 0, 0, 0, 0,17,18, 0 },
- /* idx=5: 00700 - 007FF */
- { 0,19, 0,20,21, 0, 0, 0, 0, 0, 0, 0, 0, 0,22,23 },
- /* idx=6: 00800 - 008FF */
- { 0,24,25, 0, 0,26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=7: 00900 - 009FF */
- { 0, 0, 0,27,28,29, 0, 0, 0, 0, 0,30,31, 0, 0, 0 },
- /* idx=8: 00A00 - 00AFF */
- { 0, 0, 0,32,33, 0, 0, 0, 0, 0, 0,34,35, 0, 0, 0 },
- /* idx=9: 00B00 - 00BFF */
- { 0, 0, 0,36,37, 0, 0, 0, 0, 0, 0, 0,38, 0, 0, 0 },
- /* idx=10: 00C00 - 00CFF */
- { 0, 0, 0, 0,39,40, 0, 0, 0, 0, 0,41,42, 0, 0, 0 },
- /* idx=11: 00D00 - 00DFF */
- { 0, 0, 0, 0,43, 0, 0, 0, 0, 0, 0, 0,44, 0, 0, 0 },
- /* idx=12: 00E00 - 00EFF */
- { 0, 0, 0,45,46, 0, 0, 0, 0, 0, 0,47,48, 0, 0, 0 },
- /* idx=13: 00F00 - 00FFF */
- { 0,49, 0,50, 0, 0, 0,51,52, 0, 0, 0,53, 0, 0, 0 },
- /* idx=14: 01000 - 010FF */
- { 0, 0, 0,54, 0, 0, 0, 0,55, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=15: 01300 - 013FF */
- { 0, 0, 0, 0, 0,56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=16: 01700 - 017FF */
- { 0,57, 0,58, 0, 0, 0, 0, 0, 0, 0, 0, 0,59, 0, 0 },
- /* idx=17: 01800 - 018FF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,60, 0, 0, 0, 0, 0 },
- /* idx=18: 01900 - 019FF */
- { 0, 0, 0,61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=19: 01A00 - 01AFF */
- { 0,62, 0, 0, 0, 0,63,64, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=20: 01B00 - 01BFF */
- { 0, 0, 0,65,66, 0,67,68, 0, 0,69, 0, 0, 0,70,71 },
- /* idx=21: 01C00 - 01CFF */
- { 0, 0, 0,72, 0, 0, 0, 0, 0, 0, 0, 0, 0,73,74, 0 },
- /* idx=22: 01D00 - 01DFF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,75,76,77,78 },
- /* idx=23: 02000 - 020FF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,79,80,81 },
- /* idx=24: 02C00 - 02CFF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,82,83 },
- /* idx=25: 02D00 - 02DFF */
- { 0, 0, 0, 0, 0, 0, 0,84, 0, 0, 0, 0, 0, 0,85,86 },
- /* idx=26: 03000 - 030FF */
- { 0, 0,87, 0, 0, 0, 0, 0, 0,88, 0, 0, 0, 0, 0, 0 },
- /* idx=27: 0A600 - 0A6FF */
- { 0, 0, 0, 0, 0, 0,89,90, 0, 0, 0, 0, 0, 0, 0,91 },
- /* idx=28: 0A800 - 0A8FF */
- {92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,93, 0,94,95 },
- /* idx=29: 0A900 - 0A9FF */
- { 0, 0,96, 0, 0,97, 0, 0, 0, 0, 0,98,99, 0, 0, 0 },
- /* idx=30: 0AA00 - 0AAFF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,101, 0, 0, 0 },
- /* idx=31: 0AB00 - 0ABFF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0 },
- /* idx=32: 0FB00 - 0FBFF */
- { 0,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=33: 0FE00 - 0FEFF */
- { 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=34: 10100 - 101FF */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105 },
- /* idx=35: 10A00 - 10AFF */
- {106, 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* idx=36: 11000 - 110FF */
- { 0, 0, 0, 0,108, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0 },
- /* idx=37: 1D100 - 1D1FF */
- { 0, 0, 0, 0, 0, 0,110,111,112, 0,113, 0, 0, 0, 0, 0 },
- /* idx=38: 1D200 - 1D2FF */
- { 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-/* The index table to ccc_val_index[*][16] */
-static const unsigned char ccc_index[] = {
-  0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 0, 0,15, 0, 0, 0,16,
- 17,18,19,20,21,22, 0, 0,23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,24,25, 0, 0,
- 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,27, 0,
- 28,29,30,31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,33, 0, 0,34, 0, 0, 0, 0, 0, 0,
-  0, 0,35, 0, 0, 0, 0, 0,36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0,37,38,};
-
-struct unicode_decomposition_table {
-	uint32_t nfc;
-	uint32_t cp1;
-	uint32_t cp2;
-};
-
-static const struct unicode_decomposition_table u_decomposition_table[] = {
-	{ 0x000C0 , 0x00041 , 0x00300 },
-	{ 0x000C1 , 0x00041 , 0x00301 },
-	{ 0x000C2 , 0x00041 , 0x00302 },
-	{ 0x000C3 , 0x00041 , 0x00303 },
-	{ 0x000C4 , 0x00041 , 0x00308 },
-	{ 0x000C5 , 0x00041 , 0x0030A },
-	{ 0x000C7 , 0x00043 , 0x00327 },
-	{ 0x000C8 , 0x00045 , 0x00300 },
-	{ 0x000C9 , 0x00045 , 0x00301 },
-	{ 0x000CA , 0x00045 , 0x00302 },
-	{ 0x000CB , 0x00045 , 0x00308 },
-	{ 0x000CC , 0x00049 , 0x00300 },
-	{ 0x000CD , 0x00049 , 0x00301 },
-	{ 0x000CE , 0x00049 , 0x00302 },
-	{ 0x000CF , 0x00049 , 0x00308 },
-	{ 0x000D1 , 0x0004E , 0x00303 },
-	{ 0x000D2 , 0x0004F , 0x00300 },
-	{ 0x000D3 , 0x0004F , 0x00301 },
-	{ 0x000D4 , 0x0004F , 0x00302 },
-	{ 0x000D5 , 0x0004F , 0x00303 },
-	{ 0x000D6 , 0x0004F , 0x00308 },
-	{ 0x000D9 , 0x00055 , 0x00300 },
-	{ 0x000DA , 0x00055 , 0x00301 },
-	{ 0x000DB , 0x00055 , 0x00302 },
-	{ 0x000DC , 0x00055 , 0x00308 },
-	{ 0x000DD , 0x00059 , 0x00301 },
-	{ 0x000E0 , 0x00061 , 0x00300 },
-	{ 0x000E1 , 0x00061 , 0x00301 },
-	{ 0x000E2 , 0x00061 , 0x00302 },
-	{ 0x000E3 , 0x00061 , 0x00303 },
-	{ 0x000E4 , 0x00061 , 0x00308 },
-	{ 0x000E5 , 0x00061 , 0x0030A },
-	{ 0x000E7 , 0x00063 , 0x00327 },
-	{ 0x000E8 , 0x00065 , 0x00300 },
-	{ 0x000E9 , 0x00065 , 0x00301 },
-	{ 0x000EA , 0x00065 , 0x00302 },
-	{ 0x000EB , 0x00065 , 0x00308 },
-	{ 0x000EC , 0x00069 , 0x00300 },
-	{ 0x000ED , 0x00069 , 0x00301 },
-	{ 0x000EE , 0x00069 , 0x00302 },
-	{ 0x000EF , 0x00069 , 0x00308 },
-	{ 0x000F1 , 0x0006E , 0x00303 },
-	{ 0x000F2 , 0x0006F , 0x00300 },
-	{ 0x000F3 , 0x0006F , 0x00301 },
-	{ 0x000F4 , 0x0006F , 0x00302 },
-	{ 0x000F5 , 0x0006F , 0x00303 },
-	{ 0x000F6 , 0x0006F , 0x00308 },
-	{ 0x000F9 , 0x00075 , 0x00300 },
-	{ 0x000FA , 0x00075 , 0x00301 },
-	{ 0x000FB , 0x00075 , 0x00302 },
-	{ 0x000FC , 0x00075 , 0x00308 },
-	{ 0x000FD , 0x00079 , 0x00301 },
-	{ 0x000FF , 0x00079 , 0x00308 },
-	{ 0x00100 , 0x00041 , 0x00304 },
-	{ 0x00101 , 0x00061 , 0x00304 },
-	{ 0x00102 , 0x00041 , 0x00306 },
-	{ 0x00103 , 0x00061 , 0x00306 },
-	{ 0x00104 , 0x00041 , 0x00328 },
-	{ 0x00105 , 0x00061 , 0x00328 },
-	{ 0x00106 , 0x00043 , 0x00301 },
-	{ 0x00107 , 0x00063 , 0x00301 },
-	{ 0x00108 , 0x00043 , 0x00302 },
-	{ 0x00109 , 0x00063 , 0x00302 },
-	{ 0x0010A , 0x00043 , 0x00307 },
-	{ 0x0010B , 0x00063 , 0x00307 },
-	{ 0x0010C , 0x00043 , 0x0030C },
-	{ 0x0010D , 0x00063 , 0x0030C },
-	{ 0x0010E , 0x00044 , 0x0030C },
-	{ 0x0010F , 0x00064 , 0x0030C },
-	{ 0x00112 , 0x00045 , 0x00304 },
-	{ 0x00113 , 0x00065 , 0x00304 },
-	{ 0x00114 , 0x00045 , 0x00306 },
-	{ 0x00115 , 0x00065 , 0x00306 },
-	{ 0x00116 , 0x00045 , 0x00307 },
-	{ 0x00117 , 0x00065 , 0x00307 },
-	{ 0x00118 , 0x00045 , 0x00328 },
-	{ 0x00119 , 0x00065 , 0x00328 },
-	{ 0x0011A , 0x00045 , 0x0030C },
-	{ 0x0011B , 0x00065 , 0x0030C },
-	{ 0x0011C , 0x00047 , 0x00302 },
-	{ 0x0011D , 0x00067 , 0x00302 },
-	{ 0x0011E , 0x00047 , 0x00306 },
-	{ 0x0011F , 0x00067 , 0x00306 },
-	{ 0x00120 , 0x00047 , 0x00307 },
-	{ 0x00121 , 0x00067 , 0x00307 },
-	{ 0x00122 , 0x00047 , 0x00327 },
-	{ 0x00123 , 0x00067 , 0x00327 },
-	{ 0x00124 , 0x00048 , 0x00302 },
-	{ 0x00125 , 0x00068 , 0x00302 },
-	{ 0x00128 , 0x00049 , 0x00303 },
-	{ 0x00129 , 0x00069 , 0x00303 },
-	{ 0x0012A , 0x00049 , 0x00304 },
-	{ 0x0012B , 0x00069 , 0x00304 },
-	{ 0x0012C , 0x00049 , 0x00306 },
-	{ 0x0012D , 0x00069 , 0x00306 },
-	{ 0x0012E , 0x00049 , 0x00328 },
-	{ 0x0012F , 0x00069 , 0x00328 },
-	{ 0x00130 , 0x00049 , 0x00307 },
-	{ 0x00134 , 0x0004A , 0x00302 },
-	{ 0x00135 , 0x0006A , 0x00302 },
-	{ 0x00136 , 0x0004B , 0x00327 },
-	{ 0x00137 , 0x0006B , 0x00327 },
-	{ 0x00139 , 0x0004C , 0x00301 },
-	{ 0x0013A , 0x0006C , 0x00301 },
-	{ 0x0013B , 0x0004C , 0x00327 },
-	{ 0x0013C , 0x0006C , 0x00327 },
-	{ 0x0013D , 0x0004C , 0x0030C },
-	{ 0x0013E , 0x0006C , 0x0030C },
-	{ 0x00143 , 0x0004E , 0x00301 },
-	{ 0x00144 , 0x0006E , 0x00301 },
-	{ 0x00145 , 0x0004E , 0x00327 },
-	{ 0x00146 , 0x0006E , 0x00327 },
-	{ 0x00147 , 0x0004E , 0x0030C },
-	{ 0x00148 , 0x0006E , 0x0030C },
-	{ 0x0014C , 0x0004F , 0x00304 },
-	{ 0x0014D , 0x0006F , 0x00304 },
-	{ 0x0014E , 0x0004F , 0x00306 },
-	{ 0x0014F , 0x0006F , 0x00306 },
-	{ 0x00150 , 0x0004F , 0x0030B },
-	{ 0x00151 , 0x0006F , 0x0030B },
-	{ 0x00154 , 0x00052 , 0x00301 },
-	{ 0x00155 , 0x00072 , 0x00301 },
-	{ 0x00156 , 0x00052 , 0x00327 },
-	{ 0x00157 , 0x00072 , 0x00327 },
-	{ 0x00158 , 0x00052 , 0x0030C },
-	{ 0x00159 , 0x00072 , 0x0030C },
-	{ 0x0015A , 0x00053 , 0x00301 },
-	{ 0x0015B , 0x00073 , 0x00301 },
-	{ 0x0015C , 0x00053 , 0x00302 },
-	{ 0x0015D , 0x00073 , 0x00302 },
-	{ 0x0015E , 0x00053 , 0x00327 },
-	{ 0x0015F , 0x00073 , 0x00327 },
-	{ 0x00160 , 0x00053 , 0x0030C },
-	{ 0x00161 , 0x00073 , 0x0030C },
-	{ 0x00162 , 0x00054 , 0x00327 },
-	{ 0x00163 , 0x00074 , 0x00327 },
-	{ 0x00164 , 0x00054 , 0x0030C },
-	{ 0x00165 , 0x00074 , 0x0030C },
-	{ 0x00168 , 0x00055 , 0x00303 },
-	{ 0x00169 , 0x00075 , 0x00303 },
-	{ 0x0016A , 0x00055 , 0x00304 },
-	{ 0x0016B , 0x00075 , 0x00304 },
-	{ 0x0016C , 0x00055 , 0x00306 },
-	{ 0x0016D , 0x00075 , 0x00306 },
-	{ 0x0016E , 0x00055 , 0x0030A },
-	{ 0x0016F , 0x00075 , 0x0030A },
-	{ 0x00170 , 0x00055 , 0x0030B },
-	{ 0x00171 , 0x00075 , 0x0030B },
-	{ 0x00172 , 0x00055 , 0x00328 },
-	{ 0x00173 , 0x00075 , 0x00328 },
-	{ 0x00174 , 0x00057 , 0x00302 },
-	{ 0x00175 , 0x00077 , 0x00302 },
-	{ 0x00176 , 0x00059 , 0x00302 },
-	{ 0x00177 , 0x00079 , 0x00302 },
-	{ 0x00178 , 0x00059 , 0x00308 },
-	{ 0x00179 , 0x0005A , 0x00301 },
-	{ 0x0017A , 0x0007A , 0x00301 },
-	{ 0x0017B , 0x0005A , 0x00307 },
-	{ 0x0017C , 0x0007A , 0x00307 },
-	{ 0x0017D , 0x0005A , 0x0030C },
-	{ 0x0017E , 0x0007A , 0x0030C },
-	{ 0x001A0 , 0x0004F , 0x0031B },
-	{ 0x001A1 , 0x0006F , 0x0031B },
-	{ 0x001AF , 0x00055 , 0x0031B },
-	{ 0x001B0 , 0x00075 , 0x0031B },
-	{ 0x001CD , 0x00041 , 0x0030C },
-	{ 0x001CE , 0x00061 , 0x0030C },
-	{ 0x001CF , 0x00049 , 0x0030C },
-	{ 0x001D0 , 0x00069 , 0x0030C },
-	{ 0x001D1 , 0x0004F , 0x0030C },
-	{ 0x001D2 , 0x0006F , 0x0030C },
-	{ 0x001D3 , 0x00055 , 0x0030C },
-	{ 0x001D4 , 0x00075 , 0x0030C },
-	{ 0x001D5 , 0x000DC , 0x00304 },
-	{ 0x001D6 , 0x000FC , 0x00304 },
-	{ 0x001D7 , 0x000DC , 0x00301 },
-	{ 0x001D8 , 0x000FC , 0x00301 },
-	{ 0x001D9 , 0x000DC , 0x0030C },
-	{ 0x001DA , 0x000FC , 0x0030C },
-	{ 0x001DB , 0x000DC , 0x00300 },
-	{ 0x001DC , 0x000FC , 0x00300 },
-	{ 0x001DE , 0x000C4 , 0x00304 },
-	{ 0x001DF , 0x000E4 , 0x00304 },
-	{ 0x001E0 , 0x00226 , 0x00304 },
-	{ 0x001E1 , 0x00227 , 0x00304 },
-	{ 0x001E2 , 0x000C6 , 0x00304 },
-	{ 0x001E3 , 0x000E6 , 0x00304 },
-	{ 0x001E6 , 0x00047 , 0x0030C },
-	{ 0x001E7 , 0x00067 , 0x0030C },
-	{ 0x001E8 , 0x0004B , 0x0030C },
-	{ 0x001E9 , 0x0006B , 0x0030C },
-	{ 0x001EA , 0x0004F , 0x00328 },
-	{ 0x001EB , 0x0006F , 0x00328 },
-	{ 0x001EC , 0x001EA , 0x00304 },
-	{ 0x001ED , 0x001EB , 0x00304 },
-	{ 0x001EE , 0x001B7 , 0x0030C },
-	{ 0x001EF , 0x00292 , 0x0030C },
-	{ 0x001F0 , 0x0006A , 0x0030C },
-	{ 0x001F4 , 0x00047 , 0x00301 },
-	{ 0x001F5 , 0x00067 , 0x00301 },
-	{ 0x001F8 , 0x0004E , 0x00300 },
-	{ 0x001F9 , 0x0006E , 0x00300 },
-	{ 0x001FA , 0x000C5 , 0x00301 },
-	{ 0x001FB , 0x000E5 , 0x00301 },
-	{ 0x001FC , 0x000C6 , 0x00301 },
-	{ 0x001FD , 0x000E6 , 0x00301 },
-	{ 0x001FE , 0x000D8 , 0x00301 },
-	{ 0x001FF , 0x000F8 , 0x00301 },
-	{ 0x00200 , 0x00041 , 0x0030F },
-	{ 0x00201 , 0x00061 , 0x0030F },
-	{ 0x00202 , 0x00041 , 0x00311 },
-	{ 0x00203 , 0x00061 , 0x00311 },
-	{ 0x00204 , 0x00045 , 0x0030F },
-	{ 0x00205 , 0x00065 , 0x0030F },
-	{ 0x00206 , 0x00045 , 0x00311 },
-	{ 0x00207 , 0x00065 , 0x00311 },
-	{ 0x00208 , 0x00049 , 0x0030F },
-	{ 0x00209 , 0x00069 , 0x0030F },
-	{ 0x0020A , 0x00049 , 0x00311 },
-	{ 0x0020B , 0x00069 , 0x00311 },
-	{ 0x0020C , 0x0004F , 0x0030F },
-	{ 0x0020D , 0x0006F , 0x0030F },
-	{ 0x0020E , 0x0004F , 0x00311 },
-	{ 0x0020F , 0x0006F , 0x00311 },
-	{ 0x00210 , 0x00052 , 0x0030F },
-	{ 0x00211 , 0x00072 , 0x0030F },
-	{ 0x00212 , 0x00052 , 0x00311 },
-	{ 0x00213 , 0x00072 , 0x00311 },
-	{ 0x00214 , 0x00055 , 0x0030F },
-	{ 0x00215 , 0x00075 , 0x0030F },
-	{ 0x00216 , 0x00055 , 0x00311 },
-	{ 0x00217 , 0x00075 , 0x00311 },
-	{ 0x00218 , 0x00053 , 0x00326 },
-	{ 0x00219 , 0x00073 , 0x00326 },
-	{ 0x0021A , 0x00054 , 0x00326 },
-	{ 0x0021B , 0x00074 , 0x00326 },
-	{ 0x0021E , 0x00048 , 0x0030C },
-	{ 0x0021F , 0x00068 , 0x0030C },
-	{ 0x00226 , 0x00041 , 0x00307 },
-	{ 0x00227 , 0x00061 , 0x00307 },
-	{ 0x00228 , 0x00045 , 0x00327 },
-	{ 0x00229 , 0x00065 , 0x00327 },
-	{ 0x0022A , 0x000D6 , 0x00304 },
-	{ 0x0022B , 0x000F6 , 0x00304 },
-	{ 0x0022C , 0x000D5 , 0x00304 },
-	{ 0x0022D , 0x000F5 , 0x00304 },
-	{ 0x0022E , 0x0004F , 0x00307 },
-	{ 0x0022F , 0x0006F , 0x00307 },
-	{ 0x00230 , 0x0022E , 0x00304 },
-	{ 0x00231 , 0x0022F , 0x00304 },
-	{ 0x00232 , 0x00059 , 0x00304 },
-	{ 0x00233 , 0x00079 , 0x00304 },
-	{ 0x00385 , 0x000A8 , 0x00301 },
-	{ 0x00386 , 0x00391 , 0x00301 },
-	{ 0x00388 , 0x00395 , 0x00301 },
-	{ 0x00389 , 0x00397 , 0x00301 },
-	{ 0x0038A , 0x00399 , 0x00301 },
-	{ 0x0038C , 0x0039F , 0x00301 },
-	{ 0x0038E , 0x003A5 , 0x00301 },
-	{ 0x0038F , 0x003A9 , 0x00301 },
-	{ 0x00390 , 0x003CA , 0x00301 },
-	{ 0x003AA , 0x00399 , 0x00308 },
-	{ 0x003AB , 0x003A5 , 0x00308 },
-	{ 0x003AC , 0x003B1 , 0x00301 },
-	{ 0x003AD , 0x003B5 , 0x00301 },
-	{ 0x003AE , 0x003B7 , 0x00301 },
-	{ 0x003AF , 0x003B9 , 0x00301 },
-	{ 0x003B0 , 0x003CB , 0x00301 },
-	{ 0x003CA , 0x003B9 , 0x00308 },
-	{ 0x003CB , 0x003C5 , 0x00308 },
-	{ 0x003CC , 0x003BF , 0x00301 },
-	{ 0x003CD , 0x003C5 , 0x00301 },
-	{ 0x003CE , 0x003C9 , 0x00301 },
-	{ 0x003D3 , 0x003D2 , 0x00301 },
-	{ 0x003D4 , 0x003D2 , 0x00308 },
-	{ 0x00400 , 0x00415 , 0x00300 },
-	{ 0x00401 , 0x00415 , 0x00308 },
-	{ 0x00403 , 0x00413 , 0x00301 },
-	{ 0x00407 , 0x00406 , 0x00308 },
-	{ 0x0040C , 0x0041A , 0x00301 },
-	{ 0x0040D , 0x00418 , 0x00300 },
-	{ 0x0040E , 0x00423 , 0x00306 },
-	{ 0x00419 , 0x00418 , 0x00306 },
-	{ 0x00439 , 0x00438 , 0x00306 },
-	{ 0x00450 , 0x00435 , 0x00300 },
-	{ 0x00451 , 0x00435 , 0x00308 },
-	{ 0x00453 , 0x00433 , 0x00301 },
-	{ 0x00457 , 0x00456 , 0x00308 },
-	{ 0x0045C , 0x0043A , 0x00301 },
-	{ 0x0045D , 0x00438 , 0x00300 },
-	{ 0x0045E , 0x00443 , 0x00306 },
-	{ 0x00476 , 0x00474 , 0x0030F },
-	{ 0x00477 , 0x00475 , 0x0030F },
-	{ 0x004C1 , 0x00416 , 0x00306 },
-	{ 0x004C2 , 0x00436 , 0x00306 },
-	{ 0x004D0 , 0x00410 , 0x00306 },
-	{ 0x004D1 , 0x00430 , 0x00306 },
-	{ 0x004D2 , 0x00410 , 0x00308 },
-	{ 0x004D3 , 0x00430 , 0x00308 },
-	{ 0x004D6 , 0x00415 , 0x00306 },
-	{ 0x004D7 , 0x00435 , 0x00306 },
-	{ 0x004DA , 0x004D8 , 0x00308 },
-	{ 0x004DB , 0x004D9 , 0x00308 },
-	{ 0x004DC , 0x00416 , 0x00308 },
-	{ 0x004DD , 0x00436 , 0x00308 },
-	{ 0x004DE , 0x00417 , 0x00308 },
-	{ 0x004DF , 0x00437 , 0x00308 },
-	{ 0x004E2 , 0x00418 , 0x00304 },
-	{ 0x004E3 , 0x00438 , 0x00304 },
-	{ 0x004E4 , 0x00418 , 0x00308 },
-	{ 0x004E5 , 0x00438 , 0x00308 },
-	{ 0x004E6 , 0x0041E , 0x00308 },
-	{ 0x004E7 , 0x0043E , 0x00308 },
-	{ 0x004EA , 0x004E8 , 0x00308 },
-	{ 0x004EB , 0x004E9 , 0x00308 },
-	{ 0x004EC , 0x0042D , 0x00308 },
-	{ 0x004ED , 0x0044D , 0x00308 },
-	{ 0x004EE , 0x00423 , 0x00304 },
-	{ 0x004EF , 0x00443 , 0x00304 },
-	{ 0x004F0 , 0x00423 , 0x00308 },
-	{ 0x004F1 , 0x00443 , 0x00308 },
-	{ 0x004F2 , 0x00423 , 0x0030B },
-	{ 0x004F3 , 0x00443 , 0x0030B },
-	{ 0x004F4 , 0x00427 , 0x00308 },
-	{ 0x004F5 , 0x00447 , 0x00308 },
-	{ 0x004F8 , 0x0042B , 0x00308 },
-	{ 0x004F9 , 0x0044B , 0x00308 },
-	{ 0x00622 , 0x00627 , 0x00653 },
-	{ 0x00623 , 0x00627 , 0x00654 },
-	{ 0x00624 , 0x00648 , 0x00654 },
-	{ 0x00625 , 0x00627 , 0x00655 },
-	{ 0x00626 , 0x0064A , 0x00654 },
-	{ 0x006C0 , 0x006D5 , 0x00654 },
-	{ 0x006C2 , 0x006C1 , 0x00654 },
-	{ 0x006D3 , 0x006D2 , 0x00654 },
-	{ 0x00929 , 0x00928 , 0x0093C },
-	{ 0x00931 , 0x00930 , 0x0093C },
-	{ 0x00934 , 0x00933 , 0x0093C },
-	{ 0x009CB , 0x009C7 , 0x009BE },
-	{ 0x009CC , 0x009C7 , 0x009D7 },
-	{ 0x00B48 , 0x00B47 , 0x00B56 },
-	{ 0x00B4B , 0x00B47 , 0x00B3E },
-	{ 0x00B4C , 0x00B47 , 0x00B57 },
-	{ 0x00B94 , 0x00B92 , 0x00BD7 },
-	{ 0x00BCA , 0x00BC6 , 0x00BBE },
-	{ 0x00BCB , 0x00BC7 , 0x00BBE },
-	{ 0x00BCC , 0x00BC6 , 0x00BD7 },
-	{ 0x00C48 , 0x00C46 , 0x00C56 },
-	{ 0x00CC0 , 0x00CBF , 0x00CD5 },
-	{ 0x00CC7 , 0x00CC6 , 0x00CD5 },
-	{ 0x00CC8 , 0x00CC6 , 0x00CD6 },
-	{ 0x00CCA , 0x00CC6 , 0x00CC2 },
-	{ 0x00CCB , 0x00CCA , 0x00CD5 },
-	{ 0x00D4A , 0x00D46 , 0x00D3E },
-	{ 0x00D4B , 0x00D47 , 0x00D3E },
-	{ 0x00D4C , 0x00D46 , 0x00D57 },
-	{ 0x00DDA , 0x00DD9 , 0x00DCA },
-	{ 0x00DDC , 0x00DD9 , 0x00DCF },
-	{ 0x00DDD , 0x00DDC , 0x00DCA },
-	{ 0x00DDE , 0x00DD9 , 0x00DDF },
-	{ 0x01026 , 0x01025 , 0x0102E },
-	{ 0x01B06 , 0x01B05 , 0x01B35 },
-	{ 0x01B08 , 0x01B07 , 0x01B35 },
-	{ 0x01B0A , 0x01B09 , 0x01B35 },
-	{ 0x01B0C , 0x01B0B , 0x01B35 },
-	{ 0x01B0E , 0x01B0D , 0x01B35 },
-	{ 0x01B12 , 0x01B11 , 0x01B35 },
-	{ 0x01B3B , 0x01B3A , 0x01B35 },
-	{ 0x01B3D , 0x01B3C , 0x01B35 },
-	{ 0x01B40 , 0x01B3E , 0x01B35 },
-	{ 0x01B41 , 0x01B3F , 0x01B35 },
-	{ 0x01B43 , 0x01B42 , 0x01B35 },
-	{ 0x01E00 , 0x00041 , 0x00325 },
-	{ 0x01E01 , 0x00061 , 0x00325 },
-	{ 0x01E02 , 0x00042 , 0x00307 },
-	{ 0x01E03 , 0x00062 , 0x00307 },
-	{ 0x01E04 , 0x00042 , 0x00323 },
-	{ 0x01E05 , 0x00062 , 0x00323 },
-	{ 0x01E06 , 0x00042 , 0x00331 },
-	{ 0x01E07 , 0x00062 , 0x00331 },
-	{ 0x01E08 , 0x000C7 , 0x00301 },
-	{ 0x01E09 , 0x000E7 , 0x00301 },
-	{ 0x01E0A , 0x00044 , 0x00307 },
-	{ 0x01E0B , 0x00064 , 0x00307 },
-	{ 0x01E0C , 0x00044 , 0x00323 },
-	{ 0x01E0D , 0x00064 , 0x00323 },
-	{ 0x01E0E , 0x00044 , 0x00331 },
-	{ 0x01E0F , 0x00064 , 0x00331 },
-	{ 0x01E10 , 0x00044 , 0x00327 },
-	{ 0x01E11 , 0x00064 , 0x00327 },
-	{ 0x01E12 , 0x00044 , 0x0032D },
-	{ 0x01E13 , 0x00064 , 0x0032D },
-	{ 0x01E14 , 0x00112 , 0x00300 },
-	{ 0x01E15 , 0x00113 , 0x00300 },
-	{ 0x01E16 , 0x00112 , 0x00301 },
-	{ 0x01E17 , 0x00113 , 0x00301 },
-	{ 0x01E18 , 0x00045 , 0x0032D },
-	{ 0x01E19 , 0x00065 , 0x0032D },
-	{ 0x01E1A , 0x00045 , 0x00330 },
-	{ 0x01E1B , 0x00065 , 0x00330 },
-	{ 0x01E1C , 0x00228 , 0x00306 },
-	{ 0x01E1D , 0x00229 , 0x00306 },
-	{ 0x01E1E , 0x00046 , 0x00307 },
-	{ 0x01E1F , 0x00066 , 0x00307 },
-	{ 0x01E20 , 0x00047 , 0x00304 },
-	{ 0x01E21 , 0x00067 , 0x00304 },
-	{ 0x01E22 , 0x00048 , 0x00307 },
-	{ 0x01E23 , 0x00068 , 0x00307 },
-	{ 0x01E24 , 0x00048 , 0x00323 },
-	{ 0x01E25 , 0x00068 , 0x00323 },
-	{ 0x01E26 , 0x00048 , 0x00308 },
-	{ 0x01E27 , 0x00068 , 0x00308 },
-	{ 0x01E28 , 0x00048 , 0x00327 },
-	{ 0x01E29 , 0x00068 , 0x00327 },
-	{ 0x01E2A , 0x00048 , 0x0032E },
-	{ 0x01E2B , 0x00068 , 0x0032E },
-	{ 0x01E2C , 0x00049 , 0x00330 },
-	{ 0x01E2D , 0x00069 , 0x00330 },
-	{ 0x01E2E , 0x000CF , 0x00301 },
-	{ 0x01E2F , 0x000EF , 0x00301 },
-	{ 0x01E30 , 0x0004B , 0x00301 },
-	{ 0x01E31 , 0x0006B , 0x00301 },
-	{ 0x01E32 , 0x0004B , 0x00323 },
-	{ 0x01E33 , 0x0006B , 0x00323 },
-	{ 0x01E34 , 0x0004B , 0x00331 },
-	{ 0x01E35 , 0x0006B , 0x00331 },
-	{ 0x01E36 , 0x0004C , 0x00323 },
-	{ 0x01E37 , 0x0006C , 0x00323 },
-	{ 0x01E38 , 0x01E36 , 0x00304 },
-	{ 0x01E39 , 0x01E37 , 0x00304 },
-	{ 0x01E3A , 0x0004C , 0x00331 },
-	{ 0x01E3B , 0x0006C , 0x00331 },
-	{ 0x01E3C , 0x0004C , 0x0032D },
-	{ 0x01E3D , 0x0006C , 0x0032D },
-	{ 0x01E3E , 0x0004D , 0x00301 },
-	{ 0x01E3F , 0x0006D , 0x00301 },
-	{ 0x01E40 , 0x0004D , 0x00307 },
-	{ 0x01E41 , 0x0006D , 0x00307 },
-	{ 0x01E42 , 0x0004D , 0x00323 },
-	{ 0x01E43 , 0x0006D , 0x00323 },
-	{ 0x01E44 , 0x0004E , 0x00307 },
-	{ 0x01E45 , 0x0006E , 0x00307 },
-	{ 0x01E46 , 0x0004E , 0x00323 },
-	{ 0x01E47 , 0x0006E , 0x00323 },
-	{ 0x01E48 , 0x0004E , 0x00331 },
-	{ 0x01E49 , 0x0006E , 0x00331 },
-	{ 0x01E4A , 0x0004E , 0x0032D },
-	{ 0x01E4B , 0x0006E , 0x0032D },
-	{ 0x01E4C , 0x000D5 , 0x00301 },
-	{ 0x01E4D , 0x000F5 , 0x00301 },
-	{ 0x01E4E , 0x000D5 , 0x00308 },
-	{ 0x01E4F , 0x000F5 , 0x00308 },
-	{ 0x01E50 , 0x0014C , 0x00300 },
-	{ 0x01E51 , 0x0014D , 0x00300 },
-	{ 0x01E52 , 0x0014C , 0x00301 },
-	{ 0x01E53 , 0x0014D , 0x00301 },
-	{ 0x01E54 , 0x00050 , 0x00301 },
-	{ 0x01E55 , 0x00070 , 0x00301 },
-	{ 0x01E56 , 0x00050 , 0x00307 },
-	{ 0x01E57 , 0x00070 , 0x00307 },
-	{ 0x01E58 , 0x00052 , 0x00307 },
-	{ 0x01E59 , 0x00072 , 0x00307 },
-	{ 0x01E5A , 0x00052 , 0x00323 },
-	{ 0x01E5B , 0x00072 , 0x00323 },
-	{ 0x01E5C , 0x01E5A , 0x00304 },
-	{ 0x01E5D , 0x01E5B , 0x00304 },
-	{ 0x01E5E , 0x00052 , 0x00331 },
-	{ 0x01E5F , 0x00072 , 0x00331 },
-	{ 0x01E60 , 0x00053 , 0x00307 },
-	{ 0x01E61 , 0x00073 , 0x00307 },
-	{ 0x01E62 , 0x00053 , 0x00323 },
-	{ 0x01E63 , 0x00073 , 0x00323 },
-	{ 0x01E64 , 0x0015A , 0x00307 },
-	{ 0x01E65 , 0x0015B , 0x00307 },
-	{ 0x01E66 , 0x00160 , 0x00307 },
-	{ 0x01E67 , 0x00161 , 0x00307 },
-	{ 0x01E68 , 0x01E62 , 0x00307 },
-	{ 0x01E69 , 0x01E63 , 0x00307 },
-	{ 0x01E6A , 0x00054 , 0x00307 },
-	{ 0x01E6B , 0x00074 , 0x00307 },
-	{ 0x01E6C , 0x00054 , 0x00323 },
-	{ 0x01E6D , 0x00074 , 0x00323 },
-	{ 0x01E6E , 0x00054 , 0x00331 },
-	{ 0x01E6F , 0x00074 , 0x00331 },
-	{ 0x01E70 , 0x00054 , 0x0032D },
-	{ 0x01E71 , 0x00074 , 0x0032D },
-	{ 0x01E72 , 0x00055 , 0x00324 },
-	{ 0x01E73 , 0x00075 , 0x00324 },
-	{ 0x01E74 , 0x00055 , 0x00330 },
-	{ 0x01E75 , 0x00075 , 0x00330 },
-	{ 0x01E76 , 0x00055 , 0x0032D },
-	{ 0x01E77 , 0x00075 , 0x0032D },
-	{ 0x01E78 , 0x00168 , 0x00301 },
-	{ 0x01E79 , 0x00169 , 0x00301 },
-	{ 0x01E7A , 0x0016A , 0x00308 },
-	{ 0x01E7B , 0x0016B , 0x00308 },
-	{ 0x01E7C , 0x00056 , 0x00303 },
-	{ 0x01E7D , 0x00076 , 0x00303 },
-	{ 0x01E7E , 0x00056 , 0x00323 },
-	{ 0x01E7F , 0x00076 , 0x00323 },
-	{ 0x01E80 , 0x00057 , 0x00300 },
-	{ 0x01E81 , 0x00077 , 0x00300 },
-	{ 0x01E82 , 0x00057 , 0x00301 },
-	{ 0x01E83 , 0x00077 , 0x00301 },
-	{ 0x01E84 , 0x00057 , 0x00308 },
-	{ 0x01E85 , 0x00077 , 0x00308 },
-	{ 0x01E86 , 0x00057 , 0x00307 },
-	{ 0x01E87 , 0x00077 , 0x00307 },
-	{ 0x01E88 , 0x00057 , 0x00323 },
-	{ 0x01E89 , 0x00077 , 0x00323 },
-	{ 0x01E8A , 0x00058 , 0x00307 },
-	{ 0x01E8B , 0x00078 , 0x00307 },
-	{ 0x01E8C , 0x00058 , 0x00308 },
-	{ 0x01E8D , 0x00078 , 0x00308 },
-	{ 0x01E8E , 0x00059 , 0x00307 },
-	{ 0x01E8F , 0x00079 , 0x00307 },
-	{ 0x01E90 , 0x0005A , 0x00302 },
-	{ 0x01E91 , 0x0007A , 0x00302 },
-	{ 0x01E92 , 0x0005A , 0x00323 },
-	{ 0x01E93 , 0x0007A , 0x00323 },
-	{ 0x01E94 , 0x0005A , 0x00331 },
-	{ 0x01E95 , 0x0007A , 0x00331 },
-	{ 0x01E96 , 0x00068 , 0x00331 },
-	{ 0x01E97 , 0x00074 , 0x00308 },
-	{ 0x01E98 , 0x00077 , 0x0030A },
-	{ 0x01E99 , 0x00079 , 0x0030A },
-	{ 0x01E9B , 0x0017F , 0x00307 },
-	{ 0x01EA0 , 0x00041 , 0x00323 },
-	{ 0x01EA1 , 0x00061 , 0x00323 },
-	{ 0x01EA2 , 0x00041 , 0x00309 },
-	{ 0x01EA3 , 0x00061 , 0x00309 },
-	{ 0x01EA4 , 0x000C2 , 0x00301 },
-	{ 0x01EA5 , 0x000E2 , 0x00301 },
-	{ 0x01EA6 , 0x000C2 , 0x00300 },
-	{ 0x01EA7 , 0x000E2 , 0x00300 },
-	{ 0x01EA8 , 0x000C2 , 0x00309 },
-	{ 0x01EA9 , 0x000E2 , 0x00309 },
-	{ 0x01EAA , 0x000C2 , 0x00303 },
-	{ 0x01EAB , 0x000E2 , 0x00303 },
-	{ 0x01EAC , 0x01EA0 , 0x00302 },
-	{ 0x01EAD , 0x01EA1 , 0x00302 },
-	{ 0x01EAE , 0x00102 , 0x00301 },
-	{ 0x01EAF , 0x00103 , 0x00301 },
-	{ 0x01EB0 , 0x00102 , 0x00300 },
-	{ 0x01EB1 , 0x00103 , 0x00300 },
-	{ 0x01EB2 , 0x00102 , 0x00309 },
-	{ 0x01EB3 , 0x00103 , 0x00309 },
-	{ 0x01EB4 , 0x00102 , 0x00303 },
-	{ 0x01EB5 , 0x00103 , 0x00303 },
-	{ 0x01EB6 , 0x01EA0 , 0x00306 },
-	{ 0x01EB7 , 0x01EA1 , 0x00306 },
-	{ 0x01EB8 , 0x00045 , 0x00323 },
-	{ 0x01EB9 , 0x00065 , 0x00323 },
-	{ 0x01EBA , 0x00045 , 0x00309 },
-	{ 0x01EBB , 0x00065 , 0x00309 },
-	{ 0x01EBC , 0x00045 , 0x00303 },
-	{ 0x01EBD , 0x00065 , 0x00303 },
-	{ 0x01EBE , 0x000CA , 0x00301 },
-	{ 0x01EBF , 0x000EA , 0x00301 },
-	{ 0x01EC0 , 0x000CA , 0x00300 },
-	{ 0x01EC1 , 0x000EA , 0x00300 },
-	{ 0x01EC2 , 0x000CA , 0x00309 },
-	{ 0x01EC3 , 0x000EA , 0x00309 },
-	{ 0x01EC4 , 0x000CA , 0x00303 },
-	{ 0x01EC5 , 0x000EA , 0x00303 },
-	{ 0x01EC6 , 0x01EB8 , 0x00302 },
-	{ 0x01EC7 , 0x01EB9 , 0x00302 },
-	{ 0x01EC8 , 0x00049 , 0x00309 },
-	{ 0x01EC9 , 0x00069 , 0x00309 },
-	{ 0x01ECA , 0x00049 , 0x00323 },
-	{ 0x01ECB , 0x00069 , 0x00323 },
-	{ 0x01ECC , 0x0004F , 0x00323 },
-	{ 0x01ECD , 0x0006F , 0x00323 },
-	{ 0x01ECE , 0x0004F , 0x00309 },
-	{ 0x01ECF , 0x0006F , 0x00309 },
-	{ 0x01ED0 , 0x000D4 , 0x00301 },
-	{ 0x01ED1 , 0x000F4 , 0x00301 },
-	{ 0x01ED2 , 0x000D4 , 0x00300 },
-	{ 0x01ED3 , 0x000F4 , 0x00300 },
-	{ 0x01ED4 , 0x000D4 , 0x00309 },
-	{ 0x01ED5 , 0x000F4 , 0x00309 },
-	{ 0x01ED6 , 0x000D4 , 0x00303 },
-	{ 0x01ED7 , 0x000F4 , 0x00303 },
-	{ 0x01ED8 , 0x01ECC , 0x00302 },
-	{ 0x01ED9 , 0x01ECD , 0x00302 },
-	{ 0x01EDA , 0x001A0 , 0x00301 },
-	{ 0x01EDB , 0x001A1 , 0x00301 },
-	{ 0x01EDC , 0x001A0 , 0x00300 },
-	{ 0x01EDD , 0x001A1 , 0x00300 },
-	{ 0x01EDE , 0x001A0 , 0x00309 },
-	{ 0x01EDF , 0x001A1 , 0x00309 },
-	{ 0x01EE0 , 0x001A0 , 0x00303 },
-	{ 0x01EE1 , 0x001A1 , 0x00303 },
-	{ 0x01EE2 , 0x001A0 , 0x00323 },
-	{ 0x01EE3 , 0x001A1 , 0x00323 },
-	{ 0x01EE4 , 0x00055 , 0x00323 },
-	{ 0x01EE5 , 0x00075 , 0x00323 },
-	{ 0x01EE6 , 0x00055 , 0x00309 },
-	{ 0x01EE7 , 0x00075 , 0x00309 },
-	{ 0x01EE8 , 0x001AF , 0x00301 },
-	{ 0x01EE9 , 0x001B0 , 0x00301 },
-	{ 0x01EEA , 0x001AF , 0x00300 },
-	{ 0x01EEB , 0x001B0 , 0x00300 },
-	{ 0x01EEC , 0x001AF , 0x00309 },
-	{ 0x01EED , 0x001B0 , 0x00309 },
-	{ 0x01EEE , 0x001AF , 0x00303 },
-	{ 0x01EEF , 0x001B0 , 0x00303 },
-	{ 0x01EF0 , 0x001AF , 0x00323 },
-	{ 0x01EF1 , 0x001B0 , 0x00323 },
-	{ 0x01EF2 , 0x00059 , 0x00300 },
-	{ 0x01EF3 , 0x00079 , 0x00300 },
-	{ 0x01EF4 , 0x00059 , 0x00323 },
-	{ 0x01EF5 , 0x00079 , 0x00323 },
-	{ 0x01EF6 , 0x00059 , 0x00309 },
-	{ 0x01EF7 , 0x00079 , 0x00309 },
-	{ 0x01EF8 , 0x00059 , 0x00303 },
-	{ 0x01EF9 , 0x00079 , 0x00303 },
-	{ 0x01F00 , 0x003B1 , 0x00313 },
-	{ 0x01F01 , 0x003B1 , 0x00314 },
-	{ 0x01F02 , 0x01F00 , 0x00300 },
-	{ 0x01F03 , 0x01F01 , 0x00300 },
-	{ 0x01F04 , 0x01F00 , 0x00301 },
-	{ 0x01F05 , 0x01F01 , 0x00301 },
-	{ 0x01F06 , 0x01F00 , 0x00342 },
-	{ 0x01F07 , 0x01F01 , 0x00342 },
-	{ 0x01F08 , 0x00391 , 0x00313 },
-	{ 0x01F09 , 0x00391 , 0x00314 },
-	{ 0x01F0A , 0x01F08 , 0x00300 },
-	{ 0x01F0B , 0x01F09 , 0x00300 },
-	{ 0x01F0C , 0x01F08 , 0x00301 },
-	{ 0x01F0D , 0x01F09 , 0x00301 },
-	{ 0x01F0E , 0x01F08 , 0x00342 },
-	{ 0x01F0F , 0x01F09 , 0x00342 },
-	{ 0x01F10 , 0x003B5 , 0x00313 },
-	{ 0x01F11 , 0x003B5 , 0x00314 },
-	{ 0x01F12 , 0x01F10 , 0x00300 },
-	{ 0x01F13 , 0x01F11 , 0x00300 },
-	{ 0x01F14 , 0x01F10 , 0x00301 },
-	{ 0x01F15 , 0x01F11 , 0x00301 },
-	{ 0x01F18 , 0x00395 , 0x00313 },
-	{ 0x01F19 , 0x00395 , 0x00314 },
-	{ 0x01F1A , 0x01F18 , 0x00300 },
-	{ 0x01F1B , 0x01F19 , 0x00300 },
-	{ 0x01F1C , 0x01F18 , 0x00301 },
-	{ 0x01F1D , 0x01F19 , 0x00301 },
-	{ 0x01F20 , 0x003B7 , 0x00313 },
-	{ 0x01F21 , 0x003B7 , 0x00314 },
-	{ 0x01F22 , 0x01F20 , 0x00300 },
-	{ 0x01F23 , 0x01F21 , 0x00300 },
-	{ 0x01F24 , 0x01F20 , 0x00301 },
-	{ 0x01F25 , 0x01F21 , 0x00301 },
-	{ 0x01F26 , 0x01F20 , 0x00342 },
-	{ 0x01F27 , 0x01F21 , 0x00342 },
-	{ 0x01F28 , 0x00397 , 0x00313 },
-	{ 0x01F29 , 0x00397 , 0x00314 },
-	{ 0x01F2A , 0x01F28 , 0x00300 },
-	{ 0x01F2B , 0x01F29 , 0x00300 },
-	{ 0x01F2C , 0x01F28 , 0x00301 },
-	{ 0x01F2D , 0x01F29 , 0x00301 },
-	{ 0x01F2E , 0x01F28 , 0x00342 },
-	{ 0x01F2F , 0x01F29 , 0x00342 },
-	{ 0x01F30 , 0x003B9 , 0x00313 },
-	{ 0x01F31 , 0x003B9 , 0x00314 },
-	{ 0x01F32 , 0x01F30 , 0x00300 },
-	{ 0x01F33 , 0x01F31 , 0x00300 },
-	{ 0x01F34 , 0x01F30 , 0x00301 },
-	{ 0x01F35 , 0x01F31 , 0x00301 },
-	{ 0x01F36 , 0x01F30 , 0x00342 },
-	{ 0x01F37 , 0x01F31 , 0x00342 },
-	{ 0x01F38 , 0x00399 , 0x00313 },
-	{ 0x01F39 , 0x00399 , 0x00314 },
-	{ 0x01F3A , 0x01F38 , 0x00300 },
-	{ 0x01F3B , 0x01F39 , 0x00300 },
-	{ 0x01F3C , 0x01F38 , 0x00301 },
-	{ 0x01F3D , 0x01F39 , 0x00301 },
-	{ 0x01F3E , 0x01F38 , 0x00342 },
-	{ 0x01F3F , 0x01F39 , 0x00342 },
-	{ 0x01F40 , 0x003BF , 0x00313 },
-	{ 0x01F41 , 0x003BF , 0x00314 },
-	{ 0x01F42 , 0x01F40 , 0x00300 },
-	{ 0x01F43 , 0x01F41 , 0x00300 },
-	{ 0x01F44 , 0x01F40 , 0x00301 },
-	{ 0x01F45 , 0x01F41 , 0x00301 },
-	{ 0x01F48 , 0x0039F , 0x00313 },
-	{ 0x01F49 , 0x0039F , 0x00314 },
-	{ 0x01F4A , 0x01F48 , 0x00300 },
-	{ 0x01F4B , 0x01F49 , 0x00300 },
-	{ 0x01F4C , 0x01F48 , 0x00301 },
-	{ 0x01F4D , 0x01F49 , 0x00301 },
-	{ 0x01F50 , 0x003C5 , 0x00313 },
-	{ 0x01F51 , 0x003C5 , 0x00314 },
-	{ 0x01F52 , 0x01F50 , 0x00300 },
-	{ 0x01F53 , 0x01F51 , 0x00300 },
-	{ 0x01F54 , 0x01F50 , 0x00301 },
-	{ 0x01F55 , 0x01F51 , 0x00301 },
-	{ 0x01F56 , 0x01F50 , 0x00342 },
-	{ 0x01F57 , 0x01F51 , 0x00342 },
-	{ 0x01F59 , 0x003A5 , 0x00314 },
-	{ 0x01F5B , 0x01F59 , 0x00300 },
-	{ 0x01F5D , 0x01F59 , 0x00301 },
-	{ 0x01F5F , 0x01F59 , 0x00342 },
-	{ 0x01F60 , 0x003C9 , 0x00313 },
-	{ 0x01F61 , 0x003C9 , 0x00314 },
-	{ 0x01F62 , 0x01F60 , 0x00300 },
-	{ 0x01F63 , 0x01F61 , 0x00300 },
-	{ 0x01F64 , 0x01F60 , 0x00301 },
-	{ 0x01F65 , 0x01F61 , 0x00301 },
-	{ 0x01F66 , 0x01F60 , 0x00342 },
-	{ 0x01F67 , 0x01F61 , 0x00342 },
-	{ 0x01F68 , 0x003A9 , 0x00313 },
-	{ 0x01F69 , 0x003A9 , 0x00314 },
-	{ 0x01F6A , 0x01F68 , 0x00300 },
-	{ 0x01F6B , 0x01F69 , 0x00300 },
-	{ 0x01F6C , 0x01F68 , 0x00301 },
-	{ 0x01F6D , 0x01F69 , 0x00301 },
-	{ 0x01F6E , 0x01F68 , 0x00342 },
-	{ 0x01F6F , 0x01F69 , 0x00342 },
-	{ 0x01F70 , 0x003B1 , 0x00300 },
-	{ 0x01F72 , 0x003B5 , 0x00300 },
-	{ 0x01F74 , 0x003B7 , 0x00300 },
-	{ 0x01F76 , 0x003B9 , 0x00300 },
-	{ 0x01F78 , 0x003BF , 0x00300 },
-	{ 0x01F7A , 0x003C5 , 0x00300 },
-	{ 0x01F7C , 0x003C9 , 0x00300 },
-	{ 0x01F80 , 0x01F00 , 0x00345 },
-	{ 0x01F81 , 0x01F01 , 0x00345 },
-	{ 0x01F82 , 0x01F02 , 0x00345 },
-	{ 0x01F83 , 0x01F03 , 0x00345 },
-	{ 0x01F84 , 0x01F04 , 0x00345 },
-	{ 0x01F85 , 0x01F05 , 0x00345 },
-	{ 0x01F86 , 0x01F06 , 0x00345 },
-	{ 0x01F87 , 0x01F07 , 0x00345 },
-	{ 0x01F88 , 0x01F08 , 0x00345 },
-	{ 0x01F89 , 0x01F09 , 0x00345 },
-	{ 0x01F8A , 0x01F0A , 0x00345 },
-	{ 0x01F8B , 0x01F0B , 0x00345 },
-	{ 0x01F8C , 0x01F0C , 0x00345 },
-	{ 0x01F8D , 0x01F0D , 0x00345 },
-	{ 0x01F8E , 0x01F0E , 0x00345 },
-	{ 0x01F8F , 0x01F0F , 0x00345 },
-	{ 0x01F90 , 0x01F20 , 0x00345 },
-	{ 0x01F91 , 0x01F21 , 0x00345 },
-	{ 0x01F92 , 0x01F22 , 0x00345 },
-	{ 0x01F93 , 0x01F23 , 0x00345 },
-	{ 0x01F94 , 0x01F24 , 0x00345 },
-	{ 0x01F95 , 0x01F25 , 0x00345 },
-	{ 0x01F96 , 0x01F26 , 0x00345 },
-	{ 0x01F97 , 0x01F27 , 0x00345 },
-	{ 0x01F98 , 0x01F28 , 0x00345 },
-	{ 0x01F99 , 0x01F29 , 0x00345 },
-	{ 0x01F9A , 0x01F2A , 0x00345 },
-	{ 0x01F9B , 0x01F2B , 0x00345 },
-	{ 0x01F9C , 0x01F2C , 0x00345 },
-	{ 0x01F9D , 0x01F2D , 0x00345 },
-	{ 0x01F9E , 0x01F2E , 0x00345 },
-	{ 0x01F9F , 0x01F2F , 0x00345 },
-	{ 0x01FA0 , 0x01F60 , 0x00345 },
-	{ 0x01FA1 , 0x01F61 , 0x00345 },
-	{ 0x01FA2 , 0x01F62 , 0x00345 },
-	{ 0x01FA3 , 0x01F63 , 0x00345 },
-	{ 0x01FA4 , 0x01F64 , 0x00345 },
-	{ 0x01FA5 , 0x01F65 , 0x00345 },
-	{ 0x01FA6 , 0x01F66 , 0x00345 },
-	{ 0x01FA7 , 0x01F67 , 0x00345 },
-	{ 0x01FA8 , 0x01F68 , 0x00345 },
-	{ 0x01FA9 , 0x01F69 , 0x00345 },
-	{ 0x01FAA , 0x01F6A , 0x00345 },
-	{ 0x01FAB , 0x01F6B , 0x00345 },
-	{ 0x01FAC , 0x01F6C , 0x00345 },
-	{ 0x01FAD , 0x01F6D , 0x00345 },
-	{ 0x01FAE , 0x01F6E , 0x00345 },
-	{ 0x01FAF , 0x01F6F , 0x00345 },
-	{ 0x01FB0 , 0x003B1 , 0x00306 },
-	{ 0x01FB1 , 0x003B1 , 0x00304 },
-	{ 0x01FB2 , 0x01F70 , 0x00345 },
-	{ 0x01FB3 , 0x003B1 , 0x00345 },
-	{ 0x01FB4 , 0x003AC , 0x00345 },
-	{ 0x01FB6 , 0x003B1 , 0x00342 },
-	{ 0x01FB7 , 0x01FB6 , 0x00345 },
-	{ 0x01FB8 , 0x00391 , 0x00306 },
-	{ 0x01FB9 , 0x00391 , 0x00304 },
-	{ 0x01FBA , 0x00391 , 0x00300 },
-	{ 0x01FBC , 0x00391 , 0x00345 },
-	{ 0x01FC1 , 0x000A8 , 0x00342 },
-	{ 0x01FC2 , 0x01F74 , 0x00345 },
-	{ 0x01FC3 , 0x003B7 , 0x00345 },
-	{ 0x01FC4 , 0x003AE , 0x00345 },
-	{ 0x01FC6 , 0x003B7 , 0x00342 },
-	{ 0x01FC7 , 0x01FC6 , 0x00345 },
-	{ 0x01FC8 , 0x00395 , 0x00300 },
-	{ 0x01FCA , 0x00397 , 0x00300 },
-	{ 0x01FCC , 0x00397 , 0x00345 },
-	{ 0x01FCD , 0x01FBF , 0x00300 },
-	{ 0x01FCE , 0x01FBF , 0x00301 },
-	{ 0x01FCF , 0x01FBF , 0x00342 },
-	{ 0x01FD0 , 0x003B9 , 0x00306 },
-	{ 0x01FD1 , 0x003B9 , 0x00304 },
-	{ 0x01FD2 , 0x003CA , 0x00300 },
-	{ 0x01FD6 , 0x003B9 , 0x00342 },
-	{ 0x01FD7 , 0x003CA , 0x00342 },
-	{ 0x01FD8 , 0x00399 , 0x00306 },
-	{ 0x01FD9 , 0x00399 , 0x00304 },
-	{ 0x01FDA , 0x00399 , 0x00300 },
-	{ 0x01FDD , 0x01FFE , 0x00300 },
-	{ 0x01FDE , 0x01FFE , 0x00301 },
-	{ 0x01FDF , 0x01FFE , 0x00342 },
-	{ 0x01FE0 , 0x003C5 , 0x00306 },
-	{ 0x01FE1 , 0x003C5 , 0x00304 },
-	{ 0x01FE2 , 0x003CB , 0x00300 },
-	{ 0x01FE4 , 0x003C1 , 0x00313 },
-	{ 0x01FE5 , 0x003C1 , 0x00314 },
-	{ 0x01FE6 , 0x003C5 , 0x00342 },
-	{ 0x01FE7 , 0x003CB , 0x00342 },
-	{ 0x01FE8 , 0x003A5 , 0x00306 },
-	{ 0x01FE9 , 0x003A5 , 0x00304 },
-	{ 0x01FEA , 0x003A5 , 0x00300 },
-	{ 0x01FEC , 0x003A1 , 0x00314 },
-	{ 0x01FED , 0x000A8 , 0x00300 },
-	{ 0x01FF2 , 0x01F7C , 0x00345 },
-	{ 0x01FF3 , 0x003C9 , 0x00345 },
-	{ 0x01FF4 , 0x003CE , 0x00345 },
-	{ 0x01FF6 , 0x003C9 , 0x00342 },
-	{ 0x01FF7 , 0x01FF6 , 0x00345 },
-	{ 0x01FF8 , 0x0039F , 0x00300 },
-	{ 0x01FFA , 0x003A9 , 0x00300 },
-	{ 0x01FFC , 0x003A9 , 0x00345 },
-	{ 0x0219A , 0x02190 , 0x00338 },
-	{ 0x0219B , 0x02192 , 0x00338 },
-	{ 0x021AE , 0x02194 , 0x00338 },
-	{ 0x021CD , 0x021D0 , 0x00338 },
-	{ 0x021CE , 0x021D4 , 0x00338 },
-	{ 0x021CF , 0x021D2 , 0x00338 },
-	{ 0x02204 , 0x02203 , 0x00338 },
-	{ 0x02209 , 0x02208 , 0x00338 },
-	{ 0x0220C , 0x0220B , 0x00338 },
-	{ 0x02224 , 0x02223 , 0x00338 },
-	{ 0x02226 , 0x02225 , 0x00338 },
-	{ 0x02241 , 0x0223C , 0x00338 },
-	{ 0x02244 , 0x02243 , 0x00338 },
-	{ 0x02247 , 0x02245 , 0x00338 },
-	{ 0x02249 , 0x02248 , 0x00338 },
-	{ 0x02260 , 0x0003D , 0x00338 },
-	{ 0x02262 , 0x02261 , 0x00338 },
-	{ 0x0226D , 0x0224D , 0x00338 },
-	{ 0x0226E , 0x0003C , 0x00338 },
-	{ 0x0226F , 0x0003E , 0x00338 },
-	{ 0x02270 , 0x02264 , 0x00338 },
-	{ 0x02271 , 0x02265 , 0x00338 },
-	{ 0x02274 , 0x02272 , 0x00338 },
-	{ 0x02275 , 0x02273 , 0x00338 },
-	{ 0x02278 , 0x02276 , 0x00338 },
-	{ 0x02279 , 0x02277 , 0x00338 },
-	{ 0x02280 , 0x0227A , 0x00338 },
-	{ 0x02281 , 0x0227B , 0x00338 },
-	{ 0x02284 , 0x02282 , 0x00338 },
-	{ 0x02285 , 0x02283 , 0x00338 },
-	{ 0x02288 , 0x02286 , 0x00338 },
-	{ 0x02289 , 0x02287 , 0x00338 },
-	{ 0x022AC , 0x022A2 , 0x00338 },
-	{ 0x022AD , 0x022A8 , 0x00338 },
-	{ 0x022AE , 0x022A9 , 0x00338 },
-	{ 0x022AF , 0x022AB , 0x00338 },
-	{ 0x022E0 , 0x0227C , 0x00338 },
-	{ 0x022E1 , 0x0227D , 0x00338 },
-	{ 0x022E2 , 0x02291 , 0x00338 },
-	{ 0x022E3 , 0x02292 , 0x00338 },
-	{ 0x022EA , 0x022B2 , 0x00338 },
-	{ 0x022EB , 0x022B3 , 0x00338 },
-	{ 0x022EC , 0x022B4 , 0x00338 },
-	{ 0x022ED , 0x022B5 , 0x00338 },
-	{ 0x0304C , 0x0304B , 0x03099 },
-	{ 0x0304E , 0x0304D , 0x03099 },
-	{ 0x03050 , 0x0304F , 0x03099 },
-	{ 0x03052 , 0x03051 , 0x03099 },
-	{ 0x03054 , 0x03053 , 0x03099 },
-	{ 0x03056 , 0x03055 , 0x03099 },
-	{ 0x03058 , 0x03057 , 0x03099 },
-	{ 0x0305A , 0x03059 , 0x03099 },
-	{ 0x0305C , 0x0305B , 0x03099 },
-	{ 0x0305E , 0x0305D , 0x03099 },
-	{ 0x03060 , 0x0305F , 0x03099 },
-	{ 0x03062 , 0x03061 , 0x03099 },
-	{ 0x03065 , 0x03064 , 0x03099 },
-	{ 0x03067 , 0x03066 , 0x03099 },
-	{ 0x03069 , 0x03068 , 0x03099 },
-	{ 0x03070 , 0x0306F , 0x03099 },
-	{ 0x03071 , 0x0306F , 0x0309A },
-	{ 0x03073 , 0x03072 , 0x03099 },
-	{ 0x03074 , 0x03072 , 0x0309A },
-	{ 0x03076 , 0x03075 , 0x03099 },
-	{ 0x03077 , 0x03075 , 0x0309A },
-	{ 0x03079 , 0x03078 , 0x03099 },
-	{ 0x0307A , 0x03078 , 0x0309A },
-	{ 0x0307C , 0x0307B , 0x03099 },
-	{ 0x0307D , 0x0307B , 0x0309A },
-	{ 0x03094 , 0x03046 , 0x03099 },
-	{ 0x0309E , 0x0309D , 0x03099 },
-	{ 0x030AC , 0x030AB , 0x03099 },
-	{ 0x030AE , 0x030AD , 0x03099 },
-	{ 0x030B0 , 0x030AF , 0x03099 },
-	{ 0x030B2 , 0x030B1 , 0x03099 },
-	{ 0x030B4 , 0x030B3 , 0x03099 },
-	{ 0x030B6 , 0x030B5 , 0x03099 },
-	{ 0x030B8 , 0x030B7 , 0x03099 },
-	{ 0x030BA , 0x030B9 , 0x03099 },
-	{ 0x030BC , 0x030BB , 0x03099 },
-	{ 0x030BE , 0x030BD , 0x03099 },
-	{ 0x030C0 , 0x030BF , 0x03099 },
-	{ 0x030C2 , 0x030C1 , 0x03099 },
-	{ 0x030C5 , 0x030C4 , 0x03099 },
-	{ 0x030C7 , 0x030C6 , 0x03099 },
-	{ 0x030C9 , 0x030C8 , 0x03099 },
-	{ 0x030D0 , 0x030CF , 0x03099 },
-	{ 0x030D1 , 0x030CF , 0x0309A },
-	{ 0x030D3 , 0x030D2 , 0x03099 },
-	{ 0x030D4 , 0x030D2 , 0x0309A },
-	{ 0x030D6 , 0x030D5 , 0x03099 },
-	{ 0x030D7 , 0x030D5 , 0x0309A },
-	{ 0x030D9 , 0x030D8 , 0x03099 },
-	{ 0x030DA , 0x030D8 , 0x0309A },
-	{ 0x030DC , 0x030DB , 0x03099 },
-	{ 0x030DD , 0x030DB , 0x0309A },
-	{ 0x030F4 , 0x030A6 , 0x03099 },
-	{ 0x030F7 , 0x030EF , 0x03099 },
-	{ 0x030F8 , 0x030F0 , 0x03099 },
-	{ 0x030F9 , 0x030F1 , 0x03099 },
-	{ 0x030FA , 0x030F2 , 0x03099 },
-	{ 0x030FE , 0x030FD , 0x03099 },
-	{ 0x1109A , 0x11099 , 0x110BA },
-	{ 0x1109C , 0x1109B , 0x110BA },
-	{ 0x110AB , 0x110A5 , 0x110BA },
-};
-
-#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
-
diff --git a/c/archive_string_sprintf.c b/c/archive_string_sprintf.c
deleted file mode 100644
--- a/c/archive_string_sprintf.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03-06 05:14:55Z kientzle $");
-
-/*
- * The use of printf()-family functions can be troublesome
- * for space-constrained applications.  In addition, correctly
- * implementing this function in terms of vsnprintf() requires
- * two calls (one to determine the size, another to format the
- * result), which in turn requires duplicating the argument list
- * using va_copy, which isn't yet universally available. <sigh>
- *
- * So, I've implemented a bare minimum of printf()-like capability
- * here.  This is only used to format error messages, so doesn't
- * require any floating-point support or field-width handling.
- */
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-
-#include "archive_string.h"
-#include "archive_private.h"
-
-/*
- * Utility functions to format signed/unsigned integers and append
- * them to an archive_string.
- */
-static void
-append_uint(struct archive_string *as, uintmax_t d, unsigned base)
-{
-	static const char digits[] = "0123456789abcdef";
-	if (d >= base)
-		append_uint(as, d/base, base);
-	archive_strappend_char(as, digits[d % base]);
-}
-
-static void
-append_int(struct archive_string *as, intmax_t d, unsigned base)
-{
-	uintmax_t ud;
-
-	if (d < 0) {
-		archive_strappend_char(as, '-');
-		ud = (d == INTMAX_MIN) ? (uintmax_t)(INTMAX_MAX) + 1 : (uintmax_t)(-d);
-	} else
-		ud = d;
-	append_uint(as, ud, base);
-}
-
-
-void
-archive_string_sprintf(struct archive_string *as, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	archive_string_vsprintf(as, fmt, ap);
-	va_end(ap);
-}
-
-/*
- * Like 'vsprintf', but ensures the target is big enough, resizing if
- * necessary.
- */
-void
-archive_string_vsprintf(struct archive_string *as, const char *fmt,
-    va_list ap)
-{
-	char long_flag;
-	intmax_t s; /* Signed integer temp. */
-	uintmax_t u; /* Unsigned integer temp. */
-	const char *p, *p2;
-	const wchar_t *pw;
-
-	if (archive_string_ensure(as, 64) == NULL)
-		__archive_errx(1, "Out of memory");
-
-	if (fmt == NULL) {
-		as->s[0] = 0;
-		return;
-	}
-
-	for (p = fmt; *p != '\0'; p++) {
-		const char *saved_p = p;
-
-		if (*p != '%') {
-			archive_strappend_char(as, *p);
-			continue;
-		}
-
-		p++;
-
-		long_flag = '\0';
-		switch(*p) {
-		case 'j':
-		case 'l':
-		case 'z':
-			long_flag = *p;
-			p++;
-			break;
-		}
-
-		switch (*p) {
-		case '%':
-			archive_strappend_char(as, '%');
-			break;
-		case 'c':
-			s = va_arg(ap, int);
-			archive_strappend_char(as, (char)s);
-			break;
-		case 'd':
-			switch(long_flag) {
-			case 'j': s = va_arg(ap, intmax_t); break;
-			case 'l': s = va_arg(ap, long); break;
-			case 'z': s = va_arg(ap, ssize_t); break;
-			default:  s = va_arg(ap, int); break;
-			}
-		        append_int(as, s, 10);
-			break;
-		case 's':
-			switch(long_flag) {
-			case 'l':
-				pw = va_arg(ap, wchar_t *);
-				if (pw == NULL)
-					pw = L"(null)";
-				if (archive_string_append_from_wcs(as, pw,
-				    wcslen(pw)) != 0 && errno == ENOMEM)
-					__archive_errx(1, "Out of memory");
-				break;
-			default:
-				p2 = va_arg(ap, char *);
-				if (p2 == NULL)
-					p2 = "(null)";
-				archive_strcat(as, p2);
-				break;
-			}
-			break;
-		case 'S':
-			pw = va_arg(ap, wchar_t *);
-			if (pw == NULL)
-				pw = L"(null)";
-			if (archive_string_append_from_wcs(as, pw,
-			    wcslen(pw)) != 0 && errno == ENOMEM)
-				__archive_errx(1, "Out of memory");
-			break;
-		case 'o': case 'u': case 'x': case 'X':
-			/* Common handling for unsigned integer formats. */
-			switch(long_flag) {
-			case 'j': u = va_arg(ap, uintmax_t); break;
-			case 'l': u = va_arg(ap, unsigned long); break;
-			case 'z': u = va_arg(ap, size_t); break;
-			default:  u = va_arg(ap, unsigned int); break;
-			}
-			/* Format it in the correct base. */
-			switch (*p) {
-			case 'o': append_uint(as, u, 8); break;
-			case 'u': append_uint(as, u, 10); break;
-			default: append_uint(as, u, 16); break;
-			}
-			break;
-		default:
-			/* Rewind and print the initial '%' literally. */
-			p = saved_p;
-			archive_strappend_char(as, *p);
-		}
-	}
-}
diff --git a/c/archive_util.c b/c/archive_util.c
deleted file mode 100644
--- a/c/archive_util.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/*-
- * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-/* don't use bcrypt when XP needs to be supported */
-#include <bcrypt.h>
-
-/* Common in other bcrypt implementations, but missing from VS2008. */
-#ifndef BCRYPT_SUCCESS
-#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
-#endif
-
-#elif defined(HAVE_WINCRYPT_H)
-#include <wincrypt.h>
-#endif
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#ifdef HAVE_LZ4_H
-#include <lz4.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_random_private.h"
-#include "archive_string.h"
-
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-static int archive_utility_string_sort_helper(char **, unsigned int);
-
-/* Generic initialization of 'struct archive' objects. */
-int
-__archive_clean(struct archive *a)
-{
-	archive_string_conversion_free(a);
-	return (ARCHIVE_OK);
-}
-
-int
-archive_version_number(void)
-{
-	return (ARCHIVE_VERSION_NUMBER);
-}
-
-const char *
-archive_version_string(void)
-{
-	return (ARCHIVE_VERSION_STRING);
-}
-
-int
-archive_errno(struct archive *a)
-{
-	return (a->archive_error_number);
-}
-
-const char *
-archive_error_string(struct archive *a)
-{
-
-	if (a->error != NULL  &&  *a->error != '\0')
-		return (a->error);
-	else
-		return (NULL);
-}
-
-int
-archive_file_count(struct archive *a)
-{
-	return (a->file_count);
-}
-
-int
-archive_format(struct archive *a)
-{
-	return (a->archive_format);
-}
-
-const char *
-archive_format_name(struct archive *a)
-{
-	return (a->archive_format_name);
-}
-
-
-int
-archive_compression(struct archive *a)
-{
-	return archive_filter_code(a, 0);
-}
-
-const char *
-archive_compression_name(struct archive *a)
-{
-	return archive_filter_name(a, 0);
-}
-
-
-/*
- * Return a count of the number of compressed bytes processed.
- */
-la_int64_t
-archive_position_compressed(struct archive *a)
-{
-	return archive_filter_bytes(a, -1);
-}
-
-/*
- * Return a count of the number of uncompressed bytes processed.
- */
-la_int64_t
-archive_position_uncompressed(struct archive *a)
-{
-	return archive_filter_bytes(a, 0);
-}
-
-void
-archive_clear_error(struct archive *a)
-{
-	archive_string_empty(&a->error_string);
-	a->error = NULL;
-	a->archive_error_number = 0;
-}
-
-void
-archive_set_error(struct archive *a, int error_number, const char *fmt, ...)
-{
-	va_list ap;
-
-	a->archive_error_number = error_number;
-	if (fmt == NULL) {
-		a->error = NULL;
-		return;
-	}
-
-	archive_string_empty(&(a->error_string));
-	va_start(ap, fmt);
-	archive_string_vsprintf(&(a->error_string), fmt, ap);
-	va_end(ap);
-	a->error = a->error_string.s;
-}
-
-void
-archive_copy_error(struct archive *dest, struct archive *src)
-{
-	dest->archive_error_number = src->archive_error_number;
-
-	archive_string_copy(&dest->error_string, &src->error_string);
-	dest->error = dest->error_string.s;
-}
-
-void
-__archive_errx(int retvalue, const char *msg)
-{
-	static const char msg1[] = "Fatal Internal Error in libarchive: ";
-	size_t s;
-
-	s = write(2, msg1, strlen(msg1));
-	(void)s; /* UNUSED */
-	s = write(2, msg, strlen(msg));
-	(void)s; /* UNUSED */
-	s = write(2, "\n", 1);
-	(void)s; /* UNUSED */
-	exit(retvalue);
-}
-
-/*
- * Create a temporary file
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-/*
- * Do not use Windows tmpfile() function.
- * It will make a temporary file under the root directory
- * and it'll cause permission error if a user who is
- * non-Administrator creates temporary files.
- * Also Windows version of mktemp family including _mktemp_s
- * are not secure.
- */
-static int
-__archive_mktempx(const char *tmpdir, wchar_t *template)
-{
-	static const wchar_t prefix[] = L"libarchive_";
-	static const wchar_t suffix[] = L"XXXXXXXXXX";
-	static const wchar_t num[] = {
-		L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
-		L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F',
-		L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N',
-		L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V',
-		L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd',
-		L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l',
-		L'm', L'n', L'o', L'p', L'q', L'r', L's', L't',
-		L'u', L'v', L'w', L'x', L'y', L'z'
-	};
-	struct archive_wstring temp_name;
-	wchar_t *ws;
-	DWORD attr;
-	wchar_t *xp, *ep;
-	int fd;
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	BCRYPT_ALG_HANDLE hAlg = NULL;
-#else
-	HCRYPTPROV hProv = (HCRYPTPROV)NULL;
-#endif
-	fd = -1;
-	ws = NULL;
-
-	if (template == NULL) {
-		archive_string_init(&temp_name);
-
-		/* Get a temporary directory. */
-		if (tmpdir == NULL) {
-			size_t l;
-			wchar_t *tmp;
-
-			l = GetTempPathW(0, NULL);
-			if (l == 0) {
-				la_dosmaperr(GetLastError());
-				goto exit_tmpfile;
-			}
-			tmp = malloc(l*sizeof(wchar_t));
-			if (tmp == NULL) {
-				errno = ENOMEM;
-				goto exit_tmpfile;
-			}
-			GetTempPathW((DWORD)l, tmp);
-			archive_wstrcpy(&temp_name, tmp);
-			free(tmp);
-		} else {
-			if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
-			    strlen(tmpdir)) < 0)
-				goto exit_tmpfile;
-			if (temp_name.s[temp_name.length-1] != L'/')
-				archive_wstrappend_wchar(&temp_name, L'/');
-		}
-
-		/* Check if temp_name is a directory. */
-		attr = GetFileAttributesW(temp_name.s);
-		if (attr == (DWORD)-1) {
-			if (GetLastError() != ERROR_FILE_NOT_FOUND) {
-				la_dosmaperr(GetLastError());
-				goto exit_tmpfile;
-			}
-			ws = __la_win_permissive_name_w(temp_name.s);
-			if (ws == NULL) {
-				errno = EINVAL;
-				goto exit_tmpfile;
-			}
-			attr = GetFileAttributesW(ws);
-			if (attr == (DWORD)-1) {
-				la_dosmaperr(GetLastError());
-				goto exit_tmpfile;
-			}
-		}
-		if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
-			errno = ENOTDIR;
-			goto exit_tmpfile;
-		}
-
-		/*
-		 * Create a temporary file.
-		 */
-		archive_wstrcat(&temp_name, prefix);
-		archive_wstrcat(&temp_name, suffix);
-		ep = temp_name.s + archive_strlen(&temp_name);
-		xp = ep - wcslen(suffix);
-		template = temp_name.s;
-	} else {
-		xp = wcschr(template, L'X');
-		if (xp == NULL)	/* No X, programming error */
-			abort();
-		for (ep = xp; *ep == L'X'; ep++)
-			continue;
-		if (*ep)	/* X followed by non X, programming error */
-			abort();
-	}
-
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM,
-		NULL, 0))) {
-		la_dosmaperr(GetLastError());
-		goto exit_tmpfile;
-	}
-#else
-	if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
-		CRYPT_VERIFYCONTEXT)) {
-		la_dosmaperr(GetLastError());
-		goto exit_tmpfile;
-	}
-#endif
-
-	for (;;) {
-		wchar_t *p;
-		HANDLE h;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-		/* Generate a random file name through CryptGenRandom(). */
-		p = xp;
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-		if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p,
-		    (DWORD)(ep - p)*sizeof(wchar_t), 0))) {
-			la_dosmaperr(GetLastError());
-			goto exit_tmpfile;
-		}
-#else
-		if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
-		    (BYTE*)p)) {
-			la_dosmaperr(GetLastError());
-			goto exit_tmpfile;
-		}
-#endif
-		for (; p < ep; p++)
-			*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
-
-		free(ws);
-		ws = __la_win_permissive_name_w(template);
-		if (ws == NULL) {
-			errno = EINVAL;
-			goto exit_tmpfile;
-		}
-		if (template == temp_name.s) {
-			attr = FILE_ATTRIBUTE_TEMPORARY |
-			       FILE_FLAG_DELETE_ON_CLOSE;
-		} else {
-			/* mkstemp */
-			attr = FILE_ATTRIBUTE_NORMAL;
-		}
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		ZeroMemory(&createExParams, sizeof(createExParams));
-		createExParams.dwSize = sizeof(createExParams);
-		createExParams.dwFileAttributes = attr & 0xFFFF;
-		createExParams.dwFileFlags = attr & 0xFFF00000;
-		h = CreateFile2(ws,
-		    GENERIC_READ | GENERIC_WRITE | DELETE,
-		    0,/* Not share */
-			CREATE_NEW,
-			&createExParams);
-#else
-		h = CreateFileW(ws,
-		    GENERIC_READ | GENERIC_WRITE | DELETE,
-		    0,/* Not share */
-		    NULL,
-		    CREATE_NEW,/* Create a new file only */
-		    attr,
-		    NULL);
-#endif
-		if (h == INVALID_HANDLE_VALUE) {
-			/* The same file already exists. retry with
-			 * a new filename. */
-			if (GetLastError() == ERROR_FILE_EXISTS)
-				continue;
-			/* Otherwise, fail creation temporary file. */
-			la_dosmaperr(GetLastError());
-			goto exit_tmpfile;
-		}
-		fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR);
-		if (fd == -1) {
-			la_dosmaperr(GetLastError());
-			CloseHandle(h);
-			goto exit_tmpfile;
-		} else
-			break;/* success! */
-	}
-exit_tmpfile:
-#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
-	if (hAlg != NULL)
-		BCryptCloseAlgorithmProvider(hAlg, 0);
-#else
-	if (hProv != (HCRYPTPROV)NULL)
-		CryptReleaseContext(hProv, 0);
-#endif
-	free(ws);
-	if (template == temp_name.s)
-		archive_wstring_free(&temp_name);
-	return (fd);
-}
-
-int
-__archive_mktemp(const char *tmpdir)
-{
-	return __archive_mktempx(tmpdir, NULL);
-}
-
-int
-__archive_mkstemp(wchar_t *template)
-{
-	return __archive_mktempx(NULL, template);
-}
-
-#else
-
-static int
-get_tempdir(struct archive_string *temppath)
-{
-	const char *tmp;
-
-	tmp = getenv("TMPDIR");
-	if (tmp == NULL)
-#ifdef _PATH_TMP
-		tmp = _PATH_TMP;
-#else
-                tmp = "/tmp";
-#endif
-	archive_strcpy(temppath, tmp);
-	if (temppath->s[temppath->length-1] != '/')
-		archive_strappend_char(temppath, '/');
-	return (ARCHIVE_OK);
-}
-
-#if defined(HAVE_MKSTEMP)
-
-/*
- * We can use mkstemp().
- */
-
-int
-__archive_mktemp(const char *tmpdir)
-{
-	struct archive_string temp_name;
-	int fd = -1;
-
-	archive_string_init(&temp_name);
-	if (tmpdir == NULL) {
-		if (get_tempdir(&temp_name) != ARCHIVE_OK)
-			goto exit_tmpfile;
-	} else {
-		archive_strcpy(&temp_name, tmpdir);
-		if (temp_name.s[temp_name.length-1] != '/')
-			archive_strappend_char(&temp_name, '/');
-	}
-#ifdef O_TMPFILE
-	fd = open(temp_name.s, O_RDWR|O_CLOEXEC|O_TMPFILE|O_EXCL, 0600); 
-	if(fd >= 0)
-		goto exit_tmpfile;
-#endif
-	archive_strcat(&temp_name, "libarchive_XXXXXX");
-	fd = mkstemp(temp_name.s);
-	if (fd < 0)
-		goto exit_tmpfile;
-	__archive_ensure_cloexec_flag(fd);
-	unlink(temp_name.s);
-exit_tmpfile:
-	archive_string_free(&temp_name);
-	return (fd);
-}
-
-int
-__archive_mkstemp(char *template)
-{
-	int fd = -1;
-	fd = mkstemp(template);
-	if (fd >= 0)
-		__archive_ensure_cloexec_flag(fd);
-	return (fd);
-}
-
-#else /* !HAVE_MKSTEMP */
-
-/*
- * We use a private routine.
- */
-
-static int
-__archive_mktempx(const char *tmpdir, char *template)
-{
-        static const char num[] = {
-		'0', '1', '2', '3', '4', '5', '6', '7',
-		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
-		'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
-		'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
-		'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-		'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
-		'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-		'u', 'v', 'w', 'x', 'y', 'z'
-        };
-	struct archive_string temp_name;
-	struct stat st;
-	int fd;
-	char *tp, *ep;
-
-	fd = -1;
-	if (template == NULL) {
-		archive_string_init(&temp_name);
-		if (tmpdir == NULL) {
-			if (get_tempdir(&temp_name) != ARCHIVE_OK)
-				goto exit_tmpfile;
-		} else
-			archive_strcpy(&temp_name, tmpdir);
-		if (temp_name.s[temp_name.length-1] == '/') {
-			temp_name.s[temp_name.length-1] = '\0';
-			temp_name.length --;
-		}
-		if (la_stat(temp_name.s, &st) < 0)
-			goto exit_tmpfile;
-		if (!S_ISDIR(st.st_mode)) {
-			errno = ENOTDIR;
-			goto exit_tmpfile;
-		}
-		archive_strcat(&temp_name, "/libarchive_");
-		tp = temp_name.s + archive_strlen(&temp_name);
-		archive_strcat(&temp_name, "XXXXXXXXXX");
-		ep = temp_name.s + archive_strlen(&temp_name);
-		template = temp_name.s;
-	} else {
-		tp = strchr(template, 'X');
-		if (tp == NULL)	/* No X, programming error */
-			abort();
-		for (ep = tp; *ep == 'X'; ep++)
-			continue;
-		if (*ep)	/* X followed by non X, programming error */
-			abort();
-	}
-
-	do {
-		char *p;
-
-		p = tp;
-		archive_random(p, ep - p);
-		while (p < ep) {
-			int d = *((unsigned char *)p) % sizeof(num);
-			*p++ = num[d];
-		}
-		fd = open(template, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
-			  0600);
-	} while (fd < 0 && errno == EEXIST);
-	if (fd < 0)
-		goto exit_tmpfile;
-	__archive_ensure_cloexec_flag(fd);
-	if (template == temp_name.s)
-		unlink(temp_name.s);
-exit_tmpfile:
-	if (template == temp_name.s)
-		archive_string_free(&temp_name);
-	return (fd);
-}
-
-int
-__archive_mktemp(const char *tmpdir)
-{
-	return __archive_mktempx(tmpdir, NULL);
-}
-
-int
-__archive_mkstemp(char *template)
-{
-	return __archive_mktempx(NULL, template);
-}
-
-#endif /* !HAVE_MKSTEMP */
-#endif /* !_WIN32 || __CYGWIN__ */
-
-/*
- * Set FD_CLOEXEC flag to a file descriptor if it is not set.
- * We have to set the flag if the platform does not provide O_CLOEXEC
- * or F_DUPFD_CLOEXEC flags.
- *
- * Note: This function is absolutely called after creating a new file
- * descriptor even if the platform seemingly provides O_CLOEXEC or
- * F_DUPFD_CLOEXEC macros because it is possible that the platform
- * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
- */
-void
-__archive_ensure_cloexec_flag(int fd)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	(void)fd; /* UNUSED */
-#else
-	int flags;
-
-	if (fd >= 0) {
-		flags = fcntl(fd, F_GETFD);
-		if (flags != -1 && (flags & FD_CLOEXEC) == 0)
-			fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
-	}
-#endif
-}
-
-/*
- * Utility function to sort a group of strings using quicksort.
- */
-static int
-archive_utility_string_sort_helper(char **strings, unsigned int n)
-{
-	unsigned int i, lesser_count, greater_count;
-	char **lesser, **greater, **tmp, *pivot;
-	int retval1, retval2;
-
-	/* A list of 0 or 1 elements is already sorted */
-	if (n <= 1)
-		return (ARCHIVE_OK);
-
-	lesser_count = greater_count = 0;
-	lesser = greater = NULL;
-	pivot = strings[0];
-	for (i = 1; i < n; i++)
-	{
-		if (strcmp(strings[i], pivot) < 0)
-		{
-			lesser_count++;
-			tmp = (char **)realloc(lesser,
-				lesser_count * sizeof(char *));
-			if (!tmp) {
-				free(greater);
-				free(lesser);
-				return (ARCHIVE_FATAL);
-			}
-			lesser = tmp;
-			lesser[lesser_count - 1] = strings[i];
-		}
-		else
-		{
-			greater_count++;
-			tmp = (char **)realloc(greater,
-				greater_count * sizeof(char *));
-			if (!tmp) {
-				free(greater);
-				free(lesser);
-				return (ARCHIVE_FATAL);
-			}
-			greater = tmp;
-			greater[greater_count - 1] = strings[i];
-		}
-	}
-
-	/* quicksort(lesser) */
-	retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
-	for (i = 0; i < lesser_count; i++)
-		strings[i] = lesser[i];
-	free(lesser);
-
-	/* pivot */
-	strings[lesser_count] = pivot;
-
-	/* quicksort(greater) */
-	retval2 = archive_utility_string_sort_helper(greater, greater_count);
-	for (i = 0; i < greater_count; i++)
-		strings[lesser_count + 1 + i] = greater[i];
-	free(greater);
-
-	return (retval1 < retval2) ? retval1 : retval2;
-}
-
-int
-archive_utility_string_sort(char **strings)
-{
-	  unsigned int size = 0;
-	  while (strings[size] != NULL)
-		size++;
-	  return archive_utility_string_sort_helper(strings, size);
-}
diff --git a/c/archive_version_details.c b/c/archive_version_details.c
deleted file mode 100644
--- a/c/archive_version_details.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*-
- * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#ifdef HAVE_LZ4_H
-#include <lz4.h>
-#endif
-#ifdef HAVE_ZSTD_H
-#include <zstd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-
-const char *
-archive_version_details(void)
-{
-	static struct archive_string str;
-	static int init = 0;
-	const char *zlib = archive_zlib_version();
-	const char *liblzma = archive_liblzma_version();
-	const char *bzlib = archive_bzlib_version();
-	const char *liblz4 = archive_liblz4_version();
-	const char *libzstd = archive_libzstd_version();
-
-	if (!init) {
-		archive_string_init(&str);
-
-		archive_strcat(&str, ARCHIVE_VERSION_STRING);
-		if (zlib != NULL) {
-			archive_strcat(&str, " zlib/");
-			archive_strcat(&str, zlib);
-		}
-		if (liblzma) {
-			archive_strcat(&str, " liblzma/");
-			archive_strcat(&str, liblzma);
-		}
-		if (bzlib) {
-			const char *p = bzlib;
-			const char *sep = strchr(p, ',');
-			if (sep == NULL)
-				sep = p + strlen(p);
-			archive_strcat(&str, " bz2lib/");
-			archive_strncat(&str, p, sep - p);
-		}
-		if (liblz4) {
-			archive_strcat(&str, " liblz4/");
-			archive_strcat(&str, liblz4);
-		}
-		if (libzstd) {
-			archive_strcat(&str, " libzstd/");
-			archive_strcat(&str, libzstd);
-		}
-	}
-	return str.s;
-}
-
-const char *
-archive_zlib_version(void)
-{
-#ifdef HAVE_ZLIB_H
-	return ZLIB_VERSION;
-#else
-	return NULL;
-#endif
-}
-
-const char *
-archive_liblzma_version(void)
-{
-#ifdef HAVE_LZMA_H
-	return LZMA_VERSION_STRING;
-#else
-	return NULL;
-#endif
-}
-
-const char *
-archive_bzlib_version(void)
-{
-#ifdef HAVE_BZLIB_H
-	return BZ2_bzlibVersion();
-#else
-	return NULL;
-#endif
-}
-
-const char *
-archive_liblz4_version(void)
-{
-#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
-#define str(s) #s
-#define NUMBER(x) str(x)
-	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
-#undef NUMBER
-#undef str
-#else
-	return NULL;
-#endif
-}
-
-const char *
-archive_libzstd_version(void)
-{
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
-	return ZSTD_VERSION_STRING;
-#else
-	return NULL;
-#endif
-}
diff --git a/c/archive_virtual.c b/c/archive_virtual.c
deleted file mode 100644
--- a/c/archive_virtual.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_virtual.c 201098 2009-12-28 02:58:14Z kientzle $");
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-
-int
-archive_filter_code(struct archive *a, int n)
-{
-	return ((a->vtable->archive_filter_code)(a, n));
-}
-
-int
-archive_filter_count(struct archive *a)
-{
-	return ((a->vtable->archive_filter_count)(a));
-}
-
-const char *
-archive_filter_name(struct archive *a, int n)
-{
-	return ((a->vtable->archive_filter_name)(a, n));
-}
-
-la_int64_t
-archive_filter_bytes(struct archive *a, int n)
-{
-	return ((a->vtable->archive_filter_bytes)(a, n));
-}
-
-int
-archive_free(struct archive *a)
-{
-	if (a == NULL)
-		return (ARCHIVE_OK);
-	return ((a->vtable->archive_free)(a));
-}
-
-int
-archive_write_close(struct archive *a)
-{
-	return ((a->vtable->archive_close)(a));
-}
-
-int
-archive_read_close(struct archive *a)
-{
-	return ((a->vtable->archive_close)(a));
-}
-
-int
-archive_write_fail(struct archive *a)
-{
-	a->state = ARCHIVE_STATE_FATAL;
-	return a->state;
-}
-
-int
-archive_write_free(struct archive *a)
-{
-	return archive_free(a);
-}
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* For backwards compatibility; will be removed with libarchive 4.0. */
-int
-archive_write_finish(struct archive *a)
-{
-	return archive_write_free(a);
-}
-#endif
-
-int
-archive_read_free(struct archive *a)
-{
-	return archive_free(a);
-}
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-/* For backwards compatibility; will be removed with libarchive 4.0. */
-int
-archive_read_finish(struct archive *a)
-{
-	return archive_read_free(a);
-}
-#endif
-
-int
-archive_write_header(struct archive *a, struct archive_entry *entry)
-{
-	++a->file_count;
-	return ((a->vtable->archive_write_header)(a, entry));
-}
-
-int
-archive_write_finish_entry(struct archive *a)
-{
-	return ((a->vtable->archive_write_finish_entry)(a));
-}
-
-la_ssize_t
-archive_write_data(struct archive *a, const void *buff, size_t s)
-{
-	return ((a->vtable->archive_write_data)(a, buff, s));
-}
-
-la_ssize_t
-archive_write_data_block(struct archive *a, const void *buff, size_t s,
-    la_int64_t o)
-{
-	if (a->vtable->archive_write_data_block == NULL) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "archive_write_data_block not supported");
-		a->state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	return ((a->vtable->archive_write_data_block)(a, buff, s, o));
-}
-
-int
-archive_read_next_header(struct archive *a, struct archive_entry **entry)
-{
-	return ((a->vtable->archive_read_next_header)(a, entry));
-}
-
-int
-archive_read_next_header2(struct archive *a, struct archive_entry *entry)
-{
-	return ((a->vtable->archive_read_next_header2)(a, entry));
-}
-
-int
-archive_read_data_block(struct archive *a,
-    const void **buff, size_t *s, la_int64_t *o)
-{
-	return ((a->vtable->archive_read_data_block)(a, buff, s, o));
-}
diff --git a/c/archive_windows.c b/c/archive_windows.c
deleted file mode 100644
--- a/c/archive_windows.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*-
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
- * Copyright (c) 2003-2007 Kees Zeelenberg
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * A set of compatibility glue for building libarchive on Windows platforms.
- *
- * Originally created as "libarchive-nonposix.c" by Kees Zeelenberg
- * for the GnuWin32 project, trimmed significantly by Tim Kientzle.
- *
- * Much of the original file was unnecessary for libarchive, because
- * many of the features it emulated were not strictly necessary for
- * libarchive.  I hope for this to shrink further as libarchive
- * internals are gradually reworked to sit more naturally on both
- * POSIX and Windows.  Any ideas for this are greatly appreciated.
- *
- * The biggest remaining issue is the dev/ino emulation; libarchive
- * has a couple of public APIs that rely on dev/ino uniquely
- * identifying a file.  This doesn't match well with Windows.  I'm
- * considering alternative APIs.
- */
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-#include "archive_platform.h"
-#include "archive_private.h"
-#include "archive_entry.h"
-#include <ctype.h>
-#include <errno.h>
-#include <stddef.h>
-#ifdef HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-#include <sys/stat.h>
-#include <locale.h>
-#include <process.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <windows.h>
-#include <share.h>
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-#if defined(__LA_LSEEK_NEEDED)
-static BOOL SetFilePointerEx_perso(HANDLE hFile,
-				   LARGE_INTEGER liDistanceToMove,
-				   PLARGE_INTEGER lpNewFilePointer,
-				   DWORD dwMoveMethod)
-{
-	LARGE_INTEGER li;
-	li.QuadPart = liDistanceToMove.QuadPart;
-	li.LowPart = SetFilePointer(
-		hFile, li.LowPart, &li.HighPart, dwMoveMethod);
-	if(lpNewFilePointer) {
-		lpNewFilePointer->QuadPart = li.QuadPart;
-	}
-	return li.LowPart != -1 || GetLastError() == NO_ERROR;
-}
-#endif
-
-struct ustat {
-	int64_t		st_atime;
-	uint32_t	st_atime_nsec;
-	int64_t		st_ctime;
-	uint32_t	st_ctime_nsec;
-	int64_t		st_mtime;
-	uint32_t	st_mtime_nsec;
-	gid_t		st_gid;
-	/* 64bits ino */
-	int64_t		st_ino;
-	mode_t		st_mode;
-	uint32_t	st_nlink;
-	uint64_t	st_size;
-	uid_t		st_uid;
-	dev_t		st_dev;
-	dev_t		st_rdev;
-};
-
-/* Transform 64-bits ino into 32-bits by hashing.
- * You do not forget that really unique number size is 64-bits.
- */
-#define INOSIZE (8*sizeof(ino_t)) /* 32 */
-static __inline ino_t
-getino(struct ustat *ub)
-{
-	ULARGE_INTEGER ino64;
-	ino64.QuadPart = ub->st_ino;
-	/* I don't know this hashing is correct way */
-	return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE)));
-}
-
-/*
- * Prepend "\\?\" to the path name and convert it to unicode to permit
- * an extended-length path for a maximum total path length of 32767
- * characters.
- * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
- */
-wchar_t *
-__la_win_permissive_name(const char *name)
-{
-	wchar_t *wn;
-	wchar_t *ws;
-	size_t ll;
-
-	ll = strlen(name);
-	wn = malloc((ll + 1) * sizeof(wchar_t));
-	if (wn == NULL)
-		return (NULL);
-	ll = mbstowcs(wn, name, ll);
-	if (ll == (size_t)-1) {
-		free(wn);
-		return (NULL);
-	}
-	wn[ll] = L'\0';
-	ws = __la_win_permissive_name_w(wn);
-	free(wn);
-	return (ws);
-}
-
-wchar_t *
-__la_win_permissive_name_w(const wchar_t *wname)
-{
-	wchar_t *wn, *wnp;
-	wchar_t *ws, *wsp;
-	DWORD l, len, slen;
-	int unc;
-
-	/* Get a full-pathname. */
-	l = GetFullPathNameW(wname, 0, NULL, NULL);
-	if (l == 0)
-		return (NULL);
-	/* NOTE: GetFullPathNameW has a bug that if the length of the file
-	 * name is just 1 then it returns incomplete buffer size. Thus, we
-	 * have to add three to the size to allocate a sufficient buffer
-	 * size for the full-pathname of the file name. */
-	l += 3;
-	wnp = malloc(l * sizeof(wchar_t));
-	if (wnp == NULL)
-		return (NULL);
-	len = GetFullPathNameW(wname, l, wnp, NULL);
-	wn = wnp;
-
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
-	    wnp[2] == L'?' && wnp[3] == L'\\')
-		/* We have already a permissive name. */
-		return (wn);
-
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
-		wnp[2] == L'.' && wnp[3] == L'\\') {
-		/* This is a device name */
-		if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
-		     (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
-		    wnp[5] == L':' && wnp[6] == L'\\')
-			wnp[2] = L'?';/* Not device name. */
-		return (wn);
-	}
-
-	unc = 0;
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
-		wchar_t *p = &wnp[2];
-
-		/* Skip server-name letters. */
-		while (*p != L'\\' && *p != L'\0')
-			++p;
-		if (*p == L'\\') {
-			wchar_t *rp = ++p;
-			/* Skip share-name letters. */
-			while (*p != L'\\' && *p != L'\0')
-				++p;
-			if (*p == L'\\' && p != rp) {
-				/* Now, match patterns such as
-				 * "\\server-name\share-name\" */
-				wnp += 2;
-				len -= 2;
-				unc = 1;
-			}
-		}
-	}
-
-	slen = 4 + (unc * 4) + len + 1;
-	ws = wsp = malloc(slen * sizeof(wchar_t));
-	if (ws == NULL) {
-		free(wn);
-		return (NULL);
-	}
-	/* prepend "\\?\" */
-	wcsncpy(wsp, L"\\\\?\\", 4);
-	wsp += 4;
-	slen -= 4;
-	if (unc) {
-		/* append "UNC\" ---> "\\?\UNC\" */
-		wcsncpy(wsp, L"UNC\\", 4);
-		wsp += 4;
-		slen -= 4;
-	}
-	wcsncpy(wsp, wnp, slen);
-	wsp[slen - 1] = L'\0'; /* Ensure null termination. */
-	free(wn);
-	return (ws);
-}
-
-/*
- * Create a file handle.
- * This can exceed MAX_PATH limitation.
- */
-static HANDLE
-la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
-    LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
-    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
-{
-	wchar_t *wpath;
-	HANDLE handle;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
-	handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
-	    lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
-	    hTemplateFile);
-	if (handle != INVALID_HANDLE_VALUE)
-		return (handle);
-	if (GetLastError() != ERROR_PATH_NOT_FOUND)
-		return (handle);
-#endif
-	wpath = __la_win_permissive_name(path);
-	if (wpath == NULL)
-		return INVALID_HANDLE_VALUE;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	ZeroMemory(&createExParams, sizeof(createExParams));
-	createExParams.dwSize = sizeof(createExParams);
-	createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF;
-	createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000;
-	createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000;
-	createExParams.lpSecurityAttributes = lpSecurityAttributes;
-	createExParams.hTemplateFile = hTemplateFile;
-	handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode,
-	    dwCreationDisposition, &createExParams);
-#else /* !WINAPI_PARTITION_DESKTOP */
-	handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
-	    lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
-	    hTemplateFile);
-#endif /* !WINAPI_PARTITION_DESKTOP */
-	free(wpath);
-	return (handle);
-}
-
-#if defined(__LA_LSEEK_NEEDED)
-__int64
-__la_lseek(int fd, __int64 offset, int whence)
-{
-	LARGE_INTEGER distance;
-	LARGE_INTEGER newpointer;
-	HANDLE handle;
-
-	if (fd < 0) {
-		errno = EBADF;
-		return (-1);
-	}
-	handle = (HANDLE)_get_osfhandle(fd);
-	if (GetFileType(handle) != FILE_TYPE_DISK) {
-		errno = EBADF;
-		return (-1);
-	}
-	distance.QuadPart = offset;
-	if (!SetFilePointerEx_perso(handle, distance, &newpointer, whence)) {
-		DWORD lasterr;
-
-		lasterr = GetLastError();
-		if (lasterr == ERROR_BROKEN_PIPE)
-			return (0);
-		if (lasterr == ERROR_ACCESS_DENIED)
-			errno = EBADF;
-		else
-			la_dosmaperr(lasterr);
-		return (-1);
-	}
-	return (newpointer.QuadPart);
-}
-#endif
-
-/* This can exceed MAX_PATH limitation. */
-int
-__la_open(const char *path, int flags, ...)
-{
-	va_list ap;
-	wchar_t *ws;
-	int r, pmode;
-	DWORD attr;
-
-	va_start(ap, flags);
-	pmode = va_arg(ap, int);
-	va_end(ap);
-	ws = NULL;
-	if ((flags & ~O_BINARY) == O_RDONLY) {
-		/*
-		 * When we open a directory, _open function returns
-		 * "Permission denied" error.
-		 */
-		attr = GetFileAttributesA(path);
-#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
-		if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND)
-#endif
-		{
-			ws = __la_win_permissive_name(path);
-			if (ws == NULL) {
-				errno = EINVAL;
-				return (-1);
-			}
-			attr = GetFileAttributesW(ws);
-		}
-		if (attr == (DWORD)-1) {
-			la_dosmaperr(GetLastError());
-			free(ws);
-			return (-1);
-		}
-		if (attr & FILE_ATTRIBUTE_DIRECTORY) {
-			HANDLE handle;
-#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
-			if (ws != NULL)
-				handle = CreateFileW(ws, 0, 0, NULL,
-				    OPEN_EXISTING,
-				    FILE_FLAG_BACKUP_SEMANTICS |
-				    FILE_ATTRIBUTE_READONLY,
-					NULL);
-			else
-				handle = CreateFileA(path, 0, 0, NULL,
-				    OPEN_EXISTING,
-				    FILE_FLAG_BACKUP_SEMANTICS |
-				    FILE_ATTRIBUTE_READONLY,
-					NULL);
-#else /* !WINAPI_PARTITION_DESKTOP */
-			CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-			ZeroMemory(&createExParams, sizeof(createExParams));
-			createExParams.dwSize = sizeof(createExParams);
-			createExParams.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
-			createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
-			handle = CreateFile2(ws, 0, 0,
-				OPEN_EXISTING, &createExParams);
-#endif /* !WINAPI_PARTITION_DESKTOP */
-			free(ws);
-			if (handle == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				return (-1);
-			}
-			r = _open_osfhandle((intptr_t)handle, _O_RDONLY);
-			return (r);
-		}
-	}
-	if (ws == NULL) {
-#if defined(__BORLANDC__)
-		/* Borland has no mode argument.
-		   TODO: Fix mode of new file.  */
-		r = _open(path, flags);
-#else
-		r = _open(path, flags, pmode);
-#endif
-		if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
-			/* Simulate other POSIX system action to pass our test suite. */
-			attr = GetFileAttributesA(path);
-			if (attr == (DWORD)-1)
-				la_dosmaperr(GetLastError());
-			else if (attr & FILE_ATTRIBUTE_DIRECTORY)
-				errno = EISDIR;
-			else
-				errno = EACCES;
-			return (-1);
-		}
-		if (r >= 0 || errno != ENOENT)
-			return (r);
-		ws = __la_win_permissive_name(path);
-		if (ws == NULL) {
-			errno = EINVAL;
-			return (-1);
-		}
-	}
-	r = _wopen(ws, flags, pmode);
-	if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
-		/* Simulate other POSIX system action to pass our test suite. */
-		attr = GetFileAttributesW(ws);
-		if (attr == (DWORD)-1)
-			la_dosmaperr(GetLastError());
-		else if (attr & FILE_ATTRIBUTE_DIRECTORY)
-			errno = EISDIR;
-		else
-			errno = EACCES;
-	}
-	free(ws);
-	return (r);
-}
-
-ssize_t
-__la_read(int fd, void *buf, size_t nbytes)
-{
-	HANDLE handle;
-	DWORD bytes_read, lasterr;
-	int r;
-
-#ifdef _WIN64
-	if (nbytes > UINT32_MAX)
-		nbytes = UINT32_MAX;
-#endif
-	if (fd < 0) {
-		errno = EBADF;
-		return (-1);
-	}
-	/* Do not pass 0 to third parameter of ReadFile(), read bytes.
-	 * This will not return to application side. */
-	if (nbytes == 0)
-		return (0);
-	handle = (HANDLE)_get_osfhandle(fd);
-	r = ReadFile(handle, buf, (uint32_t)nbytes,
-	    &bytes_read, NULL);
-	if (r == 0) {
-		lasterr = GetLastError();
-		if (lasterr == ERROR_NO_DATA) {
-			errno = EAGAIN;
-			return (-1);
-		}
-		if (lasterr == ERROR_BROKEN_PIPE)
-			return (0);
-		if (lasterr == ERROR_ACCESS_DENIED)
-			errno = EBADF;
-		else
-			la_dosmaperr(lasterr);
-		return (-1);
-	}
-	return ((ssize_t)bytes_read);
-}
-
-/* Convert Windows FILETIME to UTC */
-__inline static void
-fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		*t = (time_t)(utc.QuadPart / 10000000);	/* milli seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
-/* Stat by handle
- * Windows' stat() does not accept the path added "\\?\" especially "?"
- * character.
- * It means we cannot access the long name path longer than MAX_PATH.
- * So I've implemented a function similar to Windows' stat() to access the
- * long name path.
- * And I've added some feature.
- * 1. set st_ino by nFileIndexHigh and nFileIndexLow of
- *    BY_HANDLE_FILE_INFORMATION.
- * 2. set st_nlink by nNumberOfLinks of BY_HANDLE_FILE_INFORMATION.
- * 3. set st_dev by dwVolumeSerialNumber by BY_HANDLE_FILE_INFORMATION.
- */
-static int
-__hstat(HANDLE handle, struct ustat *st)
-{
-	BY_HANDLE_FILE_INFORMATION info;
-	ULARGE_INTEGER ino64;
-	DWORD ftype;
-	mode_t mode;
-	time_t t;
-	long ns;
-
-	switch (ftype = GetFileType(handle)) {
-	case FILE_TYPE_UNKNOWN:
-		errno = EBADF;
-		return (-1);
-	case FILE_TYPE_CHAR:
-	case FILE_TYPE_PIPE:
-		if (ftype == FILE_TYPE_CHAR) {
-			st->st_mode = S_IFCHR;
-			st->st_size = 0;
-		} else {
-			DWORD avail;
-
-			st->st_mode = S_IFIFO;
-			if (PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL))
-				st->st_size = avail;
-			else
-				st->st_size = 0;
-		}
-		st->st_atime = 0;
-		st->st_atime_nsec = 0;
-		st->st_mtime = 0;
-		st->st_mtime_nsec = 0;
-		st->st_ctime = 0;
-		st->st_ctime_nsec = 0;
-		st->st_ino = 0;
-		st->st_nlink = 1;
-		st->st_uid = 0;
-		st->st_gid = 0;
-		st->st_rdev = 0;
-		st->st_dev = 0;
-		return (0);
-	case FILE_TYPE_DISK:
-		break;
-	default:
-		/* This ftype is undocumented type. */
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-
-	ZeroMemory(&info, sizeof(info));
-	if (!GetFileInformationByHandle (handle, &info)) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-
-	mode = S_IRUSR | S_IRGRP | S_IROTH;
-	if ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
-		mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-	if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-		mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
-	else
-		mode |= S_IFREG;
-	st->st_mode = mode;
-
-	fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
-	st->st_atime = t;
-	st->st_atime_nsec = ns;
-	fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
-	st->st_mtime = t;
-	st->st_mtime_nsec = ns;
-	fileTimeToUTC(&info.ftCreationTime, &t, &ns);
-	st->st_ctime = t;
-	st->st_ctime_nsec = ns;
-	st->st_size =
-	    ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
-		+ (int64_t)(info.nFileSizeLow);
-#ifdef SIMULATE_WIN_STAT
-	st->st_ino = 0;
-	st->st_nlink = 1;
-	st->st_dev = 0;
-#else
-	/* Getting FileIndex as i-node. We should remove a sequence which
-	 * is high-16-bits of nFileIndexHigh. */
-	ino64.HighPart = info.nFileIndexHigh & 0x0000FFFFUL;
-	ino64.LowPart  = info.nFileIndexLow;
-	st->st_ino = ino64.QuadPart;
-	st->st_nlink = info.nNumberOfLinks;
-	if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-		++st->st_nlink;/* Add parent directory. */
-	st->st_dev = info.dwVolumeSerialNumber;
-#endif
-	st->st_uid = 0;
-	st->st_gid = 0;
-	st->st_rdev = 0;
-	return (0);
-}
-
-static void
-copy_stat(struct stat *st, struct ustat *us)
-{
-	st->st_atime = us->st_atime;
-	st->st_ctime = us->st_ctime;
-	st->st_mtime = us->st_mtime;
-	st->st_gid = us->st_gid;
-	st->st_ino = getino(us);
-	st->st_mode = us->st_mode;
-	st->st_nlink = us->st_nlink;
-	st->st_size = (off_t)us->st_size;
-	st->st_uid = us->st_uid;
-	st->st_dev = us->st_dev;
-	st->st_rdev = us->st_rdev;
-}
-
-/*
- * TODO: Remove a use of __la_fstat and __la_stat.
- * We should use GetFileInformationByHandle in place
- * where We still use the *stat functions.
- */
-int
-__la_fstat(int fd, struct stat *st)
-{
-	struct ustat u;
-	int ret;
-
-	if (fd < 0) {
-		errno = EBADF;
-		return (-1);
-	}
-	ret = __hstat((HANDLE)_get_osfhandle(fd), &u);
-	if (ret >= 0) {
-		copy_stat(st, &u);
-		if (u.st_mode & (S_IFCHR | S_IFIFO)) {
-			st->st_dev = fd;
-			st->st_rdev = fd;
-		}
-	}
-	return (ret);
-}
-
-/* This can exceed MAX_PATH limitation. */
-int
-__la_stat(const char *path, struct stat *st)
-{
-	HANDLE handle;
-	struct ustat u;
-	int ret;
-
-	handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
-		FILE_FLAG_BACKUP_SEMANTICS,
-		NULL);
-	if (handle == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-	ret = __hstat(handle, &u);
-	CloseHandle(handle);
-	if (ret >= 0) {
-		char *p;
-
-		copy_stat(st, &u);
-		p = strrchr(path, '.');
-		if (p != NULL && strlen(p) == 4) {
-			char exttype[4];
-
-			++ p;
-			exttype[0] = toupper(*p++);
-			exttype[1] = toupper(*p++);
-			exttype[2] = toupper(*p++);
-			exttype[3] = '\0';
-			if (!strcmp(exttype, "EXE") || !strcmp(exttype, "CMD") ||
-				!strcmp(exttype, "BAT") || !strcmp(exttype, "COM"))
-				st->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-		}
-	}
-	return (ret);
-}
-
-/*
- * This waitpid is limited implementation.
- */
-pid_t
-__la_waitpid(HANDLE child, int *status, int option)
-{
-	DWORD cs;
-
-	(void)option;/* UNUSED */
-	do {
-		if (GetExitCodeProcess(child, &cs) == 0) {
-			CloseHandle(child);
-			la_dosmaperr(GetLastError());
-			*status = 0;
-			return (-1);
-		}
-	} while (cs == STILL_ACTIVE);
-
-	*status = (int)(cs & 0xff);
-	return (0);
-}
-
-ssize_t
-__la_write(int fd, const void *buf, size_t nbytes)
-{
-	DWORD bytes_written;
-
-#ifdef _WIN64
-	if (nbytes > UINT32_MAX)
-		nbytes = UINT32_MAX;
-#endif
-	if (fd < 0) {
-		errno = EBADF;
-		return (-1);
-	}
-	if (!WriteFile((HANDLE)_get_osfhandle(fd), buf, (uint32_t)nbytes,
-	    &bytes_written, NULL)) {
-		DWORD lasterr;
-
-		lasterr = GetLastError();
-		if (lasterr == ERROR_ACCESS_DENIED)
-			errno = EBADF;
-		else
-			la_dosmaperr(lasterr);
-		return (-1);
-	}
-	return (bytes_written);
-}
-
-/*
- * Replace the Windows path separator '\' with '/'.
- */
-static int
-replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp)
-{
-	wchar_t *w;
-	size_t path_length;
-
-	if (wp == NULL)
-		return(0);
-	if (wcschr(wp, L'\\') == NULL)
-		return(0);
-	path_length = wcslen(wp);
-	if (archive_wstring_ensure(ws, path_length) == NULL)
-		return(-1);
-	archive_wstrncpy(ws, wp, path_length);
-	for (w = ws->s; *w; w++) {
-		if (*w == L'\\')
-			*w = L'/';
-	}
-	return(1);
-}
-
-static int
-fix_pathseparator(struct archive_entry *entry)
-{
-	struct archive_wstring ws;
-	const wchar_t *wp;
-	int ret = ARCHIVE_OK;
-
-	archive_string_init(&ws);
-	wp = archive_entry_pathname_w(entry);
-	switch (replace_pathseparator(&ws, wp)) {
-	case 0: /* Not replaced. */
-		break;
-	case 1: /* Replaced. */
-		archive_entry_copy_pathname_w(entry, ws.s);
-		break;
-	default:
-		ret = ARCHIVE_FAILED;
-	}
-	wp = archive_entry_hardlink_w(entry);
-	switch (replace_pathseparator(&ws, wp)) {
-	case 0: /* Not replaced. */
-		break;
-	case 1: /* Replaced. */
-		archive_entry_copy_hardlink_w(entry, ws.s);
-		break;
-	default:
-		ret = ARCHIVE_FAILED;
-	}
-	wp = archive_entry_symlink_w(entry);
-	switch (replace_pathseparator(&ws, wp)) {
-	case 0: /* Not replaced. */
-		break;
-	case 1: /* Replaced. */
-		archive_entry_copy_symlink_w(entry, ws.s);
-		break;
-	default:
-		ret = ARCHIVE_FAILED;
-	}
-	archive_wstring_free(&ws);
-	return(ret);
-}
-
-struct archive_entry *
-__la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
-{
-	struct archive_entry *entry_main;
-	const wchar_t *wp;
-	int has_backslash = 0;
-	int ret;
-
-	wp = archive_entry_pathname_w(entry);
-	if (wp != NULL && wcschr(wp, L'\\') != NULL)
-		has_backslash = 1;
-	if (!has_backslash) {
-		wp = archive_entry_hardlink_w(entry);
-		if (wp != NULL && wcschr(wp, L'\\') != NULL)
-			has_backslash = 1;
-	}
-	if (!has_backslash) {
-		wp = archive_entry_symlink_w(entry);
-		if (wp != NULL && wcschr(wp, L'\\') != NULL)
-			has_backslash = 1;
-	}
-	/*
-	 * If there is no backslash chars, return the original.
-	 */
-	if (!has_backslash)
-		return (entry);
-
-	/* Copy entry so we can modify it as needed. */
-	entry_main = archive_entry_clone(entry);
-	if (entry_main == NULL)
-		return (NULL);
-	/* Replace the Windows path-separator '\' with '/'. */
-	ret = fix_pathseparator(entry_main);
-	if (ret < ARCHIVE_WARN) {
-		archive_entry_free(entry_main);
-		return (NULL);
-	}
-	return (entry_main);
-}
-
-
-/*
- * The following function was modified from PostgreSQL sources and is
- * subject to the copyright below.
- */
-/*-------------------------------------------------------------------------
- *
- * win32error.c
- *	  Map win32 error codes to errno values
- *
- * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*
-PostgreSQL Database Management System
-(formerly known as Postgres, then as Postgres95)
-
-Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
-
-Portions Copyright (c) 1994, The Regents of the University of California
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose, without fee, and without a written agreement
-is hereby granted, provided that the above copyright notice and this
-paragraph and the following two paragraphs appear in all copies.
-
-IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
-DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
-LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
-DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
-PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-*/
-
-static const struct {
-	DWORD		winerr;
-	int		doserr;
-} doserrors[] =
-{
-	{	ERROR_INVALID_FUNCTION, EINVAL	},
-	{	ERROR_FILE_NOT_FOUND, ENOENT	},
-	{	ERROR_PATH_NOT_FOUND, ENOENT	},
-	{	ERROR_TOO_MANY_OPEN_FILES, EMFILE	},
-	{	ERROR_ACCESS_DENIED, EACCES	},
-	{	ERROR_INVALID_HANDLE, EBADF	},
-	{	ERROR_ARENA_TRASHED, ENOMEM	},
-	{	ERROR_NOT_ENOUGH_MEMORY, ENOMEM	},
-	{	ERROR_INVALID_BLOCK, ENOMEM	},
-	{	ERROR_BAD_ENVIRONMENT, E2BIG	},
-	{	ERROR_BAD_FORMAT, ENOEXEC	},
-	{	ERROR_INVALID_ACCESS, EINVAL	},
-	{	ERROR_INVALID_DATA, EINVAL	},
-	{	ERROR_INVALID_DRIVE, ENOENT	},
-	{	ERROR_CURRENT_DIRECTORY, EACCES	},
-	{	ERROR_NOT_SAME_DEVICE, EXDEV	},
-	{	ERROR_NO_MORE_FILES, ENOENT	},
-	{	ERROR_LOCK_VIOLATION, EACCES	},
-	{	ERROR_SHARING_VIOLATION, EACCES	},
-	{	ERROR_BAD_NETPATH, ENOENT	},
-	{	ERROR_NETWORK_ACCESS_DENIED, EACCES	},
-	{	ERROR_BAD_NET_NAME, ENOENT	},
-	{	ERROR_FILE_EXISTS, EEXIST	},
-	{	ERROR_CANNOT_MAKE, EACCES	},
-	{	ERROR_FAIL_I24, EACCES	},
-	{	ERROR_INVALID_PARAMETER, EINVAL	},
-	{	ERROR_NO_PROC_SLOTS, EAGAIN	},
-	{	ERROR_DRIVE_LOCKED, EACCES	},
-	{	ERROR_BROKEN_PIPE, EPIPE	},
-	{	ERROR_DISK_FULL, ENOSPC	},
-	{	ERROR_INVALID_TARGET_HANDLE, EBADF	},
-	{	ERROR_INVALID_HANDLE, EINVAL	},
-	{	ERROR_WAIT_NO_CHILDREN, ECHILD	},
-	{	ERROR_CHILD_NOT_COMPLETE, ECHILD	},
-	{	ERROR_DIRECT_ACCESS_HANDLE, EBADF	},
-	{	ERROR_NEGATIVE_SEEK, EINVAL	},
-	{	ERROR_SEEK_ON_DEVICE, EACCES	},
-	{	ERROR_DIR_NOT_EMPTY, ENOTEMPTY	},
-	{	ERROR_NOT_LOCKED, EACCES	},
-	{	ERROR_BAD_PATHNAME, ENOENT	},
-	{	ERROR_MAX_THRDS_REACHED, EAGAIN	},
-	{	ERROR_LOCK_FAILED, EACCES	},
-	{	ERROR_ALREADY_EXISTS, EEXIST	},
-	{	ERROR_FILENAME_EXCED_RANGE, ENOENT	},
-	{	ERROR_NESTING_NOT_ALLOWED, EAGAIN	},
-	{	ERROR_NOT_ENOUGH_QUOTA, ENOMEM	}
-};
-
-void
-__la_dosmaperr(unsigned long e)
-{
-	int			i;
-
-	if (e == 0)
-	{
-		errno = 0;
-		return;
-	}
-
-	for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
-	{
-		if (doserrors[i].winerr == e)
-		{
-			errno = doserrors[i].doserr;
-			return;
-		}
-	}
-
-	/* fprintf(stderr, "unrecognized win32 error code: %lu", e); */
-	errno = EINVAL;
-	return;
-}
-
-#endif /* _WIN32 && !__CYGWIN__ */
diff --git a/c/archive_windows.h b/c/archive_windows.h
deleted file mode 100644
--- a/c/archive_windows.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*-
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
- * Copyright (c) 2003-2006 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * TODO: A lot of stuff in here isn't actually used by libarchive and
- * can be trimmed out.  Note that this file is used by libarchive and
- * libarchive_test but nowhere else.  (But note that it gets compiled
- * with many different Windows environments, including MinGW, Visual
- * Studio, and Cygwin.  Significant changes should be tested in all three.)
- */
-
-/*
- * TODO: Don't use off_t in here.  Use __int64 instead.  Note that
- * Visual Studio and the Windows SDK define off_t as 32 bits; Win32's
- * more modern file handling APIs all use __int64 instead of off_t.
- */
-
-#ifndef LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
-#define	LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-/* Start of configuration for native Win32  */
-#ifndef MINGW_HAS_SECURE_API
-#define MINGW_HAS_SECURE_API 1
-#endif
-
-#include <errno.h>
-#define	set_errno(val)	((errno)=val)
-#include <io.h>
-#include <stdlib.h>   //brings in NULL
-#if defined(HAVE_STDINT_H)
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <process.h>
-#include <direct.h>
-#if defined(__MINGW32__) && defined(HAVE_UNISTD_H)
-/* Prevent build error from a type mismatch of ftruncate().
- * This unistd.h defines it as ftruncate(int, off_t). */
-#include <unistd.h>
-#endif
-#define NOCRYPT
-#include <windows.h>
-//#define	EFTYPE 7
-
-#if defined(__BORLANDC__)
-#pragma warn -8068	/* Constant out of range in comparison. */
-#pragma warn -8072	/* Suspicious pointer arithmetic. */
-#endif
-
-#ifndef NULL
-#ifdef  __cplusplus
-#define	NULL    0
-#else
-#define	NULL    ((void *)0)
-#endif
-#endif
-
-/* Alias the Windows _function to the POSIX equivalent. */
-#define	close		_close
-#define	fcntl(fd, cmd, flg)	/* No operation. */
-#ifndef fileno
-#define	fileno		_fileno
-#endif
-#ifdef fstat
-#undef fstat
-#endif
-#define	fstat		__la_fstat
-#if !defined(__BORLANDC__)
-#ifdef lseek
-#undef lseek
-#endif
-#define	lseek		_lseeki64
-#else
-#define	lseek		__la_lseek
-#define __LA_LSEEK_NEEDED
-#endif
-#define	lstat		__la_stat
-#define	open		__la_open
-#define	read		__la_read
-#if !defined(__BORLANDC__) && !defined(__WATCOMC__)
-#define setmode		_setmode
-#endif
-#define	la_stat(path,stref)		__la_stat(path,stref)
-#if !defined(__WATCOMC__)
-#if !defined(__BORLANDC__)
-#define	strdup		_strdup
-#endif
-#define	tzset		_tzset
-#if !defined(__BORLANDC__)
-#define	umask		_umask
-#endif
-#endif
-#define	waitpid		__la_waitpid
-#define	write		__la_write
-
-#if !defined(__WATCOMC__)
-
-#ifndef O_RDONLY
-#define	O_RDONLY	_O_RDONLY
-#define	O_WRONLY	_O_WRONLY
-#define	O_TRUNC		_O_TRUNC
-#define	O_CREAT		_O_CREAT
-#define	O_EXCL		_O_EXCL
-#define	O_BINARY	_O_BINARY
-#endif
-
-#ifndef _S_IFIFO
-  #define	_S_IFIFO        0010000   /* pipe */
-#endif
-#ifndef _S_IFCHR
-  #define	_S_IFCHR        0020000   /* character special */
-#endif
-#ifndef _S_IFDIR
-  #define	_S_IFDIR        0040000   /* directory */
-#endif
-#ifndef _S_IFBLK
-  #define	_S_IFBLK        0060000   /* block special */
-#endif
-#ifndef _S_IFLNK
-  #define	_S_IFLNK        0120000   /* symbolic link */
-#endif
-#ifndef _S_IFSOCK
-  #define	_S_IFSOCK       0140000   /* socket */
-#endif
-#ifndef	_S_IFREG
-  #define	_S_IFREG        0100000   /* regular */
-#endif
-#ifndef	_S_IFMT
-  #define	_S_IFMT         0170000   /* file type mask */
-#endif
-
-#ifndef S_IFIFO
-#define	S_IFIFO     _S_IFIFO
-#endif
-//#define	S_IFCHR  _S_IFCHR
-//#define	S_IFDIR  _S_IFDIR
-#ifndef S_IFBLK
-#define	S_IFBLK     _S_IFBLK
-#endif
-#ifndef S_IFLNK
-#define	S_IFLNK     _S_IFLNK
-#endif
-#ifndef S_IFSOCK
-#define	S_IFSOCK    _S_IFSOCK
-#endif
-//#define	S_IFREG  _S_IFREG
-//#define	S_IFMT   _S_IFMT
-
-#ifndef S_ISBLK
-#define	S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)	/* block special */
-#define	S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)	/* fifo or socket */
-#define	S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)	/* char special */
-#define	S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)	/* directory */
-#define	S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)	/* regular file */
-#endif
-#define	S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK) /* Symbolic link */
-#define	S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* Socket */
-
-#define	_S_ISUID        0004000   /* set user id on execution */
-#define	_S_ISGID        0002000   /* set group id on execution */
-#define	_S_ISVTX        0001000   /* save swapped text even after use */
-
-#define	S_ISUID        _S_ISUID
-#define	S_ISGID        _S_ISGID
-#define	S_ISVTX        _S_ISVTX
-
-#define	_S_IRWXU	     (_S_IREAD | _S_IWRITE | _S_IEXEC)
-#define	_S_IXUSR	     _S_IEXEC  /* read permission, user */
-#define	_S_IWUSR	     _S_IWRITE /* write permission, user */
-#define	_S_IRUSR	     _S_IREAD  /* execute/search permission, user */
-#define	_S_IRWXG        (_S_IRWXU >> 3)
-#define	_S_IXGRP        (_S_IXUSR >> 3) /* read permission, group */
-#define	_S_IWGRP        (_S_IWUSR >> 3) /* write permission, group */
-#define	_S_IRGRP        (_S_IRUSR >> 3) /* execute/search permission, group */
-#define	_S_IRWXO        (_S_IRWXG >> 3)
-#define	_S_IXOTH        (_S_IXGRP >> 3) /* read permission, other */
-#define	_S_IWOTH        (_S_IWGRP >> 3) /* write permission, other */
-#define	_S_IROTH        (_S_IRGRP  >> 3) /* execute/search permission, other */
-
-#ifndef S_IRWXU
-#define	S_IRWXU	     _S_IRWXU
-#define	S_IXUSR	     _S_IXUSR
-#define	S_IWUSR	     _S_IWUSR
-#define	S_IRUSR	     _S_IRUSR
-#endif
-#ifndef S_IRWXG
-#define	S_IRWXG        _S_IRWXG
-#define	S_IXGRP        _S_IXGRP
-#define	S_IWGRP        _S_IWGRP
-#endif
-#ifndef S_IRGRP
-#define	S_IRGRP        _S_IRGRP
-#endif
-#ifndef S_IRWXO
-#define	S_IRWXO        _S_IRWXO
-#define	S_IXOTH        _S_IXOTH
-#define	S_IWOTH        _S_IWOTH
-#define	S_IROTH        _S_IROTH
-#endif
-
-#endif
-
-#define	F_DUPFD	  	0	/* Duplicate file descriptor.  */
-#define	F_GETFD		1	/* Get file descriptor flags.  */
-#define	F_SETFD		2	/* Set file descriptor flags.  */
-#define	F_GETFL		3	/* Get file status flags.  */
-#define	F_SETFL		4	/* Set file status flags.  */
-#define	F_GETOWN		5	/* Get owner (receiver of SIGIO).  */
-#define	F_SETOWN		6	/* Set owner (receiver of SIGIO).  */
-#define	F_GETLK		7	/* Get record locking info.  */
-#define	F_SETLK		8	/* Set record locking info (non-blocking).  */
-#define	F_SETLKW		9	/* Set record locking info (blocking).  */
-
-/* XXX missing */
-#define	F_GETLK64	7	/* Get record locking info.  */
-#define	F_SETLK64	8	/* Set record locking info (non-blocking).  */
-#define	F_SETLKW64	9	/* Set record locking info (blocking).  */
-
-/* File descriptor flags used with F_GETFD and F_SETFD.  */
-#define	FD_CLOEXEC	1	/* Close on exec.  */
-
-//NOT SURE IF O_NONBLOCK is OK here but at least the 0x0004 flag is not used by anything else...
-#define	O_NONBLOCK 0x0004 /* Non-blocking I/O.  */
-//#define	O_NDELAY   O_NONBLOCK
-
-/* Symbolic constants for the access() function */
-#if !defined(F_OK)
-    #define	R_OK    4       /*  Test for read permission    */
-    #define	W_OK    2       /*  Test for write permission   */
-    #define	X_OK    1       /*  Test for execute permission */
-    #define	F_OK    0       /*  Test for existence of file  */
-#endif
-
-
-/* Replacement POSIX function */
-extern int	 __la_fstat(int fd, struct stat *st);
-extern int	 __la_lstat(const char *path, struct stat *st);
-#if defined(__LA_LSEEK_NEEDED)
-extern __int64	 __la_lseek(int fd, __int64 offset, int whence);
-#endif
-extern int	 __la_open(const char *path, int flags, ...);
-extern ssize_t	 __la_read(int fd, void *buf, size_t nbytes);
-extern int	 __la_stat(const char *path, struct stat *st);
-extern pid_t	 __la_waitpid(HANDLE child, int *status, int option);
-extern ssize_t	 __la_write(int fd, const void *buf, size_t nbytes);
-
-#define _stat64i32(path, st)	__la_stat(path, st)
-#define _stat64(path, st)	__la_stat(path, st)
-/* for status returned by la_waitpid */
-#define WIFEXITED(sts)		((sts & 0x100) == 0)
-#define WEXITSTATUS(sts)	(sts & 0x0FF)
-
-extern wchar_t *__la_win_permissive_name(const char *name);
-extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname);
-extern void __la_dosmaperr(unsigned long e);
-#define la_dosmaperr(e) __la_dosmaperr(e)
-extern struct archive_entry *__la_win_entry_in_posix_pathseparator(
-    struct archive_entry *);
-
-#if defined(HAVE_WCRTOMB) && defined(__BORLANDC__)
-typedef int mbstate_t;
-size_t wcrtomb(char *, wchar_t, mbstate_t *);
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-WINBASEAPI BOOL WINAPI GetVolumePathNameW(
-       LPCWSTR lpszFileName,
-       LPWSTR lpszVolumePathName,
-       DWORD cchBufferLength
-       );
-# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */
-typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
-       LARGE_INTEGER FileOffset;
-       LARGE_INTEGER Length;
-} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;
-#  define FSCTL_SET_SPARSE \
-     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA)
-#  define FSCTL_QUERY_ALLOCATED_RANGES \
-     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51,  METHOD_NEITHER, FILE_READ_DATA)
-# endif
-#endif
-
-#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */
diff --git a/c/archive_write.c b/c/archive_write.c
deleted file mode 100644
--- a/c/archive_write.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write.c 201099 2009-12-28 03:03:00Z kientzle $");
-
-/*
- * This file contains the "essential" portions of the write API, that
- * is, stuff that will essentially always be used by any client that
- * actually needs to write an archive.  Optional pieces have been, as
- * far as possible, separated out into separate files to reduce
- * needlessly bloating statically-linked clients.
- */
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-
-static int	_archive_filter_code(struct archive *, int);
-static const char *_archive_filter_name(struct archive *, int);
-static int64_t	_archive_filter_bytes(struct archive *, int);
-static int  _archive_write_filter_count(struct archive *);
-static int	_archive_write_close(struct archive *);
-static int	_archive_write_free(struct archive *);
-static int	_archive_write_header(struct archive *, struct archive_entry *);
-static int	_archive_write_finish_entry(struct archive *);
-static ssize_t	_archive_write_data(struct archive *, const void *, size_t);
-
-struct archive_none {
-	size_t buffer_size;
-	size_t avail;
-	char *buffer;
-	char *next;
-};
-
-static const struct archive_vtable
-archive_write_vtable = {
-	.archive_close = _archive_write_close,
-	.archive_filter_bytes = _archive_filter_bytes,
-	.archive_filter_code = _archive_filter_code,
-	.archive_filter_name = _archive_filter_name,
-	.archive_filter_count = _archive_write_filter_count,
-	.archive_free = _archive_write_free,
-	.archive_write_header = _archive_write_header,
-	.archive_write_finish_entry = _archive_write_finish_entry,
-	.archive_write_data = _archive_write_data,
-};
-
-/*
- * Allocate, initialize and return an archive object.
- */
-struct archive *
-archive_write_new(void)
-{
-	struct archive_write *a;
-	unsigned char *nulls;
-
-	a = (struct archive_write *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_WRITE_MAGIC;
-	a->archive.state = ARCHIVE_STATE_NEW;
-	a->archive.vtable = &archive_write_vtable;
-	/*
-	 * The value 10240 here matches the traditional tar default,
-	 * but is otherwise arbitrary.
-	 * TODO: Set the default block size from the format selected.
-	 */
-	a->bytes_per_block = 10240;
-	a->bytes_in_last_block = -1;	/* Default */
-
-	/* Initialize a block of nulls for padding purposes. */
-	a->null_length = 1024;
-	nulls = (unsigned char *)calloc(1, a->null_length);
-	if (nulls == NULL) {
-		free(a);
-		return (NULL);
-	}
-	a->nulls = nulls;
-	return (&a->archive);
-}
-
-/*
- * Set the block size.  Returns 0 if successful.
- */
-int
-archive_write_set_bytes_per_block(struct archive *_a, int bytes_per_block)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_bytes_per_block");
-	a->bytes_per_block = bytes_per_block;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Get the current block size.  -1 if it has never been set.
- */
-int
-archive_write_get_bytes_per_block(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_get_bytes_per_block");
-	return (a->bytes_per_block);
-}
-
-/*
- * Set the size for the last block.
- * Returns 0 if successful.
- */
-int
-archive_write_set_bytes_in_last_block(struct archive *_a, int bytes)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_set_bytes_in_last_block");
-	a->bytes_in_last_block = bytes;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Return the value set above.  -1 indicates it has not been set.
- */
-int
-archive_write_get_bytes_in_last_block(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_get_bytes_in_last_block");
-	return (a->bytes_in_last_block);
-}
-
-/*
- * dev/ino of a file to be rejected.  Used to prevent adding
- * an archive to itself recursively.
- */
-int
-archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_set_skip_file");
-	a->skip_file_set = 1;
-	a->skip_file_dev = d;
-	a->skip_file_ino = i;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Allocate and return the next filter structure.
- */
-struct archive_write_filter *
-__archive_write_allocate_filter(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f;
-
-	f = calloc(1, sizeof(*f));
-
-	if (f == NULL)
-		return (NULL);
-
-	f->archive = _a;
-	f->state = ARCHIVE_WRITE_FILTER_STATE_NEW;
-	if (a->filter_first == NULL)
-		a->filter_first = f;
-	else
-		a->filter_last->next_filter = f;
-	a->filter_last = f;
-	return f;
-}
-
-/*
- * Write data to a particular filter.
- */
-int
-__archive_write_filter(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	int r;
-	/* Never write to non-open filters */
-	if (f->state != ARCHIVE_WRITE_FILTER_STATE_OPEN)
-		return(ARCHIVE_FATAL);
-	if (length == 0)
-		return(ARCHIVE_OK);
-	if (f->write == NULL)
-		/* If unset, a fatal error has already occurred, so this filter
-		 * didn't open. We cannot write anything. */
-		return(ARCHIVE_FATAL);
-	r = (f->write)(f, buff, length);
-	f->bytes_written += length;
-	return (r);
-}
-
-/*
- * Recursive function for opening the filter chain
- * Last filter is opened first
- */
-static int
-__archive_write_open_filter(struct archive_write_filter *f)
-{
-	int ret;
-
-	ret = ARCHIVE_OK;
-	if (f->next_filter != NULL)
-		ret = __archive_write_open_filter(f->next_filter);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	if (f->state != ARCHIVE_WRITE_FILTER_STATE_NEW)
-		return (ARCHIVE_FATAL);
-	if (f->open == NULL) {
-		f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN;
-		return (ARCHIVE_OK);
-	}
-	ret = (f->open)(f);
-	if (ret == ARCHIVE_OK)
-		f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN;
-	else
-		f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL;
-	return (ret);
-}
-
-/*
- * Open all filters
- */
-static int
-__archive_write_filters_open(struct archive_write *a)
-{
-	return (__archive_write_open_filter(a->filter_first));
-}
-
-/*
- * Close all filtes
- */
-static int
-__archive_write_filters_close(struct archive_write *a)
-{
-	struct archive_write_filter *f;
-	int ret, ret1;
-	ret = ARCHIVE_OK;
-	for (f = a->filter_first; f != NULL; f = f->next_filter) {
-		/* Do not close filters that are not open */
-		if (f->state == ARCHIVE_WRITE_FILTER_STATE_OPEN) {
-			if (f->close != NULL) {
-				ret1 = (f->close)(f);
-				if (ret1 < ret)
-					ret = ret1;
-				if (ret1 == ARCHIVE_OK) {
-					f->state =
-					    ARCHIVE_WRITE_FILTER_STATE_CLOSED;
-				} else {
-					f->state =
-					    ARCHIVE_WRITE_FILTER_STATE_FATAL;
-				}
-			} else
-				f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
-		}
-	}
-	return (ret);
-}
-
-int
-__archive_write_output(struct archive_write *a, const void *buff, size_t length)
-{
-	return (__archive_write_filter(a->filter_first, buff, length));
-}
-
-static int
-__archive_write_filters_flush(struct archive_write *a)
-{
-	struct archive_write_filter *f;
-	int ret, ret1;
-
-	ret = ARCHIVE_OK;
-	for (f = a->filter_first; f != NULL; f = f->next_filter) {
-		if (f->flush != NULL && f->bytes_written > 0) {
-			ret1 = (f->flush)(f);
-			if (ret1 < ret)
-				ret = ret1;
-			if (ret1 < ARCHIVE_WARN)
-				f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL;
-		}
-	}
-	return (ret);
-}
-
-int
-__archive_write_nulls(struct archive_write *a, size_t length)
-{
-	if (length == 0)
-		return (ARCHIVE_OK);
-
-	while (length > 0) {
-		size_t to_write = length < a->null_length ? length : a->null_length;
-		int r = __archive_write_output(a, a->nulls, to_write);
-		if (r < ARCHIVE_OK)
-			return (r);
-		length -= to_write;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_client_open(struct archive_write_filter *f)
-{
-	struct archive_write *a = (struct archive_write *)f->archive;
-	struct archive_none *state;
-	void *buffer;
-	size_t buffer_size;
-	int ret;
-
-	f->bytes_per_block = archive_write_get_bytes_per_block(f->archive);
-	f->bytes_in_last_block =
-	    archive_write_get_bytes_in_last_block(f->archive);
-	buffer_size = f->bytes_per_block;
-
-	state = (struct archive_none *)calloc(1, sizeof(*state));
-	buffer = (char *)malloc(buffer_size);
-	if (state == NULL || buffer == NULL) {
-		free(state);
-		free(buffer);
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for output buffering");
-		return (ARCHIVE_FATAL);
-	}
-
-	state->buffer_size = buffer_size;
-	state->buffer = buffer;
-	state->next = state->buffer;
-	state->avail = state->buffer_size;
-	f->data = state;
-
-	if (a->client_opener == NULL)
-		return (ARCHIVE_OK);
-	ret = a->client_opener(f->archive, a->client_data);
-	if (ret != ARCHIVE_OK) {
-		free(state->buffer);
-		free(state);
-		f->data = NULL;
-	}
-	return (ret);
-}
-
-static int
-archive_write_client_write(struct archive_write_filter *f,
-    const void *_buff, size_t length)
-{
-	struct archive_write *a = (struct archive_write *)f->archive;
-        struct archive_none *state = (struct archive_none *)f->data;
-	const char *buff = (const char *)_buff;
-	ssize_t remaining, to_copy;
-	ssize_t bytes_written;
-
-	remaining = length;
-
-	/*
-	 * If there is no buffer for blocking, just pass the data
-	 * straight through to the client write callback.  In
-	 * particular, this supports "no write delay" operation for
-	 * special applications.  Just set the block size to zero.
-	 */
-	if (state->buffer_size == 0) {
-		while (remaining > 0) {
-			bytes_written = (a->client_writer)(&a->archive,
-			    a->client_data, buff, remaining);
-			if (bytes_written <= 0)
-				return (ARCHIVE_FATAL);
-			remaining -= bytes_written;
-			buff += bytes_written;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/* 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 = ((size_t)remaining > state->avail) ?
-			state->avail : (size_t)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) {
-			char *p = state->buffer;
-			size_t to_write = state->buffer_size;
-			while (to_write > 0) {
-				bytes_written = (a->client_writer)(&a->archive,
-				    a->client_data, p, to_write);
-				if (bytes_written <= 0)
-					return (ARCHIVE_FATAL);
-				if ((size_t)bytes_written > to_write) {
-					archive_set_error(&(a->archive),
-					    -1, "write overrun");
-					return (ARCHIVE_FATAL);
-				}
-				p += bytes_written;
-				to_write -= bytes_written;
-			}
-			state->next = state->buffer;
-			state->avail = state->buffer_size;
-		}
-	}
-
-	while ((size_t)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);
-		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;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_client_free(struct archive_write_filter *f)
-{
-	struct archive_write *a = (struct archive_write *)f->archive;
-
-	if (a->client_freer)
-		(*a->client_freer)(&a->archive, a->client_data);
-	a->client_data = NULL;
-
-	/* Clear passphrase. */
-	if (a->passphrase != NULL) {
-		memset(a->passphrase, 0, strlen(a->passphrase));
-		free(a->passphrase);
-		a->passphrase = NULL;
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_client_close(struct archive_write_filter *f)
-{
-	struct archive_write *a = (struct archive_write *)f->archive;
-	struct archive_none *state = (struct archive_none *)f->data;
-	ssize_t block_length;
-	ssize_t target_block_length;
-	ssize_t bytes_written;
-	size_t to_write;
-	char *p;
-	int ret = ARCHIVE_OK;
-
-	/* If there's pending data, pad and write the last block */
-	if (state->next != state->buffer) {
-		block_length = state->buffer_size - state->avail;
-
-		/* Tricky calculation to determine size of last block */
-		if (a->bytes_in_last_block <= 0)
-			/* Default or Zero: pad to full block */
-			target_block_length = a->bytes_per_block;
-		else
-			/* Round to next multiple of bytes_in_last_block. */
-			target_block_length = a->bytes_in_last_block *
-			    ( (block_length + a->bytes_in_last_block - 1) /
-			        a->bytes_in_last_block);
-		if (target_block_length > a->bytes_per_block)
-			target_block_length = a->bytes_per_block;
-		if (block_length < target_block_length) {
-			memset(state->next, 0,
-			    target_block_length - block_length);
-			block_length = target_block_length;
-		}
-		p = state->buffer;
-		to_write = block_length;
-		while (to_write > 0) {
-			bytes_written = (a->client_writer)(&a->archive,
-			    a->client_data, p, to_write);
-			if (bytes_written <= 0) {
-				ret = ARCHIVE_FATAL;
-				break;
-			}
-			if ((size_t)bytes_written > to_write) {
-				archive_set_error(&(a->archive),
-						  -1, "write overrun");
-				ret = ARCHIVE_FATAL;
-				break;
-			}
-			p += bytes_written;
-			to_write -= bytes_written;
-		}
-	}
-	if (a->client_closer)
-		(*a->client_closer)(&a->archive, a->client_data);
-	free(state->buffer);
-	free(state);
-
-	/* Clear the close handler myself not to be called again. */
-	f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
-	return (ret);
-}
-
-/*
- * Open the archive using the current settings.
- */
-int
-archive_write_open2(struct archive *_a, void *client_data,
-    archive_open_callback *opener, archive_write_callback *writer,
-    archive_close_callback *closer, archive_free_callback *freer)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *client_filter;
-	int ret, r1;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_open");
-	archive_clear_error(&a->archive);
-
-	a->client_writer = writer;
-	a->client_opener = opener;
-	a->client_closer = closer;
-	a->client_freer = freer;
-	a->client_data = client_data;
-
-	client_filter = __archive_write_allocate_filter(_a);
-
-	if (client_filter == NULL)
-		return (ARCHIVE_FATAL);
-
-	client_filter->open = archive_write_client_open;
-	client_filter->write = archive_write_client_write;
-	client_filter->close = archive_write_client_close;
-	client_filter->free = archive_write_client_free;
-
-	ret = __archive_write_filters_open(a);
-	if (ret < ARCHIVE_WARN) {
-		r1 = __archive_write_filters_close(a);
-		__archive_write_filters_free(_a);
-		return (r1 < ret ? r1 : ret);
-	}
-
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	if (a->format_init)
-		ret = (a->format_init)(a);
-	return (ret);
-}
-
-int
-archive_write_open(struct archive *_a, void *client_data,
-    archive_open_callback *opener, archive_write_callback *writer,
-    archive_close_callback *closer)
-{
-	return archive_write_open2(_a, client_data, opener, writer,
-	    closer, NULL);
-}
-
-/*
- * Close out the archive.
- */
-static int
-_archive_write_close(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL,
-	    "archive_write_close");
-	if (a->archive.state == ARCHIVE_STATE_NEW
-	    || a->archive.state == ARCHIVE_STATE_CLOSED)
-		return (ARCHIVE_OK); /* Okay to close() when not open. */
-
-	archive_clear_error(&a->archive);
-
-	/* Finish the last entry if a finish callback is specified */
-	if (a->archive.state == ARCHIVE_STATE_DATA
-	    && a->format_finish_entry != NULL)
-		r = ((a->format_finish_entry)(a));
-
-	/* Finish off the archive. */
-	/* TODO: have format closers invoke compression close. */
-	if (a->format_close != NULL) {
-		r1 = (a->format_close)(a);
-		if (r1 < r)
-			r = r1;
-	}
-
-	/* Finish the compression and close the stream. */
-	r1 = __archive_write_filters_close(a);
-	if (r1 < r)
-		r = r1;
-
-	if (a->archive.state != ARCHIVE_STATE_FATAL)
-		a->archive.state = ARCHIVE_STATE_CLOSED;
-	return (r);
-}
-
-static int
-_archive_write_filter_count(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *p = a->filter_first;
-	int count = 0;
-	while(p) {
-		count++;
-		p = p->next_filter;
-	}
-	return count;
-}
-
-void
-__archive_write_filters_free(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r = ARCHIVE_OK, r1;
-
-	while (a->filter_first != NULL) {
-		struct archive_write_filter *next
-		    = a->filter_first->next_filter;
-		if (a->filter_first->free != NULL) {
-			r1 = (*a->filter_first->free)(a->filter_first);
-			if (r > r1)
-				r = r1;
-		}
-		free(a->filter_first);
-		a->filter_first = next;
-	}
-	a->filter_last = NULL;
-}
-
-/*
- * Destroy the archive structure.
- *
- * Be careful: user might just call write_new and then write_free.
- * Don't assume we actually wrote anything or performed any non-trivial
- * initialization.
- */
-static int
-_archive_write_free(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r = ARCHIVE_OK, r1;
-
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	/* It is okay to call free() in state FATAL. */
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_free");
-	if (a->archive.state != ARCHIVE_STATE_FATAL)
-		r = archive_write_close(&a->archive);
-
-	/* Release format resources. */
-	if (a->format_free != NULL) {
-		r1 = (a->format_free)(a);
-		if (r1 < r)
-			r = r1;
-	}
-
-	__archive_write_filters_free(_a);
-
-	/* Release various dynamic buffers. */
-	free((void *)(uintptr_t)(const void *)a->nulls);
-	archive_string_free(&a->archive.error_string);
-	if (a->passphrase != NULL) {
-		/* A passphrase should be cleaned. */
-		memset(a->passphrase, 0, strlen(a->passphrase));
-		free(a->passphrase);
-	}
-	a->archive.magic = 0;
-	__archive_clean(&a->archive);
-	free(a);
-	return (r);
-}
-
-/*
- * Write the appropriate header.
- */
-static int
-_archive_write_header(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int ret, r2;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_DATA | ARCHIVE_STATE_HEADER, "archive_write_header");
-	archive_clear_error(&a->archive);
-
-	if (a->format_write_header == NULL) {
-		archive_set_error(&(a->archive), -1,
-		    "Format must be set before you can write to an archive.");
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-
-	/* In particular, "retry" and "fatal" get returned immediately. */
-	ret = archive_write_finish_entry(&a->archive);
-	if (ret == ARCHIVE_FATAL) {
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	if (ret < ARCHIVE_OK && ret != ARCHIVE_WARN)
-		return (ret);
-
-	if (a->skip_file_set &&
-	    archive_entry_dev_is_set(entry) &&
-	    archive_entry_ino_is_set(entry) &&
-	    archive_entry_dev(entry) == (dev_t)a->skip_file_dev &&
-	    archive_entry_ino64(entry) == a->skip_file_ino) {
-		archive_set_error(&a->archive, 0,
-		    "Can't add archive to itself");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Flush filters at boundary. */
-	r2 = __archive_write_filters_flush(a);
-	if (r2 == ARCHIVE_FAILED) {
-		return (ARCHIVE_FAILED);
-	}
-	if (r2 == ARCHIVE_FATAL) {
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	if (r2 < ret)
-		ret = r2;
-
-	/* Format and write header. */
-	r2 = ((a->format_write_header)(a, entry));
-	if (r2 == ARCHIVE_FAILED) {
-		return (ARCHIVE_FAILED);
-	}
-	if (r2 == ARCHIVE_FATAL) {
-		a->archive.state = ARCHIVE_STATE_FATAL;
-		return (ARCHIVE_FATAL);
-	}
-	if (r2 < ret)
-		ret = r2;
-
-	a->archive.state = ARCHIVE_STATE_DATA;
-	return (ret);
-}
-
-static int
-_archive_write_finish_entry(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int ret = ARCHIVE_OK;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_finish_entry");
-	if (a->archive.state & ARCHIVE_STATE_DATA
-	    && a->format_finish_entry != NULL)
-		ret = (a->format_finish_entry)(a);
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	return (ret);
-}
-
-/*
- * Note that the compressor is responsible for blocking.
- */
-static ssize_t
-_archive_write_data(struct archive *_a, const void *buff, size_t s)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	const size_t max_write = INT_MAX;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_DATA, "archive_write_data");
-	/* In particular, this catches attempts to pass negative values. */
-	if (s > max_write)
-		s = max_write;
-	archive_clear_error(&a->archive);
-	return ((a->format_write_data)(a, buff, s));
-}
-
-static struct archive_write_filter *
-filter_lookup(struct archive *_a, int n)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = a->filter_first;
-	if (n == -1)
-		return a->filter_last;
-	if (n < 0)
-		return NULL;
-	while (n > 0 && f != NULL) {
-		f = f->next_filter;
-		--n;
-	}
-	return f;
-}
-
-static int
-_archive_filter_code(struct archive *_a, int n)
-{
-	struct archive_write_filter *f = filter_lookup(_a, n);
-	return f == NULL ? -1 : f->code;
-}
-
-static const char *
-_archive_filter_name(struct archive *_a, int n)
-{
-	struct archive_write_filter *f = filter_lookup(_a, n);
-	return f != NULL ? f->name : NULL;
-}
-
-static int64_t
-_archive_filter_bytes(struct archive *_a, int n)
-{
-	struct archive_write_filter *f = filter_lookup(_a, n);
-	return f == NULL ? -1 : f->bytes_written;
-}
diff --git a/c/archive_write_add_filter.c b/c/archive_write_add_filter.c
deleted file mode 100644
--- a/c/archive_write_add_filter.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (c) 2012 Ondrej Holy
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-/* A table that maps filter codes to functions. */
-static const
-struct { int code; int (*setter)(struct archive *); } codes[] =
-{
-	{ ARCHIVE_FILTER_NONE,		archive_write_add_filter_none },
-	{ ARCHIVE_FILTER_GZIP,		archive_write_add_filter_gzip },
-	{ ARCHIVE_FILTER_BZIP2,		archive_write_add_filter_bzip2 },
-	{ ARCHIVE_FILTER_COMPRESS,	archive_write_add_filter_compress },
-	{ ARCHIVE_FILTER_GRZIP,		archive_write_add_filter_grzip },
-	{ ARCHIVE_FILTER_LRZIP,		archive_write_add_filter_lrzip },
-	{ ARCHIVE_FILTER_LZ4,		archive_write_add_filter_lz4 },
-	{ ARCHIVE_FILTER_LZIP,		archive_write_add_filter_lzip },
-	{ ARCHIVE_FILTER_LZMA,		archive_write_add_filter_lzma },
-	{ ARCHIVE_FILTER_LZOP,		archive_write_add_filter_lzip },
-	{ ARCHIVE_FILTER_UU,		archive_write_add_filter_uuencode },
-	{ ARCHIVE_FILTER_XZ,		archive_write_add_filter_xz },
-	{ ARCHIVE_FILTER_ZSTD,		archive_write_add_filter_zstd },
-	{ -1,			NULL }
-};
-
-int
-archive_write_add_filter(struct archive *a, int code)
-{
-	int i;
-
-	for (i = 0; codes[i].code != -1; i++) {
-		if (code == codes[i].code)
-			return ((codes[i].setter)(a));
-	}
-
-	archive_set_error(a, EINVAL, "No such filter");
-	return (ARCHIVE_FATAL);
-}
diff --git a/c/archive_write_add_filter_b64encode.c b/c/archive_write_add_filter_b64encode.c
deleted file mode 100644
--- a/c/archive_write_add_filter_b64encode.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-#define LBYTES	57
-
-struct private_b64encode {
-	int			mode;
-	struct archive_string	name;
-	struct archive_string	encoded_buff;
-	size_t			bs;
-	size_t			hold_len;
-	unsigned char		hold[LBYTES];
-};
-
-static int archive_filter_b64encode_options(struct archive_write_filter *,
-    const char *, const char *);
-static int archive_filter_b64encode_open(struct archive_write_filter *);
-static int archive_filter_b64encode_write(struct archive_write_filter *,
-    const void *, size_t);
-static int archive_filter_b64encode_close(struct archive_write_filter *);
-static int archive_filter_b64encode_free(struct archive_write_filter *);
-static void la_b64_encode(struct archive_string *, const unsigned char *, size_t);
-static int64_t atol8(const char *, size_t);
-
-static const char base64[] = {
-	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-	'w', 'x', 'y', 'z', '0', '1', '2', '3',
-	'4', '5', '6', '7', '8', '9', '+', '/'
-};
-
-/*
- * Add a compress filter to this write handle.
- */
-int
-archive_write_add_filter_b64encode(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_b64encode *state;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
-
-	state = (struct private_b64encode *)calloc(1, sizeof(*state));
-	if (state == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for b64encode filter");
-		return (ARCHIVE_FATAL);
-	}
-	archive_strcpy(&state->name, "-");
-	state->mode = 0644;
-
-	f->data = state;
-	f->name = "b64encode";
-	f->code = ARCHIVE_FILTER_UU;
-	f->open = archive_filter_b64encode_open;
-	f->options = archive_filter_b64encode_options;
-	f->write = archive_filter_b64encode_write;
-	f->close = archive_filter_b64encode_close;
-	f->free = archive_filter_b64encode_free;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Set write options.
- */
-static int
-archive_filter_b64encode_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct private_b64encode *state = (struct private_b64encode *)f->data;
-
-	if (strcmp(key, "mode") == 0) {
-		if (value == NULL) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "mode option requires octal digits");
-			return (ARCHIVE_FAILED);
-		}
-		state->mode = (int)atol8(value, strlen(value)) & 0777;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "name") == 0) {
-		if (value == NULL) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "name option requires a string");
-			return (ARCHIVE_FAILED);
-		}
-		archive_strcpy(&state->name, value);
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Setup callback.
- */
-static int
-archive_filter_b64encode_open(struct archive_write_filter *f)
-{
-	struct private_b64encode *state = (struct private_b64encode *)f->data;
-	size_t bs = 65536, bpb;
-
-	if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-		/* Buffer size should be a multiple number of the of bytes
-		 * per block for performance. */
-		bpb = archive_write_get_bytes_per_block(f->archive);
-		if (bpb > bs)
-			bs = bpb;
-		else if (bpb != 0)
-			bs -= bs % bpb;
-	}
-
-	state->bs = bs;
-	if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for b64encode buffer");
-		return (ARCHIVE_FATAL);
-	}
-
-	archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
-	    state->mode, state->name.s);
-
-	f->data = state;
-	return (0);
-}
-
-static void
-la_b64_encode(struct archive_string *as, const unsigned char *p, size_t len)
-{
-	int c;
-
-	for (; len >= 3; p += 3, len -= 3) {
-		c = p[0] >> 2;
-		archive_strappend_char(as, base64[c]);
-		c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
-		archive_strappend_char(as, base64[c]);
-		c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
-		archive_strappend_char(as, base64[c]);
-		c = p[2] & 0x3f;
-		archive_strappend_char(as, base64[c]);
-	}
-	if (len > 0) {
-		c = p[0] >> 2;
-		archive_strappend_char(as, base64[c]);
-		c = (p[0] & 0x03) << 4;
-		if (len == 1) {
-			archive_strappend_char(as, base64[c]);
-			archive_strappend_char(as, '=');
-			archive_strappend_char(as, '=');
-		} else {
-			c |= (p[1] & 0xf0) >> 4;
-			archive_strappend_char(as, base64[c]);
-			c = (p[1] & 0x0f) << 2;
-			archive_strappend_char(as, base64[c]);
-			archive_strappend_char(as, '=');
-		}
-	}
-	archive_strappend_char(as, '\n');
-}
-
-/*
- * Write data to the encoded stream.
- */
-static int
-archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_b64encode *state = (struct private_b64encode *)f->data;
-	const unsigned char *p = buff;
-	int ret = ARCHIVE_OK;
-
-	if (length == 0)
-		return (ret);
-
-	if (state->hold_len) {
-		while (state->hold_len < LBYTES && length > 0) {
-			state->hold[state->hold_len++] = *p++;
-			length--;
-		}
-		if (state->hold_len < LBYTES)
-			return (ret);
-		la_b64_encode(&state->encoded_buff, state->hold, LBYTES);
-		state->hold_len = 0;
-	}
-
-	for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
-		la_b64_encode(&state->encoded_buff, p, LBYTES);
-
-	/* Save remaining bytes. */
-	if (length > 0) {
-		memcpy(state->hold, p, length);
-		state->hold_len = length;
-	}
-	while (archive_strlen(&state->encoded_buff) >= state->bs) {
-		ret = __archive_write_filter(f->next_filter,
-		    state->encoded_buff.s, state->bs);
-		memmove(state->encoded_buff.s,
-		    state->encoded_buff.s + state->bs,
-		    state->encoded_buff.length - state->bs);
-		state->encoded_buff.length -= state->bs;
-	}
-
-	return (ret);
-}
-
-
-/*
- * Finish the compression...
- */
-static int
-archive_filter_b64encode_close(struct archive_write_filter *f)
-{
-	struct private_b64encode *state = (struct private_b64encode *)f->data;
-
-	/* Flush remaining bytes. */
-	if (state->hold_len != 0)
-		la_b64_encode(&state->encoded_buff, state->hold, state->hold_len);
-	archive_string_sprintf(&state->encoded_buff, "====\n");
-	/* Write the last block */
-	archive_write_set_bytes_in_last_block(f->archive, 1);
-	return __archive_write_filter(f->next_filter,
-	    state->encoded_buff.s, archive_strlen(&state->encoded_buff));
-}
-
-static int
-archive_filter_b64encode_free(struct archive_write_filter *f)
-{
-	struct private_b64encode *state = (struct private_b64encode *)f->data;
-
-	archive_string_free(&state->name);
-	archive_string_free(&state->encoded_buff);
-	free(state);
-	return (ARCHIVE_OK);
-}
-
-static int64_t
-atol8(const char *p, size_t char_cnt)
-{
-	int64_t l;
-	int digit;
-        
-	l = 0;
-	while (char_cnt-- > 0) {
-		if (*p >= '0' && *p <= '7')
-			digit = *p - '0';
-		else
-			break;
-		p++;
-		l <<= 3;
-		l |= digit;
-	}
-	return (l);
-}
-
diff --git a/c/archive_write_add_filter_by_name.c b/c/archive_write_add_filter_by_name.c
deleted file mode 100644
--- a/c/archive_write_add_filter_by_name.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-/* A table that maps names to functions. */
-static const
-struct { const char *name; int (*setter)(struct archive *); } names[] =
-{
-	{ "b64encode",		archive_write_add_filter_b64encode },
-	{ "bzip2",		archive_write_add_filter_bzip2 },
-	{ "compress",		archive_write_add_filter_compress },
-	{ "grzip",		archive_write_add_filter_grzip },
-	{ "gzip",		archive_write_add_filter_gzip },
-	{ "lrzip",		archive_write_add_filter_lrzip },
-	{ "lz4",		archive_write_add_filter_lz4 },
-	{ "lzip",		archive_write_add_filter_lzip },
-	{ "lzma",		archive_write_add_filter_lzma },
-	{ "lzop",		archive_write_add_filter_lzop },
-	{ "uuencode",		archive_write_add_filter_uuencode },
-	{ "xz",			archive_write_add_filter_xz },
-	{ "zstd",		archive_write_add_filter_zstd },
-	{ NULL,			NULL }
-};
-
-int
-archive_write_add_filter_by_name(struct archive *a, const char *name)
-{
-	int i;
-
-	for (i = 0; names[i].name != NULL; i++) {
-		if (strcmp(name, names[i].name) == 0)
-			return ((names[i].setter)(a));
-	}
-
-	archive_set_error(a, EINVAL, "No such filter '%s'", name);
-	a->state = ARCHIVE_STATE_FATAL;
-	return (ARCHIVE_FATAL);
-}
diff --git a/c/archive_write_add_filter_bzip2.c b/c/archive_write_add_filter_bzip2.c
deleted file mode 100644
--- a/c/archive_write_add_filter_bzip2.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_bzip2.c 201091 2009-12-28 02:22:41Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_write_set_compression_bzip2(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_bzip2(a));
-}
-#endif
-
-struct private_data {
-	int		 compression_level;
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	bz_stream	 stream;
-	int64_t		 total_in;
-	char		*compressed;
-	size_t		 compressed_buffer_size;
-#else
-	struct archive_write_program_data *pdata;
-#endif
-};
-
-static int archive_compressor_bzip2_close(struct archive_write_filter *);
-static int archive_compressor_bzip2_free(struct archive_write_filter *);
-static int archive_compressor_bzip2_open(struct archive_write_filter *);
-static int archive_compressor_bzip2_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_compressor_bzip2_write(struct archive_write_filter *,
-		    const void *, size_t);
-
-/*
- * Add a bzip2 compression filter to this write handle.
- */
-int
-archive_write_add_filter_bzip2(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_data *data;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_bzip2");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 9; /* default */
-
-	f->data = data;
-	f->options = &archive_compressor_bzip2_options;
-	f->close = &archive_compressor_bzip2_close;
-	f->free = &archive_compressor_bzip2_free;
-	f->open = &archive_compressor_bzip2_open;
-	f->code = ARCHIVE_FILTER_BZIP2;
-	f->name = "bzip2";
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	return (ARCHIVE_OK);
-#else
-	data->pdata = __archive_write_program_allocate("bzip2");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 0;
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Using external bzip2 program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Set write options.
- */
-static int
-archive_compressor_bzip2_options(struct archive_write_filter *f,
-    const char *key, const char *value)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->compression_level = value[0] - '0';
-		/* Make '0' be a synonym for '1'. */
-		/* This way, bzip2 compressor supports the same 0..9
-		 * range of levels as gzip. */
-		if (data->compression_level < 1)
-			data->compression_level = 1;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-/* Don't compile this if we don't have bzlib. */
-
-/*
- * Yuck.  bzlib.h is not const-correct, so I need this one bit
- * of ugly hackery to convert a const * pointer to a non-const pointer.
- */
-#define	SET_NEXT_IN(st,src)					\
-	(st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
-static int drive_compressor(struct archive_write_filter *,
-		    struct private_data *, int finishing);
-
-/*
- * Setup callback.
- */
-static int
-archive_compressor_bzip2_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	if (data->compressed == NULL) {
-		size_t bs = 65536, bpb;
-		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-			/* Buffer size should be a multiple number of the of bytes
-			 * per block for performance. */
-			bpb = archive_write_get_bytes_per_block(f->archive);
-			if (bpb > bs)
-				bs = bpb;
-			else if (bpb != 0)
-				bs -= bs % bpb;
-		}
-		data->compressed_buffer_size = bs;
-		data->compressed
-		    = (char *)malloc(data->compressed_buffer_size);
-		if (data->compressed == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	memset(&data->stream, 0, sizeof(data->stream));
-	data->stream.next_out = data->compressed;
-	data->stream.avail_out = (uint32_t)data->compressed_buffer_size;
-	f->write = archive_compressor_bzip2_write;
-
-	/* Initialize compression library */
-	ret = BZ2_bzCompressInit(&(data->stream),
-	    data->compression_level, 0, 30);
-	if (ret == BZ_OK) {
-		f->data = data;
-		return (ARCHIVE_OK);
-	}
-
-	/* Library setup failed: clean up. */
-	archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-	    "Internal error initializing compression library");
-
-	/* Override the error message if we know what really went wrong. */
-	switch (ret) {
-	case BZ_PARAM_ERROR:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "invalid setup parameter");
-		break;
-	case BZ_MEM_ERROR:
-		archive_set_error(f->archive, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "out of memory");
-		break;
-	case BZ_CONFIG_ERROR:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "mis-compiled library");
-		break;
-	}
-
-	return (ARCHIVE_FATAL);
-
-}
-
-/*
- * Write data to the compressed stream.
- *
- * Returns ARCHIVE_OK if all data written, error otherwise.
- */
-static int
-archive_compressor_bzip2_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	/* Update statistics */
-	data->total_in += length;
-
-	/* Compress input data to output buffer */
-	SET_NEXT_IN(data, buff);
-	data->stream.avail_in = (uint32_t)length;
-	if (drive_compressor(f, data, 0))
-		return (ARCHIVE_FATAL);
-	return (ARCHIVE_OK);
-}
-
-
-/*
- * Finish the compression.
- */
-static int
-archive_compressor_bzip2_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	/* Finish compression cycle. */
-	ret = drive_compressor(f, data, 1);
-	if (ret == ARCHIVE_OK) {
-		/* Write the last block */
-		ret = __archive_write_filter(f->next_filter,
-		    data->compressed,
-		    data->compressed_buffer_size - data->stream.avail_out);
-	}
-
-	switch (BZ2_bzCompressEnd(&(data->stream))) {
-	case BZ_OK:
-		break;
-	default:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER,
-		    "Failed to clean up compressor");
-		ret = ARCHIVE_FATAL;
-	}
-	return ret;
-}
-
-static int
-archive_compressor_bzip2_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	free(data->compressed);
-	free(data);
-	f->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Utility function to push input data through compressor, writing
- * full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
- */
-static int
-drive_compressor(struct archive_write_filter *f,
-    struct private_data *data, int finishing)
-{
-	int ret;
-
-	for (;;) {
-		if (data->stream.avail_out == 0) {
-			ret = __archive_write_filter(f->next_filter,
-			    data->compressed,
-			    data->compressed_buffer_size);
-			if (ret != ARCHIVE_OK) {
-				/* TODO: Handle this write failure */
-				return (ARCHIVE_FATAL);
-			}
-			data->stream.next_out = data->compressed;
-			data->stream.avail_out = (uint32_t)data->compressed_buffer_size;
-		}
-
-		/* If there's nothing to do, we're done. */
-		if (!finishing && data->stream.avail_in == 0)
-			return (ARCHIVE_OK);
-
-		ret = BZ2_bzCompress(&(data->stream),
-		    finishing ? BZ_FINISH : BZ_RUN);
-
-		switch (ret) {
-		case BZ_RUN_OK:
-			/* In non-finishing case, did compressor
-			 * consume everything? */
-			if (!finishing && data->stream.avail_in == 0)
-				return (ARCHIVE_OK);
-			break;
-		case BZ_FINISH_OK:  /* Finishing: There's more work to do */
-			break;
-		case BZ_STREAM_END: /* Finishing: all done */
-			/* Only occurs in finishing case */
-			return (ARCHIVE_OK);
-		default:
-			/* Any other return value indicates an error */
-			archive_set_error(f->archive,
-			    ARCHIVE_ERRNO_PROGRAMMER,
-			    "Bzip2 compression failed;"
-			    " BZ2_bzCompress() returned %d",
-			    ret);
-			return (ARCHIVE_FATAL);
-		}
-	}
-}
-
-#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
-
-static int
-archive_compressor_bzip2_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	archive_strcpy(&as, "bzip2");
-
-	/* Specify compression level. */
-	if (data->compression_level > 0) {
-		archive_strcat(&as, " -");
-		archive_strappend_char(&as, '0' + data->compression_level);
-	}
-	f->write = archive_compressor_bzip2_write;
-
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_compressor_bzip2_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-static int
-archive_compressor_bzip2_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	__archive_write_program_free(data->pdata);
-	free(data);
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
diff --git a/c/archive_write_add_filter_compress.c b/c/archive_write_add_filter_compress.c
deleted file mode 100644
--- a/c/archive_write_add_filter_compress.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*-
- * Copyright (c) 2008 Joerg Sonnenberger
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*-
- * Copyright (c) 1985, 1986, 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Diomidis Spinellis and James A. Woods, derived from original
- * work by Spencer Thomas and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_compress.c 201111 2009-12-28 03:33:05Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-
-#define	HSIZE		69001	/* 95% occupancy */
-#define	HSHIFT		8	/* 8 - trunc(log2(HSIZE / 65536)) */
-#define	CHECK_GAP 10000		/* Ratio check interval. */
-
-#define	MAXCODE(bits)	((1 << (bits)) - 1)
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define	FIRST	257		/* First free entry. */
-#define	CLEAR	256		/* Table clear output code. */
-
-struct private_data {
-	int64_t in_count, out_count, checkpoint;
-
-	int code_len;			/* Number of bits/code. */
-	int cur_maxcode;		/* Maximum code, given n_bits. */
-	int max_maxcode;		/* Should NEVER generate this code. */
-	int hashtab [HSIZE];
-	unsigned short codetab [HSIZE];
-	int first_free;		/* First unused entry. */
-	int compress_ratio;
-
-	int cur_code, cur_fcode;
-
-	int bit_offset;
-	unsigned char bit_buf;
-
-	unsigned char	*compressed;
-	size_t		 compressed_buffer_size;
-	size_t		 compressed_offset;
-};
-
-static int archive_compressor_compress_open(struct archive_write_filter *);
-static int archive_compressor_compress_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_compressor_compress_close(struct archive_write_filter *);
-static int archive_compressor_compress_free(struct archive_write_filter *);
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_write_set_compression_compress(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_compress(a));
-}
-#endif
-
-/*
- * Add a compress filter to this write handle.
- */
-int
-archive_write_add_filter_compress(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_compress");
-	f->open = &archive_compressor_compress_open;
-	f->code = ARCHIVE_FILTER_COMPRESS;
-	f->name = "compress";
-	return (ARCHIVE_OK);
-}
-
-/*
- * Setup callback.
- */
-static int
-archive_compressor_compress_open(struct archive_write_filter *f)
-{
-	struct private_data *state;
-	size_t bs = 65536, bpb;
-
-	f->code = ARCHIVE_FILTER_COMPRESS;
-	f->name = "compress";
-
-	state = (struct private_data *)calloc(1, sizeof(*state));
-	if (state == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for compression");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-		/* Buffer size should be a multiple number of the of bytes
-		 * per block for performance. */
-		bpb = archive_write_get_bytes_per_block(f->archive);
-		if (bpb > bs)
-			bs = bpb;
-		else if (bpb != 0)
-			bs -= bs % bpb;
-	}
-	state->compressed_buffer_size = bs;
-	state->compressed = malloc(state->compressed_buffer_size);
-
-	if (state->compressed == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for compression buffer");
-		free(state);
-		return (ARCHIVE_FATAL);
-	}
-
-	f->write = archive_compressor_compress_write;
-	f->close = archive_compressor_compress_close;
-	f->free = archive_compressor_compress_free;
-
-	state->max_maxcode = 0x10000;	/* Should NEVER generate this code. */
-	state->in_count = 0;		/* Length of input. */
-	state->bit_buf = 0;
-	state->bit_offset = 0;
-	state->out_count = 3;		/* Includes 3-byte header mojo. */
-	state->compress_ratio = 0;
-	state->checkpoint = CHECK_GAP;
-	state->code_len = 9;
-	state->cur_maxcode = MAXCODE(state->code_len);
-	state->first_free = FIRST;
-
-	memset(state->hashtab, 0xff, sizeof(state->hashtab));
-
-	/* Prime output buffer with a gzip header. */
-	state->compressed[0] = 0x1f; /* Compress */
-	state->compressed[1] = 0x9d;
-	state->compressed[2] = 0x90; /* Block mode, 16bit max */
-	state->compressed_offset = 3;
-
-	f->data = state;
-	return (0);
-}
-
-/*-
- * Output the given code.
- * Inputs:
- * 	code:	A n_bits-bit integer.  If == -1, then EOF.  This assumes
- *		that n_bits <= (long)wordsize - 1.
- * Outputs:
- * 	Outputs code to the file.
- * Assumptions:
- *	Chars are 8 bits long.
- * Algorithm:
- * 	Maintain a BITS character long buffer (so that 8 codes will
- * fit in it exactly).  Use the VAX insv instruction to insert each
- * code in turn.  When the buffer fills up empty it and start over.
- */
-
-static const unsigned char rmask[9] =
-	{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-
-static int
-output_byte(struct archive_write_filter *f, unsigned char c)
-{
-	struct private_data *state = f->data;
-
-	state->compressed[state->compressed_offset++] = c;
-	++state->out_count;
-
-	if (state->compressed_buffer_size == state->compressed_offset) {
-		int ret = __archive_write_filter(f->next_filter,
-		    state->compressed, state->compressed_buffer_size);
-		if (ret != ARCHIVE_OK)
-			return ARCHIVE_FATAL;
-		state->compressed_offset = 0;
-	}
-
-	return ARCHIVE_OK;
-}
-
-static int
-output_code(struct archive_write_filter *f, int ocode)
-{
-	struct private_data *state = f->data;
-	int bits, ret, clear_flg, bit_offset;
-
-	clear_flg = ocode == CLEAR;
-
-	/*
-	 * Since ocode is always >= 8 bits, only need to mask the first
-	 * hunk on the left.
-	 */
-	bit_offset = state->bit_offset % 8;
-	state->bit_buf |= (ocode << bit_offset) & 0xff;
-	output_byte(f, state->bit_buf);
-
-	bits = state->code_len - (8 - bit_offset);
-	ocode >>= 8 - bit_offset;
-	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
-	if (bits >= 8) {
-		output_byte(f, ocode & 0xff);
-		ocode >>= 8;
-		bits -= 8;
-	}
-	/* Last bits. */
-	state->bit_offset += state->code_len;
-	state->bit_buf = ocode & rmask[bits];
-	if (state->bit_offset == state->code_len * 8)
-		state->bit_offset = 0;
-
-	/*
-	 * If the next entry is going to be too big for the ocode size,
-	 * then increase it, if possible.
-	 */
-	if (clear_flg || state->first_free > state->cur_maxcode) {
-	       /*
-		* Write the whole buffer, because the input side won't
-		* discover the size increase until after it has read it.
-		*/
-		if (state->bit_offset > 0) {
-			while (state->bit_offset < state->code_len * 8) {
-				ret = output_byte(f, state->bit_buf);
-				if (ret != ARCHIVE_OK)
-					return ret;
-				state->bit_offset += 8;
-				state->bit_buf = 0;
-			}
-		}
-		state->bit_buf = 0;
-		state->bit_offset = 0;
-
-		if (clear_flg) {
-			state->code_len = 9;
-			state->cur_maxcode = MAXCODE(state->code_len);
-		} else {
-			state->code_len++;
-			if (state->code_len == 16)
-				state->cur_maxcode = state->max_maxcode;
-			else
-				state->cur_maxcode = MAXCODE(state->code_len);
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-output_flush(struct archive_write_filter *f)
-{
-	struct private_data *state = f->data;
-	int ret;
-
-	/* At EOF, write the rest of the buffer. */
-	if (state->bit_offset % 8) {
-		state->code_len = (state->bit_offset % 8 + 7) / 8;
-		ret = output_byte(f, state->bit_buf);
-		if (ret != ARCHIVE_OK)
-			return ret;
-	}
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Write data to the compressed stream.
- */
-static int
-archive_compressor_compress_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct private_data *state = (struct private_data *)f->data;
-	int i;
-	int ratio;
-	int c, disp, ret;
-	const unsigned char *bp;
-
-	if (length == 0)
-		return ARCHIVE_OK;
-
-	bp = buff;
-
-	if (state->in_count == 0) {
-		state->cur_code = *bp++;
-		++state->in_count;
-		--length;
-	}
-
-	while (length--) {
-		c = *bp++;
-		state->in_count++;
-		state->cur_fcode = (c << 16) | state->cur_code;
-		i = ((c << HSHIFT) ^ state->cur_code);	/* Xor hashing. */
-
-		if (state->hashtab[i] == state->cur_fcode) {
-			state->cur_code = state->codetab[i];
-			continue;
-		}
-		if (state->hashtab[i] < 0)	/* Empty slot. */
-			goto nomatch;
-		/* Secondary hash (after G. Knott). */
-		if (i == 0)
-			disp = 1;
-		else
-			disp = HSIZE - i;
- probe:
-		if ((i -= disp) < 0)
-			i += HSIZE;
-
-		if (state->hashtab[i] == state->cur_fcode) {
-			state->cur_code = state->codetab[i];
-			continue;
-		}
-		if (state->hashtab[i] >= 0)
-			goto probe;
- nomatch:
-		ret = output_code(f, state->cur_code);
-		if (ret != ARCHIVE_OK)
-			return ret;
-		state->cur_code = c;
-		if (state->first_free < state->max_maxcode) {
-			state->codetab[i] = state->first_free++;	/* code -> hashtable */
-			state->hashtab[i] = state->cur_fcode;
-			continue;
-		}
-		if (state->in_count < state->checkpoint)
-			continue;
-
-		state->checkpoint = state->in_count + CHECK_GAP;
-
-		if (state->in_count <= 0x007fffff && state->out_count != 0)
-			ratio = (int)(state->in_count * 256 / state->out_count);
-		else if ((ratio = (int)(state->out_count / 256)) == 0)
-			ratio = 0x7fffffff;
-		else
-			ratio = (int)(state->in_count / ratio);
-
-		if (ratio > state->compress_ratio)
-			state->compress_ratio = ratio;
-		else {
-			state->compress_ratio = 0;
-			memset(state->hashtab, 0xff, sizeof(state->hashtab));
-			state->first_free = FIRST;
-			ret = output_code(f, CLEAR);
-			if (ret != ARCHIVE_OK)
-				return ret;
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-
-/*
- * Finish the compression...
- */
-static int
-archive_compressor_compress_close(struct archive_write_filter *f)
-{
-	struct private_data *state = (struct private_data *)f->data;
-	int ret;
-
-	ret = output_code(f, state->cur_code);
-	if (ret != ARCHIVE_OK)
-		return ret;
-	ret = output_flush(f);
-	if (ret != ARCHIVE_OK)
-		return ret;
-
-	/* Write the last block */
-	ret = __archive_write_filter(f->next_filter,
-	    state->compressed, state->compressed_offset);
-	return (ret);
-}
-
-static int
-archive_compressor_compress_free(struct archive_write_filter *f)
-{
-	struct private_data *state = (struct private_data *)f->data;
-
-	free(state->compressed);
-	free(state);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_add_filter_grzip.c b/c/archive_write_add_filter_grzip.c
deleted file mode 100644
--- a/c/archive_write_add_filter_grzip.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_write_private.h"
-
-struct write_grzip {
-	struct archive_write_program_data *pdata;
-};
-
-static int archive_write_grzip_open(struct archive_write_filter *);
-static int archive_write_grzip_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_write_grzip_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_write_grzip_close(struct archive_write_filter *);
-static int archive_write_grzip_free(struct archive_write_filter *);
-
-int
-archive_write_add_filter_grzip(struct archive *_a)
-{
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct write_grzip *data;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->pdata = __archive_write_program_allocate("grzip");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	f->name = "grzip";
-	f->code = ARCHIVE_FILTER_GRZIP;
-	f->data = data;
-	f->open = archive_write_grzip_open;
-	f->options = archive_write_grzip_options;
-	f->write = archive_write_grzip_write;
-	f->close = archive_write_grzip_close;
-	f->free = archive_write_grzip_free;
-
-	/* Note: This filter always uses an external program, so we
-	 * return "warn" to inform of the fact. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external grzip program for grzip compression");
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_grzip_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	(void)f; /* UNUSED */
-	(void)key; /* UNUSED */
-	(void)value; /* UNUSED */
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_grzip_open(struct archive_write_filter *f)
-{
-	struct write_grzip *data = (struct write_grzip *)f->data;
-
-	return __archive_write_program_open(f, data->pdata, "grzip");
-}
-
-static int
-archive_write_grzip_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct write_grzip *data = (struct write_grzip *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_write_grzip_close(struct archive_write_filter *f)
-{
-	struct write_grzip *data = (struct write_grzip *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-static int
-archive_write_grzip_free(struct archive_write_filter *f)
-{
-	struct write_grzip *data = (struct write_grzip *)f->data;
-
-	__archive_write_program_free(data->pdata);
-	free(data);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_add_filter_gzip.c b/c/archive_write_add_filter_gzip.c
deleted file mode 100644
--- a/c/archive_write_add_filter_gzip.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201081 2009-12-28 02:04:42Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_write_set_compression_gzip(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_gzip(a));
-}
-#endif
-
-/* Don't compile this if we don't have zlib. */
-
-struct private_data {
-	int		 compression_level;
-	int		 timestamp;
-#ifdef HAVE_ZLIB_H
-	z_stream	 stream;
-	int64_t		 total_in;
-	unsigned char	*compressed;
-	size_t		 compressed_buffer_size;
-	unsigned long	 crc;
-#else
-	struct archive_write_program_data *pdata;
-#endif
-};
-
-/*
- * Yuck.  zlib.h is not const-correct, so I need this one bit
- * of ugly hackery to convert a const * pointer to a non-const pointer.
- */
-#define	SET_NEXT_IN(st,src)					\
-	(st)->stream.next_in = (Bytef *)(uintptr_t)(const void *)(src)
-
-static int archive_compressor_gzip_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_compressor_gzip_open(struct archive_write_filter *);
-static int archive_compressor_gzip_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_compressor_gzip_close(struct archive_write_filter *);
-static int archive_compressor_gzip_free(struct archive_write_filter *);
-#ifdef HAVE_ZLIB_H
-static int drive_compressor(struct archive_write_filter *,
-		    struct private_data *, int finishing);
-#endif
-
-
-/*
- * Add a gzip compression filter to this write handle.
- */
-int
-archive_write_add_filter_gzip(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_data *data;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_gzip");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	f->data = data;
-	f->open = &archive_compressor_gzip_open;
-	f->options = &archive_compressor_gzip_options;
-	f->close = &archive_compressor_gzip_close;
-	f->free = &archive_compressor_gzip_free;
-	f->code = ARCHIVE_FILTER_GZIP;
-	f->name = "gzip";
-#ifdef HAVE_ZLIB_H
-	data->compression_level = Z_DEFAULT_COMPRESSION;
-	return (ARCHIVE_OK);
-#else
-	data->pdata = __archive_write_program_allocate("gzip");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 0;
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Using external gzip program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-static int
-archive_compressor_gzip_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-#ifdef HAVE_ZLIB_H
-	free(data->compressed);
-#else
-	__archive_write_program_free(data->pdata);
-#endif
-	free(data);
-	f->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Set write options.
- */
-static int
-archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->compression_level = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "timestamp") == 0) {
-		data->timestamp = (value == NULL)?-1:1;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-#ifdef HAVE_ZLIB_H
-/*
- * Setup callback.
- */
-static int
-archive_compressor_gzip_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	if (data->compressed == NULL) {
-		size_t bs = 65536, bpb;
-		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-			/* Buffer size should be a multiple number of
-			 * the of bytes per block for performance. */
-			bpb = archive_write_get_bytes_per_block(f->archive);
-			if (bpb > bs)
-				bs = bpb;
-			else if (bpb != 0)
-				bs -= bs % bpb;
-		}
-		data->compressed_buffer_size = bs;
-		data->compressed
-		    = (unsigned char *)malloc(data->compressed_buffer_size);
-		if (data->compressed == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	data->crc = crc32(0L, NULL, 0);
-	data->stream.next_out = data->compressed;
-	data->stream.avail_out = (uInt)data->compressed_buffer_size;
-
-	/* Prime output buffer with a gzip header. */
-	data->compressed[0] = 0x1f; /* GZip signature bytes */
-	data->compressed[1] = 0x8b;
-	data->compressed[2] = 0x08; /* "Deflate" compression */
-	data->compressed[3] = 0; /* No options */
-	if (data->timestamp >= 0) {
-		time_t t = time(NULL);
-		data->compressed[4] = (uint8_t)(t)&0xff;  /* Timestamp */
-		data->compressed[5] = (uint8_t)(t>>8)&0xff;
-		data->compressed[6] = (uint8_t)(t>>16)&0xff;
-		data->compressed[7] = (uint8_t)(t>>24)&0xff;
-	} else
-		memset(&data->compressed[4], 0, 4);
-    if (data->compression_level == 9)
-	    data->compressed[8] = 2;
-    else if(data->compression_level == 1)
-	    data->compressed[8] = 4;
-    else
-	    data->compressed[8] = 0;
-	data->compressed[9] = 3; /* OS=Unix */
-	data->stream.next_out += 10;
-	data->stream.avail_out -= 10;
-
-	f->write = archive_compressor_gzip_write;
-
-	/* Initialize compression library. */
-	ret = deflateInit2(&(data->stream),
-	    data->compression_level,
-	    Z_DEFLATED,
-	    -15 /* < 0 to suppress zlib header */,
-	    8,
-	    Z_DEFAULT_STRATEGY);
-
-	if (ret == Z_OK) {
-		f->data = data;
-		return (ARCHIVE_OK);
-	}
-
-	/* Library setup failed: clean up. */
-	archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, "Internal error "
-	    "initializing compression library");
-
-	/* Override the error message if we know what really went wrong. */
-	switch (ret) {
-	case Z_STREAM_ERROR:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing "
-		    "compression library: invalid setup parameter");
-		break;
-	case Z_MEM_ERROR:
-		archive_set_error(f->archive, ENOMEM,
-		    "Internal error initializing compression library");
-		break;
-	case Z_VERSION_ERROR:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing "
-		    "compression library: invalid library version");
-		break;
-	}
-
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Write data to the compressed stream.
- */
-static int
-archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	/* Update statistics */
-	data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length);
-	data->total_in += length;
-
-	/* Compress input data to output buffer */
-	SET_NEXT_IN(data, buff);
-	data->stream.avail_in = (uInt)length;
-	if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
-		return (ret);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Finish the compression...
- */
-static int
-archive_compressor_gzip_close(struct archive_write_filter *f)
-{
-	unsigned char trailer[8];
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	/* Finish compression cycle */
-	ret = drive_compressor(f, data, 1);
-	if (ret == ARCHIVE_OK) {
-		/* Write the last compressed data. */
-		ret = __archive_write_filter(f->next_filter,
-		    data->compressed,
-		    data->compressed_buffer_size - data->stream.avail_out);
-	}
-	if (ret == ARCHIVE_OK) {
-		/* Build and write out 8-byte trailer. */
-		trailer[0] = (uint8_t)(data->crc)&0xff;
-		trailer[1] = (uint8_t)(data->crc >> 8)&0xff;
-		trailer[2] = (uint8_t)(data->crc >> 16)&0xff;
-		trailer[3] = (uint8_t)(data->crc >> 24)&0xff;
-		trailer[4] = (uint8_t)(data->total_in)&0xff;
-		trailer[5] = (uint8_t)(data->total_in >> 8)&0xff;
-		trailer[6] = (uint8_t)(data->total_in >> 16)&0xff;
-		trailer[7] = (uint8_t)(data->total_in >> 24)&0xff;
-		ret = __archive_write_filter(f->next_filter, trailer, 8);
-	}
-
-	switch (deflateEnd(&(data->stream))) {
-	case Z_OK:
-		break;
-	default:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		ret = ARCHIVE_FATAL;
-	}
-	return ret;
-}
-
-/*
- * Utility function to push input data through compressor,
- * writing full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
- */
-static int
-drive_compressor(struct archive_write_filter *f,
-    struct private_data *data, int finishing)
-{
-	int ret;
-
-	for (;;) {
-		if (data->stream.avail_out == 0) {
-			ret = __archive_write_filter(f->next_filter,
-			    data->compressed,
-			    data->compressed_buffer_size);
-			if (ret != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			data->stream.next_out = data->compressed;
-			data->stream.avail_out =
-			    (uInt)data->compressed_buffer_size;
-		}
-
-		/* If there's nothing to do, we're done. */
-		if (!finishing && data->stream.avail_in == 0)
-			return (ARCHIVE_OK);
-
-		ret = deflate(&(data->stream),
-		    finishing ? Z_FINISH : Z_NO_FLUSH );
-
-		switch (ret) {
-		case Z_OK:
-			/* In non-finishing case, check if compressor
-			 * consumed everything */
-			if (!finishing && data->stream.avail_in == 0)
-				return (ARCHIVE_OK);
-			/* In finishing case, this return always means
-			 * there's more work */
-			break;
-		case Z_STREAM_END:
-			/* This return can only occur in finishing case. */
-			return (ARCHIVE_OK);
-		default:
-			/* Any other return value indicates an error. */
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "GZip compression failed:"
-			    " deflate() call returned status %d",
-			    ret);
-			return (ARCHIVE_FATAL);
-		}
-	}
-}
-
-#else /* HAVE_ZLIB_H */
-
-static int
-archive_compressor_gzip_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	archive_strcpy(&as, "gzip");
-
-	/* Specify compression level. */
-	if (data->compression_level > 0) {
-		archive_strcat(&as, " -");
-		archive_strappend_char(&as, '0' + data->compression_level);
-	}
-	if (data->timestamp < 0)
-		/* Do not save timestamp. */
-		archive_strcat(&as, " -n");
-	else if (data->timestamp > 0)
-		/* Save timestamp. */
-		archive_strcat(&as, " -N");
-
-	f->write = archive_compressor_gzip_write;
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_compressor_gzip_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-#endif /* HAVE_ZLIB_H */
diff --git a/c/archive_write_add_filter_lrzip.c b/c/archive_write_add_filter_lrzip.c
deleted file mode 100644
--- a/c/archive_write_add_filter_lrzip.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-struct write_lrzip {
-	struct archive_write_program_data *pdata;
-	int	compression_level;
-	enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression;
-};
-
-static int archive_write_lrzip_open(struct archive_write_filter *);
-static int archive_write_lrzip_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_write_lrzip_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_write_lrzip_close(struct archive_write_filter *);
-static int archive_write_lrzip_free(struct archive_write_filter *);
-
-int
-archive_write_add_filter_lrzip(struct archive *_a)
-{
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct write_lrzip *data;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->pdata = __archive_write_program_allocate("lrzip");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	f->name = "lrzip";
-	f->code = ARCHIVE_FILTER_LRZIP;
-	f->data = data;
-	f->open = archive_write_lrzip_open;
-	f->options = archive_write_lrzip_options;
-	f->write = archive_write_lrzip_write;
-	f->close = archive_write_lrzip_close;
-	f->free = archive_write_lrzip_free;
-
-	/* Note: This filter always uses an external program, so we
-	 * return "warn" to inform of the fact. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lrzip program for lrzip compression");
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct write_lrzip *data = (struct write_lrzip *)f->data;
-
-	if (strcmp(key, "compression") == 0) {
-		if (value == NULL)
-			return (ARCHIVE_WARN);
-		else if (strcmp(value, "bzip2") == 0)
-			data->compression = bzip2;
-		else if (strcmp(value, "gzip") == 0)
-			data->compression = gzip;
-		else if (strcmp(value, "lzo") == 0)
-			data->compression = lzo;
-		else if (strcmp(value, "none") == 0)
-			data->compression = none;
-		else if (strcmp(value, "zpaq") == 0)
-			data->compression = zpaq;
-		else
-			return (ARCHIVE_WARN);
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->compression_level = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_lrzip_open(struct archive_write_filter *f)
-{
-	struct write_lrzip *data = (struct write_lrzip *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	archive_strcpy(&as, "lrzip -q");
-
-	/* Specify compression type. */
-	switch (data->compression) {
-	case lzma:/* default compression */
-		break;
-	case bzip2:
-		archive_strcat(&as, " -b");
-		break;
-	case gzip:
-		archive_strcat(&as, " -g");
-		break;
-	case lzo:
-		archive_strcat(&as, " -l");
-		break;
-	case none:
-		archive_strcat(&as, " -n");
-		break;
-	case zpaq:
-		archive_strcat(&as, " -z");
-		break;
-	}
-
-	/* Specify compression level. */
-	if (data->compression_level > 0) {
-		archive_strcat(&as, " -L ");
-		archive_strappend_char(&as, '0' + data->compression_level);
-	}
-
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_write_lrzip_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct write_lrzip *data = (struct write_lrzip *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_write_lrzip_close(struct archive_write_filter *f)
-{
-	struct write_lrzip *data = (struct write_lrzip *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-static int
-archive_write_lrzip_free(struct archive_write_filter *f)
-{
-	struct write_lrzip *data = (struct write_lrzip *)f->data;
-
-	__archive_write_program_free(data->pdata);
-	free(data);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_add_filter_lz4.c b/c/archive_write_add_filter_lz4.c
deleted file mode 100644
--- a/c/archive_write_add_filter_lz4.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_LZ4_H
-#include <lz4.h>
-#endif
-#ifdef HAVE_LZ4HC_H
-#include <lz4hc.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_xxhash.h"
-
-#define LZ4_MAGICNUMBER	0x184d2204
-
-struct private_data {
-	int		 compression_level;
-	unsigned	 header_written:1;
-	unsigned	 version_number:1;
-	unsigned	 block_independence:1;
-	unsigned	 block_checksum:1;
-	unsigned	 stream_size:1;
-	unsigned	 stream_checksum:1;
-	unsigned	 preset_dictionary:1;
-	unsigned	 block_maximum_size:3;
-#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
-	int64_t		 total_in;
-	char		*out;
-	char		*out_buffer;
-	size_t		 out_buffer_size;
-	size_t		 out_block_size;
-	char		*in;
-	char		*in_buffer_allocated;
-	char		*in_buffer;
-	size_t		 in_buffer_size;
-	size_t		 block_size;
-
-	void		*xxh32_state;
-	void		*lz4_stream;
-#else
-	struct archive_write_program_data *pdata;
-#endif
-};
-
-static int archive_filter_lz4_close(struct archive_write_filter *);
-static int archive_filter_lz4_free(struct archive_write_filter *);
-static int archive_filter_lz4_open(struct archive_write_filter *);
-static int archive_filter_lz4_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_filter_lz4_write(struct archive_write_filter *,
-		    const void *, size_t);
-
-/*
- * Add a lz4 compression filter to this write handle.
- */
-int
-archive_write_add_filter_lz4(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_data *data;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lz4");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Setup default settings.
-	 */
-	data->compression_level = 1;
-	data->version_number = 0x01;
-	data->block_independence = 1;
-	data->block_checksum = 0;
-	data->stream_size = 0;
-	data->stream_checksum = 1;
-	data->preset_dictionary = 0;
-	data->block_maximum_size = 7;
-
-	/*
-	 * Setup a filter setting.
-	 */
-	f->data = data;
-	f->options = &archive_filter_lz4_options;
-	f->close = &archive_filter_lz4_close;
-	f->free = &archive_filter_lz4_free;
-	f->open = &archive_filter_lz4_open;
-	f->code = ARCHIVE_FILTER_LZ4;
-	f->name = "lz4";
-#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
-	return (ARCHIVE_OK);
-#else
-	/*
-	 * We don't have lz4 library, and execute external lz4 program
-	 * instead.
-	 */
-	data->pdata = __archive_write_program_allocate("lz4");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 0;
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Using external lz4 program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-/*
- * Set write options.
- */
-static int
-archive_filter_lz4_options(struct archive_write_filter *f,
-    const char *key, const char *value)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		int val;
-		if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-
-#ifndef HAVE_LZ4HC_H
-		if(val >= 3)
-		{
-			archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER,
-				"High compression not included in this build");
-			return (ARCHIVE_FATAL);
-		}
-#endif
-		data->compression_level = val;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "stream-checksum") == 0) {
-		data->stream_checksum = value != NULL;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "block-checksum") == 0) {
-		data->block_checksum = value != NULL;
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "block-size") == 0) {
-		if (value == NULL || !(value[0] >= '4' && value[0] <= '7') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->block_maximum_size = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "block-dependence") == 0) {
-		data->block_independence = value == NULL;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
-/* Don't compile this if we don't have liblz4. */
-
-static int drive_compressor(struct archive_write_filter *, const char *,
-    size_t);
-static int drive_compressor_independence(struct archive_write_filter *,
-    const char *, size_t);
-static int drive_compressor_dependence(struct archive_write_filter *,
-    const char *, size_t);
-static int lz4_write_stream_descriptor(struct archive_write_filter *);
-static ssize_t lz4_write_one_block(struct archive_write_filter *, const char *,
-    size_t);
-
-
-/*
- * Setup callback.
- */
-static int
-archive_filter_lz4_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	size_t required_size;
-	static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024,
-			   4 * 1024 * 1024 };
-	size_t pre_block_size;
-
-	if (data->block_maximum_size < 4)
-		data->block_size = bkmap[0];
-	else
-		data->block_size = bkmap[data->block_maximum_size - 4];
-
-	required_size = 4 + 15 + 4 + data->block_size + 4 + 4;
-	if (data->out_buffer_size < required_size) {
-		size_t bs = required_size, bpb;
-		free(data->out_buffer);
-		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-			/* Buffer size should be a multiple number of
-			 * the of bytes per block for performance. */
-			bpb = archive_write_get_bytes_per_block(f->archive);
-			if (bpb > bs)
-				bs = bpb;
-			else if (bpb != 0) {
-				bs += bpb;
-				bs -= bs % bpb;
-			}
-		}
-		data->out_block_size = bs;
-		bs += required_size;
-		data->out_buffer = malloc(bs);
-		data->out = data->out_buffer;
-		data->out_buffer_size = bs;
-	}
-
-	pre_block_size = (data->block_independence)? 0: 64 * 1024;
-	if (data->in_buffer_size < data->block_size + pre_block_size) {
-		free(data->in_buffer_allocated);
-		data->in_buffer_size = data->block_size;
-		data->in_buffer_allocated =
-		    malloc(data->in_buffer_size + pre_block_size);
-		data->in_buffer = data->in_buffer_allocated + pre_block_size;
-		if (!data->block_independence && data->compression_level >= 3)
-		    data->in_buffer = data->in_buffer_allocated;
-		data->in = data->in_buffer;
-		data->in_buffer_size = data->block_size;
-	}
-
-	if (data->out_buffer == NULL || data->in_buffer_allocated == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for compression buffer");
-		return (ARCHIVE_FATAL);
-	}
-
-	f->write = archive_filter_lz4_write;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Write data to the out stream.
- *
- * Returns ARCHIVE_OK if all data written, error otherwise.
- */
-static int
-archive_filter_lz4_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret = ARCHIVE_OK;
-	const char *p;
-	size_t remaining;
-	ssize_t size;
-
-	/* If we haven't written a stream descriptor, we have to do it first. */
-	if (!data->header_written) {
-		ret = lz4_write_stream_descriptor(f);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		data->header_written = 1;
-	}
-
-	/* Update statistics */
-	data->total_in += length;
-
-	p = (const char *)buff;
-	remaining = length;
-	while (remaining) {
-		size_t l;
-		/* Compress input data to output buffer */
-		size = lz4_write_one_block(f, p, remaining);
-		if (size < ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		l = data->out - data->out_buffer;
-		if (l >= data->out_block_size) {
-			ret = __archive_write_filter(f->next_filter,
-			    data->out_buffer, data->out_block_size);
-			l -= data->out_block_size;
-			memcpy(data->out_buffer,
-			    data->out_buffer + data->out_block_size, l);
-			data->out = data->out_buffer + l;
-			if (ret < ARCHIVE_WARN)
-				break;
-		}
-		p += size;
-		remaining -= size;
-	}
-
-	return (ret);
-}
-
-/*
- * Finish the compression.
- */
-static int
-archive_filter_lz4_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	/* Finish compression cycle. */
-	ret = (int)lz4_write_one_block(f, NULL, 0);
-	if (ret >= 0) {
-		/*
-		 * Write the last block and the end of the stream data.
-		 */
-
-		/* Write End Of Stream. */
-		memset(data->out, 0, 4); data->out += 4;
-		/* Write Stream checksum if needed. */
-		if (data->stream_checksum) {
-			unsigned int checksum;
-			checksum = __archive_xxhash.XXH32_digest(
-					data->xxh32_state);
-			data->xxh32_state = NULL;
-			archive_le32enc(data->out, checksum);
-			data->out += 4;
-		}
-		ret = __archive_write_filter(f->next_filter,
-			    data->out_buffer, data->out - data->out_buffer);
-	}
-	return ret;
-}
-
-static int
-archive_filter_lz4_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data->lz4_stream != NULL) {
-#ifdef HAVE_LZ4HC_H
-		if (data->compression_level >= 3)
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-			LZ4_freeStreamHC(data->lz4_stream);
-#else
-			LZ4_freeHC(data->lz4_stream);
-#endif
-		else
-#endif
-#if LZ4_VERSION_MINOR >= 3
-			LZ4_freeStream(data->lz4_stream);
-#else
-			LZ4_free(data->lz4_stream);
-#endif
-	}
-	free(data->out_buffer);
-	free(data->in_buffer_allocated);
-	free(data->xxh32_state);
-	free(data);
-	f->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-lz4_write_stream_descriptor(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	uint8_t *sd;
-
-	sd = (uint8_t *)data->out;
-	/* Write Magic Number. */
-	archive_le32enc(&sd[0], LZ4_MAGICNUMBER);
-	/* FLG */
-	sd[4] = (data->version_number << 6)
-	      | (data->block_independence << 5)
-	      | (data->block_checksum << 4)
-	      | (data->stream_size << 3)
-	      | (data->stream_checksum << 2)
-	      | (data->preset_dictionary << 0);
-	/* BD */
-	sd[5] = (data->block_maximum_size << 4);
-	sd[6] = (__archive_xxhash.XXH32(&sd[4], 2, 0) >> 8) & 0xff;
-	data->out += 7;
-	if (data->stream_checksum)
-		data->xxh32_state = __archive_xxhash.XXH32_init(0);
-	else
-		data->xxh32_state = NULL;
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-lz4_write_one_block(struct archive_write_filter *f, const char *p,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	ssize_t r;
-
-	if (p == NULL) {
-		/* Compress remaining uncompressed data. */
-		if (data->in_buffer == data->in)
-			return 0;
-		else {
-			size_t l = data->in - data->in_buffer;
-			r = drive_compressor(f, data->in_buffer, l);
-			if (r == ARCHIVE_OK)
-				r = (ssize_t)l;
-		}
-	} else if ((data->block_independence || data->compression_level < 3) &&
-	    data->in_buffer == data->in && length >= data->block_size) {
-		r = drive_compressor(f, p, data->block_size);
-		if (r == ARCHIVE_OK)
-			r = (ssize_t)data->block_size;
-	} else {
-		size_t remaining_size = data->in_buffer_size -
-			(data->in - data->in_buffer);
-		size_t l = (remaining_size > length)? length: remaining_size;
-		memcpy(data->in, p, l);
-		data->in += l;
-		if (l == remaining_size) {
-			r = drive_compressor(f, data->in_buffer,
-			    data->block_size);
-			if (r == ARCHIVE_OK)
-				r = (ssize_t)l;
-			data->in = data->in_buffer;
-		} else
-			r = (ssize_t)l;
-	}
-
-	return (r);
-}
-
-
-/*
- * Utility function to push input data through compressor, writing
- * full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
- */
-static int
-drive_compressor(struct archive_write_filter *f, const char *p, size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data->stream_checksum)
-		__archive_xxhash.XXH32_update(data->xxh32_state,
-			p, (int)length);
-	if (data->block_independence)
-		return drive_compressor_independence(f, p, length);
-	else
-		return drive_compressor_dependence(f, p, length);
-}
-
-static int
-drive_compressor_independence(struct archive_write_filter *f, const char *p,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	unsigned int outsize;
-
-#ifdef HAVE_LZ4HC_H
-	if (data->compression_level >= 3)
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-		outsize = LZ4_compress_HC(p, data->out + 4,
-		     (int)length, (int)data->block_size,
-		    data->compression_level);
-#else
-		outsize = LZ4_compressHC2_limitedOutput(p, data->out + 4,
-		    (int)length, (int)data->block_size,
-		    data->compression_level);
-#endif
-	else
-#endif
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-		outsize = LZ4_compress_default(p, data->out + 4,
-		    (int)length, (int)data->block_size);
-#else
-		outsize = LZ4_compress_limitedOutput(p, data->out + 4,
-		    (int)length, (int)data->block_size);
-#endif
-
-	if (outsize) {
-		/* The buffer is compressed. */
-		archive_le32enc(data->out, outsize);
-		data->out += 4;
-	} else {
-		/* The buffer is not compressed. The compressed size was
-		 * bigger than its uncompressed size. */
-		archive_le32enc(data->out, (uint32_t)(length | 0x80000000));
-		data->out += 4;
-		memcpy(data->out, p, length);
-		outsize = (uint32_t)length;
-	}
-	data->out += outsize;
-	if (data->block_checksum) {
-		unsigned int checksum =
-		    __archive_xxhash.XXH32(data->out - outsize, outsize, 0);
-		archive_le32enc(data->out, checksum);
-		data->out += 4;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-drive_compressor_dependence(struct archive_write_filter *f, const char *p,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int outsize;
-
-#define DICT_SIZE	(64 * 1024)
-#ifdef HAVE_LZ4HC_H
-	if (data->compression_level >= 3) {
-		if (data->lz4_stream == NULL) {
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-			data->lz4_stream = LZ4_createStreamHC();
-			LZ4_resetStreamHC(data->lz4_stream, data->compression_level);
-#else
-			data->lz4_stream =
-			    LZ4_createHC(data->in_buffer_allocated);
-#endif
-			if (data->lz4_stream == NULL) {
-				archive_set_error(f->archive, ENOMEM,
-				    "Can't allocate data for compression"
-				    " buffer");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		else
-			LZ4_loadDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
-
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-		outsize = LZ4_compress_HC_continue(
-		    data->lz4_stream, p, data->out + 4, (int)length,
-		    (int)data->block_size);
-#else
-		outsize = LZ4_compressHC2_limitedOutput_continue(
-		    data->lz4_stream, p, data->out + 4, (int)length,
-		    (int)data->block_size, data->compression_level);
-#endif
-	} else
-#endif
-	{
-		if (data->lz4_stream == NULL) {
-			data->lz4_stream = LZ4_createStream();
-			if (data->lz4_stream == NULL) {
-				archive_set_error(f->archive, ENOMEM,
-				    "Can't allocate data for compression"
-				    " buffer");
-				return (ARCHIVE_FATAL);
-			}
-		}
-		else
-			LZ4_loadDict(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
-
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-		outsize = LZ4_compress_fast_continue(
-		    data->lz4_stream, p, data->out + 4, (int)length,
-		    (int)data->block_size, 1);
-#else
-		outsize = LZ4_compress_limitedOutput_continue(
-		    data->lz4_stream, p, data->out + 4, (int)length,
-		    (int)data->block_size);
-#endif
-	}
-
-	if (outsize) {
-		/* The buffer is compressed. */
-		archive_le32enc(data->out, outsize);
-		data->out += 4;
-	} else {
-		/* The buffer is not compressed. The compressed size was
-		 * bigger than its uncompressed size. */
-		archive_le32enc(data->out, (uint32_t)(length | 0x80000000));
-		data->out += 4;
-		memcpy(data->out, p, length);
-		outsize = (uint32_t)length;
-	}
-	data->out += outsize;
-	if (data->block_checksum) {
-		unsigned int checksum =
-		    __archive_xxhash.XXH32(data->out - outsize, outsize, 0);
-		archive_le32enc(data->out, checksum);
-		data->out += 4;
-	}
-
-	if (length == data->block_size) {
-#ifdef HAVE_LZ4HC_H
-		if (data->compression_level >= 3) {
-#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
-			LZ4_saveDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
-#else
-			LZ4_slideInputBufferHC(data->lz4_stream);
-#endif
-			data->in_buffer = data->in_buffer_allocated + DICT_SIZE;
-		}
-		else
-#endif
-			LZ4_saveDict(data->lz4_stream,
-			    data->in_buffer_allocated, DICT_SIZE);
-#undef DICT_SIZE
-	}
-	return (ARCHIVE_OK);
-}
-
-#else /* HAVE_LIBLZ4 */
-
-static int
-archive_filter_lz4_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	archive_strcpy(&as, "lz4 -z -q -q");
-
-	/* Specify a compression level. */
-	if (data->compression_level > 0) {
-		archive_strcat(&as, " -");
-		archive_strappend_char(&as, '0' + data->compression_level);
-	}
-	/* Specify a block size. */
-	archive_strcat(&as, " -B");
-	archive_strappend_char(&as, '0' + data->block_maximum_size);
-
-	if (data->block_checksum)
-		archive_strcat(&as, " -BX");
-	if (data->stream_checksum == 0)
-		archive_strcat(&as, " --no-frame-crc");
-	if (data->block_independence == 0)
-		archive_strcat(&as, " -BD");
-
-	f->write = archive_filter_lz4_write;
-
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_filter_lz4_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_filter_lz4_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-static int
-archive_filter_lz4_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	__archive_write_program_free(data->pdata);
-	free(data);
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_LIBLZ4 */
diff --git a/c/archive_write_add_filter_lzop.c b/c/archive_write_add_filter_lzop.c
deleted file mode 100644
--- a/c/archive_write_add_filter_lzop.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-//#undef HAVE_LZO_LZOCONF_H
-//#undef HAVE_LZO_LZO1X_H
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-#ifdef HAVE_LZO_LZOCONF_H
-#include <lzo/lzoconf.h>
-#endif
-#ifdef HAVE_LZO_LZO1X_H
-#include <lzo/lzo1x.h>
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_endian.h"
-#include "archive_write_private.h"
-
-enum lzo_method {
-	METHOD_LZO1X_1 = 1,
-	METHOD_LZO1X_1_15 = 2,
-	METHOD_LZO1X_999 = 3
-};
-struct write_lzop {
-	int compression_level;
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-	unsigned char	*uncompressed;
-	size_t		 uncompressed_buffer_size;
-	size_t		 uncompressed_avail_bytes;
-	unsigned char	*compressed;
-	size_t		 compressed_buffer_size;
-	enum lzo_method	 method;
-	unsigned char	 level;
-	lzo_voidp	 work_buffer;
-	lzo_uint32	 work_buffer_size;
-	char		 header_written;
-#else
-	struct archive_write_program_data *pdata;
-#endif
-};
-
-static int archive_write_lzop_open(struct archive_write_filter *);
-static int archive_write_lzop_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_write_lzop_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_write_lzop_close(struct archive_write_filter *);
-static int archive_write_lzop_free(struct archive_write_filter *);
-
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-/* Maximum block size. */
-#define BLOCK_SIZE			(256 * 1024)
-/* Block information is composed of uncompressed size(4 bytes),
- * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
- * in this lzop writer. */
-#define BLOCK_INfO_SIZE			12
-
-#define HEADER_VERSION			9
-#define HEADER_LIBVERSION		11
-#define HEADER_METHOD			15
-#define HEADER_LEVEL			16
-#define HEADER_MTIME_LOW		25
-#define HEADER_MTIME_HIGH		29
-#define HEADER_H_CHECKSUM		34
-
-/*
- * Header template.
- */
-static const unsigned char header[] = {
-	/* LZOP Magic code 9 bytes */
-	0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a,
-	/* LZOP utility version(fake data) 2 bytes */
-	0x10, 0x30,
-	/* LZO library version 2 bytes */
-	0x09, 0x40,
-	/* Minimum required LZO library version 2 bytes */
-	0x09, 0x40,
-	/* Method */
-	1,
-	/* Level */
-	5,
-	/* Flags 4 bytes
-	 *  -OS Unix
-	 *  -Stdout
-	 *  -Stdin
-	 *  -Adler32 used for uncompressed data 4 bytes */
-	0x03, 0x00, 0x00, 0x0d,
-	/* Mode (AE_IFREG | 0644) 4 bytes */
-	0x00, 0x00, 0x81, 0xa4,
-	/* Mtime low 4 bytes */
-	0x00, 0x00, 0x00, 0x00,
-	/* Mtime high 4 bytes */
-	0x00, 0x00, 0x00, 0x00,
-	/* Filename length */
-	0x00,
-	/* Header checksum 4 bytes */
-	0x00, 0x00, 0x00, 0x00,
-};
-#endif
-
-int
-archive_write_add_filter_lzop(struct archive *_a)
-{
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct write_lzop *data;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	f->name = "lzop";
-	f->code = ARCHIVE_FILTER_LZOP;
-	f->data = data;
-	f->open = archive_write_lzop_open;
-	f->options = archive_write_lzop_options;
-	f->write = archive_write_lzop_write;
-	f->close = archive_write_lzop_close;
-	f->free = archive_write_lzop_free;
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-	if (lzo_init() != LZO_E_OK) {
-		free(data);
-		archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-		    "lzo_init(type check) failed");
-		return (ARCHIVE_FATAL);
-	}
-	if (lzo_version() < 0x940) {
-		free(data);
-		archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-		    "liblzo library is too old(%s < 0.940)",
-		    lzo_version_string());
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 5;
-	return (ARCHIVE_OK);
-#else
-	data->pdata = __archive_write_program_allocate("lzop");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(_a, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	data->compression_level = 0;
-	/* Note: We return "warn" to inform of using an external lzop
-	 * program. */
-	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
-	    "Using external lzop program for lzop compression");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-static int
-archive_write_lzop_free(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-	free(data->uncompressed);
-	free(data->compressed);
-	free(data->work_buffer);
-#else
-	__archive_write_program_free(data->pdata);
-#endif
-	free(data);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_lzop_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->compression_level = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
-static int
-archive_write_lzop_open(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-
-	switch (data->compression_level) {
-	case 1:
-		data->method = METHOD_LZO1X_1_15; data->level = 1; break;
-	default:
-	case 2: case 3: case 4: case 5: case 6:
-		data->method = METHOD_LZO1X_1; data->level = 5; break;
-	case 7:
-		data->method = METHOD_LZO1X_999; data->level = 7; break;
-	case 8:
-		data->method = METHOD_LZO1X_999; data->level = 8; break;
-	case 9:
-		data->method = METHOD_LZO1X_999; data->level = 9; break;
-	}
-	switch (data->method) {
-	case METHOD_LZO1X_1:
-		data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break;
-	case METHOD_LZO1X_1_15:
-		data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break;
-	case METHOD_LZO1X_999:
-		data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break;
-	}
-	if (data->work_buffer == NULL) {
-		data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size);
-		if (data->work_buffer == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	if (data->compressed == NULL) {
-		data->compressed_buffer_size = sizeof(header) +
-		    BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3;
-		data->compressed = (unsigned char *)
-		    malloc(data->compressed_buffer_size);
-		if (data->compressed == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	if (data->uncompressed == NULL) {
-		data->uncompressed_buffer_size = BLOCK_SIZE;
-		data->uncompressed = (unsigned char *)
-		    malloc(data->uncompressed_buffer_size);
-		if (data->uncompressed == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-		data->uncompressed_avail_bytes = BLOCK_SIZE;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-make_header(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-	int64_t t;
-	uint32_t checksum;
-
-	memcpy(data->compressed, header, sizeof(header));
-	/* Overwrite library version. */
-	data->compressed[HEADER_LIBVERSION] = (unsigned char )
-	    (lzo_version() >> 8) & 0xff;
-	data->compressed[HEADER_LIBVERSION + 1] = (unsigned char )
-	    lzo_version() & 0xff;
-	/* Overwrite method and level. */
-	data->compressed[HEADER_METHOD] = (unsigned char)data->method;
-	data->compressed[HEADER_LEVEL] = data->level;
-	/* Overwrite mtime with current time. */
-	t = (int64_t)time(NULL);
-	archive_be32enc(&data->compressed[HEADER_MTIME_LOW],
-	    (uint32_t)(t & 0xffffffff));
-	archive_be32enc(&data->compressed[HEADER_MTIME_HIGH],
-	    (uint32_t)((t >> 32) & 0xffffffff));
-	/* Overwrite header checksum with calculated value. */
-	checksum = lzo_adler32(1, data->compressed + HEADER_VERSION,
-			(lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION));
-	archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum);
-	return (sizeof(header));
-}
-
-static int
-drive_compressor(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-	unsigned char *p;
-	const int block_info_bytes = 12;
-	int header_bytes, r;
-	lzo_uint usize, csize;
-	uint32_t checksum;
-
-	if (!data->header_written) {
-		header_bytes = make_header(f);
-		data->header_written = 1;
-	} else
-		header_bytes = 0;
-	p = data->compressed;
-
-	usize = (lzo_uint)
-	    (data->uncompressed_buffer_size - data->uncompressed_avail_bytes);
-	csize = 0;
-	switch (data->method) {
-	default:
-	case METHOD_LZO1X_1:
-		r = lzo1x_1_compress(data->uncompressed, usize,
-			p + header_bytes + block_info_bytes, &csize,
-			data->work_buffer);
-		break;
-	case METHOD_LZO1X_1_15:
-		r = lzo1x_1_15_compress(data->uncompressed, usize,
-			p + header_bytes + block_info_bytes, &csize,
-			data->work_buffer);
-		break;
-	case METHOD_LZO1X_999:
-		r = lzo1x_999_compress_level(data->uncompressed, usize,
-			p + header_bytes + block_info_bytes, &csize,
-			data->work_buffer, NULL, 0, 0, data->level);
-		break;
-	}
-	if (r != LZO_E_OK) {
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Lzop compression failed: returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Store uncompressed size. */
-	archive_be32enc(p + header_bytes, (uint32_t)usize);
-	/* Store the checksum of the uncompressed data. */
-	checksum = lzo_adler32(1, data->uncompressed, usize);
-	archive_be32enc(p + header_bytes + 8, checksum);
-
-	if (csize < usize) {
-		/* Store compressed size. */
-		archive_be32enc(p + header_bytes + 4, (uint32_t)csize);
-		r = __archive_write_filter(f->next_filter, data->compressed,
-			header_bytes + block_info_bytes + csize);
-	} else {
-		/*
-		 * This case, we output uncompressed data instead.
-		 */
-		/* Store uncompressed size as compressed size. */
-		archive_be32enc(p + header_bytes + 4, (uint32_t)usize);
-		r = __archive_write_filter(f->next_filter, data->compressed,
-			header_bytes + block_info_bytes);
-		if (r != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		r = __archive_write_filter(f->next_filter, data->uncompressed,
-			usize);
-	}
-
-	if (r != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_lzop_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-	const char *p = buff;
-	int r;
-
-	do {
-		if (data->uncompressed_avail_bytes > length) {
-			memcpy(data->uncompressed
-				+ data->uncompressed_buffer_size
-				- data->uncompressed_avail_bytes,
-			    p, length);
-			data->uncompressed_avail_bytes -= length;
-			return (ARCHIVE_OK);
-		}
-
-		memcpy(data->uncompressed + data->uncompressed_buffer_size
-			- data->uncompressed_avail_bytes,
-		    p, data->uncompressed_avail_bytes);
-		length -= data->uncompressed_avail_bytes;
-		p += data->uncompressed_avail_bytes;
-		data->uncompressed_avail_bytes = 0;
-
-		r = drive_compressor(f);
-		if (r != ARCHIVE_OK) return (r);
-		data->uncompressed_avail_bytes = BLOCK_SIZE;
-	} while (length);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_lzop_close(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-	const uint32_t endmark = 0;
-	int r;
-
-	if (data->uncompressed_avail_bytes < BLOCK_SIZE) {
-		/* Compress and output remaining data. */
-		r = drive_compressor(f);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-	/* Write a zero uncompressed size as the end mark of the series of
-	 * compressed block. */
-	return __archive_write_filter(f->next_filter, &endmark, sizeof(endmark));
-}
-
-#else
-static int
-archive_write_lzop_open(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	archive_strcpy(&as, "lzop");
-	/* Specify compression level. */
-	if (data->compression_level > 0) {
-		archive_strappend_char(&as, ' ');
-		archive_strappend_char(&as, '-');
-		archive_strappend_char(&as, '0' + data->compression_level);
-	}
-
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_write_lzop_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_write_lzop_close(struct archive_write_filter *f)
-{
-	struct write_lzop *data = (struct write_lzop *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-#endif
diff --git a/c/archive_write_add_filter_none.c b/c/archive_write_add_filter_none.c
deleted file mode 100644
--- a/c/archive_write_add_filter_none.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_none.c 201080 2009-12-28 02:03:54Z kientzle $");
-
-#include "archive.h"
-
-int
-archive_write_set_compression_none(struct archive *a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_add_filter_none(struct archive *a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_add_filter_program.c b/c/archive_write_add_filter_program.c
deleted file mode 100644
--- a/c/archive_write_add_filter_program.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*-
- * Copyright (c) 2007 Joerg Sonnenberger
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c 201104 2009-12-28 03:14:30Z kientzle $");
-
-#ifdef HAVE_SYS_WAIT_H
-#  include <sys/wait.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#  include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#  include <fcntl.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#  include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-#include "filter_fork.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_write_set_compression_program(struct archive *a, const char *cmd)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_program(a, cmd));
-}
-#endif
-
-struct archive_write_program_data {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	HANDLE		 child;
-#else
-	pid_t		 child;
-#endif
-	int		 child_stdin, child_stdout;
-
-	char		*child_buf;
-	size_t		 child_buf_len, child_buf_avail;
-	char		*program_name;
-};
-
-struct private_data {
-	struct archive_write_program_data *pdata;
-	struct archive_string description;
-	char		*cmd;
-};
-
-static int archive_compressor_program_open(struct archive_write_filter *);
-static int archive_compressor_program_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_compressor_program_close(struct archive_write_filter *);
-static int archive_compressor_program_free(struct archive_write_filter *);
-
-/*
- * Add a filter to this write handle that passes all data through an
- * external program.
- */
-int
-archive_write_add_filter_program(struct archive *_a, const char *cmd)
-{
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_data *data;
-	static const char prefix[] = "Program: ";
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
-
-	f->data = calloc(1, sizeof(*data));
-	if (f->data == NULL)
-		goto memerr;
-	data = (struct private_data *)f->data;
-
-	data->cmd = strdup(cmd);
-	if (data->cmd == NULL)
-		goto memerr;
-
-	data->pdata = __archive_write_program_allocate(cmd);
-	if (data->pdata == NULL)
-		goto memerr;
-
-	/* Make up a description string. */
-	if (archive_string_ensure(&data->description,
-	    strlen(prefix) + strlen(cmd) + 1) == NULL)
-		goto memerr;
-	archive_strcpy(&data->description, prefix);
-	archive_strcat(&data->description, cmd);
-
-	f->name = data->description.s;
-	f->code = ARCHIVE_FILTER_PROGRAM;
-	f->open = archive_compressor_program_open;
-	f->write = archive_compressor_program_write;
-	f->close = archive_compressor_program_close;
-	f->free = archive_compressor_program_free;
-	return (ARCHIVE_OK);
-memerr:
-	archive_compressor_program_free(f);
-	archive_set_error(_a, ENOMEM,
-	    "Can't allocate memory for filter program");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-archive_compressor_program_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_open(f, data->pdata, data->cmd);
-}
-
-static int
-archive_compressor_program_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_compressor_program_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-static int
-archive_compressor_program_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data) {
-		free(data->cmd);
-		archive_string_free(&data->description);
-		__archive_write_program_free(data->pdata);
-		free(data);
-		f->data = NULL;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Allocate resources for executing an external program.
- */
-struct archive_write_program_data *
-__archive_write_program_allocate(const char *program)
-{
-	struct archive_write_program_data *data;
-
-	data = calloc(1, sizeof(struct archive_write_program_data));
-	if (data == NULL)
-		return (data);
-	data->child_stdin = -1;
-	data->child_stdout = -1;
-	data->program_name = strdup(program);
-	return (data);
-}
-
-/*
- * Release the resources.
- */
-int
-__archive_write_program_free(struct archive_write_program_data *data)
-{
-
-	if (data) {
-		free(data->program_name);
-		free(data->child_buf);
-		free(data);
-	}
-	return (ARCHIVE_OK);
-}
-
-int
-__archive_write_program_open(struct archive_write_filter *f,
-    struct archive_write_program_data *data, const char *cmd)
-{
-	int ret;
-
-	if (data->child_buf == NULL) {
-		data->child_buf_len = 65536;
-		data->child_buf_avail = 0;
-		data->child_buf = malloc(data->child_buf_len);
-
-		if (data->child_buf == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	ret = __archive_create_child(cmd, &data->child_stdin,
-		    &data->child_stdout, &data->child);
-	if (ret != ARCHIVE_OK) {
-		archive_set_error(f->archive, EINVAL,
-		    "Can't launch external program: %s", cmd);
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-child_write(struct archive_write_filter *f,
-    struct archive_write_program_data *data, const char *buf, size_t buf_len)
-{
-	ssize_t ret;
-
-	if (data->child_stdin == -1)
-		return (-1);
-
-	if (buf_len == 0)
-		return (-1);
-
-	for (;;) {
-		do {
-			ret = write(data->child_stdin, buf, buf_len);
-		} while (ret == -1 && errno == EINTR);
-
-		if (ret > 0)
-			return (ret);
-		if (ret == 0) {
-			close(data->child_stdin);
-			data->child_stdin = -1;
-			fcntl(data->child_stdout, F_SETFL, 0);
-			return (0);
-		}
-		if (ret == -1 && errno != EAGAIN)
-			return (-1);
-
-		if (data->child_stdout == -1) {
-			fcntl(data->child_stdin, F_SETFL, 0);
-			__archive_check_child(data->child_stdin,
-				data->child_stdout);
-			continue;
-		}
-
-		do {
-			ret = read(data->child_stdout,
-			    data->child_buf + data->child_buf_avail,
-			    data->child_buf_len - data->child_buf_avail);
-		} while (ret == -1 && errno == EINTR);
-
-		if (ret == 0 || (ret == -1 && errno == EPIPE)) {
-			close(data->child_stdout);
-			data->child_stdout = -1;
-			fcntl(data->child_stdin, F_SETFL, 0);
-			continue;
-		}
-		if (ret == -1 && errno == EAGAIN) {
-			__archive_check_child(data->child_stdin,
-				data->child_stdout);
-			continue;
-		}
-		if (ret == -1)
-			return (-1);
-
-		data->child_buf_avail += ret;
-
-		ret = __archive_write_filter(f->next_filter,
-		    data->child_buf, data->child_buf_avail);
-		if (ret != ARCHIVE_OK)
-			return (-1);
-		data->child_buf_avail = 0;
-	}
-}
-
-/*
- * Write data to the filter stream.
- */
-int
-__archive_write_program_write(struct archive_write_filter *f,
-    struct archive_write_program_data *data, const void *buff, size_t length)
-{
-	ssize_t ret;
-	const char *buf;
-
-	if (data->child == 0)
-		return (ARCHIVE_OK);
-
-	buf = buff;
-	while (length > 0) {
-		ret = child_write(f, data, buf, length);
-		if (ret == -1 || ret == 0) {
-			archive_set_error(f->archive, EIO,
-			    "Can't write to program: %s", data->program_name);
-			return (ARCHIVE_FATAL);
-		}
-		length -= ret;
-		buf += ret;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Finish the filtering...
- */
-int
-__archive_write_program_close(struct archive_write_filter *f,
-    struct archive_write_program_data *data)
-{
-	int ret, status;
-	ssize_t bytes_read;
-
-	if (data->child == 0)
-		return ARCHIVE_OK;
-
-	ret = 0;
-	close(data->child_stdin);
-	data->child_stdin = -1;
-	fcntl(data->child_stdout, F_SETFL, 0);
-
-	for (;;) {
-		do {
-			bytes_read = read(data->child_stdout,
-			    data->child_buf + data->child_buf_avail,
-			    data->child_buf_len - data->child_buf_avail);
-		} while (bytes_read == -1 && errno == EINTR);
-
-		if (bytes_read == 0 || (bytes_read == -1 && errno == EPIPE))
-			break;
-
-		if (bytes_read == -1) {
-			archive_set_error(f->archive, errno,
-			    "Error reading from program: %s", data->program_name);
-			ret = ARCHIVE_FATAL;
-			goto cleanup;
-		}
-		data->child_buf_avail += bytes_read;
-
-		ret = __archive_write_filter(f->next_filter,
-		    data->child_buf, data->child_buf_avail);
-		if (ret != ARCHIVE_OK) {
-			ret = ARCHIVE_FATAL;
-			goto cleanup;
-		}
-		data->child_buf_avail = 0;
-	}
-
-cleanup:
-	/* Shut down the child. */
-	if (data->child_stdin != -1)
-		close(data->child_stdin);
-	if (data->child_stdout != -1)
-		close(data->child_stdout);
-	while (waitpid(data->child, &status, 0) == -1 && errno == EINTR)
-		continue;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	CloseHandle(data->child);
-#endif
-	data->child = 0;
-
-	if (status != 0) {
-		archive_set_error(f->archive, EIO,
-		    "Error closing program: %s", data->program_name);
-		ret = ARCHIVE_FATAL;
-	}
-	return ret;
-}
-
diff --git a/c/archive_write_add_filter_uuencode.c b/c/archive_write_add_filter_uuencode.c
deleted file mode 100644
--- a/c/archive_write_add_filter_uuencode.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*-
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-#define LBYTES 45
-
-struct private_uuencode {
-	int			mode;
-	struct archive_string	name;
-	struct archive_string	encoded_buff;
-	size_t			bs;
-	size_t			hold_len;
-	unsigned char		hold[LBYTES];
-};
-
-static int archive_filter_uuencode_options(struct archive_write_filter *,
-    const char *, const char *);
-static int archive_filter_uuencode_open(struct archive_write_filter *);
-static int archive_filter_uuencode_write(struct archive_write_filter *,
-    const void *, size_t);
-static int archive_filter_uuencode_close(struct archive_write_filter *);
-static int archive_filter_uuencode_free(struct archive_write_filter *);
-static void uu_encode(struct archive_string *, const unsigned char *, size_t);
-static int64_t atol8(const char *, size_t);
-
-/*
- * Add a compress filter to this write handle.
- */
-int
-archive_write_add_filter_uuencode(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_uuencode *state;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
-
-	state = (struct private_uuencode *)calloc(1, sizeof(*state));
-	if (state == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for uuencode filter");
-		return (ARCHIVE_FATAL);
-	}
-	archive_strcpy(&state->name, "-");
-	state->mode = 0644;
-
-	f->data = state;
-	f->name = "uuencode";
-	f->code = ARCHIVE_FILTER_UU;
-	f->open = archive_filter_uuencode_open;
-	f->options = archive_filter_uuencode_options;
-	f->write = archive_filter_uuencode_write;
-	f->close = archive_filter_uuencode_close;
-	f->free = archive_filter_uuencode_free;
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Set write options.
- */
-static int
-archive_filter_uuencode_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct private_uuencode *state = (struct private_uuencode *)f->data;
-
-	if (strcmp(key, "mode") == 0) {
-		if (value == NULL) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "mode option requires octal digits");
-			return (ARCHIVE_FAILED);
-		}
-		state->mode = (int)atol8(value, strlen(value)) & 0777;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "name") == 0) {
-		if (value == NULL) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "name option requires a string");
-			return (ARCHIVE_FAILED);
-		}
-		archive_strcpy(&state->name, value);
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Setup callback.
- */
-static int
-archive_filter_uuencode_open(struct archive_write_filter *f)
-{
-	struct private_uuencode *state = (struct private_uuencode *)f->data;
-	size_t bs = 65536, bpb;
-
-	if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-		/* Buffer size should be a multiple number of the of bytes
-		 * per block for performance. */
-		bpb = archive_write_get_bytes_per_block(f->archive);
-		if (bpb > bs)
-			bs = bpb;
-		else if (bpb != 0)
-			bs -= bs % bpb;
-	}
-
-	state->bs = bs;
-	if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
-		archive_set_error(f->archive, ENOMEM,
-		    "Can't allocate data for uuencode buffer");
-		return (ARCHIVE_FATAL);
-	}
-
-	archive_string_sprintf(&state->encoded_buff, "begin %o %s\n",
-	    state->mode, state->name.s);
-
-	f->data = state;
-	return (0);
-}
-
-static void
-uu_encode(struct archive_string *as, const unsigned char *p, size_t len)
-{
-	int c;
-
-	c = (int)len;
-	archive_strappend_char(as, c?c + 0x20:'`');
-	for (; len >= 3; p += 3, len -= 3) {
-		c = p[0] >> 2;
-		archive_strappend_char(as, c?c + 0x20:'`');
-		c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
-		archive_strappend_char(as, c?c + 0x20:'`');
-		c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
-		archive_strappend_char(as, c?c + 0x20:'`');
-		c = p[2] & 0x3f;
-		archive_strappend_char(as, c?c + 0x20:'`');
-	}
-	if (len > 0) {
-		c = p[0] >> 2;
-		archive_strappend_char(as, c?c + 0x20:'`');
-		c = (p[0] & 0x03) << 4;
-		if (len == 1) {
-			archive_strappend_char(as, c?c + 0x20:'`');
-			archive_strappend_char(as, '`');
-			archive_strappend_char(as, '`');
-		} else {
-			c |= (p[1] & 0xf0) >> 4;
-			archive_strappend_char(as, c?c + 0x20:'`');
-			c = (p[1] & 0x0f) << 2;
-			archive_strappend_char(as, c?c + 0x20:'`');
-			archive_strappend_char(as, '`');
-		}
-	}
-	archive_strappend_char(as, '\n');
-}
-
-/*
- * Write data to the encoded stream.
- */
-static int
-archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_uuencode *state = (struct private_uuencode *)f->data;
-	const unsigned char *p = buff;
-	int ret = ARCHIVE_OK;
-
-	if (length == 0)
-		return (ret);
-
-	if (state->hold_len) {
-		while (state->hold_len < LBYTES && length > 0) {
-			state->hold[state->hold_len++] = *p++;
-			length--;
-		}
-		if (state->hold_len < LBYTES)
-			return (ret);
-		uu_encode(&state->encoded_buff, state->hold, LBYTES);
-		state->hold_len = 0;
-	}
-
-	for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
-		uu_encode(&state->encoded_buff, p, LBYTES);
-
-	/* Save remaining bytes. */
-	if (length > 0) {
-		memcpy(state->hold, p, length);
-		state->hold_len = length;
-	}
-	while (archive_strlen(&state->encoded_buff) >= state->bs) {
-		ret = __archive_write_filter(f->next_filter,
-		    state->encoded_buff.s, state->bs);
-		memmove(state->encoded_buff.s,
-		    state->encoded_buff.s + state->bs,
-		    state->encoded_buff.length - state->bs);
-		state->encoded_buff.length -= state->bs;
-	}
-
-	return (ret);
-}
-
-
-/*
- * Finish the compression...
- */
-static int
-archive_filter_uuencode_close(struct archive_write_filter *f)
-{
-	struct private_uuencode *state = (struct private_uuencode *)f->data;
-
-	/* Flush remaining bytes. */
-	if (state->hold_len != 0)
-		uu_encode(&state->encoded_buff, state->hold, state->hold_len);
-	archive_string_sprintf(&state->encoded_buff, "`\nend\n");
-	/* Write the last block */
-	archive_write_set_bytes_in_last_block(f->archive, 1);
-	return __archive_write_filter(f->next_filter,
-	    state->encoded_buff.s, archive_strlen(&state->encoded_buff));
-}
-
-static int
-archive_filter_uuencode_free(struct archive_write_filter *f)
-{
-	struct private_uuencode *state = (struct private_uuencode *)f->data;
-
-	archive_string_free(&state->name);
-	archive_string_free(&state->encoded_buff);
-	free(state);
-	return (ARCHIVE_OK);
-}
-
-static int64_t
-atol8(const char *p, size_t char_cnt)
-{
-	int64_t l;
-	int digit;
-        
-	l = 0;
-	while (char_cnt-- > 0) {
-		if (*p >= '0' && *p <= '7')
-			digit = *p - '0';
-		else
-			break;
-		p++;
-		l <<= 3;
-		l |= digit;
-	}
-	return (l);
-}
-
diff --git a/c/archive_write_add_filter_xz.c b/c/archive_write_add_filter_xz.c
deleted file mode 100644
--- a/c/archive_write_add_filter_xz.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2009-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_xz.c 201108 2009-12-28 03:28:21Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-
-#if ARCHIVE_VERSION_NUMBER < 4000000
-int
-archive_write_set_compression_lzip(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_lzip(a));
-}
-
-int
-archive_write_set_compression_lzma(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_lzma(a));
-}
-
-int
-archive_write_set_compression_xz(struct archive *a)
-{
-	__archive_write_filters_free(a);
-	return (archive_write_add_filter_xz(a));
-}
-
-#endif
-
-#ifndef HAVE_LZMA_H
-int
-archive_write_add_filter_xz(struct archive *a)
-{
-	archive_set_error(a, ARCHIVE_ERRNO_MISC,
-	    "xz compression not supported on this platform");
-	return (ARCHIVE_FATAL);
-}
-
-int
-archive_write_add_filter_lzma(struct archive *a)
-{
-	archive_set_error(a, ARCHIVE_ERRNO_MISC,
-	    "lzma compression not supported on this platform");
-	return (ARCHIVE_FATAL);
-}
-
-int
-archive_write_add_filter_lzip(struct archive *a)
-{
-	archive_set_error(a, ARCHIVE_ERRNO_MISC,
-	    "lzma compression not supported on this platform");
-	return (ARCHIVE_FATAL);
-}
-#else
-/* Don't compile this if we don't have liblzma. */
-
-struct private_data {
-	int		 compression_level;
-	uint32_t	 threads;
-	lzma_stream	 stream;
-	lzma_filter	 lzmafilters[2];
-	lzma_options_lzma lzma_opt;
-	int64_t		 total_in;
-	unsigned char	*compressed;
-	size_t		 compressed_buffer_size;
-	int64_t		 total_out;
-	/* the CRC32 value of uncompressed data for lzip */
-	uint32_t	 crc32;
-};
-
-static int	archive_compressor_xz_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int	archive_compressor_xz_open(struct archive_write_filter *);
-static int	archive_compressor_xz_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int	archive_compressor_xz_close(struct archive_write_filter *);
-static int	archive_compressor_xz_free(struct archive_write_filter *);
-static int	drive_compressor(struct archive_write_filter *,
-		    struct private_data *, int finishing);
-
-struct option_value {
-	uint32_t dict_size;
-	uint32_t nice_len;
-	lzma_match_finder mf;
-};
-static const struct option_value option_values[] = {
-	{ 1 << 16, 32, LZMA_MF_HC3},
-	{ 1 << 20, 32, LZMA_MF_HC3},
-	{ 3 << 19, 32, LZMA_MF_HC4},
-	{ 1 << 21, 32, LZMA_MF_BT4},
-	{ 3 << 20, 32, LZMA_MF_BT4},
-	{ 1 << 22, 32, LZMA_MF_BT4},
-	{ 1 << 23, 64, LZMA_MF_BT4},
-	{ 1 << 24, 64, LZMA_MF_BT4},
-	{ 3 << 23, 64, LZMA_MF_BT4},
-	{ 1 << 25, 64, LZMA_MF_BT4}
-};
-
-static int
-common_setup(struct archive_write_filter *f)
-{
-	struct private_data *data;
-	struct archive_write *a = (struct archive_write *)f->archive;
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	f->data = data;
-	data->compression_level = LZMA_PRESET_DEFAULT;
-	data->threads = 1;
-	f->open = &archive_compressor_xz_open;
-	f->close = archive_compressor_xz_close;
-	f->free = archive_compressor_xz_free;
-	f->options = &archive_compressor_xz_options;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Add an xz compression filter to this write handle.
- */
-int
-archive_write_add_filter_xz(struct archive *_a)
-{
-	struct archive_write_filter *f;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_xz");
-	f = __archive_write_allocate_filter(_a);
-	r = common_setup(f);
-	if (r == ARCHIVE_OK) {
-		f->code = ARCHIVE_FILTER_XZ;
-		f->name = "xz";
-	}
-	return (r);
-}
-
-/* LZMA is handled identically, we just need a different compression
- * code set.  (The liblzma setup looks at the code to determine
- * the one place that XZ and LZMA require different handling.) */
-int
-archive_write_add_filter_lzma(struct archive *_a)
-{
-	struct archive_write_filter *f;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lzma");
-	f = __archive_write_allocate_filter(_a);
-	r = common_setup(f);
-	if (r == ARCHIVE_OK) {
-		f->code = ARCHIVE_FILTER_LZMA;
-		f->name = "lzma";
-	}
-	return (r);
-}
-
-int
-archive_write_add_filter_lzip(struct archive *_a)
-{
-	struct archive_write_filter *f;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lzip");
-	f = __archive_write_allocate_filter(_a);
-	r = common_setup(f);
-	if (r == ARCHIVE_OK) {
-		f->code = ARCHIVE_FILTER_LZIP;
-		f->name = "lzip";
-	}
-	return (r);
-}
-
-static int
-archive_compressor_xz_init_stream(struct archive_write_filter *f,
-    struct private_data *data)
-{
-	static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT;
-	int ret;
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-	lzma_mt mt_options;
-#endif
-
-	data->stream = lzma_stream_init_data;
-	data->stream.next_out = data->compressed;
-	data->stream.avail_out = data->compressed_buffer_size;
-	if (f->code == ARCHIVE_FILTER_XZ) {
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-		if (data->threads != 1) {
-			memset(&mt_options, 0, sizeof(mt_options));
-			mt_options.threads = data->threads;
-			mt_options.timeout = 300;
-			mt_options.filters = data->lzmafilters;
-			mt_options.check = LZMA_CHECK_CRC64;
-			ret = lzma_stream_encoder_mt(&(data->stream),
-			    &mt_options);
-		} else
-#endif
-			ret = lzma_stream_encoder(&(data->stream),
-			    data->lzmafilters, LZMA_CHECK_CRC64);
-	} else if (f->code == ARCHIVE_FILTER_LZMA) {
-		ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt);
-	} else {	/* ARCHIVE_FILTER_LZIP */
-		int dict_size = data->lzma_opt.dict_size;
-		int ds, log2dic, wedges;
-
-		/* Calculate a coded dictionary size */
-		if (dict_size < (1 << 12) || dict_size > (1 << 29)) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "Unacceptable dictionary size for lzip: %d",
-			    dict_size);
-			return (ARCHIVE_FATAL);
-		}
-		for (log2dic = 29; log2dic >= 12; log2dic--) {
-			if (dict_size & (1 << log2dic))
-				break;
-		}
-		if (dict_size > (1 << log2dic)) {
-			log2dic++;
-			wedges =
-			    ((1 << log2dic) - dict_size) / (1 << (log2dic - 4));
-		} else
-			wedges = 0;
-		ds = ((wedges << 5) & 0xe0) | (log2dic & 0x1f);
-
-		data->crc32 = 0;
-		/* Make a header */
-		data->compressed[0] = 0x4C;
-		data->compressed[1] = 0x5A;
-		data->compressed[2] = 0x49;
-		data->compressed[3] = 0x50;
-		data->compressed[4] = 1;/* Version */
-		data->compressed[5] = (unsigned char)ds;
-		data->stream.next_out += 6;
-		data->stream.avail_out -= 6;
-
-		ret = lzma_raw_encoder(&(data->stream), data->lzmafilters);
-	}
-	if (ret == LZMA_OK)
-		return (ARCHIVE_OK);
-
-	switch (ret) {
-	case LZMA_MEM_ERROR:
-		archive_set_error(f->archive, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "Cannot allocate memory");
-		break;
-	default:
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "It's a bug in liblzma");
-		break;
-	}
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Setup callback.
- */
-static int
-archive_compressor_xz_open(struct archive_write_filter *f)
-{
-	struct private_data *data = f->data;
-	int ret;
-
-	if (data->compressed == NULL) {
-		size_t bs = 65536, bpb;
-		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-			/* Buffer size should be a multiple number of the of bytes
-			 * per block for performance. */
-			bpb = archive_write_get_bytes_per_block(f->archive);
-			if (bpb > bs)
-				bs = bpb;
-			else if (bpb != 0)
-				bs -= bs % bpb;
-		}
-		data->compressed_buffer_size = bs;
-		data->compressed
-		    = (unsigned char *)malloc(data->compressed_buffer_size);
-		if (data->compressed == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	f->write = archive_compressor_xz_write;
-
-	/* Initialize compression library. */
-	if (f->code == ARCHIVE_FILTER_LZIP) {
-		const struct option_value *val =
-		    &option_values[data->compression_level];
-
-		data->lzma_opt.dict_size = val->dict_size;
-		data->lzma_opt.preset_dict = NULL;
-		data->lzma_opt.preset_dict_size = 0;
-		data->lzma_opt.lc = LZMA_LC_DEFAULT;
-		data->lzma_opt.lp = LZMA_LP_DEFAULT;
-		data->lzma_opt.pb = LZMA_PB_DEFAULT;
-		data->lzma_opt.mode =
-		    data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL;
-		data->lzma_opt.nice_len = val->nice_len;
-		data->lzma_opt.mf = val->mf;
-		data->lzma_opt.depth = 0;
-		data->lzmafilters[0].id = LZMA_FILTER_LZMA1;
-		data->lzmafilters[0].options = &data->lzma_opt;
-		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
-	} else {
-		if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) {
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "Internal error initializing compression library");
-		}
-		data->lzmafilters[0].id = LZMA_FILTER_LZMA2;
-		data->lzmafilters[0].options = &data->lzma_opt;
-		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
-	}
-	ret = archive_compressor_xz_init_stream(f, data);
-	if (ret == LZMA_OK) {
-		f->data = data;
-		return (0);
-	}
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Set write options.
- */
-static int
-archive_compressor_xz_options(struct archive_write_filter *f,
-    const char *key, const char *value)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0')
-			return (ARCHIVE_WARN);
-		data->compression_level = value[0] - '0';
-		if (data->compression_level > 9)
-			data->compression_level = 9;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "threads") == 0) {
-		char *endptr;
-
-		if (value == NULL)
-			return (ARCHIVE_WARN);
-		errno = 0;
-		data->threads = (int)strtoul(value, &endptr, 10);
-		if (errno != 0 || *endptr != '\0') {
-			data->threads = 1;
-			return (ARCHIVE_WARN);
-		}
-		if (data->threads == 0) {
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-			data->threads = lzma_cputhreads();
-#else
-			data->threads = 1;
-#endif
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Write data to the compressed stream.
- */
-static int
-archive_compressor_xz_write(struct archive_write_filter *f,
-    const void *buff, size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	/* Update statistics */
-	data->total_in += length;
-	if (f->code == ARCHIVE_FILTER_LZIP)
-		data->crc32 = lzma_crc32(buff, length, data->crc32);
-
-	/* Compress input data to output buffer */
-	data->stream.next_in = buff;
-	data->stream.avail_in = length;
-	if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
-		return (ret);
-
-	return (ARCHIVE_OK);
-}
-
-
-/*
- * Finish the compression...
- */
-static int
-archive_compressor_xz_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	int ret;
-
-	ret = drive_compressor(f, data, 1);
-	if (ret == ARCHIVE_OK) {
-		data->total_out +=
-		    data->compressed_buffer_size - data->stream.avail_out;
-		ret = __archive_write_filter(f->next_filter,
-		    data->compressed,
-		    data->compressed_buffer_size - data->stream.avail_out);
-		if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) {
-			archive_le32enc(data->compressed, data->crc32);
-			archive_le64enc(data->compressed+4, data->total_in);
-			archive_le64enc(data->compressed+12, data->total_out + 20);
-			ret = __archive_write_filter(f->next_filter,
-			    data->compressed, 20);
-		}
-	}
-	lzma_end(&(data->stream));
-	return ret;
-}
-
-static int
-archive_compressor_xz_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	free(data->compressed);
-	free(data);
-	f->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Utility function to push input data through compressor,
- * writing full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
- */
-static int
-drive_compressor(struct archive_write_filter *f,
-    struct private_data *data, int finishing)
-{
-	int ret;
-
-	for (;;) {
-		if (data->stream.avail_out == 0) {
-			data->total_out += data->compressed_buffer_size;
-			ret = __archive_write_filter(f->next_filter,
-			    data->compressed,
-			    data->compressed_buffer_size);
-			if (ret != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			data->stream.next_out = data->compressed;
-			data->stream.avail_out = data->compressed_buffer_size;
-		}
-
-		/* If there's nothing to do, we're done. */
-		if (!finishing && data->stream.avail_in == 0)
-			return (ARCHIVE_OK);
-
-		ret = lzma_code(&(data->stream),
-		    finishing ? LZMA_FINISH : LZMA_RUN );
-
-		switch (ret) {
-		case LZMA_OK:
-			/* In non-finishing case, check if compressor
-			 * consumed everything */
-			if (!finishing && data->stream.avail_in == 0)
-				return (ARCHIVE_OK);
-			/* In finishing case, this return always means
-			 * there's more work */
-			break;
-		case LZMA_STREAM_END:
-			/* This return can only occur in finishing case. */
-			if (finishing)
-				return (ARCHIVE_OK);
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "lzma compression data error");
-			return (ARCHIVE_FATAL);
-		case LZMA_MEMLIMIT_ERROR:
-			archive_set_error(f->archive, ENOMEM,
-			    "lzma compression error: "
-			    "%ju MiB would have been needed",
-			    (uintmax_t)((lzma_memusage(&(data->stream))
-				    + 1024 * 1024 -1)
-				/ (1024 * 1024)));
-			return (ARCHIVE_FATAL);
-		default:
-			/* Any other return value indicates an error. */
-			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-			    "lzma compression failed:"
-			    " lzma_code() call returned status %d",
-			    ret);
-			return (ARCHIVE_FATAL);
-		}
-	}
-}
-
-#endif /* HAVE_LZMA_H */
diff --git a/c/archive_write_add_filter_zstd.c b/c/archive_write_add_filter_zstd.c
deleted file mode 100644
--- a/c/archive_write_add_filter_zstd.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*-
- * Copyright (c) 2017 Sean Purcell
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-__FBSDID("$FreeBSD$");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ZSTD_H
-#include <zstd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-/* Don't compile this if we don't have zstd.h */
-
-struct private_data {
-	int		 compression_level;
-	int		 threads;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-	enum {
-		running,
-		finishing,
-		resetting,
-	} state;
-	int		 frame_per_file;
-	size_t		 min_frame_size;
-	size_t		 max_frame_size;
-	size_t		 cur_frame;
-	size_t		 cur_frame_in;
-	size_t		 cur_frame_out;
-	size_t		 total_in;
-	ZSTD_CStream	*cstream;
-	ZSTD_outBuffer	 out;
-#else
-	struct archive_write_program_data *pdata;
-#endif
-};
-
-/* If we don't have the library use default range values (zstdcli.c v1.4.0) */
-#define CLEVEL_MIN -99
-#define CLEVEL_STD_MIN 0 /* prior to 1.3.4 and more recent without using --fast */
-#define CLEVEL_DEFAULT 3
-#define CLEVEL_STD_MAX 19 /* without using --ultra */
-#define CLEVEL_MAX 22
-
-#define MINVER_NEGCLEVEL 10304
-#define MINVER_MINCLEVEL 10306
-
-static int archive_compressor_zstd_options(struct archive_write_filter *,
-		    const char *, const char *);
-static int archive_compressor_zstd_open(struct archive_write_filter *);
-static int archive_compressor_zstd_write(struct archive_write_filter *,
-		    const void *, size_t);
-static int archive_compressor_zstd_flush(struct archive_write_filter *);
-static int archive_compressor_zstd_close(struct archive_write_filter *);
-static int archive_compressor_zstd_free(struct archive_write_filter *);
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-static int drive_compressor(struct archive_write_filter *,
-		    struct private_data *, int, const void *, size_t);
-#endif
-
-
-/*
- * Add a zstd compression filter to this write handle.
- */
-int
-archive_write_add_filter_zstd(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *f = __archive_write_allocate_filter(_a);
-	struct private_data *data;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
-
-	data = calloc(1, sizeof(*data));
-	if (data == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	f->data = data;
-	f->open = &archive_compressor_zstd_open;
-	f->options = &archive_compressor_zstd_options;
-	f->flush = &archive_compressor_zstd_flush;
-	f->close = &archive_compressor_zstd_close;
-	f->free = &archive_compressor_zstd_free;
-	f->code = ARCHIVE_FILTER_ZSTD;
-	f->name = "zstd";
-	data->compression_level = CLEVEL_DEFAULT;
-	data->threads = 0;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-	data->frame_per_file = 0;
-	data->min_frame_size = 0;
-	data->max_frame_size = SIZE_MAX;
-	data->cur_frame_in = 0;
-	data->cur_frame_out = 0;
-	data->cstream = ZSTD_createCStream();
-	if (data->cstream == NULL) {
-		free(data);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Failed to allocate zstd compressor object");
-		return (ARCHIVE_FATAL);
-	}
-
-	return (ARCHIVE_OK);
-#else
-	data->pdata = __archive_write_program_allocate("zstd");
-	if (data->pdata == NULL) {
-		free(data);
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Using external zstd program");
-	return (ARCHIVE_WARN);
-#endif
-}
-
-static int
-archive_compressor_zstd_free(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-	ZSTD_freeCStream(data->cstream);
-	free(data->out.dst);
-#else
-	__archive_write_program_free(data->pdata);
-#endif
-	free(data);
-	f->data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int string_to_number(const char *string, intmax_t *numberp)
-{
-	char *end;
-
-	if (string == NULL || *string == '\0')
-		return (ARCHIVE_WARN);
-	*numberp = strtoimax(string, &end, 10);
-	if (end == string || *end != '\0' || errno == EOVERFLOW) {
-		*numberp = 0;
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Set write options.
- */
-static int
-archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
-    const char *value)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (strcmp(key, "compression-level") == 0) {
-		intmax_t level;
-		if (string_to_number(value, &level) != ARCHIVE_OK) {
-			return (ARCHIVE_WARN);
-		}
-		/* If we don't have the library, hard-code the max level */
-		int minimum = CLEVEL_MIN;
-		int maximum = CLEVEL_MAX;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-		maximum = ZSTD_maxCLevel();
-#if ZSTD_VERSION_NUMBER >= MINVER_MINCLEVEL
-		if (ZSTD_versionNumber() >= MINVER_MINCLEVEL) {
-			minimum = ZSTD_minCLevel();
-		}
-		else
-#endif
-		if (ZSTD_versionNumber() < MINVER_NEGCLEVEL) {
-			minimum = CLEVEL_STD_MIN;
-		}
-#endif
-		if (level < minimum || level > maximum) {
-			return (ARCHIVE_WARN);
-		}
-		data->compression_level = (int)level;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "threads") == 0) {
-		intmax_t threads;
-		if (string_to_number(value, &threads) != ARCHIVE_OK) {
-			return (ARCHIVE_WARN);
-		}
-		if (threads < 0) {
-			return (ARCHIVE_WARN);
-		}
-		data->threads = (int)threads;
-		return (ARCHIVE_OK);
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-	} else if (strcmp(key, "frame-per-file") == 0) {
-		data->frame_per_file = 1;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "min-frame-size") == 0) {
-		intmax_t min_frame_size;
-		if (string_to_number(value, &min_frame_size) != ARCHIVE_OK) {
-			return (ARCHIVE_WARN);
-		}
-		if (min_frame_size < 0) {
-			return (ARCHIVE_WARN);
-		}
-		data->min_frame_size = min_frame_size;
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "max-frame-size") == 0) {
-		intmax_t max_frame_size;
-		if (string_to_number(value, &max_frame_size) != ARCHIVE_OK) {
-			return (ARCHIVE_WARN);
-		}
-		if (max_frame_size < 1024) {
-			return (ARCHIVE_WARN);
-		}
-		data->max_frame_size = max_frame_size;
-		return (ARCHIVE_OK);
-#endif
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
-/*
- * Setup callback.
- */
-static int
-archive_compressor_zstd_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data->out.dst == NULL) {
-		size_t bs = ZSTD_CStreamOutSize(), bpb;
-		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
-			/* Buffer size should be a multiple number of
-			 * the of bytes per block for performance. */
-			bpb = archive_write_get_bytes_per_block(f->archive);
-			if (bpb > bs)
-				bs = bpb;
-			else if (bpb != 0)
-				bs -= bs % bpb;
-		}
-		data->out.size = bs;
-		data->out.pos = 0;
-		data->out.dst
-		    = (unsigned char *)malloc(data->out.size);
-		if (data->out.dst == NULL) {
-			archive_set_error(f->archive, ENOMEM,
-			    "Can't allocate data for compression buffer");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	f->write = archive_compressor_zstd_write;
-
-	if (ZSTD_isError(ZSTD_initCStream(data->cstream,
-	    data->compression_level))) {
-		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing zstd compressor object");
-		return (ARCHIVE_FATAL);
-	}
-
-	ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_nbWorkers, data->threads);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Write data to the compressed stream.
- */
-static int
-archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return (drive_compressor(f, data, 0, buff, length));
-}
-
-/*
- * Flush the compressed stream.
- */
-static int
-archive_compressor_zstd_flush(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data->frame_per_file && data->state == running &&
-	    data->cur_frame_out > data->min_frame_size)
-		data->state = finishing;
-	return (drive_compressor(f, data, 1, NULL, 0));
-}
-
-/*
- * Finish the compression...
- */
-static int
-archive_compressor_zstd_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	if (data->state == running)
-		data->state = finishing;
-	return (drive_compressor(f, data, 1, NULL, 0));
-}
-
-/*
- * Utility function to push input data through compressor,
- * writing full output blocks as necessary.
- */
-static int
-drive_compressor(struct archive_write_filter *f,
-    struct private_data *data, int flush, const void *src, size_t length)
-{
-	ZSTD_inBuffer in = { .src = src, .size = length, .pos = 0 };
-	size_t ipos, opos, zstdret = 0;
-	int ret;
-
-	for (;;) {
-		ipos = in.pos;
-		opos = data->out.pos;
-		switch (data->state) {
-		case running:
-			if (in.pos == in.size)
-				return (ARCHIVE_OK);
-			zstdret = ZSTD_compressStream(data->cstream,
-			    &data->out, &in);
-			if (ZSTD_isError(zstdret))
-				goto zstd_fatal;
-			break;
-		case finishing:
-			zstdret = ZSTD_endStream(data->cstream, &data->out);
-			if (ZSTD_isError(zstdret))
-				goto zstd_fatal;
-			if (zstdret == 0)
-				data->state = resetting;
-			break;
-		case resetting:
-			ZSTD_CCtx_reset(data->cstream, ZSTD_reset_session_only);
-			data->cur_frame++;
-			data->cur_frame_in = 0;
-			data->cur_frame_out = 0;
-			data->state = running;
-			break;
-		}
-		data->total_in += in.pos - ipos;
-		data->cur_frame_in += in.pos - ipos;
-		data->cur_frame_out += data->out.pos - opos;
-		if (data->state == running &&
-		    data->cur_frame_in >= data->max_frame_size) {
-			data->state = finishing;
-		}
-		if (data->out.pos == data->out.size ||
-		    (flush && data->out.pos > 0)) {
-			ret = __archive_write_filter(f->next_filter,
-			    data->out.dst, data->out.pos);
-			if (ret != ARCHIVE_OK)
-				goto fatal;
-			data->out.pos = 0;
-		}
-	}
-zstd_fatal:
-	archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
-	    "Zstd compression failed: %s",
-	    ZSTD_getErrorName(zstdret));
-fatal:
-	return (ARCHIVE_FATAL);
-}
-
-#else /* HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR */
-
-static int
-archive_compressor_zstd_open(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-	struct archive_string as;
-	int r;
-
-	archive_string_init(&as);
-	/* --no-check matches library default */
-	archive_strcpy(&as, "zstd --no-check");
-
-	if (data->compression_level < CLEVEL_STD_MIN) {
-		archive_string_sprintf(&as, " --fast=%d", -data->compression_level);
-	} else {
-		archive_string_sprintf(&as, " -%d", data->compression_level);
-	}
-
-	if (data->compression_level > CLEVEL_STD_MAX) {
-		archive_strcat(&as, " --ultra");
-	}
-
-	if (data->threads != 0) {
-		archive_string_sprintf(&as, " --threads=%d", data->threads);
-	}
-
-	f->write = archive_compressor_zstd_write;
-	r = __archive_write_program_open(f, data->pdata, as.s);
-	archive_string_free(&as);
-	return (r);
-}
-
-static int
-archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
-    size_t length)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_write(f, data->pdata, buff, length);
-}
-
-static int
-archive_compressor_zstd_flush(struct archive_write_filter *f)
-{
-	(void)f; /* UNUSED */
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_compressor_zstd_close(struct archive_write_filter *f)
-{
-	struct private_data *data = (struct private_data *)f->data;
-
-	return __archive_write_program_close(f, data->pdata);
-}
-
-#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR */
diff --git a/c/archive_write_disk_posix.c b/c/archive_write_disk_posix.c
deleted file mode 100644
--- a/c/archive_write_disk_posix.c
+++ /dev/null
@@ -1,4759 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_ACL_H
-#include <sys/acl.h>
-#endif
-#ifdef HAVE_SYS_EXTATTR_H
-#include <sys/extattr.h>
-#endif
-#if HAVE_SYS_XATTR_H
-#include <sys/xattr.h>
-#elif HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#endif
-#ifdef HAVE_SYS_EA_H
-#include <sys/ea.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-#ifdef HAVE_COPYFILE_H
-#include <copyfile.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>	/* for Linux file flags */
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h>	/* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h>	/* Linux file flags, broken on Cygwin */
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef F_GETTIMES /* Tru64 specific */
-#include <sys/fcntl1.h>
-#endif
-
-/*
- * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
- *
- * It assumes that the input is an integer type of no more than 64 bits.
- * If the number is less than zero, t must be a signed type, so it fits in
- * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
- * without loss. But it could be a large unsigned value, so we have to clip it
- * to INT64_MAX.*
- */
-#define to_int64_time(t) \
-   ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
-
-#if __APPLE__
-#include <TargetConditionals.h>
-#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
-#include <quarantine.h>
-#define HAVE_QUARANTINE 1
-#endif
-#endif
-
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-/* TODO: Support Mac OS 'quarantine' feature.  This is really just a
- * standard tag to mark files that have been downloaded as "tainted".
- * On Mac OS, we should mark the extracted files as tainted if the
- * archive being read was tainted.  Windows has a similar feature; we
- * should investigate ways to support this generically. */
-
-#include "archive.h"
-#include "archive_acl_private.h"
-#include "archive_string.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_write_disk_private.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
-#endif
-
-/* Ignore non-int O_NOFOLLOW constant. */
-/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
-#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
-#undef O_NOFOLLOW
-#endif
-
-#ifndef O_NOFOLLOW
-#define O_NOFOLLOW 0
-#endif
-
-#ifndef AT_FDCWD
-#define AT_FDCWD -100
-#endif
-
-struct fixup_entry {
-	struct fixup_entry	*next;
-	struct archive_acl	 acl;
-	mode_t			 mode;
-	__LA_MODE_T		 filetype;
-	int64_t			 atime;
-	int64_t                  birthtime;
-	int64_t			 mtime;
-	int64_t			 ctime;
-	unsigned long		 atime_nanos;
-	unsigned long            birthtime_nanos;
-	unsigned long		 mtime_nanos;
-	unsigned long		 ctime_nanos;
-	unsigned long		 fflags_set;
-	size_t			 mac_metadata_size;
-	void			*mac_metadata;
-	int			 fixup; /* bitmask of what needs fixing */
-	char			*name;
-};
-
-/*
- * We use a bitmask to track which operations remain to be done for
- * this file.  In particular, this helps us avoid unnecessary
- * operations when it's possible to take care of one step as a
- * side-effect of another.  For example, mkdir() can specify the mode
- * for the newly-created object but symlink() cannot.  This means we
- * can skip chmod() if mkdir() succeeded, but we must explicitly
- * chmod() if we're trying to create a directory that already exists
- * (mkdir() failed) or if we're restoring a symlink.  Similarly, we
- * need to verify UID/GID before trying to restore SUID/SGID bits;
- * that verification can occur explicitly through a stat() call or
- * implicitly because of a successful chown() call.
- */
-#define	TODO_MODE_FORCE		0x40000000
-#define	TODO_MODE_BASE		0x20000000
-#define	TODO_SUID		0x10000000
-#define	TODO_SUID_CHECK		0x08000000
-#define	TODO_SGID		0x04000000
-#define	TODO_SGID_CHECK		0x02000000
-#define	TODO_APPLEDOUBLE	0x01000000
-#define	TODO_MODE		(TODO_MODE_BASE|TODO_SUID|TODO_SGID)
-#define	TODO_TIMES		ARCHIVE_EXTRACT_TIME
-#define	TODO_OWNER		ARCHIVE_EXTRACT_OWNER
-#define	TODO_FFLAGS		ARCHIVE_EXTRACT_FFLAGS
-#define	TODO_ACLS		ARCHIVE_EXTRACT_ACL
-#define	TODO_XATTR		ARCHIVE_EXTRACT_XATTR
-#define	TODO_MAC_METADATA	ARCHIVE_EXTRACT_MAC_METADATA
-#define	TODO_HFS_COMPRESSION	ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
-
-struct archive_write_disk {
-	struct archive	archive;
-
-	mode_t			 user_umask;
-	struct fixup_entry	*fixup_list;
-	struct fixup_entry	*current_fixup;
-	int64_t			 user_uid;
-	int			 skip_file_set;
-	int64_t			 skip_file_dev;
-	int64_t			 skip_file_ino;
-	time_t			 start_time;
-
-	int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
-	void  (*cleanup_gid)(void *private);
-	void			*lookup_gid_data;
-	int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
-	void  (*cleanup_uid)(void *private);
-	void			*lookup_uid_data;
-
-	/*
-	 * Full path of last file to satisfy symlink checks.
-	 */
-	struct archive_string	path_safe;
-
-	/*
-	 * Cached stat data from disk for the current entry.
-	 * If this is valid, pst points to st.  Otherwise,
-	 * pst is null.
-	 */
-	struct stat		 st;
-	struct stat		*pst;
-
-	/* Information about the object being restored right now. */
-	struct archive_entry	*entry; /* Entry being extracted. */
-	char			*name; /* Name of entry, possibly edited. */
-	struct archive_string	 _name_data; /* backing store for 'name' */
-	char			*tmpname; /* Temporary name * */
-	struct archive_string	 _tmpname_data; /* backing store for 'tmpname' */
-	/* Tasks remaining for this object. */
-	int			 todo;
-	/* Tasks deferred until end-of-archive. */
-	int			 deferred;
-	/* Options requested by the client. */
-	int			 flags;
-	/* Handle for the file we're restoring. */
-	int			 fd;
-	/* Current offset for writing data to the file. */
-	int64_t			 offset;
-	/* Last offset actually written to disk. */
-	int64_t			 fd_offset;
-	/* Total bytes actually written to files. */
-	int64_t			 total_bytes_written;
-	/* Maximum size of file, -1 if unknown. */
-	int64_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. */
-	mode_t			 mode;
-	/* UID/GID to use in restoring this entry. */
-	int64_t			 uid;
-	int64_t			 gid;
-	/*
-	 * HFS+ Compression.
-	 */
-	/* Xattr "com.apple.decmpfs". */
-	uint32_t		 decmpfs_attr_size;
-	unsigned char		*decmpfs_header_p;
-	/* ResourceFork set options used for fsetxattr. */
-	int			 rsrc_xattr_options;
-	/* Xattr "com.apple.ResourceFork". */
-	unsigned char		*resource_fork;
-	size_t			 resource_fork_allocated_size;
-	unsigned int		 decmpfs_block_count;
-	uint32_t		*decmpfs_block_info;
-	/* Buffer for compressed data. */
-	unsigned char		*compressed_buffer;
-	size_t			 compressed_buffer_size;
-	size_t			 compressed_buffer_remaining;
-	/* The offset of the ResourceFork where compressed data will
-	 * be placed. */
-	uint32_t		 compressed_rsrc_position;
-	uint32_t		 compressed_rsrc_position_v;
-	/* Buffer for uncompressed data. */
-	char			*uncompressed_buffer;
-	size_t			 block_remaining_bytes;
-	size_t			 file_remaining_bytes;
-#ifdef HAVE_ZLIB_H
-	z_stream		 stream;
-	int			 stream_valid;
-	int			 decmpfs_compression_level;
-#endif
-};
-
-/*
- * Default mode for dirs created automatically (will be modified by umask).
- * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
- * by the process' file creation mask."
- */
-#define	DEFAULT_DIR_MODE 0777
-/*
- * Dir modes are restored in two steps:  During the extraction, the permissions
- * in the archive are modified to match the following limits.  During
- * the post-extract fixup pass, the permissions from the archive are
- * applied.
- */
-#define	MINIMUM_DIR_MODE 0700
-#define	MAXIMUM_DIR_MODE 0775
-
-/*
- * Maximum uncompressed size of a decmpfs block.
- */
-#define MAX_DECMPFS_BLOCK_SIZE	(64 * 1024)
-/*
- * HFS+ compression type.
- */
-#define CMP_XATTR		3/* Compressed data in xattr. */
-#define CMP_RESOURCE_FORK	4/* Compressed data in resource fork. */
-/*
- * HFS+ compression resource fork.
- */
-#define RSRC_H_SIZE	260	/* Base size of Resource fork header. */
-#define RSRC_F_SIZE	50	/* Size of Resource fork footer. */
-/* Size to write compressed data to resource fork. */
-#define COMPRESSED_W_SIZE	(64 * 1024)
-/* decmpfs definitions. */
-#define MAX_DECMPFS_XATTR_SIZE		3802
-#ifndef DECMPFS_XATTR_NAME
-#define DECMPFS_XATTR_NAME		"com.apple.decmpfs"
-#endif
-#define DECMPFS_MAGIC			0x636d7066
-#define DECMPFS_COMPRESSION_MAGIC	0
-#define DECMPFS_COMPRESSION_TYPE	4
-#define DECMPFS_UNCOMPRESSED_SIZE	8
-#define DECMPFS_HEADER_SIZE		16
-
-#define HFS_BLOCKS(s)	((s) >> 12)
-
-
-static int	la_opendirat(int, const char *);
-static int	la_mktemp(struct archive_write_disk *);
-static int	la_verify_filetype(mode_t, __LA_MODE_T);
-static void	fsobj_error(int *, struct archive_string *, int, const char *,
-		    const char *);
-static int	check_symlinks_fsobj(char *, int *, struct archive_string *,
-		    int, int);
-static int	check_symlinks(struct archive_write_disk *);
-static int	create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *,
-		    const char *pathname);
-#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
-static void	edit_deep_directories(struct archive_write_disk *ad);
-#endif
-static int	cleanup_pathname_fsobj(char *, int *, struct archive_string *,
-		    int);
-static int	cleanup_pathname(struct archive_write_disk *);
-static int	create_dir(struct archive_write_disk *, char *);
-static int	create_parent_dir(struct archive_write_disk *, char *);
-static ssize_t	hfs_write_data_block(struct archive_write_disk *,
-		    const char *, size_t);
-static int	fixup_appledouble(struct archive_write_disk *, const char *);
-static int	older(struct stat *, struct archive_entry *);
-static int	restore_entry(struct archive_write_disk *);
-static int	set_mac_metadata(struct archive_write_disk *, const char *,
-				 const void *, size_t);
-static int	set_xattrs(struct archive_write_disk *);
-static int	clear_nochange_fflags(struct archive_write_disk *);
-static int	set_fflags(struct archive_write_disk *);
-static int	set_fflags_platform(struct archive_write_disk *, int fd,
-		    const char *name, mode_t mode,
-		    unsigned long fflags_set, unsigned long fflags_clear);
-static int	set_ownership(struct archive_write_disk *);
-static int	set_mode(struct archive_write_disk *, int mode);
-static int	set_time(int, int, const char *, time_t, long, time_t, long);
-static int	set_times(struct archive_write_disk *, int, int, const char *,
-		    time_t, long, time_t, long, time_t, long, time_t, long);
-static int	set_times_from_entry(struct archive_write_disk *);
-static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
-static ssize_t	write_data_block(struct archive_write_disk *,
-		    const char *, size_t);
-static void close_file_descriptor(struct archive_write_disk *);
-
-static int	_archive_write_disk_close(struct archive *);
-static int	_archive_write_disk_free(struct archive *);
-static int	_archive_write_disk_header(struct archive *,
-		    struct archive_entry *);
-static int64_t	_archive_write_disk_filter_bytes(struct archive *, int);
-static int	_archive_write_disk_finish_entry(struct archive *);
-static ssize_t	_archive_write_disk_data(struct archive *, const void *,
-		    size_t);
-static ssize_t	_archive_write_disk_data_block(struct archive *, const void *,
-		    size_t, int64_t);
-
-static int
-la_mktemp(struct archive_write_disk *a)
-{
-	int oerrno, fd;
-	mode_t mode;
-
-	archive_string_empty(&a->_tmpname_data);
-	archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
-	a->tmpname = a->_tmpname_data.s;
-
-	fd = __archive_mkstemp(a->tmpname);
-	if (fd == -1)
-		return -1;
-
-	mode = a->mode & 0777 & ~a->user_umask;
-	if (fchmod(fd, mode) == -1) {
-		oerrno = errno;
-		close(fd);
-		errno = oerrno;
-		return -1;
-	}
-	return fd;
-}
-
-static int
-la_opendirat(int fd, const char *path) {
-	const int flags = O_CLOEXEC
-#if defined(O_BINARY)
-	    | O_BINARY
-#endif
-#if defined(O_DIRECTORY)
-	    | O_DIRECTORY
-#endif
-#if defined(O_PATH)
-	    | O_PATH
-#elif defined(O_SEARCH)
-	    | O_SEARCH
-#elif defined(__FreeBSD__) && defined(O_EXEC)
-	    | O_EXEC
-#else
-	    | O_RDONLY
-#endif
-	    ;
-
-#if !defined(HAVE_OPENAT)
-	if (fd != AT_FDCWD) {
-		errno = ENOTSUP;
-		return (-1);
-	} else
-		return (open(path, flags));
-#else
-	return (openat(fd, path, flags));
-#endif
-}
-
-static int
-la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
-	int ret = 0;
-
-	switch (filetype) {
-	case AE_IFREG:
-		ret = (S_ISREG(mode));
-		break;
-	case AE_IFDIR:
-		ret = (S_ISDIR(mode));
-		break;
-	case AE_IFLNK:
-		ret = (S_ISLNK(mode));
-		break;
-	case AE_IFSOCK:
-		ret = (S_ISSOCK(mode));
-		break;
-	case AE_IFCHR:
-		ret = (S_ISCHR(mode));
-		break;
-	case AE_IFBLK:
-		ret = (S_ISBLK(mode));
-		break;
-	case AE_IFIFO:
-		ret = (S_ISFIFO(mode));
-		break;
-	default:
-		break;
-	}
-
-	return (ret);
-}
-
-static int
-lazy_stat(struct archive_write_disk *a)
-{
-	if (a->pst != NULL) {
-		/* Already have stat() data available. */
-		return (ARCHIVE_OK);
-	}
-#ifdef HAVE_FSTAT
-	if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
-		a->pst = &a->st;
-		return (ARCHIVE_OK);
-	}
-#endif
-	/*
-	 * XXX At this point, symlinks should not be hit, otherwise
-	 * XXX a race occurred.  Do we want to check explicitly for that?
-	 */
-#ifdef HAVE_LSTAT
-	if (lstat(a->name, &a->st) == 0)
-#else
-	if (la_stat(a->name, &a->st) == 0)
-#endif
-	{
-		a->pst = &a->st;
-		return (ARCHIVE_OK);
-	}
-	archive_set_error(&a->archive, errno, "Couldn't stat file");
-	return (ARCHIVE_WARN);
-}
-
-static const struct archive_vtable
-archive_write_disk_vtable = {
-	.archive_close = _archive_write_disk_close,
-	.archive_filter_bytes = _archive_write_disk_filter_bytes,
-	.archive_free = _archive_write_disk_free,
-	.archive_write_header = _archive_write_disk_header,
-	.archive_write_finish_entry = _archive_write_disk_finish_entry,
-	.archive_write_data = _archive_write_disk_data,
-	.archive_write_data_block = _archive_write_disk_data_block,
-};
-
-static int64_t
-_archive_write_disk_filter_bytes(struct archive *_a, int n)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	(void)n; /* UNUSED */
-	if (n == -1 || n == 0)
-		return (a->total_bytes_written);
-	return (-1);
-}
-
-
-int
-archive_write_disk_set_options(struct archive *_a, int flags)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-
-	a->flags = flags;
-	return (ARCHIVE_OK);
-}
-
-
-/*
- * Extract this entry to disk.
- *
- * TODO: Validate hardlinks.  According to the standards, we're
- * supposed to check each extracted hardlink and squawk if it refers
- * to a file that we didn't restore.  I'm not entirely convinced this
- * is a good idea, but more importantly: Is there any way to validate
- * hardlinks without keeping a complete list of filenames from the
- * entire archive?? Ugh.
- *
- */
-static int
-_archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	struct fixup_entry *fe;
-	const char *linkname;
-	int ret, r;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_disk_header");
-	archive_clear_error(&a->archive);
-	if (a->archive.state & ARCHIVE_STATE_DATA) {
-		r = _archive_write_disk_finish_entry(&a->archive);
-		if (r == ARCHIVE_FATAL)
-			return (r);
-	}
-
-	/* Set up for this particular entry. */
-	a->pst = NULL;
-	a->current_fixup = NULL;
-	a->deferred = 0;
-	if (a->entry) {
-		archive_entry_free(a->entry);
-		a->entry = NULL;
-	}
-	a->entry = archive_entry_clone(entry);
-	a->fd = -1;
-	a->fd_offset = 0;
-	a->offset = 0;
-	a->restore_pwd = -1;
-	a->uid = a->user_uid;
-	a->mode = archive_entry_mode(a->entry);
-	if (archive_entry_size_is_set(a->entry))
-		a->filesize = archive_entry_size(a->entry);
-	else
-		a->filesize = -1;
-	archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
-	a->name = a->_name_data.s;
-	archive_clear_error(&a->archive);
-
-	/*
-	 * Clean up the requested path.  This is necessary for correct
-	 * dir restores; the dir restore logic otherwise gets messed
-	 * up by nonsense like "dir/.".
-	 */
-	ret = cleanup_pathname(a);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	/*
-	 * Check if we have a hardlink that points to itself.
-	 */
-	linkname = archive_entry_hardlink(a->entry);
-	if (linkname != NULL && strcmp(a->name, linkname) == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Skipping hardlink pointing to itself: %s",
-		    a->name);
-		return (ARCHIVE_WARN);
-	}
-
-	/*
-	 * Query the umask so we get predictable mode settings.
-	 * This gets done on every call to _write_header in case the
-	 * user edits their umask during the extraction for some
-	 * reason.
-	 */
-	umask(a->user_umask = umask(0));
-
-	/* Figure out what we need to do for this entry. */
-	a->todo = TODO_MODE_BASE;
-	if (a->flags & ARCHIVE_EXTRACT_PERM) {
-		a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
-		/*
-		 * SGID requires an extra "check" step because we
-		 * cannot easily predict the GID that the system will
-		 * assign.  (Different systems assign GIDs to files
-		 * based on a variety of criteria, including process
-		 * credentials and the gid of the enclosing
-		 * directory.)  We can only restore the SGID bit if
-		 * the file has the right GID, and we only know the
-		 * GID if we either set it (see set_ownership) or if
-		 * we've actually called stat() on the file after it
-		 * was restored.  Since there are several places at
-		 * which we might verify the GID, we need a TODO bit
-		 * to keep track.
-		 */
-		if (a->mode & S_ISGID)
-			a->todo |= TODO_SGID | TODO_SGID_CHECK;
-		/*
-		 * Verifying the SUID is simpler, but can still be
-		 * done in multiple ways, hence the separate "check" bit.
-		 */
-		if (a->mode & S_ISUID)
-			a->todo |= TODO_SUID | TODO_SUID_CHECK;
-	} else {
-		/*
-		 * User didn't request full permissions, so don't
-		 * restore SUID, SGID bits and obey umask.
-		 */
-		a->mode &= ~S_ISUID;
-		a->mode &= ~S_ISGID;
-		a->mode &= ~S_ISVTX;
-		a->mode &= ~a->user_umask;
-	}
-	if (a->flags & ARCHIVE_EXTRACT_OWNER)
-		a->todo |= TODO_OWNER;
-	if (a->flags & ARCHIVE_EXTRACT_TIME)
-		a->todo |= TODO_TIMES;
-	if (a->flags & ARCHIVE_EXTRACT_ACL) {
-#if ARCHIVE_ACL_DARWIN
-		/*
-		 * On MacOS, platform ACLs get stored in mac_metadata, too.
-		 * If we intend to extract mac_metadata and it is present
-		 * we skip extracting libarchive NFSv4 ACLs.
-		 */
-		size_t metadata_size;
-
-		if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
-		    archive_entry_mac_metadata(a->entry,
-		    &metadata_size) == NULL || metadata_size == 0)
-#endif
-#if ARCHIVE_ACL_LIBRICHACL
-		/*
-		 * RichACLs are stored in an extended attribute.
-		 * If we intend to extract extended attributes and have this
-		 * attribute we skip extracting libarchive NFSv4 ACLs.
-		 */
-		short extract_acls = 1;
-		if (a->flags & ARCHIVE_EXTRACT_XATTR && (
-		    archive_entry_acl_types(a->entry) &
-		    ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
-			const char *attr_name;
-			const void *attr_value;
-			size_t attr_size;
-			int i = archive_entry_xattr_reset(a->entry);
-			while (i--) {
-				archive_entry_xattr_next(a->entry, &attr_name,
-				    &attr_value, &attr_size);
-				if (attr_name != NULL && attr_value != NULL &&
-				    attr_size > 0 && strcmp(attr_name,
-				    "trusted.richacl") == 0) {
-					extract_acls = 0;
-					break;
-				}
-			}
-		}
-		if (extract_acls)
-#endif
-#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
-		{
-#endif
-		if (archive_entry_filetype(a->entry) == AE_IFDIR)
-			a->deferred |= TODO_ACLS;
-		else
-			a->todo |= TODO_ACLS;
-#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
-		}
-#endif
-	}
-	if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
-		if (archive_entry_filetype(a->entry) == AE_IFDIR)
-			a->deferred |= TODO_MAC_METADATA;
-		else
-			a->todo |= TODO_MAC_METADATA;
-	}
-#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
-	if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) {
-		unsigned long set, clear;
-		archive_entry_fflags(a->entry, &set, &clear);
-		if ((set & ~clear) & UF_COMPRESSED) {
-			a->todo |= TODO_HFS_COMPRESSION;
-			a->decmpfs_block_count = (unsigned)-1;
-		}
-	}
-	if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 &&
-	    (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) {
-		a->todo |= TODO_HFS_COMPRESSION;
-		a->decmpfs_block_count = (unsigned)-1;
-	}
-	{
-		const char *p;
-
-		/* Check if the current file name is a type of the
-		 * resource fork file. */
-		p = strrchr(a->name, '/');
-		if (p == NULL)
-			p = a->name;
-		else
-			p++;
-		if (p[0] == '.' && p[1] == '_') {
-			/* Do not compress "._XXX" files. */
-			a->todo &= ~TODO_HFS_COMPRESSION;
-			if (a->filesize > 0)
-				a->todo |= TODO_APPLEDOUBLE;
-		}
-	}
-#endif
-
-	if (a->flags & ARCHIVE_EXTRACT_XATTR) {
-#if ARCHIVE_XATTR_DARWIN
-		/*
-		 * On MacOS, extended attributes get stored in mac_metadata,
-		 * too. If we intend to extract mac_metadata and it is present
-		 * we skip extracting extended attributes.
-		 */
-		size_t metadata_size;
-
-		if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
-		    archive_entry_mac_metadata(a->entry,
-		    &metadata_size) == NULL || metadata_size == 0)
-#endif
-		a->todo |= TODO_XATTR;
-	}
-	if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
-		a->todo |= TODO_FFLAGS;
-	if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
-		ret = check_symlinks(a);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-	}
-#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
-	/* If path exceeds PATH_MAX, shorten the path. */
-	edit_deep_directories(a);
-#endif
-
-	ret = restore_entry(a);
-
-#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
-	/*
-	 * Check if the filesystem the file is restoring on supports
-	 * HFS+ Compression. If not, cancel HFS+ Compression.
-	 */
-	if (a->todo | TODO_HFS_COMPRESSION) {
-		/*
-		 * NOTE: UF_COMPRESSED is ignored even if the filesystem
-		 * supports HFS+ Compression because the file should
-		 * have at least an extended attribute "com.apple.decmpfs"
-		 * before the flag is set to indicate that the file have
-		 * been compressed. If the filesystem does not support
-		 * HFS+ Compression the system call will fail.
-		 */
-		if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
-			a->todo &= ~TODO_HFS_COMPRESSION;
-	}
-#endif
-
-	/*
-	 * TODO: There are rumours that some extended attributes must
-	 * be restored before file data is written.  If this is true,
-	 * then we either need to write all extended attributes both
-	 * before and after restoring the data, or find some rule for
-	 * determining which must go first and which last.  Due to the
-	 * many ways people are using xattrs, this may prove to be an
-	 * intractable problem.
-	 */
-
-#ifdef HAVE_FCHDIR
-	/* If we changed directory above, restore it here. */
-	if (a->restore_pwd >= 0) {
-		r = fchdir(a->restore_pwd);
-		if (r != 0) {
-			archive_set_error(&a->archive, errno,
-			    "chdir() failure");
-			ret = ARCHIVE_FATAL;
-		}
-		close(a->restore_pwd);
-		a->restore_pwd = -1;
-	}
-#endif
-
-	/*
-	 * Fixup uses the unedited pathname from archive_entry_pathname(),
-	 * because it is relative to the base dir and the edited path
-	 * might be relative to some intermediate dir as a result of the
-	 * deep restore logic.
-	 */
-	if (a->deferred & TODO_MODE) {
-		fe = current_fixup(a, archive_entry_pathname(entry));
-		if (fe == NULL)
-			return (ARCHIVE_FATAL);
-		fe->filetype = archive_entry_filetype(entry);
-		fe->fixup |= TODO_MODE_BASE;
-		fe->mode = a->mode;
-	}
-
-	if ((a->deferred & TODO_TIMES)
-		&& (archive_entry_mtime_is_set(entry)
-		    || archive_entry_atime_is_set(entry))) {
-		fe = current_fixup(a, archive_entry_pathname(entry));
-		if (fe == NULL)
-			return (ARCHIVE_FATAL);
-		fe->filetype = archive_entry_filetype(entry);
-		fe->mode = a->mode;
-		fe->fixup |= TODO_TIMES;
-		if (archive_entry_atime_is_set(entry)) {
-			fe->atime = archive_entry_atime(entry);
-			fe->atime_nanos = archive_entry_atime_nsec(entry);
-		} else {
-			/* If atime is unset, use start time. */
-			fe->atime = a->start_time;
-			fe->atime_nanos = 0;
-		}
-		if (archive_entry_mtime_is_set(entry)) {
-			fe->mtime = archive_entry_mtime(entry);
-			fe->mtime_nanos = archive_entry_mtime_nsec(entry);
-		} else {
-			/* If mtime is unset, use start time. */
-			fe->mtime = a->start_time;
-			fe->mtime_nanos = 0;
-		}
-		if (archive_entry_birthtime_is_set(entry)) {
-			fe->birthtime = archive_entry_birthtime(entry);
-			fe->birthtime_nanos = archive_entry_birthtime_nsec(
-			    entry);
-		} else {
-			/* If birthtime is unset, use mtime. */
-			fe->birthtime = fe->mtime;
-			fe->birthtime_nanos = fe->mtime_nanos;
-		}
-	}
-
-	if (a->deferred & TODO_ACLS) {
-		fe = current_fixup(a, archive_entry_pathname(entry));
-		if (fe == NULL)
-			return (ARCHIVE_FATAL);
-		fe->filetype = archive_entry_filetype(entry);
-		fe->fixup |= TODO_ACLS;
-		archive_acl_copy(&fe->acl, archive_entry_acl(entry));
-	}
-
-	if (a->deferred & TODO_MAC_METADATA) {
-		const void *metadata;
-		size_t metadata_size;
-		metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
-		if (metadata != NULL && metadata_size > 0) {
-			fe = current_fixup(a, archive_entry_pathname(entry));
-			if (fe == NULL)
-				return (ARCHIVE_FATAL);
-			fe->filetype = archive_entry_filetype(entry);
-			fe->mac_metadata = malloc(metadata_size);
-			if (fe->mac_metadata != NULL) {
-				memcpy(fe->mac_metadata, metadata,
-				    metadata_size);
-				fe->mac_metadata_size = metadata_size;
-				fe->fixup |= TODO_MAC_METADATA;
-			}
-		}
-	}
-
-	if (a->deferred & TODO_FFLAGS) {
-		fe = current_fixup(a, archive_entry_pathname(entry));
-		if (fe == NULL)
-			return (ARCHIVE_FATAL);
-		fe->filetype = archive_entry_filetype(entry);
-		fe->fixup |= TODO_FFLAGS;
-		/* TODO: Complete this.. defer fflags from below. */
-	}
-
-	/* We've created the object and are ready to pour data into it. */
-	if (ret >= ARCHIVE_WARN)
-		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;
-	}
-
-	return (ret);
-}
-
-int
-archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
-	a->skip_file_set = 1;
-	a->skip_file_dev = d;
-	a->skip_file_ino = i;
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
-{
-	uint64_t start_size = size;
-	ssize_t bytes_written = 0;
-	ssize_t block_size = 0, bytes_to_write;
-
-	if (size == 0)
-		return (ARCHIVE_OK);
-
-	if (a->filesize == 0 || a->fd < 0) {
-		archive_set_error(&a->archive, 0,
-		    "Attempt to write to an empty file");
-		return (ARCHIVE_WARN);
-	}
-
-	if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
-#if HAVE_STRUCT_STAT_ST_BLKSIZE
-		int r;
-		if ((r = lazy_stat(a)) != ARCHIVE_OK)
-			return (r);
-		block_size = a->pst->st_blksize;
-#else
-		/* XXX TODO XXX Is there a more appropriate choice here ? */
-		/* This needn't match the filesystem allocation size. */
-		block_size = 16*1024;
-#endif
-	}
-
-	/* If this write would run beyond the file size, truncate it. */
-	if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
-		start_size = size = (size_t)(a->filesize - a->offset);
-
-	/* Write the data. */
-	while (size > 0) {
-		if (block_size == 0) {
-			bytes_to_write = size;
-		} else {
-			/* We're sparsifying the file. */
-			const char *p, *end;
-			int64_t block_end;
-
-			/* Skip leading zero bytes. */
-			for (p = buff, end = buff + size; p < end; ++p) {
-				if (*p != '\0')
-					break;
-			}
-			a->offset += p - buff;
-			size -= p - buff;
-			buff = p;
-			if (size == 0)
-				break;
-
-			/* Calculate next block boundary after offset. */
-			block_end
-			    = (a->offset / block_size + 1) * block_size;
-
-			/* If the adjusted write would cross block boundary,
-			 * truncate it to the block boundary. */
-			bytes_to_write = size;
-			if (a->offset + bytes_to_write > block_end)
-				bytes_to_write = block_end - a->offset;
-		}
-		/* Seek if necessary to the specified offset. */
-		if (a->offset != a->fd_offset) {
-			if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
-				archive_set_error(&a->archive, errno,
-				    "Seek failed");
-				return (ARCHIVE_FATAL);
-			}
-			a->fd_offset = a->offset;
-		}
-		bytes_written = write(a->fd, buff, bytes_to_write);
-		if (bytes_written < 0) {
-			archive_set_error(&a->archive, errno, "Write failed");
-			return (ARCHIVE_WARN);
-		}
-		buff += bytes_written;
-		size -= bytes_written;
-		a->total_bytes_written += bytes_written;
-		a->offset += bytes_written;
-		a->fd_offset = a->offset;
-	}
-	return (start_size - size);
-}
-
-#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
-	&& defined(HAVE_ZLIB_H)
-
-/*
- * Set UF_COMPRESSED file flag.
- * This have to be called after hfs_write_decmpfs() because if the
- * file does not have "com.apple.decmpfs" xattr the flag is ignored.
- */
-static int
-hfs_set_compressed_fflag(struct archive_write_disk *a)
-{
-	int r;
-
-	if ((r = lazy_stat(a)) != ARCHIVE_OK)
-		return (r);
-
-	a->st.st_flags |= UF_COMPRESSED;
-	if (fchflags(a->fd, a->st.st_flags) != 0) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to set UF_COMPRESSED file flag");
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * HFS+ Compression decmpfs
- *
- *     +------------------------------+ +0
- *     |      Magic(LE 4 bytes)       |
- *     +------------------------------+
- *     |      Type(LE 4 bytes)        |
- *     +------------------------------+
- *     | Uncompressed size(LE 8 bytes)|
- *     +------------------------------+ +16
- *     |                              |
- *     |       Compressed data        |
- *     |  (Placed only if Type == 3)  |
- *     |                              |
- *     +------------------------------+  +3802 = MAX_DECMPFS_XATTR_SIZE
- *
- *  Type is 3: decmpfs has compressed data.
- *  Type is 4: Resource Fork has compressed data.
- */
-/*
- * Write "com.apple.decmpfs"
- */
-static int
-hfs_write_decmpfs(struct archive_write_disk *a)
-{
-	int r;
-	uint32_t compression_type;
-
-	r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p,
-	    a->decmpfs_attr_size, 0, 0);
-	if (r < 0) {
-		archive_set_error(&a->archive, errno,
-		    "Cannot restore xattr:%s", DECMPFS_XATTR_NAME);
-		compression_type = archive_le32dec(
-		    &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]);
-		if (compression_type == CMP_RESOURCE_FORK)
-			fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME,
-			    XATTR_SHOWCOMPRESSION);
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * HFS+ Compression Resource Fork
- *
- *     +-----------------------------+
- *     |     Header(260 bytes)       |
- *     +-----------------------------+
- *     |   Block count(LE 4 bytes)   |
- *     +-----------------------------+  --+
- * +-- |     Offset (LE 4 bytes)     |    |
- * |   | [distance from Block count] |    | Block 0
- * |   +-----------------------------+    |
- * |   | Compressed size(LE 4 bytes) |    |
- * |   +-----------------------------+  --+
- * |   |                             |
- * |   |      ..................     |
- * |   |                             |
- * |   +-----------------------------+  --+
- * |   |     Offset (LE 4 bytes)     |    |
- * |   +-----------------------------+    | Block (Block count -1)
- * |   | Compressed size(LE 4 bytes) |    |
- * +-> +-----------------------------+  --+
- *     |   Compressed data(n bytes)  |  Block 0
- *     +-----------------------------+
- *     |                             |
- *     |      ..................     |
- *     |                             |
- *     +-----------------------------+
- *     |   Compressed data(n bytes)  |  Block (Block count -1)
- *     +-----------------------------+
- *     |      Footer(50 bytes)       |
- *     +-----------------------------+
- *
- */
-/*
- * Write the header of "com.apple.ResourceFork"
- */
-static int
-hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff,
-    size_t bytes, uint32_t position)
-{
-	int ret;
-
-	ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes,
-	    position, a->rsrc_xattr_options);
-	if (ret < 0) {
-		archive_set_error(&a->archive, errno,
-		    "Cannot restore xattr: %s at %u pos %u bytes",
-		    XATTR_RESOURCEFORK_NAME,
-		    (unsigned)position,
-		    (unsigned)bytes);
-		return (ARCHIVE_WARN);
-	}
-	a->rsrc_xattr_options &= ~XATTR_CREATE;
-	return (ARCHIVE_OK);
-}
-
-static int
-hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed)
-{
-	int ret;
-
-	ret = hfs_write_resource_fork(a, a->compressed_buffer,
-	    bytes_compressed, a->compressed_rsrc_position);
-	if (ret == ARCHIVE_OK)
-		a->compressed_rsrc_position += bytes_compressed;
-	return (ret);
-}
-
-static int
-hfs_write_resource_fork_header(struct archive_write_disk *a)
-{
-	unsigned char *buff;
-	uint32_t rsrc_bytes;
-	uint32_t rsrc_header_bytes;
-
-	/*
-	 * Write resource fork header + block info.
-	 */
-	buff = a->resource_fork;
-	rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE;
-	rsrc_header_bytes =
-		RSRC_H_SIZE +		/* Header base size. */
-		4 +			/* Block count. */
-		(a->decmpfs_block_count * 8);/* Block info */
-	archive_be32enc(buff, 0x100);
-	archive_be32enc(buff + 4, rsrc_bytes);
-	archive_be32enc(buff + 8, rsrc_bytes - 256);
-	archive_be32enc(buff + 12, 0x32);
-	memset(buff + 16, 0, 240);
-	archive_be32enc(buff + 256, rsrc_bytes - 260);
-	return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0);
-}
-
-static size_t
-hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size)
-{
-	static const char rsrc_footer[RSRC_F_SIZE] = {
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c',  'm',
-		'p', 'f',   0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
-		0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00
-	};
-	if (buff_size < sizeof(rsrc_footer))
-		return (0);
-	memcpy(buff, rsrc_footer, sizeof(rsrc_footer));
-	return (sizeof(rsrc_footer));
-}
-
-static int
-hfs_reset_compressor(struct archive_write_disk *a)
-{
-	int ret;
-
-	if (a->stream_valid)
-		ret = deflateReset(&a->stream);
-	else
-		ret = deflateInit(&a->stream, a->decmpfs_compression_level);
-
-	if (ret != Z_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to initialize compressor");
-		return (ARCHIVE_FATAL);
-	} else
-		a->stream_valid = 1;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-hfs_decompress(struct archive_write_disk *a)
-{
-	uint32_t *block_info;
-	unsigned int block_count;
-	uint32_t data_pos, data_size;
-	ssize_t r;
-	ssize_t bytes_written, bytes_to_write;
-	unsigned char *b;
-
-	block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
-	block_count = archive_le32dec(block_info++);
-	while (block_count--) {
-		data_pos = RSRC_H_SIZE + archive_le32dec(block_info++);
-		data_size = archive_le32dec(block_info++);
-		r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME,
-		    a->compressed_buffer, data_size, data_pos, 0);
-		if (r != data_size)  {
-			archive_set_error(&a->archive,
-			    (r < 0)?errno:ARCHIVE_ERRNO_MISC,
-			    "Failed to read resource fork");
-			return (ARCHIVE_WARN);
-		}
-		if (a->compressed_buffer[0] == 0xff) {
-			bytes_to_write = data_size -1;
-			b = a->compressed_buffer + 1;
-		} else {
-			uLong dest_len = MAX_DECMPFS_BLOCK_SIZE;
-			int zr;
-
-			zr = uncompress((Bytef *)a->uncompressed_buffer,
-			    &dest_len, a->compressed_buffer, data_size);
-			if (zr != Z_OK) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Failed to decompress resource fork");
-				return (ARCHIVE_WARN);
-			}
-			bytes_to_write = dest_len;
-			b = (unsigned char *)a->uncompressed_buffer;
-		}
-		do {
-			bytes_written = write(a->fd, b, bytes_to_write);
-			if (bytes_written < 0) {
-				archive_set_error(&a->archive, errno,
-				    "Write failed");
-				return (ARCHIVE_WARN);
-			}
-			bytes_to_write -= bytes_written;
-			b += bytes_written;
-		} while (bytes_to_write > 0);
-	}
-	r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0);
-	if (r == -1)  {
-		archive_set_error(&a->archive, errno,
-		    "Failed to remove resource fork");
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
-    size_t size)
-{
-	unsigned char *buffer_compressed;
-	size_t bytes_compressed;
-	size_t bytes_used;
-	int ret;
-
-	ret = hfs_reset_compressor(a);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	if (a->compressed_buffer == NULL) {
-		size_t block_size;
-
-		block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE +
-		    + compressBound(MAX_DECMPFS_BLOCK_SIZE);
-		a->compressed_buffer = malloc(block_size);
-		if (a->compressed_buffer == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Resource Fork");
-			return (ARCHIVE_FATAL);
-		}
-		a->compressed_buffer_size = block_size;
-		a->compressed_buffer_remaining = block_size;
-	}
-
-	buffer_compressed = a->compressed_buffer +
-	    a->compressed_buffer_size - a->compressed_buffer_remaining;
-	a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff;
-	a->stream.avail_in = size;
-	a->stream.next_out = buffer_compressed;
-	a->stream.avail_out = a->compressed_buffer_remaining;
-	do {
-		ret = deflate(&a->stream, Z_FINISH);
-		switch (ret) {
-		case Z_OK:
-		case Z_STREAM_END:
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Failed to compress data");
-			return (ARCHIVE_FAILED);
-		}
-	} while (ret == Z_OK);
-	bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out;
-
-	/*
-	 * If the compressed size is larger than the original size,
-	 * throw away compressed data, use uncompressed data instead.
-	 */
-	if (bytes_compressed > size) {
-		buffer_compressed[0] = 0xFF;/* uncompressed marker. */
-		memcpy(buffer_compressed + 1, buff, size);
-		bytes_compressed = size + 1;
-	}
-	a->compressed_buffer_remaining -= bytes_compressed;
-
-	/*
-	 * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE
-	 * and the block count in the file is only one, store compressed
-	 * data to decmpfs xattr instead of the resource fork.
-	 */
-	if (a->decmpfs_block_count == 1 &&
-	    (a->decmpfs_attr_size + bytes_compressed)
-	      <= MAX_DECMPFS_XATTR_SIZE) {
-		archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
-		    CMP_XATTR);
-		memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE,
-		    buffer_compressed, bytes_compressed);
-		a->decmpfs_attr_size += bytes_compressed;
-		a->compressed_buffer_remaining = a->compressed_buffer_size;
-		/*
-		 * Finish HFS+ Compression.
-		 * - Write the decmpfs xattr.
-		 * - Set the UF_COMPRESSED file flag.
-		 */
-		ret = hfs_write_decmpfs(a);
-		if (ret == ARCHIVE_OK)
-			ret = hfs_set_compressed_fflag(a);
-		return (ret);
-	}
-
-	/* Update block info. */
-	archive_le32enc(a->decmpfs_block_info++,
-	    a->compressed_rsrc_position_v - RSRC_H_SIZE);
-	archive_le32enc(a->decmpfs_block_info++, bytes_compressed);
-	a->compressed_rsrc_position_v += bytes_compressed;
-
-	/*
-	 * Write the compressed data to the resource fork.
-	 */
-	bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining;
-	while (bytes_used >= COMPRESSED_W_SIZE) {
-		ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		bytes_used -= COMPRESSED_W_SIZE;
-		if (bytes_used > COMPRESSED_W_SIZE)
-			memmove(a->compressed_buffer,
-			    a->compressed_buffer + COMPRESSED_W_SIZE,
-			    bytes_used);
-		else
-			memcpy(a->compressed_buffer,
-			    a->compressed_buffer + COMPRESSED_W_SIZE,
-			    bytes_used);
-	}
-	a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used;
-
-	/*
-	 * If the current block is the last block, write the remaining
-	 * compressed data and the resource fork footer.
-	 */
-	if (a->file_remaining_bytes == 0) {
-		size_t rsrc_size;
-		int64_t bk;
-
-		/* Append the resource footer. */
-		rsrc_size = hfs_set_resource_fork_footer(
-		    a->compressed_buffer + bytes_used,
-		    a->compressed_buffer_remaining);
-		ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
-		a->compressed_buffer_remaining = a->compressed_buffer_size;
-
-		/* If the compressed size is not enough smaller than
-		 * the uncompressed size. cancel HFS+ compression.
-		 * TODO: study a behavior of ditto utility and improve
-		 * the condition to fall back into no HFS+ compression. */
-		bk = HFS_BLOCKS(a->compressed_rsrc_position);
-		bk += bk >> 7;
-		if (bk > HFS_BLOCKS(a->filesize))
-			return hfs_decompress(a);
-		/*
-		 * Write the resourcefork header.
-		 */
-		if (ret == ARCHIVE_OK)
-			ret = hfs_write_resource_fork_header(a);
-		/*
-		 * Finish HFS+ Compression.
-		 * - Write the decmpfs xattr.
-		 * - Set the UF_COMPRESSED file flag.
-		 */
-		if (ret == ARCHIVE_OK)
-			ret = hfs_write_decmpfs(a);
-		if (ret == ARCHIVE_OK)
-			ret = hfs_set_compressed_fflag(a);
-	}
-	return (ret);
-}
-
-static ssize_t
-hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
-    size_t size)
-{
-	const char *buffer_to_write;
-	size_t bytes_to_write;
-	int ret;
-
-	if (a->decmpfs_block_count == (unsigned)-1) {
-		void *new_block;
-		size_t new_size;
-		unsigned int block_count;
-
-		if (a->decmpfs_header_p == NULL) {
-			new_block = malloc(MAX_DECMPFS_XATTR_SIZE
-			    + sizeof(uint32_t));
-			if (new_block == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for decmpfs");
-				return (ARCHIVE_FATAL);
-			}
-			a->decmpfs_header_p = new_block;
-		}
-		a->decmpfs_attr_size = DECMPFS_HEADER_SIZE;
-		archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC],
-		    DECMPFS_MAGIC);
-		archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
-		    CMP_RESOURCE_FORK);
-		archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE],
-		    a->filesize);
-
-		/* Calculate a block count of the file. */
-		block_count =
-		    (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) /
-			MAX_DECMPFS_BLOCK_SIZE;
-		/*
-		 * Allocate buffer for resource fork.
-		 * Set up related pointers;
-		 */
-		new_size =
-		    RSRC_H_SIZE + /* header */
-		    4 + /* Block count */
-		    (block_count * sizeof(uint32_t) * 2) +
-		    RSRC_F_SIZE; /* footer */
-		if (new_size > a->resource_fork_allocated_size) {
-			new_block = realloc(a->resource_fork, new_size);
-			if (new_block == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for ResourceFork");
-				return (ARCHIVE_FATAL);
-			}
-			a->resource_fork_allocated_size = new_size;
-			a->resource_fork = new_block;
-		}
-
-		/* Allocate uncompressed buffer */
-		if (a->uncompressed_buffer == NULL) {
-			new_block = malloc(MAX_DECMPFS_BLOCK_SIZE);
-			if (new_block == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for decmpfs");
-				return (ARCHIVE_FATAL);
-			}
-			a->uncompressed_buffer = new_block;
-		}
-		a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
-		a->file_remaining_bytes = a->filesize;
-		a->compressed_buffer_remaining = a->compressed_buffer_size;
-
-		/*
-		 * Set up a resource fork.
-		 */
-		a->rsrc_xattr_options = XATTR_CREATE;
-		/* Get the position where we are going to set a bunch
-		 * of block info. */
-		a->decmpfs_block_info =
-		    (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
-		/* Set the block count to the resource fork. */
-		archive_le32enc(a->decmpfs_block_info++, block_count);
-		/* Get the position where we are going to set compressed
-		 * data. */
-		a->compressed_rsrc_position =
-		    RSRC_H_SIZE + 4 + (block_count * 8);
-		a->compressed_rsrc_position_v = a->compressed_rsrc_position;
-		a->decmpfs_block_count = block_count;
-	}
-
-	/* Ignore redundant bytes. */
-	if (a->file_remaining_bytes == 0)
-		return ((ssize_t)size);
-
-	/* Do not overrun a block size. */
-	if (size > a->block_remaining_bytes)
-		bytes_to_write = a->block_remaining_bytes;
-	else
-		bytes_to_write = size;
-	/* Do not overrun the file size. */
-	if (bytes_to_write > a->file_remaining_bytes)
-		bytes_to_write = a->file_remaining_bytes;
-
-	/* For efficiency, if a copy length is full of the uncompressed
-	 * buffer size, do not copy writing data to it. */
-	if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE)
-		buffer_to_write = buff;
-	else {
-		memcpy(a->uncompressed_buffer +
-		    MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
-		    buff, bytes_to_write);
-		buffer_to_write = a->uncompressed_buffer;
-	}
-	a->block_remaining_bytes -= bytes_to_write;
-	a->file_remaining_bytes -= bytes_to_write;
-
-	if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) {
-		ret = hfs_drive_compressor(a, buffer_to_write,
-		    MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes);
-		if (ret < 0)
-			return (ret);
-		a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
-	}
-	/* Ignore redundant bytes. */
-	if (a->file_remaining_bytes == 0)
-		return ((ssize_t)size);
-	return (bytes_to_write);
-}
-
-static ssize_t
-hfs_write_data_block(struct archive_write_disk *a, const char *buff,
-    size_t size)
-{
-	uint64_t start_size = size;
-	ssize_t bytes_written = 0;
-	ssize_t bytes_to_write;
-
-	if (size == 0)
-		return (ARCHIVE_OK);
-
-	if (a->filesize == 0 || a->fd < 0) {
-		archive_set_error(&a->archive, 0,
-		    "Attempt to write to an empty file");
-		return (ARCHIVE_WARN);
-	}
-
-	/* If this write would run beyond the file size, truncate it. */
-	if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
-		start_size = size = (size_t)(a->filesize - a->offset);
-
-	/* Write the data. */
-	while (size > 0) {
-		bytes_to_write = size;
-		/* Seek if necessary to the specified offset. */
-		if (a->offset < a->fd_offset) {
-			/* Can't support backward move. */
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Seek failed");
-			return (ARCHIVE_FATAL);
-		} else if (a->offset > a->fd_offset) {
-			uint64_t skip = a->offset - a->fd_offset;
-			char nullblock[1024];
-
-			memset(nullblock, 0, sizeof(nullblock));
-			while (skip > 0) {
-				if (skip > sizeof(nullblock))
-					bytes_written = hfs_write_decmpfs_block(
-					    a, nullblock, sizeof(nullblock));
-				else
-					bytes_written = hfs_write_decmpfs_block(
-					    a, nullblock, skip);
-				if (bytes_written < 0) {
-					archive_set_error(&a->archive, errno,
-					    "Write failed");
-					return (ARCHIVE_WARN);
-				}
-				skip -= bytes_written;
-			}
-
-			a->fd_offset = a->offset;
-		}
-		bytes_written =
-		    hfs_write_decmpfs_block(a, buff, bytes_to_write);
-		if (bytes_written < 0)
-			return (bytes_written);
-		buff += bytes_written;
-		size -= bytes_written;
-		a->total_bytes_written += bytes_written;
-		a->offset += bytes_written;
-		a->fd_offset = a->offset;
-	}
-	return (start_size - size);
-}
-#else
-static ssize_t
-hfs_write_data_block(struct archive_write_disk *a, const char *buff,
-    size_t size)
-{
-	return (write_data_block(a, buff, size));
-}
-#endif
-
-static ssize_t
-_archive_write_disk_data_block(struct archive *_a,
-    const void *buff, size_t size, int64_t offset)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	ssize_t r;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_DATA, "archive_write_data_block");
-
-	a->offset = offset;
-	if (a->todo & TODO_HFS_COMPRESSION)
-		r = hfs_write_data_block(a, buff, size);
-	else
-		r = write_data_block(a, buff, size);
-	if (r < ARCHIVE_OK)
-		return (r);
-	if ((size_t)r < size) {
-		archive_set_error(&a->archive, 0,
-		    "Too much data: Truncating file at %ju bytes",
-		    (uintmax_t)a->filesize);
-		return (ARCHIVE_WARN);
-	}
-#if ARCHIVE_VERSION_NUMBER < 3999000
-	return (ARCHIVE_OK);
-#else
-	return (size);
-#endif
-}
-
-static ssize_t
-_archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_DATA, "archive_write_data");
-
-	if (a->todo & TODO_HFS_COMPRESSION)
-		return (hfs_write_data_block(a, buff, size));
-	return (write_data_block(a, buff, size));
-}
-
-static int
-_archive_write_disk_finish_entry(struct archive *_a)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	int ret = ARCHIVE_OK;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_finish_entry");
-	if (a->archive.state & ARCHIVE_STATE_HEADER)
-		return (ARCHIVE_OK);
-	archive_clear_error(&a->archive);
-
-	/* Pad or truncate file to the right size. */
-	if (a->fd < 0) {
-		/* There's no file. */
-	} else if (a->filesize < 0) {
-		/* File size is unknown, so we can't set the size. */
-	} else if (a->fd_offset == a->filesize) {
-		/* Last write ended at exactly the filesize; we're done. */
-		/* Hopefully, this is the common case. */
-#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
-	} else if (a->todo & TODO_HFS_COMPRESSION) {
-		char null_d[1024];
-		ssize_t r;
-
-		if (a->file_remaining_bytes)
-			memset(null_d, 0, sizeof(null_d));
-		while (a->file_remaining_bytes) {
-			if (a->file_remaining_bytes > sizeof(null_d))
-				r = hfs_write_data_block(
-				    a, null_d, sizeof(null_d));
-			else
-				r = hfs_write_data_block(
-				    a, null_d, a->file_remaining_bytes);
-			if (r < 0) {
-				close_file_descriptor(a);
-				return ((int)r);
-			}
-		}
-#endif
-	} else {
-#if HAVE_FTRUNCATE
-		if (ftruncate(a->fd, a->filesize) == -1 &&
-		    a->filesize == 0) {
-			archive_set_error(&a->archive, errno,
-			    "File size could not be restored");
-			close_file_descriptor(a);
-			return (ARCHIVE_FAILED);
-		}
-#endif
-		/*
-		 * Not all platforms implement the XSI option to
-		 * extend files via ftruncate.  Stat() the file again
-		 * to see what happened.
-		 */
-		a->pst = NULL;
-        if ((ret = lazy_stat(a)) != ARCHIVE_OK) {
-            close_file_descriptor(a);
-            return (ret);
-        }
-		/* We can use lseek()/write() to extend the file if
-		 * ftruncate didn't work or isn't available. */
-		if (a->st.st_size < a->filesize) {
-			const char nul = '\0';
-			if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
-				archive_set_error(&a->archive, errno,
-				    "Seek failed");
-				close_file_descriptor(a);
-				return (ARCHIVE_FATAL);
-			}
-			if (write(a->fd, &nul, 1) < 0) {
-				archive_set_error(&a->archive, errno,
-				    "Write to restore size failed");
-				close_file_descriptor(a);
-				return (ARCHIVE_FATAL);
-			}
-			a->pst = NULL;
-		}
-	}
-
-	/* Restore metadata. */
-
-	/*
-	 * This is specific to Mac OS X.
-	 * If the current file is an AppleDouble file, it should be
-	 * linked with the data fork file and remove it.
-	 */
-	if (a->todo & TODO_APPLEDOUBLE) {
-		int r2 = fixup_appledouble(a, a->name);
-		if (r2 == ARCHIVE_EOF) {
-			/* The current file has been successfully linked
-			 * with the data fork file and removed. So there
-			 * is nothing to do on the current file.  */
-			goto finish_metadata;
-		}
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Look up the "real" UID only if we're going to need it.
-	 * TODO: the TODO_SGID condition can be dropped here, can't it?
-	 */
-	if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
-		a->uid = archive_write_disk_uid(&a->archive,
-		    archive_entry_uname(a->entry),
-		    archive_entry_uid(a->entry));
-	}
-	/* Look up the "real" GID only if we're going to need it. */
-	/* TODO: the TODO_SUID condition can be dropped here, can't it? */
-	if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
-		a->gid = archive_write_disk_gid(&a->archive,
-		    archive_entry_gname(a->entry),
-		    archive_entry_gid(a->entry));
-	 }
-
-	/*
-	 * Restore ownership before set_mode tries to restore suid/sgid
-	 * bits.  If we set the owner, we know what it is and can skip
-	 * a stat() call to examine the ownership of the file on disk.
-	 */
-	if (a->todo & TODO_OWNER) {
-		int r2 = set_ownership(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * HYPOTHESIS:
-	 * If we're not root, we won't be setting any security
-	 * attributes that may be wiped by the set_mode() routine
-	 * below.  We also can't set xattr on non-owner-writable files,
-	 * which may be the state after set_mode(). Perform
-	 * set_xattrs() first based on these constraints.
-	 */
-	if (a->user_uid != 0 &&
-	    (a->todo & TODO_XATTR)) {
-		int r2 = set_xattrs(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * set_mode must precede ACLs on systems such as Solaris and
-	 * FreeBSD where setting the mode implicitly clears extended ACLs
-	 */
-	if (a->todo & TODO_MODE) {
-		int r2 = set_mode(a, a->mode);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Security-related extended attributes (such as
-	 * security.capability on Linux) have to be restored last,
-	 * since they're implicitly removed by other file changes.
-	 * We do this last only when root.
-	 */
-	if (a->user_uid == 0 &&
-	    (a->todo & TODO_XATTR)) {
-		int r2 = set_xattrs(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Some flags prevent file modification; they must be restored after
-	 * file contents are written.
-	 */
-	if (a->todo & TODO_FFLAGS) {
-		int r2 = set_fflags(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Time must follow most other metadata;
-	 * otherwise atime will get changed.
-	 */
-	if (a->todo & TODO_TIMES) {
-		int r2 = set_times_from_entry(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Mac extended metadata includes ACLs.
-	 */
-	if (a->todo & TODO_MAC_METADATA) {
-		const void *metadata;
-		size_t metadata_size;
-		metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
-		if (metadata != NULL && metadata_size > 0) {
-			int r2 = set_mac_metadata(a, archive_entry_pathname(
-			    a->entry), metadata, metadata_size);
-			if (r2 < ret) ret = r2;
-		}
-	}
-
-	/*
-	 * ACLs must be restored after timestamps because there are
-	 * ACLs that prevent attribute changes (including time).
-	 */
-	if (a->todo & TODO_ACLS) {
-		int r2;
-		r2 = archive_write_disk_set_acls(&a->archive, a->fd,
-		    archive_entry_pathname(a->entry),
-		    archive_entry_acl(a->entry),
-		    archive_entry_mode(a->entry));
-		if (r2 < ret) ret = r2;
-	}
-
-finish_metadata:
-	/* If there's an fd, we can close it now. */
-	if (a->fd >= 0) {
-		close(a->fd);
-		a->fd = -1;
-		if (a->tmpname) {
-			if (rename(a->tmpname, a->name) == -1) {
-				archive_set_error(&a->archive, errno,
-				    "Failed to rename temporary file");
-				ret = ARCHIVE_FAILED;
-				unlink(a->tmpname);
-			}
-			a->tmpname = NULL;
-		}
-	}
-	/* If there's an entry, we can release it now. */
-	archive_entry_free(a->entry);
-	a->entry = NULL;
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	return (ret);
-}
-
-int
-archive_write_disk_set_group_lookup(struct archive *_a,
-    void *private_data,
-    la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
-    void (*cleanup_gid)(void *private))
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
-
-	if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
-		(a->cleanup_gid)(a->lookup_gid_data);
-
-	a->lookup_gid = lookup_gid;
-	a->cleanup_gid = cleanup_gid;
-	a->lookup_gid_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_disk_set_user_lookup(struct archive *_a,
-    void *private_data,
-    int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
-    void (*cleanup_uid)(void *private))
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
-
-	if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
-		(a->cleanup_uid)(a->lookup_uid_data);
-
-	a->lookup_uid = lookup_uid;
-	a->cleanup_uid = cleanup_uid;
-	a->lookup_uid_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
-{
-       struct archive_write_disk *a = (struct archive_write_disk *)_a;
-       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-           ARCHIVE_STATE_ANY, "archive_write_disk_gid");
-       if (a->lookup_gid)
-               return (a->lookup_gid)(a->lookup_gid_data, name, id);
-       return (id);
-}
- 
-int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_uid");
-	if (a->lookup_uid)
-		return (a->lookup_uid)(a->lookup_uid_data, name, id);
-	return (id);
-}
-
-/*
- * Create a new archive_write_disk object and initialize it with global state.
- */
-struct archive *
-archive_write_disk_new(void)
-{
-	struct archive_write_disk *a;
-
-	a = (struct archive_write_disk *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
-	/* We're ready to write a header immediately. */
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	a->archive.vtable = &archive_write_disk_vtable;
-	a->start_time = time(NULL);
-	/* Query and restore the umask. */
-	umask(a->user_umask = umask(0));
-#ifdef HAVE_GETEUID
-	a->user_uid = geteuid();
-#endif /* HAVE_GETEUID */
-	if (archive_string_ensure(&a->path_safe, 512) == NULL) {
-		free(a);
-		return (NULL);
-	}
-	a->path_safe.s[0] = 0;
-
-#ifdef HAVE_ZLIB_H
-	a->decmpfs_compression_level = 5;
-#endif
-	return (&a->archive);
-}
-
-
-/*
- * If pathname is longer than PATH_MAX, chdir to a suitable
- * intermediate dir and edit the path down to a shorter suffix.  Note
- * that this routine never returns an error; if the chdir() attempt
- * fails for any reason, we just go ahead with the long pathname.  The
- * object creation is likely to fail, but any error will get handled
- * at that time.
- */
-#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
-static void
-edit_deep_directories(struct archive_write_disk *a)
-{
-	int ret;
-	char *tail = a->name;
-
-	/* If path is short, avoid the open() below. */
-	if (strlen(tail) < PATH_MAX)
-		return;
-
-	/* Try to record our starting dir. */
-	a->restore_pwd = la_opendirat(AT_FDCWD, ".");
-	__archive_ensure_cloexec_flag(a->restore_pwd);
-	if (a->restore_pwd < 0)
-		return;
-
-	/* As long as the path is too long... */
-	while (strlen(tail) >= PATH_MAX) {
-		/* Locate a dir prefix shorter than PATH_MAX. */
-		tail += PATH_MAX - 8;
-		while (tail > a->name && *tail != '/')
-			tail--;
-		/* Exit if we find a too-long path component. */
-		if (tail <= a->name)
-			return;
-		/* Create the intermediate dir and chdir to it. */
-		*tail = '\0'; /* Terminate dir portion */
-		ret = create_dir(a, a->name);
-		if (ret == ARCHIVE_OK && chdir(a->name) != 0)
-			ret = ARCHIVE_FAILED;
-		*tail = '/'; /* Restore the / we removed. */
-		if (ret != ARCHIVE_OK)
-			return;
-		tail++;
-		/* The chdir() succeeded; we've now shortened the path. */
-		a->name = tail;
-	}
-	return;
-}
-#endif
-
-/*
- * The main restore function.
- */
-static int
-restore_entry(struct archive_write_disk *a)
-{
-	int ret = ARCHIVE_OK, en;
-
-	if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
-		/*
-		 * TODO: Fix this.  Apparently, there are platforms
-		 * that still allow root to hose the entire filesystem
-		 * by unlinking a dir.  The S_ISDIR() test above
-		 * prevents us from using unlink() here if the new
-		 * object is a dir, but that doesn't mean the old
-		 * object isn't a dir.
-		 */
-		if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
-			(void)clear_nochange_fflags(a);
-		if (unlink(a->name) == 0) {
-			/* We removed it, reset cached stat. */
-			a->pst = NULL;
-		} else if (errno == ENOENT) {
-			/* File didn't exist, that's just as good. */
-		} else if (rmdir(a->name) == 0) {
-			/* It was a dir, but now it's gone. */
-			a->pst = NULL;
-		} else {
-			/* We tried, but couldn't get rid of it. */
-			archive_set_error(&a->archive, errno,
-			    "Could not unlink");
-			return(ARCHIVE_FAILED);
-		}
-	}
-
-	/* Try creating it first; if this fails, we'll try to recover. */
-	en = create_filesystem_object(a);
-
-	if ((en == ENOTDIR || en == ENOENT)
-	    && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
-		/* If the parent dir doesn't exist, try creating it. */
-		create_parent_dir(a, a->name);
-		/* Now try to create the object again. */
-		en = create_filesystem_object(a);
-	}
-
-	if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
-		archive_set_error(&a->archive, en,
-		    "Hard-link target '%s' does not exist.",
-		    archive_entry_hardlink(a->entry));
-		return (ARCHIVE_FAILED);
-	}
-
-	if ((en == EISDIR || en == EEXIST)
-	    && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
-		/* If we're not overwriting, we're done. */
-		if (S_ISDIR(a->mode)) {
-			/* Don't overwrite any settings on existing directories. */
-			a->todo = 0;
-		}
-		archive_entry_unset_size(a->entry);
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * Some platforms return EISDIR if you call
-	 * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
-	 * return EEXIST.  POSIX is ambiguous, requiring EISDIR
-	 * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
-	 * on an existing item.
-	 */
-	if (en == EISDIR) {
-		/* A dir is in the way of a non-dir, rmdir it. */
-		if (rmdir(a->name) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't remove already-existing dir");
-			return (ARCHIVE_FAILED);
-		}
-		a->pst = NULL;
-		/* Try again. */
-		en = create_filesystem_object(a);
-	} else if (en == EEXIST) {
-		/*
-		 * We know something is in the way, but we don't know what;
-		 * we need to find out before we go any further.
-		 */
-		int r = 0;
-		/*
-		 * The SECURE_SYMLINKS logic has already removed a
-		 * symlink to a dir if the client wants that.  So
-		 * follow the symlink if we're creating a dir.
-		 */
-		if (S_ISDIR(a->mode))
-			r = la_stat(a->name, &a->st);
-		/*
-		 * If it's not a dir (or it's a broken symlink),
-		 * then don't follow it.
-		 */
-		if (r != 0 || !S_ISDIR(a->mode))
-#ifdef HAVE_LSTAT
-			r = lstat(a->name, &a->st);
-#else
-			r = la_stat(a->name, &a->st);
-#endif
-		if (r != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't stat existing object");
-			return (ARCHIVE_FAILED);
-		}
-
-		/*
-		 * NO_OVERWRITE_NEWER doesn't apply to directories.
-		 */
-		if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
-		    &&  !S_ISDIR(a->st.st_mode)) {
-			if (!older(&(a->st), a->entry)) {
-				archive_entry_unset_size(a->entry);
-				return (ARCHIVE_OK);
-			}
-		}
-
-		/* If it's our archive, we're done. */
-		if (a->skip_file_set &&
-		    a->st.st_dev == (dev_t)a->skip_file_dev &&
-		    a->st.st_ino == (ino_t)a->skip_file_ino) {
-			archive_set_error(&a->archive, 0,
-			    "Refusing to overwrite archive");
-			return (ARCHIVE_FAILED);
-		}
-
-		if (!S_ISDIR(a->st.st_mode)) {
-			if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
-				(void)clear_nochange_fflags(a);
-
-			if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
-			    S_ISREG(a->st.st_mode)) {
-				/* Use a temporary file to extract */
-				if ((a->fd = la_mktemp(a)) == -1) {
-					archive_set_error(&a->archive, errno,
-					    "Can't create temporary file");
-					return ARCHIVE_FAILED;
-				}
-				a->pst = NULL;
-				en = 0;
-			} else {
-				/* A non-dir is in the way, unlink it. */
-				if (unlink(a->name) != 0) {
-					archive_set_error(&a->archive, errno,
-					    "Can't unlink already-existing "
-					    "object");
-					return (ARCHIVE_FAILED);
-				}
-				a->pst = NULL;
-				/* Try again. */
-				en = create_filesystem_object(a);
-			}
-		} else if (!S_ISDIR(a->mode)) {
-			/* A dir is in the way of a non-dir, rmdir it. */
-			if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
-				(void)clear_nochange_fflags(a);
-			if (rmdir(a->name) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Can't replace existing directory with non-directory");
-				return (ARCHIVE_FAILED);
-			}
-			/* Try again. */
-			en = create_filesystem_object(a);
-		} else {
-			/*
-			 * There's a dir in the way of a dir.  Don't
-			 * waste time with rmdir()/mkdir(), just fix
-			 * up the permissions on the existing dir.
-			 * Note that we don't change perms on existing
-			 * dirs unless _EXTRACT_PERM is specified.
-			 */
-			if ((a->mode != a->st.st_mode)
-			    && (a->todo & TODO_MODE_FORCE))
-				a->deferred |= (a->todo & TODO_MODE);
-			/* Ownership doesn't need deferred fixup. */
-			en = 0; /* Forget the EEXIST. */
-		}
-	}
-
-	if (en) {
-		/* Everything failed; give up here. */
-		if ((&a->archive)->error == NULL)
-			archive_set_error(&a->archive, en, "Can't create '%s'",
-			    a->name);
-		return (ARCHIVE_FAILED);
-	}
-
-	a->pst = NULL; /* Cached stat data no longer valid. */
-	return (ret);
-}
-
-/*
- * Returns 0 if creation succeeds, or else returns errno value from
- * the failed system call.   Note:  This function should only ever perform
- * a single system call.
- */
-static int
-create_filesystem_object(struct archive_write_disk *a)
-{
-	/* Create the entry. */
-	const char *linkname;
-	mode_t final_mode, mode;
-	int r;
-	/* these for check_symlinks_fsobj */
-	char *linkname_copy;	/* non-const copy of linkname */
-	struct stat st;
-	struct archive_string error_string;
-	int error_number;
-
-	/* We identify hard/symlinks according to the link names. */
-	/* Since link(2) and symlink(2) don't handle modes, we're done here. */
-	linkname = archive_entry_hardlink(a->entry);
-	if (linkname != NULL) {
-#if !HAVE_LINK
-		return (EPERM);
-#else
-		archive_string_init(&error_string);
-		linkname_copy = strdup(linkname);
-		if (linkname_copy == NULL) {
-		    return (EPERM);
-		}
-		/*
-		 * TODO: consider using the cleaned-up path as the link
-		 * target?
-		 */
-		r = cleanup_pathname_fsobj(linkname_copy, &error_number,
-		    &error_string, a->flags);
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, error_number, "%s",
-			    error_string.s);
-			free(linkname_copy);
-			archive_string_free(&error_string);
-			/*
-			 * EPERM is more appropriate than error_number for our
-			 * callers
-			 */
-			return (EPERM);
-		}
-		r = check_symlinks_fsobj(linkname_copy, &error_number,
-		    &error_string, a->flags, 1);
-		if (r != ARCHIVE_OK) {
-			archive_set_error(&a->archive, error_number, "%s",
-			    error_string.s);
-			free(linkname_copy);
-			archive_string_free(&error_string);
-			/*
-			 * EPERM is more appropriate than error_number for our
-			 * callers
-			 */
-			return (EPERM);
-		}
-		free(linkname_copy);
-		archive_string_free(&error_string);
-		/*
-		 * Unlinking and linking here is really not atomic,
-		 * but doing it right, would require us to construct
-		 * an mktemplink() function, and then use rename(2).
-		 */
-		if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
-			unlink(a->name);
-#ifdef HAVE_LINKAT
-		r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
-		    0) ? errno : 0;
-#else
-		r = link(linkname, a->name) ? errno : 0;
-#endif
-		/*
-		 * New cpio and pax formats allow hardlink entries
-		 * to carry data, so we may have to open the file
-		 * for hardlink entries.
-		 *
-		 * If the hardlink was successfully created and
-		 * the archive doesn't have carry data for it,
-		 * consider it to be non-authoritative for meta data.
-		 * This is consistent with GNU tar and BSD pax.
-		 * If the hardlink does carry data, let the last
-		 * archive entry decide ownership.
-		 */
-		if (r == 0 && a->filesize <= 0) {
-			a->todo = 0;
-			a->deferred = 0;
-		} else if (r == 0 && a->filesize > 0) {
-#ifdef HAVE_LSTAT
-			r = lstat(a->name, &st);
-#else
-			r = la_stat(a->name, &st);
-#endif
-			if (r != 0)
-				r = errno;
-			else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
-				a->fd = open(a->name, O_WRONLY | O_TRUNC |
-				    O_BINARY | O_CLOEXEC | O_NOFOLLOW);
-				__archive_ensure_cloexec_flag(a->fd);
-				if (a->fd < 0)
-					r = errno;
-			}
-		}
-		return (r);
-#endif
-	}
-	linkname = archive_entry_symlink(a->entry);
-	if (linkname != NULL) {
-#if HAVE_SYMLINK
-		/*
-		 * Unlinking and linking here is really not atomic,
-		 * but doing it right, would require us to construct
-		 * an mktempsymlink() function, and then use rename(2).
-		 */
-		if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
-			unlink(a->name);
-		return symlink(linkname, a->name) ? errno : 0;
-#else
-		return (EPERM);
-#endif
-	}
-
-	/*
-	 * The remaining system calls all set permissions, so let's
-	 * try to take advantage of that to avoid an extra chmod()
-	 * call.  (Recall that umask is set to zero right now!)
-	 */
-
-	/* Mode we want for the final restored object (w/o file type bits). */
-	final_mode = a->mode & 07777;
-	/*
-	 * The mode that will actually be restored in this step.  Note
-	 * that SUID, SGID, etc, require additional work to ensure
-	 * security, so we never restore them at this point.
-	 */
-	mode = final_mode & 0777 & ~a->user_umask;
-
-	/* 
-	 * Always create writable such that [f]setxattr() works if we're not
-	 * root.
-	 */
-	if (a->user_uid != 0 &&
-	    a->todo & (TODO_HFS_COMPRESSION | TODO_XATTR)) {
-		mode |= 0200;
-	}
-
-	switch (a->mode & AE_IFMT) {
-	default:
-		/* POSIX requires that we fall through here. */
-		/* FALLTHROUGH */
-	case AE_IFREG:
-		a->tmpname = NULL;
-		a->fd = open(a->name,
-		    O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
-		__archive_ensure_cloexec_flag(a->fd);
-		r = (a->fd < 0);
-		break;
-	case AE_IFCHR:
-#ifdef HAVE_MKNOD
-		/* Note: we use AE_IFCHR for the case label, and
-		 * S_IFCHR for the mknod() call.  This is correct.  */
-		r = mknod(a->name, mode | S_IFCHR,
-		    archive_entry_rdev(a->entry));
-		break;
-#else
-		/* TODO: Find a better way to warn about our inability
-		 * to restore a char device node. */
-		return (EINVAL);
-#endif /* HAVE_MKNOD */
-	case AE_IFBLK:
-#ifdef HAVE_MKNOD
-		r = mknod(a->name, mode | S_IFBLK,
-		    archive_entry_rdev(a->entry));
-		break;
-#else
-		/* TODO: Find a better way to warn about our inability
-		 * to restore a block device node. */
-		return (EINVAL);
-#endif /* HAVE_MKNOD */
-	case AE_IFDIR:
-		mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
-		r = mkdir(a->name, mode);
-		if (r == 0) {
-			/* Defer setting dir times. */
-			a->deferred |= (a->todo & TODO_TIMES);
-			a->todo &= ~TODO_TIMES;
-			/* Never use an immediate chmod(). */
-			/* We can't avoid the chmod() entirely if EXTRACT_PERM
-			 * because of SysV SGID inheritance. */
-			if ((mode != final_mode)
-			    || (a->flags & ARCHIVE_EXTRACT_PERM))
-				a->deferred |= (a->todo & TODO_MODE);
-			a->todo &= ~TODO_MODE;
-		}
-		break;
-	case AE_IFIFO:
-#ifdef HAVE_MKFIFO
-		r = mkfifo(a->name, mode);
-		break;
-#else
-		/* TODO: Find a better way to warn about our inability
-		 * to restore a fifo. */
-		return (EINVAL);
-#endif /* HAVE_MKFIFO */
-	}
-
-	/* All the system calls above set errno on failure. */
-	if (r)
-		return (errno);
-
-	/* If we managed to set the final mode, we've avoided a chmod(). */
-	if (mode == final_mode)
-		a->todo &= ~TODO_MODE;
-	return (0);
-}
-
-/*
- * Cleanup function for archive_extract.  Mostly, this involves processing
- * the fixup list, which is used to address a number of problems:
- *   * Dir permissions might prevent us from restoring a file in that
- *     dir, so we restore the dir with minimum 0700 permissions first,
- *     then correct the mode at the end.
- *   * Similarly, the act of restoring a file touches the directory
- *     and changes the timestamp on the dir, so we have to touch-up dir
- *     timestamps at the end as well.
- *   * Some file flags can interfere with the restore by, for example,
- *     preventing the creation of hardlinks to those files.
- *   * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
- *
- * Note that tar/cpio do not require that archives be in a particular
- * order; there is no way to know when the last file has been restored
- * within a directory, so there's no way to optimize the memory usage
- * here by fixing up the directory any earlier than the
- * end-of-archive.
- *
- * XXX TODO: Directory ACLs should be restored here, for the same
- * reason we set directory perms here. XXX
- */
-static int
-_archive_write_disk_close(struct archive *_a)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	struct fixup_entry *next, *p;
-	struct stat st;
-	char *c;
-	int fd, ret, openflags;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_disk_close");
-	ret = _archive_write_disk_finish_entry(&a->archive);
-
-	/* Sort dir list so directories are fixed up in depth-first order. */
-	p = sort_dir_list(a->fixup_list);
-
-	while (p != NULL) {
-		fd = -1;
-		a->pst = NULL; /* Mark stat cache as out-of-date. */
-
-		/* We must strip trailing slashes from the path to avoid
-		   dereferencing symbolic links to directories */
-		c = p->name;
-		while (*c != '\0')
-			c++;
-		while (c != p->name && *(c - 1) == '/') {
-			c--;
-			*c = '\0';
-		}
-
-		if (p->fixup == 0)
-			goto skip_fixup_entry;
-		else {
-			/*
-			 * We need to verify if the type of the file
-			 * we are going to open matches the file type
-			 * of the fixup entry.
-			 */
-			openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
-			    | O_CLOEXEC;
-#if defined(O_DIRECTORY)
-			if (p->filetype == AE_IFDIR)
-				openflags |= O_DIRECTORY;
-#endif
-			fd = open(p->name, openflags);
-
-#if defined(O_DIRECTORY)
-			/*
-			 * If we support O_DIRECTORY and open was
-			 * successful we can skip the file type check
-			 * for directories. For other file types
-			 * we need to verify via fstat() or lstat()
-			 */
-			if (fd == -1 || p->filetype != AE_IFDIR) {
-#if HAVE_FSTAT
-				if (fd > 0 && (
-				    fstat(fd, &st) != 0 ||
-				    la_verify_filetype(st.st_mode,
-				    p->filetype) == 0)) {
-					goto skip_fixup_entry;
-				} else
-#endif
-				if (
-#ifdef HAVE_LSTAT
-					lstat(p->name, &st) != 0 ||
-#else
-					la_stat(p->name, &st) != 0 ||
-#endif
-				    la_verify_filetype(st.st_mode,
-				    p->filetype) == 0) {
-					goto skip_fixup_entry;
-				}
-			}
-#else
-#if HAVE_FSTAT
-			if (fd > 0 && (
-			    fstat(fd, &st) != 0 ||
-			    la_verify_filetype(st.st_mode,
-			    p->filetype) == 0)) {
-				goto skip_fixup_entry;
-			} else
-#endif
-			if (
-#ifdef HAVE_LSTAT
-				lstat(p->name, &st) != 0 ||
-#else
-				la_stat(p->name, &st) != 0 ||
-#endif
-			    la_verify_filetype(st.st_mode,
-			    p->filetype) == 0) {
-				goto skip_fixup_entry;
-			}
-#endif
-		}
-		if (p->fixup & TODO_TIMES) {
-			set_times(a, fd, p->mode, p->name,
-			    p->atime, p->atime_nanos,
-			    p->birthtime, p->birthtime_nanos,
-			    p->mtime, p->mtime_nanos,
-			    p->ctime, p->ctime_nanos);
-		}
-		if (p->fixup & TODO_MODE_BASE) {
-#ifdef HAVE_FCHMOD
-			if (fd >= 0)
-				fchmod(fd, p->mode & 07777);
-			else
-#endif
-#ifdef HAVE_LCHMOD
-			lchmod(p->name, p->mode & 07777);
-#else
-			chmod(p->name, p->mode & 07777);
-#endif
-		}
-		if (p->fixup & TODO_ACLS)
-			archive_write_disk_set_acls(&a->archive, fd,
-			    p->name, &p->acl, p->mode);
-		if (p->fixup & TODO_FFLAGS)
-			set_fflags_platform(a, fd, p->name,
-			    p->mode, p->fflags_set, 0);
-		if (p->fixup & TODO_MAC_METADATA)
-			set_mac_metadata(a, p->name, p->mac_metadata,
-					 p->mac_metadata_size);
-skip_fixup_entry:
-		next = p->next;
-		archive_acl_clear(&p->acl);
-		free(p->mac_metadata);
-		free(p->name);
-		if (fd >= 0)
-			close(fd);
-		free(p);
-		p = next;
-	}
-	a->fixup_list = NULL;
-	return (ret);
-}
-
-static int
-_archive_write_disk_free(struct archive *_a)
-{
-	struct archive_write_disk *a;
-	int ret;
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
-	a = (struct archive_write_disk *)_a;
-	ret = _archive_write_disk_close(&a->archive);
-	archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
-	archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
-	archive_entry_free(a->entry);
-	archive_string_free(&a->_name_data);
-	archive_string_free(&a->_tmpname_data);
-	archive_string_free(&a->archive.error_string);
-	archive_string_free(&a->path_safe);
-	a->archive.magic = 0;
-	__archive_clean(&a->archive);
-	free(a->decmpfs_header_p);
-	free(a->resource_fork);
-	free(a->compressed_buffer);
-	free(a->uncompressed_buffer);
-#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
-	&& defined(HAVE_ZLIB_H)
-	if (a->stream_valid) {
-		switch (deflateEnd(&a->stream)) {
-		case Z_OK:
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Failed to clean up compressor");
-			ret = ARCHIVE_FATAL;
-			break;
-		}
-	}
-#endif
-	free(a);
-	return (ret);
-}
-
-/*
- * Simple O(n log n) merge sort to order the fixup list.  In
- * particular, we want to restore dir timestamps depth-first.
- */
-static struct fixup_entry *
-sort_dir_list(struct fixup_entry *p)
-{
-	struct fixup_entry *a, *b, *t;
-
-	if (p == NULL)
-		return (NULL);
-	/* A one-item list is already sorted. */
-	if (p->next == NULL)
-		return (p);
-
-	/* Step 1: split the list. */
-	t = p;
-	a = p->next->next;
-	while (a != NULL) {
-		/* Step a twice, t once. */
-		a = a->next;
-		if (a != NULL)
-			a = a->next;
-		t = t->next;
-	}
-	/* Now, t is at the mid-point, so break the list here. */
-	b = t->next;
-	t->next = NULL;
-	a = p;
-
-	/* Step 2: Recursively sort the two sub-lists. */
-	a = sort_dir_list(a);
-	b = sort_dir_list(b);
-
-	/* Step 3: Merge the returned lists. */
-	/* Pick the first element for the merged list. */
-	if (strcmp(a->name, b->name) > 0) {
-		t = p = a;
-		a = a->next;
-	} else {
-		t = p = b;
-		b = b->next;
-	}
-
-	/* Always put the later element on the list first. */
-	while (a != NULL && b != NULL) {
-		if (strcmp(a->name, b->name) > 0) {
-			t->next = a;
-			a = a->next;
-		} else {
-			t->next = b;
-			b = b->next;
-		}
-		t = t->next;
-	}
-
-	/* Only one list is non-empty, so just splice it on. */
-	if (a != NULL)
-		t->next = a;
-	if (b != NULL)
-		t->next = b;
-
-	return (p);
-}
-
-/*
- * Returns a new, initialized fixup entry.
- *
- * TODO: Reduce the memory requirements for this list by using a tree
- * structure rather than a simple list of names.
- */
-static struct fixup_entry *
-new_fixup(struct archive_write_disk *a, const char *pathname)
-{
-	struct fixup_entry *fe;
-
-	fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
-	if (fe == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for a fixup");
-		return (NULL);
-	}
-	fe->next = a->fixup_list;
-	a->fixup_list = fe;
-	fe->fixup = 0;
-	fe->filetype = 0;
-	fe->name = strdup(pathname);
-	return (fe);
-}
-
-/*
- * Returns a fixup structure for the current entry.
- */
-static struct fixup_entry *
-current_fixup(struct archive_write_disk *a, const char *pathname)
-{
-	if (a->current_fixup == NULL)
-		a->current_fixup = new_fixup(a, pathname);
-	return (a->current_fixup);
-}
-
-/* Error helper for new *_fsobj functions */
-static void
-fsobj_error(int *a_eno, struct archive_string *a_estr,
-    int err, const char *errstr, const char *path)
-{
-	if (a_eno)
-		*a_eno = err;
-	if (a_estr)
-		archive_string_sprintf(a_estr, "%s%s", errstr, path);
-}
-
-/*
- * TODO: Someday, integrate this with the deep dir support; they both
- * scan the path and both can be optimized by comparing against other
- * recent paths.
- */
-/*
- * Checks the given path to see if any elements along it are symlinks.  Returns
- * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
- */
-static int
-check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
-    int flags, int checking_linkname)
-{
-#if !defined(HAVE_LSTAT) && \
-    !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
-	/* Platform doesn't have lstat, so we can't look for symlinks. */
-	(void)path; /* UNUSED */
-	(void)a_eno; /* UNUSED */
-	(void)a_estr; /* UNUSED */
-	(void)flags; /* UNUSED */
-	(void)checking_linkname; /* UNUSED */
-	return (ARCHIVE_OK);
-#else
-	int res = ARCHIVE_OK;
-	char *tail;
-	char *head;
-	int last;
-	char c = '\0';
-	int r;
-	struct stat st;
-	int chdir_fd;
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-	int fd;
-#endif
-
-	/* Nothing to do here if name is empty */
-	if(path[0] == '\0')
-	    return (ARCHIVE_OK);
-
-	/*
-	 * Guard against symlink tricks.  Reject any archive entry whose
-	 * destination would be altered by a symlink.
-	 *
-	 * Walk the filename in chunks separated by '/'.  For each segment:
-	 *  - if it doesn't exist, continue
-	 *  - if it's symlink, abort or remove it
-	 *  - if it's a directory and it's not the last chunk, cd into it
-	 * As we go:
-	 *  head points to the current (relative) path
-	 *  tail points to the temporary \0 terminating the segment we're
-	 *      currently examining
-	 *  c holds what used to be in *tail
-	 *  last is 1 if this is the last tail
-	 */
-	chdir_fd = la_opendirat(AT_FDCWD, ".");
-	__archive_ensure_cloexec_flag(chdir_fd);
-	if (chdir_fd < 0) {
-		fsobj_error(a_eno, a_estr, errno,
-		    "Could not open ", path);
-		return (ARCHIVE_FATAL);
-	}
-	head = path;
-	tail = path;
-	last = 0;
-	/* TODO: reintroduce a safe cache here? */
-	/* Skip the root directory if the path is absolute. */
-	if(tail == path && tail[0] == '/')
-		++tail;
-	/* Keep going until we've checked the entire name.
-	 * head, tail, path all alias the same string, which is
-	 * temporarily zeroed at tail, so be careful restoring the
-	 * stashed (c=tail[0]) for error messages.
-	 * Exiting the loop with break is okay; continue is not.
-	 */
-	while (!last) {
-		/*
-		 * Skip the separator we just consumed, plus any adjacent ones
-		 */
-		while (*tail == '/')
-		    ++tail;
-		/* Skip the next path element. */
-		while (*tail != '\0' && *tail != '/')
-			++tail;
-		/* is this the last path component? */
-		last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
-		/* temporarily truncate the string here */
-		c = tail[0];
-		tail[0] = '\0';
-		/* Check that we haven't hit a symlink. */
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-		r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW);
-#elif defined(HAVE_LSTAT)
-		r = lstat(head, &st);
-#else
-		r = la_stat(head, &st);
-#endif
-		if (r != 0) {
-			tail[0] = c;
-			/* We've hit a dir that doesn't exist; stop now. */
-			if (errno == ENOENT) {
-				break;
-			} else {
-				/*
-				 * Treat any other error as fatal - best to be
-				 * paranoid here.
-				 * Note: This effectively disables deep
-				 * directory support when security checks are
-				 * enabled. Otherwise, very long pathnames that
-				 * trigger an error here could evade the
-				 * sandbox.
-				 * TODO: We could do better, but it would
-				 * probably require merging the symlink checks
-				 * with the deep-directory editing.
-				 */
-				fsobj_error(a_eno, a_estr, errno,
-				    "Could not stat ", path);
-				res = ARCHIVE_FAILED;
-				break;
-			}
-		} else if (S_ISDIR(st.st_mode)) {
-			if (!last) {
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-				fd = la_opendirat(chdir_fd, head);
-				if (fd < 0)
-					r = -1;
-				else {
-					r = 0;
-					close(chdir_fd);
-					chdir_fd = fd;
-				}
-#else
-				r = chdir(head);
-#endif
-				if (r != 0) {
-					tail[0] = c;
-					fsobj_error(a_eno, a_estr, errno,
-					    "Could not chdir ", path);
-					res = (ARCHIVE_FATAL);
-					break;
-				}
-				/* Our view is now from inside this dir: */
-				head = tail + 1;
-			}
-		} else if (S_ISLNK(st.st_mode)) {
-			if (last && checking_linkname) {
-#ifdef HAVE_LINKAT
-				/*
-				 * Hardlinks to symlinks are safe to write
-				 * if linkat() is supported as it does not
-				 * follow symlinks.
-				 */
-				res = ARCHIVE_OK;
-#else
-				/*
-				 * We return ARCHIVE_FAILED here as we are
-				 * not able to safely write hardlinks
-				 * to symlinks.
-				 */
-				tail[0] = c;
-				fsobj_error(a_eno, a_estr, errno,
-				    "Cannot write hardlink to symlink ",
-				    path);
-				res = ARCHIVE_FAILED;
-#endif
-				break;
-			} else
-			if (last) {
-				/*
-				 * Last element is symlink; remove it
-				 * so we can overwrite it with the
-				 * item being extracted.
-				 */
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-				r = unlinkat(chdir_fd, head, 0);
-#else
-				r = unlink(head);
-#endif
-				if (r != 0) {
-					tail[0] = c;
-					fsobj_error(a_eno, a_estr, errno,
-					    "Could not remove symlink ",
-					    path);
-					res = ARCHIVE_FAILED;
-					break;
-				}
-				/*
-				 * Even if we did remove it, a warning
-				 * is in order.  The warning is silly,
-				 * though, if we're just replacing one
-				 * symlink with another symlink.
-				 */
-				tail[0] = c;
-				/*
-				 * FIXME:  not sure how important this is to
-				 * restore
-				 */
-				/*
-				if (!S_ISLNK(path)) {
-					fsobj_error(a_eno, a_estr, 0,
-					    "Removing symlink ", path);
-				}
-				*/
-				/* Symlink gone.  No more problem! */
-				res = ARCHIVE_OK;
-				break;
-			} else if (flags & ARCHIVE_EXTRACT_UNLINK) {
-				/* User asked us to remove problems. */
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-				r = unlinkat(chdir_fd, head, 0);
-#else
-				r = unlink(head);
-#endif
-				if (r != 0) {
-					tail[0] = c;
-					fsobj_error(a_eno, a_estr, 0,
-					    "Cannot remove intervening "
-					    "symlink ", path);
-					res = ARCHIVE_FAILED;
-					break;
-				}
-				tail[0] = c;
-			} else if ((flags &
-			    ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
-				/*
-				 * We are not the last element and we want to
-				 * follow symlinks if they are a directory.
-				 * 
-				 * This is needed to extract hardlinks over
-				 * symlinks.
-				 */
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-				r = fstatat(chdir_fd, head, &st, 0);
-#else
-				r = la_stat(head, &st);
-#endif
-				if (r != 0) {
-					tail[0] = c;
-					if (errno == ENOENT) {
-						break;
-					} else {
-						fsobj_error(a_eno, a_estr,
-						    errno,
-						    "Could not stat ", path);
-						res = (ARCHIVE_FAILED);
-						break;
-					}
-				} else if (S_ISDIR(st.st_mode)) {
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-					fd = la_opendirat(chdir_fd, head);
-					if (fd < 0)
-						r = -1;
-					else {
-						r = 0;
-						close(chdir_fd);
-						chdir_fd = fd;
-					}
-#else
-					r = chdir(head);
-#endif
-					if (r != 0) {
-						tail[0] = c;
-						fsobj_error(a_eno, a_estr,
-						    errno,
-						    "Could not chdir ", path);
-						res = (ARCHIVE_FATAL);
-						break;
-					}
-					/*
-					 * Our view is now from inside
-					 * this dir:
-					 */
-					head = tail + 1;
-				} else {
-					tail[0] = c;
-					fsobj_error(a_eno, a_estr, 0,
-					    "Cannot extract through "
-					    "symlink ", path);
-					res = ARCHIVE_FAILED;
-					break;
-				}
-			} else {
-				tail[0] = c;
-				fsobj_error(a_eno, a_estr, 0,
-				    "Cannot extract through symlink ", path);
-				res = ARCHIVE_FAILED;
-				break;
-			}
-		}
-		/* be sure to always maintain this */
-		tail[0] = c;
-		if (tail[0] != '\0')
-			tail++; /* Advance to the next segment. */
-	}
-	/* Catches loop exits via break */
-	tail[0] = c;
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
-	/* If we operate with openat(), fstatat() and unlinkat() there was
-	 * no chdir(), so just close the fd */
-	if (chdir_fd >= 0)
-		close(chdir_fd);
-#elif HAVE_FCHDIR
-	/* If we changed directory above, restore it here. */
-	if (chdir_fd >= 0) {
-		r = fchdir(chdir_fd);
-		if (r != 0) {
-			fsobj_error(a_eno, a_estr, errno,
-			    "chdir() failure", "");
-		}
-		close(chdir_fd);
-		chdir_fd = -1;
-		if (r != 0) {
-			res = (ARCHIVE_FATAL);
-		}
-	}
-#endif
-	/* TODO: reintroduce a safe cache here? */
-	return res;
-#endif
-}
-
-/*
- * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
- * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
- */
-static int
-check_symlinks(struct archive_write_disk *a)
-{
-	struct archive_string error_string;
-	int error_number;
-	int rc;
-	archive_string_init(&error_string);
-	rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
-	    a->flags, 0);
-	if (rc != ARCHIVE_OK) {
-		archive_set_error(&a->archive, error_number, "%s",
-		    error_string.s);
-	}
-	archive_string_free(&error_string);
-	a->pst = NULL;	/* to be safe */
-	return rc;
-}
-
-
-#if defined(__CYGWIN__)
-/*
- * 1. Convert a path separator from '\' to '/' .
- *    We shouldn't check multibyte character directly because some
- *    character-set have been using the '\' character for a part of
- *    its multibyte character code.
- * 2. Replace unusable characters in Windows with underscore('_').
- * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
- */
-static void
-cleanup_pathname_win(char *path)
-{
-	wchar_t wc;
-	char *p;
-	size_t alen, l;
-	int mb, complete, utf8;
-
-	alen = 0;
-	mb = 0;
-	complete = 1;
-	utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
-	for (p = path; *p != '\0'; p++) {
-		++alen;
-		if (*p == '\\') {
-			/* If previous byte is smaller than 128,
-			 * this is not second byte of multibyte characters,
-			 * so we can replace '\' with '/'. */
-			if (utf8 || !mb)
-				*p = '/';
-			else
-				complete = 0;/* uncompleted. */
-		} else if (*(unsigned char *)p > 127)
-			mb = 1;
-		else
-			mb = 0;
-		/* Rewrite the path name if its next character is unusable. */
-		if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
-		    *p == '<' || *p == '>' || *p == '|')
-			*p = '_';
-	}
-	if (complete)
-		return;
-
-	/*
-	 * Convert path separator in wide-character.
-	 */
-	p = path;
-	while (*p != '\0' && alen) {
-		l = mbtowc(&wc, p, alen);
-		if (l == (size_t)-1) {
-			while (*p != '\0') {
-				if (*p == '\\')
-					*p = '/';
-				++p;
-			}
-			break;
-		}
-		if (l == 1 && wc == L'\\')
-			*p = '/';
-		p += l;
-		alen -= l;
-	}
-}
-#endif
-
-/*
- * Canonicalize the pathname.  In particular, this strips duplicate
- * '/' characters, '.' elements, and trailing '/'.  It also raises an
- * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is
- * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
- * is set) if the path is absolute.
- */
-static int
-cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
-    int flags)
-{
-	char *dest, *src;
-	char separator = '\0';
-
-	dest = src = path;
-	if (*src == '\0') {
-		fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
-		    "Invalid empty ", "pathname");
-		return (ARCHIVE_FAILED);
-	}
-
-#if defined(__CYGWIN__)
-	cleanup_pathname_win(path);
-#endif
-	/* Skip leading '/'. */
-	if (*src == '/') {
-		if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
-			fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
-			    "Path is ", "absolute");
-			return (ARCHIVE_FAILED);
-		}
-
-		separator = *src++;
-	}
-
-	/* Scan the pathname one element at a time. */
-	for (;;) {
-		/* src points to first char after '/' */
-		if (src[0] == '\0') {
-			break;
-		} else if (src[0] == '/') {
-			/* Found '//', ignore second one. */
-			src++;
-			continue;
-		} else if (src[0] == '.') {
-			if (src[1] == '\0') {
-				/* Ignore trailing '.' */
-				break;
-			} else if (src[1] == '/') {
-				/* Skip './'. */
-				src += 2;
-				continue;
-			} else if (src[1] == '.') {
-				if (src[2] == '/' || src[2] == '\0') {
-					/* Conditionally warn about '..' */
-					if (flags
-					    & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
-						fsobj_error(a_eno, a_estr,
-						    ARCHIVE_ERRNO_MISC,
-						    "Path contains ", "'..'");
-						return (ARCHIVE_FAILED);
-					}
-				}
-				/*
-				 * Note: Under no circumstances do we
-				 * remove '..' elements.  In
-				 * particular, restoring
-				 * '/foo/../bar/' should create the
-				 * 'foo' dir as a side-effect.
-				 */
-			}
-		}
-
-		/* Copy current element, including leading '/'. */
-		if (separator)
-			*dest++ = '/';
-		while (*src != '\0' && *src != '/') {
-			*dest++ = *src++;
-		}
-
-		if (*src == '\0')
-			break;
-
-		/* Skip '/' separator. */
-		separator = *src++;
-	}
-	/*
-	 * We've just copied zero or more path elements, not including the
-	 * final '/'.
-	 */
-	if (dest == path) {
-		/*
-		 * Nothing got copied.  The path must have been something
-		 * like '.' or '/' or './' or '/././././/./'.
-		 */
-		if (separator)
-			*dest++ = '/';
-		else
-			*dest++ = '.';
-	}
-	/* Terminate the result. */
-	*dest = '\0';
-	return (ARCHIVE_OK);
-}
-
-static int
-cleanup_pathname(struct archive_write_disk *a)
-{
-	struct archive_string error_string;
-	int error_number;
-	int rc;
-	archive_string_init(&error_string);
-	rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
-	    a->flags);
-	if (rc != ARCHIVE_OK) {
-		archive_set_error(&a->archive, error_number, "%s",
-		    error_string.s);
-	}
-	archive_string_free(&error_string);
-	return rc;
-}
-
-/*
- * Create the parent directory of the specified path, assuming path
- * is already in mutable storage.
- */
-static int
-create_parent_dir(struct archive_write_disk *a, char *path)
-{
-	char *slash;
-	int r;
-
-	/* Remove tail element to obtain parent name. */
-	slash = strrchr(path, '/');
-	if (slash == NULL)
-		return (ARCHIVE_OK);
-	*slash = '\0';
-	r = create_dir(a, path);
-	*slash = '/';
-	return (r);
-}
-
-/*
- * Create the specified dir, recursing to create parents as necessary.
- *
- * Returns ARCHIVE_OK if the path exists when we're done here.
- * Otherwise, returns ARCHIVE_FAILED.
- * Assumes path is in mutable storage; path is unchanged on exit.
- */
-static int
-create_dir(struct archive_write_disk *a, char *path)
-{
-	struct stat st;
-	struct fixup_entry *le;
-	char *slash, *base;
-	mode_t mode_final, mode;
-	int r;
-
-	/* Check for special names and just skip them. */
-	slash = strrchr(path, '/');
-	if (slash == NULL)
-		base = path;
-	else
-		base = slash + 1;
-
-	if (base[0] == '\0' ||
-	    (base[0] == '.' && base[1] == '\0') ||
-	    (base[0] == '.' && base[1] == '.' && base[2] == '\0')) {
-		/* Don't bother trying to create null path, '.', or '..'. */
-		if (slash != NULL) {
-			*slash = '\0';
-			r = create_dir(a, path);
-			*slash = '/';
-			return (r);
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * Yes, this should be stat() and not lstat().  Using lstat()
-	 * here loses the ability to extract through symlinks.  Also note
-	 * that this should not use the a->st cache.
-	 */
-	if (la_stat(path, &st) == 0) {
-		if (S_ISDIR(st.st_mode))
-			return (ARCHIVE_OK);
-		if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
-			archive_set_error(&a->archive, EEXIST,
-			    "Can't create directory '%s'", path);
-			return (ARCHIVE_FAILED);
-		}
-		if (unlink(path) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't create directory '%s': "
-			    "Conflicting file cannot be removed",
-			    path);
-			return (ARCHIVE_FAILED);
-		}
-	} else if (errno != ENOENT && errno != ENOTDIR) {
-		/* Stat failed? */
-		archive_set_error(&a->archive, errno,
-		    "Can't test directory '%s'", path);
-		return (ARCHIVE_FAILED);
-	} else if (slash != NULL) {
-		*slash = '\0';
-		r = create_dir(a, path);
-		*slash = '/';
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	/*
-	 * Mode we want for the final restored directory.  Per POSIX,
-	 * implicitly-created dirs must be created obeying the umask.
-	 * There's no mention whether this is different for privileged
-	 * restores (which the rest of this code handles by pretending
-	 * umask=0).  I've chosen here to always obey the user's umask for
-	 * implicit dirs, even if _EXTRACT_PERM was specified.
-	 */
-	mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
-	/* Mode we want on disk during the restore process. */
-	mode = mode_final;
-	mode |= MINIMUM_DIR_MODE;
-	mode &= MAXIMUM_DIR_MODE;
-	if (mkdir(path, mode) == 0) {
-		if (mode != mode_final) {
-			le = new_fixup(a, path);
-			if (le == NULL)
-				return (ARCHIVE_FATAL);
-			le->fixup |=TODO_MODE_BASE;
-			le->mode = mode_final;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * Without the following check, a/b/../b/c/d fails at the
-	 * second visit to 'b', so 'd' can't be created.  Note that we
-	 * don't add it to the fixup list here, as it's already been
-	 * added.
-	 */
-	if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
-		return (ARCHIVE_OK);
-
-	archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
-	    path);
-	return (ARCHIVE_FAILED);
-}
-
-/*
- * Note: Although we can skip setting the user id if the desired user
- * id matches the current user, we cannot skip setting the group, as
- * many systems set the gid based on the containing directory.  So
- * we have to perform a chown syscall if we want to set the SGID
- * bit.  (The alternative is to stat() and then possibly chown(); it's
- * more efficient to skip the stat() and just always chown().)  Note
- * that a successful chown() here clears the TODO_SGID_CHECK bit, which
- * allows set_mode to skip the stat() check for the GID.
- */
-static int
-set_ownership(struct archive_write_disk *a)
-{
-#if !defined(__CYGWIN__) && !defined(__linux__)
-/*
- * On Linux, a process may have the CAP_CHOWN capability.
- * On Windows there is no 'root' user with uid 0.
- * Elsewhere we can skip calling chown if we are not root and the desired
- * user id does not match the current user.
- */
-	if (a->user_uid != 0 && a->user_uid != a->uid) {
-		archive_set_error(&a->archive, errno,
-		    "Can't set UID=%jd", (intmax_t)a->uid);
-		return (ARCHIVE_WARN);
-	}
-#endif
-
-#ifdef HAVE_FCHOWN
-	/* If we have an fd, we can avoid a race. */
-	if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) {
-		/* We've set owner and know uid/gid are correct. */
-		a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
-		return (ARCHIVE_OK);
-	}
-#endif
-
-	/* We prefer lchown() but will use chown() if that's all we have. */
-	/* Of course, if we have neither, this will always fail. */
-#ifdef HAVE_LCHOWN
-	if (lchown(a->name, a->uid, a->gid) == 0) {
-		/* We've set owner and know uid/gid are correct. */
-		a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
-		return (ARCHIVE_OK);
-	}
-#elif HAVE_CHOWN
-	if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) {
-		/* We've set owner and know uid/gid are correct. */
-		a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
-		return (ARCHIVE_OK);
-	}
-#endif
-
-	archive_set_error(&a->archive, errno,
-	    "Can't set user=%jd/group=%jd for %s",
-	    (intmax_t)a->uid, (intmax_t)a->gid, a->name);
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Note: Returns 0 on success, non-zero on failure.
- */
-static int
-set_time(int fd, int mode, const char *name,
-    time_t atime, long atime_nsec,
-    time_t mtime, long mtime_nsec)
-{
-	/* Select the best implementation for this platform. */
-#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
-	/*
-	 * utimensat() and futimens() are defined in
-	 * POSIX.1-2008. They support ns resolution and setting times
-	 * on fds and symlinks.
-	 */
-	struct timespec ts[2];
-	(void)mode; /* UNUSED */
-	ts[0].tv_sec = atime;
-	ts[0].tv_nsec = atime_nsec;
-	ts[1].tv_sec = mtime;
-	ts[1].tv_nsec = mtime_nsec;
-	if (fd >= 0)
-		return futimens(fd, ts);
-	return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
-
-#elif HAVE_UTIMES
-	/*
-	 * The utimes()-family functions support µs-resolution and
-	 * setting times fds and symlinks.  utimes() is documented as
-	 * LEGACY by POSIX, futimes() and lutimes() are not described
-	 * in POSIX.
-	 */
-	struct timeval times[2];
-
-	times[0].tv_sec = atime;
-	times[0].tv_usec = atime_nsec / 1000;
-	times[1].tv_sec = mtime;
-	times[1].tv_usec = mtime_nsec / 1000;
-
-#ifdef HAVE_FUTIMES
-	if (fd >= 0)
-		return (futimes(fd, times));
-#else
-	(void)fd; /* UNUSED */
-#endif
-#ifdef HAVE_LUTIMES
-	(void)mode; /* UNUSED */
-	return (lutimes(name, times));
-#else
-	if (S_ISLNK(mode))
-		return (0);
-	return (utimes(name, times));
-#endif
-
-#elif defined(HAVE_UTIME)
-	/*
-	 * utime() is POSIX-standard but only supports 1s resolution and
-	 * does not support fds or symlinks.
-	 */
-	struct utimbuf times;
-	(void)fd; /* UNUSED */
-	(void)name; /* UNUSED */
-	(void)atime_nsec; /* UNUSED */
-	(void)mtime_nsec; /* UNUSED */
-	times.actime = atime;
-	times.modtime = mtime;
-	if (S_ISLNK(mode))
-		return (ARCHIVE_OK);
-	return (utime(name, &times));
-
-#else
-	/*
-	 * We don't know how to set the time on this platform.
-	 */
-	(void)fd; /* UNUSED */
-	(void)mode; /* UNUSED */
-	(void)name; /* UNUSED */
-	(void)atime; /* UNUSED */
-	(void)atime_nsec; /* UNUSED */
-	(void)mtime; /* UNUSED */
-	(void)mtime_nsec; /* UNUSED */
-	return (ARCHIVE_WARN);
-#endif
-}
-
-#ifdef F_SETTIMES
-static int
-set_time_tru64(int fd, int mode, const char *name,
-    time_t atime, long atime_nsec,
-    time_t mtime, long mtime_nsec,
-    time_t ctime, long ctime_nsec)
-{
-	struct attr_timbuf tstamp;
-	tstamp.atime.tv_sec = atime;
-	tstamp.mtime.tv_sec = mtime;
-	tstamp.ctime.tv_sec = ctime;
-#if defined (__hpux) && defined (__ia64)
-	tstamp.atime.tv_nsec = atime_nsec;
-	tstamp.mtime.tv_nsec = mtime_nsec;
-	tstamp.ctime.tv_nsec = ctime_nsec;
-#else
-	tstamp.atime.tv_usec = atime_nsec / 1000;
-	tstamp.mtime.tv_usec = mtime_nsec / 1000;
-	tstamp.ctime.tv_usec = ctime_nsec / 1000;
-#endif
-	return (fcntl(fd,F_SETTIMES,&tstamp));
-}
-#endif /* F_SETTIMES */
-
-static int
-set_times(struct archive_write_disk *a,
-    int fd, int mode, const char *name,
-    time_t atime, long atime_nanos,
-    time_t birthtime, long birthtime_nanos,
-    time_t mtime, long mtime_nanos,
-    time_t cctime, long ctime_nanos)
-{
-	/* Note: set_time doesn't use libarchive return conventions!
-	 * It uses syscall conventions.  So 0 here instead of ARCHIVE_OK. */
-	int r1 = 0, r2 = 0;
-
-#ifdef F_SETTIMES
-	 /*
-	 * on Tru64 try own fcntl first which can restore even the
-	 * ctime, fall back to default code path below if it fails
-	 * or if we are not running as root
-	 */
-	if (a->user_uid == 0 &&
-	    set_time_tru64(fd, mode, name,
-			   atime, atime_nanos, mtime,
-			   mtime_nanos, cctime, ctime_nanos) == 0) {
-		return (ARCHIVE_OK);
-	}
-#else /* Tru64 */
-	(void)cctime; /* UNUSED */
-	(void)ctime_nanos; /* UNUSED */
-#endif /* Tru64 */
-
-#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
-	/*
-	 * If you have struct stat.st_birthtime, we assume BSD
-	 * birthtime semantics, in which {f,l,}utimes() updates
-	 * birthtime to earliest mtime.  So we set the time twice,
-	 * first using the birthtime, then using the mtime.  If
-	 * birthtime == mtime, this isn't necessary, so we skip it.
-	 * If birthtime > mtime, then this won't work, so we skip it.
-	 */
-	if (birthtime < mtime
-	    || (birthtime == mtime && birthtime_nanos < mtime_nanos))
-		r1 = set_time(fd, mode, name,
-			      atime, atime_nanos,
-			      birthtime, birthtime_nanos);
-#else
-	(void)birthtime; /* UNUSED */
-	(void)birthtime_nanos; /* UNUSED */
-#endif
-	r2 = set_time(fd, mode, name,
-		      atime, atime_nanos,
-		      mtime, mtime_nanos);
-	if (r1 != 0 || r2 != 0) {
-		archive_set_error(&a->archive, errno,
-				  "Can't restore time");
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-set_times_from_entry(struct archive_write_disk *a)
-{
-	time_t atime, birthtime, mtime, cctime;
-	long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
-
-	/* Suitable defaults. */
-	atime = birthtime = mtime = cctime = a->start_time;
-	atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
-
-	/* If no time was provided, we're done. */
-	if (!archive_entry_atime_is_set(a->entry)
-#if HAVE_STRUCT_STAT_ST_BIRTHTIME
-	    && !archive_entry_birthtime_is_set(a->entry)
-#endif
-	    && !archive_entry_mtime_is_set(a->entry))
-		return (ARCHIVE_OK);
-
-	if (archive_entry_atime_is_set(a->entry)) {
-		atime = archive_entry_atime(a->entry);
-		atime_nsec = archive_entry_atime_nsec(a->entry);
-	}
-	if (archive_entry_birthtime_is_set(a->entry)) {
-		birthtime = archive_entry_birthtime(a->entry);
-		birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
-	}
-	if (archive_entry_mtime_is_set(a->entry)) {
-		mtime = archive_entry_mtime(a->entry);
-		mtime_nsec = archive_entry_mtime_nsec(a->entry);
-	}
-	if (archive_entry_ctime_is_set(a->entry)) {
-		cctime = archive_entry_ctime(a->entry);
-		ctime_nsec = archive_entry_ctime_nsec(a->entry);
-	}
-
-	return set_times(a, a->fd, a->mode, a->name,
-			 atime, atime_nsec,
-			 birthtime, birthtime_nsec,
-			 mtime, mtime_nsec,
-			 cctime, ctime_nsec);
-}
-
-static int
-set_mode(struct archive_write_disk *a, int mode)
-{
-	int r = ARCHIVE_OK;
-	int r2;
-	mode &= 07777; /* Strip off file type bits. */
-
-	if (a->todo & TODO_SGID_CHECK) {
-		/*
-		 * If we don't know the GID is right, we must stat()
-		 * to verify it.  We can't just check the GID of this
-		 * process, since systems sometimes set GID from
-		 * the enclosing dir or based on ACLs.
-		 */
-		if ((r = lazy_stat(a)) != ARCHIVE_OK)
-			return (r);
-		if (a->pst->st_gid != a->gid) {
-			mode &= ~ S_ISGID;
-			if (a->flags & ARCHIVE_EXTRACT_OWNER) {
-				/*
-				 * This is only an error if you
-				 * requested owner restore.  If you
-				 * didn't, we'll try to restore
-				 * sgid/suid, but won't consider it a
-				 * problem if we can't.
-				 */
-				archive_set_error(&a->archive, -1,
-				    "Can't restore SGID bit");
-				r = ARCHIVE_WARN;
-			}
-		}
-		/* While we're here, double-check the UID. */
-		if (a->pst->st_uid != a->uid
-		    && (a->todo & TODO_SUID)) {
-			mode &= ~ S_ISUID;
-			if (a->flags & ARCHIVE_EXTRACT_OWNER) {
-				archive_set_error(&a->archive, -1,
-				    "Can't restore SUID bit");
-				r = ARCHIVE_WARN;
-			}
-		}
-		a->todo &= ~TODO_SGID_CHECK;
-		a->todo &= ~TODO_SUID_CHECK;
-	} else if (a->todo & TODO_SUID_CHECK) {
-		/*
-		 * If we don't know the UID is right, we can just check
-		 * the user, since all systems set the file UID from
-		 * the process UID.
-		 */
-		if (a->user_uid != a->uid) {
-			mode &= ~ S_ISUID;
-			if (a->flags & ARCHIVE_EXTRACT_OWNER) {
-				archive_set_error(&a->archive, -1,
-				    "Can't make file SUID");
-				r = ARCHIVE_WARN;
-			}
-		}
-		a->todo &= ~TODO_SUID_CHECK;
-	}
-
-	if (S_ISLNK(a->mode)) {
-#ifdef HAVE_LCHMOD
-		/*
-		 * If this is a symlink, use lchmod().  If the
-		 * platform doesn't support lchmod(), just skip it.  A
-		 * platform that doesn't provide a way to set
-		 * permissions on symlinks probably ignores
-		 * permissions on symlinks, so a failure here has no
-		 * impact.
-		 */
-		if (lchmod(a->name, mode) != 0) {
-			switch (errno) {
-			case ENOTSUP:
-			case ENOSYS:
-#if ENOTSUP != EOPNOTSUPP
-			case EOPNOTSUPP:
-#endif
-				/*
-				 * if lchmod is defined but the platform
-				 * doesn't support it, silently ignore
-				 * error
-				 */
-				break;
-			default:
-				archive_set_error(&a->archive, errno,
-				    "Can't set permissions to 0%o", (int)mode);
-				r = ARCHIVE_WARN;
-			}
-		}
-#endif
-	} else if (!S_ISDIR(a->mode)) {
-		/*
-		 * If it's not a symlink and not a dir, then use
-		 * fchmod() or chmod(), depending on whether we have
-		 * an fd.  Dirs get their perms set during the
-		 * post-extract fixup, which is handled elsewhere.
-		 */
-#ifdef HAVE_FCHMOD
-		if (a->fd >= 0)
-			r2 = fchmod(a->fd, mode);
-		else
-#endif
-		/* If this platform lacks fchmod(), then
-		 * we'll just use chmod(). */
-		r2 = chmod(a->name, mode);
-
-		if (r2 != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't set permissions to 0%o", (int)mode);
-			r = ARCHIVE_WARN;
-		}
-	}
-	return (r);
-}
-
-static int
-set_fflags(struct archive_write_disk *a)
-{
-	struct fixup_entry *le;
-	unsigned long	set, clear;
-	int		r;
-	mode_t		mode = archive_entry_mode(a->entry);
-	/*
-	 * Make 'critical_flags' hold all file flags that can't be
-	 * immediately restored.  For example, on BSD systems,
-	 * SF_IMMUTABLE prevents hardlinks from being created, so
-	 * should not be set until after any hardlinks are created.  To
-	 * preserve some semblance of portability, this uses #ifdef
-	 * extensively.  Ugly, but it works.
-	 *
-	 * Yes, Virginia, this does create a security race.  It's mitigated
-	 * somewhat by the practice of creating dirs 0700 until the extract
-	 * is done, but it would be nice if we could do more than that.
-	 * People restoring critical file systems should be wary of
-	 * other programs that might try to muck with files as they're
-	 * being restored.
-	 */
-	const int	critical_flags = 0
-#ifdef SF_IMMUTABLE
-	    | SF_IMMUTABLE
-#endif
-#ifdef UF_IMMUTABLE
-	    | UF_IMMUTABLE
-#endif
-#ifdef SF_APPEND
-	    | SF_APPEND
-#endif
-#ifdef UF_APPEND
-	    | UF_APPEND
-#endif
-#if defined(FS_APPEND_FL)
-	    | FS_APPEND_FL
-#elif defined(EXT2_APPEND_FL)
-	    | EXT2_APPEND_FL
-#endif
-#if defined(FS_IMMUTABLE_FL)
-	    | FS_IMMUTABLE_FL
-#elif defined(EXT2_IMMUTABLE_FL)
-	    | EXT2_IMMUTABLE_FL
-#endif
-#ifdef FS_JOURNAL_DATA_FL
-	    | FS_JOURNAL_DATA_FL
-#endif
-	;
-
-	if (a->todo & TODO_FFLAGS) {
-		archive_entry_fflags(a->entry, &set, &clear);
-
-		/*
-		 * The first test encourages the compiler to eliminate
-		 * all of this if it's not necessary.
-		 */
-		if ((critical_flags != 0)  &&  (set & critical_flags)) {
-			le = current_fixup(a, a->name);
-			if (le == NULL)
-				return (ARCHIVE_FATAL);
-			le->filetype = archive_entry_filetype(a->entry);
-			le->fixup |= TODO_FFLAGS;
-			le->fflags_set = set;
-			/* Store the mode if it's not already there. */
-			if ((le->fixup & TODO_MODE) == 0)
-				le->mode = mode;
-		} else {
-			r = set_fflags_platform(a, a->fd,
-			    a->name, mode, set, clear);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-clear_nochange_fflags(struct archive_write_disk *a)
-{
-	mode_t		mode = archive_entry_mode(a->entry);
-	const int nochange_flags = 0
-#ifdef SF_IMMUTABLE
-	    | SF_IMMUTABLE
-#endif
-#ifdef UF_IMMUTABLE
-	    | UF_IMMUTABLE
-#endif
-#ifdef SF_APPEND
-	    | SF_APPEND
-#endif
-#ifdef UF_APPEND
-	    | UF_APPEND
-#endif
-#ifdef EXT2_APPEND_FL
-	    | EXT2_APPEND_FL
-#endif
-#ifdef EXT2_IMMUTABLE_FL
-	    | EXT2_IMMUTABLE_FL
-#endif
-	;
-
-	return (set_fflags_platform(a, a->fd, a->name, mode, 0,
-	    nochange_flags));
-}
-
-
-#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS)
-/*
- * BSD reads flags using stat() and sets them with one of {f,l,}chflags()
- */
-static int
-set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
-    mode_t mode, unsigned long set, unsigned long clear)
-{
-	int r;
-	const int sf_mask = 0
-#ifdef SF_APPEND
-	    | SF_APPEND
-#endif
-#ifdef SF_ARCHIVED
-	    | SF_ARCHIVED
-#endif
-#ifdef SF_IMMUTABLE
-	    | SF_IMMUTABLE
-#endif
-#ifdef SF_NOUNLINK
-	    | SF_NOUNLINK
-#endif
-	;
-	(void)mode; /* UNUSED */
-
-	if (set == 0  && clear == 0)
-		return (ARCHIVE_OK);
-
-	/*
-	 * XXX Is the stat here really necessary?  Or can I just use
-	 * the 'set' flags directly?  In particular, I'm not sure
-	 * about the correct approach if we're overwriting an existing
-	 * file that already has flags on it. XXX
-	 */
-	if ((r = lazy_stat(a)) != ARCHIVE_OK)
-		return (r);
-
-	a->st.st_flags &= ~clear;
-	a->st.st_flags |= set;
-
-	/* Only super-user may change SF_* flags */
-
-	if (a->user_uid != 0)
-		a->st.st_flags &= ~sf_mask;
-
-#ifdef HAVE_FCHFLAGS
-	/* If platform has fchflags() and we were given an fd, use it. */
-	if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0)
-		return (ARCHIVE_OK);
-#endif
-	/*
-	 * If we can't use the fd to set the flags, we'll use the
-	 * pathname to set flags.  We prefer lchflags() but will use
-	 * chflags() if we must.
-	 */
-#ifdef HAVE_LCHFLAGS
-	if (lchflags(name, a->st.st_flags) == 0)
-		return (ARCHIVE_OK);
-#elif defined(HAVE_CHFLAGS)
-	if (S_ISLNK(a->st.st_mode)) {
-		archive_set_error(&a->archive, errno,
-		    "Can't set file flags on symlink.");
-		return (ARCHIVE_WARN);
-	}
-	if (chflags(name, a->st.st_flags) == 0)
-		return (ARCHIVE_OK);
-#endif
-	archive_set_error(&a->archive, errno,
-	    "Failed to set file flags");
-	return (ARCHIVE_WARN);
-}
-
-#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
-       defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
-      (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
-       defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
-/*
- * Linux uses ioctl() to read and write file flags.
- */
-static int
-set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
-    mode_t mode, unsigned long set, unsigned long clear)
-{
-	int		 ret;
-	int		 myfd = fd;
-	int newflags, oldflags;
-	/*
-	 * Linux has no define for the flags that are only settable by
-	 * the root user.  This code may seem a little complex, but
-	 * there seem to be some Linux systems that lack these
-	 * defines. (?)  The code below degrades reasonably gracefully
-	 * if sf_mask is incomplete.
-	 */
-	const int sf_mask = 0
-#if defined(FS_IMMUTABLE_FL)
-	    | FS_IMMUTABLE_FL
-#elif defined(EXT2_IMMUTABLE_FL)
-	    | EXT2_IMMUTABLE_FL
-#endif
-#if defined(FS_APPEND_FL)
-	    | FS_APPEND_FL
-#elif defined(EXT2_APPEND_FL)
-	    | EXT2_APPEND_FL
-#endif
-#if defined(FS_JOURNAL_DATA_FL)
-	    | FS_JOURNAL_DATA_FL
-#endif
-	;
-
-	if (set == 0 && clear == 0)
-		return (ARCHIVE_OK);
-	/* Only regular files and dirs can have flags. */
-	if (!S_ISREG(mode) && !S_ISDIR(mode))
-		return (ARCHIVE_OK);
-
-	/* If we weren't given an fd, open it ourselves. */
-	if (myfd < 0) {
-		myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
-		    O_CLOEXEC | O_NOFOLLOW);
-		__archive_ensure_cloexec_flag(myfd);
-	}
-	if (myfd < 0)
-		return (ARCHIVE_OK);
-
-	/*
-	 * XXX As above, this would be way simpler if we didn't have
-	 * to read the current flags from disk. XXX
-	 */
-	ret = ARCHIVE_OK;
-
-	/* Read the current file flags. */
-	if (ioctl(myfd,
-#ifdef FS_IOC_GETFLAGS
-	    FS_IOC_GETFLAGS,
-#else
-	    EXT2_IOC_GETFLAGS,
-#endif
-	    &oldflags) < 0)
-		goto fail;
-
-	/* Try setting the flags as given. */
-	newflags = (oldflags & ~clear) | set;
-	if (ioctl(myfd,
-#ifdef FS_IOC_SETFLAGS
-	    FS_IOC_SETFLAGS,
-#else
-	    EXT2_IOC_SETFLAGS,
-#endif
-	    &newflags) >= 0)
-		goto cleanup;
-	if (errno != EPERM)
-		goto fail;
-
-	/* If we couldn't set all the flags, try again with a subset. */
-	newflags &= ~sf_mask;
-	oldflags &= sf_mask;
-	newflags |= oldflags;
-	if (ioctl(myfd,
-#ifdef FS_IOC_SETFLAGS
-	    FS_IOC_SETFLAGS,
-#else
-	    EXT2_IOC_SETFLAGS,
-#endif
-	    &newflags) >= 0)
-		goto cleanup;
-
-	/* We couldn't set the flags, so report the failure. */
-fail:
-	archive_set_error(&a->archive, errno,
-	    "Failed to set file flags");
-	ret = ARCHIVE_WARN;
-cleanup:
-	if (fd < 0)
-		close(myfd);
-	return (ret);
-}
-
-#else
-
-/*
- * Of course, some systems have neither BSD chflags() nor Linux' flags
- * support through ioctl().
- */
-static int
-set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
-    mode_t mode, unsigned long set, unsigned long clear)
-{
-	(void)a; /* UNUSED */
-	(void)fd; /* UNUSED */
-	(void)name; /* UNUSED */
-	(void)mode; /* UNUSED */
-	(void)set; /* UNUSED */
-	(void)clear; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-#endif /* __linux */
-
-#ifndef HAVE_COPYFILE_H
-/* Default is to simply drop Mac extended metadata. */
-static int
-set_mac_metadata(struct archive_write_disk *a, const char *pathname,
-		 const void *metadata, size_t metadata_size)
-{
-	(void)a; /* UNUSED */
-	(void)pathname; /* UNUSED */
-	(void)metadata; /* UNUSED */
-	(void)metadata_size; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-static int
-fixup_appledouble(struct archive_write_disk *a, const char *pathname)
-{
-	(void)a; /* UNUSED */
-	(void)pathname; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-#else
-
-/*
- * On Mac OS, we use copyfile() to unpack the metadata and
- * apply it to the target file.
- */
-
-#if defined(HAVE_SYS_XATTR_H)
-static int
-copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd)
-{
-	ssize_t xattr_size;
-	char *xattr_names = NULL, *xattr_val = NULL;
-	int ret = ARCHIVE_OK, xattr_i;
-
-	xattr_size = flistxattr(tmpfd, NULL, 0, 0);
-	if (xattr_size == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to read metadata(xattr)");
-		ret = ARCHIVE_WARN;
-		goto exit_xattr;
-	}
-	xattr_names = malloc(xattr_size);
-	if (xattr_names == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for metadata(xattr)");
-		ret = ARCHIVE_FATAL;
-		goto exit_xattr;
-	}
-	xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0);
-	if (xattr_size == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to read metadata(xattr)");
-		ret = ARCHIVE_WARN;
-		goto exit_xattr;
-	}
-	for (xattr_i = 0; xattr_i < xattr_size;
-	    xattr_i += strlen(xattr_names + xattr_i) + 1) {
-		char *xattr_val_saved;
-		ssize_t s;
-		int f;
-
-		s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0);
-		if (s == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get metadata(xattr)");
-			ret = ARCHIVE_WARN;
-			goto exit_xattr;
-		}
-		xattr_val_saved = xattr_val;
-		xattr_val = realloc(xattr_val, s);
-		if (xattr_val == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Failed to get metadata(xattr)");
-			ret = ARCHIVE_WARN;
-			free(xattr_val_saved);
-			goto exit_xattr;
-		}
-		s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0);
-		if (s == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get metadata(xattr)");
-			ret = ARCHIVE_WARN;
-			goto exit_xattr;
-		}
-		f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0);
-		if (f == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to get metadata(xattr)");
-			ret = ARCHIVE_WARN;
-			goto exit_xattr;
-		}
-	}
-exit_xattr:
-	free(xattr_names);
-	free(xattr_val);
-	return (ret);
-}
-#endif
-
-static int
-copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
-{
-#ifndef HAVE_SYS_ACL_H
-	return 0;
-#else
-	acl_t acl, dfacl = NULL;
-	int acl_r, ret = ARCHIVE_OK;
-
-	acl = acl_get_fd(tmpfd);
-	if (acl == NULL) {
-		if (errno == ENOENT)
-			/* There are not any ACLs. */
-			return (ret);
-		archive_set_error(&a->archive, errno,
-		    "Failed to get metadata(acl)");
-		ret = ARCHIVE_WARN;
-		goto exit_acl;
-	}
-	dfacl = acl_dup(acl);
-	acl_r = acl_set_fd(dffd, dfacl);
-	if (acl_r == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to get metadata(acl)");
-		ret = ARCHIVE_WARN;
-		goto exit_acl;
-	}
-exit_acl:
-	if (acl)
-		acl_free(acl);
-	if (dfacl)
-		acl_free(dfacl);
-	return (ret);
-#endif
-}
-
-static int
-create_tempdatafork(struct archive_write_disk *a, const char *pathname)
-{
-	struct archive_string tmpdatafork;
-	int tmpfd;
-
-	archive_string_init(&tmpdatafork);
-	archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
-	tmpfd = mkstemp(tmpdatafork.s);
-	if (tmpfd < 0) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to mkstemp");
-		archive_string_free(&tmpdatafork);
-		return (-1);
-	}
-	if (copyfile(pathname, tmpdatafork.s, 0,
-	    COPYFILE_UNPACK | COPYFILE_NOFOLLOW
-	    | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to restore metadata");
-		close(tmpfd);
-		tmpfd = -1;
-	}
-	unlink(tmpdatafork.s);
-	archive_string_free(&tmpdatafork);
-	return (tmpfd);
-}
-
-static int
-copy_metadata(struct archive_write_disk *a, const char *metadata,
-    const char *datafork, int datafork_compressed)
-{
-	int ret = ARCHIVE_OK;
-
-	if (datafork_compressed) {
-		int dffd, tmpfd;
-
-		tmpfd = create_tempdatafork(a, metadata);
-		if (tmpfd == -1)
-			return (ARCHIVE_WARN);
-
-		/*
-		 * Do not open the data fork compressed by HFS+ compression
-		 * with at least a writing mode(O_RDWR or O_WRONLY). it
-		 * makes the data fork uncompressed.
-		 */
-		dffd = open(datafork, 0);
-		if (dffd == -1) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to open the data fork for metadata");
-			close(tmpfd);
-			return (ARCHIVE_WARN);
-		}
-
-#if defined(HAVE_SYS_XATTR_H)
-		ret = copy_xattrs(a, tmpfd, dffd);
-		if (ret == ARCHIVE_OK)
-#endif
-			ret = copy_acls(a, tmpfd, dffd);
-		close(tmpfd);
-		close(dffd);
-	} else {
-		if (copyfile(metadata, datafork, 0,
-		    COPYFILE_UNPACK | COPYFILE_NOFOLLOW
-		    | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Failed to restore metadata");
-			ret = ARCHIVE_WARN;
-		}
-	}
-	return (ret);
-}
-
-static int
-set_mac_metadata(struct archive_write_disk *a, const char *pathname,
-		 const void *metadata, size_t metadata_size)
-{
-	struct archive_string tmp;
-	ssize_t written;
-	int fd;
-	int ret = ARCHIVE_OK;
-
-	/* This would be simpler if copyfile() could just accept the
-	 * metadata as a block of memory; then we could sidestep this
-	 * silly dance of writing the data to disk just so that
-	 * copyfile() can read it back in again. */
-	archive_string_init(&tmp);
-	archive_strcpy(&tmp, pathname);
-	archive_strcat(&tmp, ".XXXXXX");
-	fd = mkstemp(tmp.s);
-
-	if (fd < 0) {
-		archive_set_error(&a->archive, errno,
-				  "Failed to restore metadata");
-		archive_string_free(&tmp);
-		return (ARCHIVE_WARN);
-	}
-	written = write(fd, metadata, metadata_size);
-	close(fd);
-	if ((size_t)written != metadata_size) {
-		archive_set_error(&a->archive, errno,
-				  "Failed to restore metadata");
-		ret = ARCHIVE_WARN;
-	} else {
-		int compressed;
-
-#if defined(UF_COMPRESSED)
-		if ((a->todo & TODO_HFS_COMPRESSION) != 0 &&
-		    (ret = lazy_stat(a)) == ARCHIVE_OK)
-			compressed = a->st.st_flags & UF_COMPRESSED;
-		else
-#endif
-			compressed = 0;
-		ret = copy_metadata(a, tmp.s, pathname, compressed);
-	}
-	unlink(tmp.s);
-	archive_string_free(&tmp);
-	return (ret);
-}
-
-static int
-fixup_appledouble(struct archive_write_disk *a, const char *pathname)
-{
-	char buff[8];
-	struct stat st;
-	const char *p;
-	struct archive_string datafork;
-	int fd = -1, ret = ARCHIVE_OK;
-
-	archive_string_init(&datafork);
-	/* Check if the current file name is a type of the resource
-	 * fork file. */
-	p = strrchr(pathname, '/');
-	if (p == NULL)
-		p = pathname;
-	else
-		p++;
-	if (p[0] != '.' || p[1] != '_')
-		goto skip_appledouble;
-
-	/*
-	 * Check if the data fork file exists.
-	 *
-	 * TODO: Check if this write disk object has handled it.
-	 */
-	archive_strncpy(&datafork, pathname, p - pathname);
-	archive_strcat(&datafork, p + 2);
-	if (
-#ifdef HAVE_LSTAT
-		lstat(datafork.s, &st) == -1 ||
-#else
-		la_stat(datafork.s, &st) == -1 ||
-#endif
-	    (st.st_mode & AE_IFMT) != AE_IFREG)
-		goto skip_appledouble;
-
-	/*
-	 * Check if the file is in the AppleDouble form.
-	 */
-	fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
-	__archive_ensure_cloexec_flag(fd);
-	if (fd == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to open a restoring file");
-		ret = ARCHIVE_WARN;
-		goto skip_appledouble;
-	}
-	if (read(fd, buff, 8) == -1) {
-		archive_set_error(&a->archive, errno,
-		    "Failed to read a restoring file");
-		close(fd);
-		ret = ARCHIVE_WARN;
-		goto skip_appledouble;
-	}
-	close(fd);
-	/* Check AppleDouble Magic Code. */
-	if (archive_be32dec(buff) != 0x00051607)
-		goto skip_appledouble;
-	/* Check AppleDouble Version. */
-	if (archive_be32dec(buff+4) != 0x00020000)
-		goto skip_appledouble;
-
-	ret = copy_metadata(a, pathname, datafork.s,
-#if defined(UF_COMPRESSED)
-	    st.st_flags & UF_COMPRESSED);
-#else
-	    0);
-#endif
-	if (ret == ARCHIVE_OK) {
-		unlink(pathname);
-		ret = ARCHIVE_EOF;
-	}
-skip_appledouble:
-	archive_string_free(&datafork);
-	return (ret);
-}
-#endif
-
-#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
-/*
- * Restore extended attributes -  Linux, Darwin and AIX implementations:
- * AIX' ea interface is syntaxwise identical to the Linux xattr interface.
- */
-static int
-set_xattrs(struct archive_write_disk *a)
-{
-	struct archive_entry *entry = a->entry;
-	struct archive_string errlist;
-	int ret = ARCHIVE_OK;
-	int i = archive_entry_xattr_reset(entry);
-	short fail = 0;
-
-	archive_string_init(&errlist);
-
-	while (i--) {
-		const char *name;
-		const void *value;
-		size_t size;
-		int e;
-
-		archive_entry_xattr_next(entry, &name, &value, &size);
-
-		if (name == NULL)
-			continue;
-#if ARCHIVE_XATTR_LINUX
-		/* Linux: quietly skip POSIX.1e ACL extended attributes */
-		if (strncmp(name, "system.", 7) == 0 &&
-		   (strcmp(name + 7, "posix_acl_access") == 0 ||
-		    strcmp(name + 7, "posix_acl_default") == 0))
-			continue;
-		if (strncmp(name, "trusted.SGI_", 12) == 0 &&
-		   (strcmp(name + 12, "ACL_DEFAULT") == 0 ||
-		    strcmp(name + 12, "ACL_FILE") == 0))
-			continue;
-
-		/* Linux: xfsroot namespace is obsolete and unsupported */
-		if (strncmp(name, "xfsroot.", 8) == 0) {
-			fail = 1;
-			archive_strcat(&errlist, name);
-			archive_strappend_char(&errlist, ' ');
-			continue;
-		}
-#endif
-
-		if (a->fd >= 0) {
-#if ARCHIVE_XATTR_LINUX
-			e = fsetxattr(a->fd, name, value, size, 0);
-#elif ARCHIVE_XATTR_DARWIN
-			e = fsetxattr(a->fd, name, value, size, 0, 0);
-#elif ARCHIVE_XATTR_AIX
-			e = fsetea(a->fd, name, value, size, 0);
-#endif
-		} else {
-#if ARCHIVE_XATTR_LINUX
-			e = lsetxattr(archive_entry_pathname(entry),
-			    name, value, size, 0);
-#elif ARCHIVE_XATTR_DARWIN
-			e = setxattr(archive_entry_pathname(entry),
-			    name, value, size, 0, XATTR_NOFOLLOW);
-#elif ARCHIVE_XATTR_AIX
-			e = lsetea(archive_entry_pathname(entry),
-			    name, value, size, 0);
-#endif
-		}
-		if (e == -1) {
-			ret = ARCHIVE_WARN;
-			archive_strcat(&errlist, name);
-			archive_strappend_char(&errlist, ' ');
-			if (errno != ENOTSUP && errno != ENOSYS)
-				fail = 1;
-		}
-	}
-
-	if (ret == ARCHIVE_WARN) {
-		if (fail && errlist.length > 0) {
-			errlist.length--;
-			errlist.s[errlist.length] = '\0';
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Cannot restore extended attributes: %s",
-			    errlist.s);
-		} else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Cannot restore extended "
-			    "attributes on this file system.");
-	}
-
-	archive_string_free(&errlist);
-	return (ret);
-}
-#elif ARCHIVE_XATTR_FREEBSD
-/*
- * Restore extended attributes -  FreeBSD implementation
- */
-static int
-set_xattrs(struct archive_write_disk *a)
-{
-	struct archive_entry *entry = a->entry;
-	struct archive_string errlist;
-	int ret = ARCHIVE_OK;
-	int i = archive_entry_xattr_reset(entry);
-	short fail = 0;
-
-	archive_string_init(&errlist);
-
-	while (i--) {
-		const char *name;
-		const void *value;
-		size_t size;
-		archive_entry_xattr_next(entry, &name, &value, &size);
-		if (name != NULL) {
-			int e;
-			int namespace;
-
-			namespace = EXTATTR_NAMESPACE_USER;
-
-			if (strncmp(name, "user.", 5) == 0) {
-				/* "user." attributes go to user namespace */
-				name += 5;
-				namespace = EXTATTR_NAMESPACE_USER;
-			} else if (strncmp(name, "system.", 7) == 0) {
-				name += 7;
-				namespace = EXTATTR_NAMESPACE_SYSTEM;
-				if (!strcmp(name, "nfs4.acl") ||
-				    !strcmp(name, "posix1e.acl_access") ||
-				    !strcmp(name, "posix1e.acl_default"))
-					continue;
-			} else {
-				/* Other namespaces are unsupported */
-				archive_strcat(&errlist, name);
-				archive_strappend_char(&errlist, ' ');
-				fail = 1;
-				ret = ARCHIVE_WARN;
-				continue;
-			}
-
-			if (a->fd >= 0) {
-				/*
-				 * On FreeBSD, extattr_set_fd does not
-				 * return the same as
-				 * extattr_set_file. It returns zero
-				 * on success, non-zero on failure.
-				 *
-				 * We can detect the failure by
-				 * manually setting errno prior to the
-				 * call and checking after.
-				 *
-				 * If errno remains zero, fake the
-				 * return value by setting e to size.
-				 *
-				 * This is a hack for now until I
-				 * (Shawn Webb) get FreeBSD to fix the
-				 * issue, if that's even possible.
-				 */
-				errno = 0;
-				e = extattr_set_fd(a->fd, namespace, name,
-				    value, size);
-				if (e == 0 && errno == 0) {
-					e = size;
-				}
-			} else {
-				e = extattr_set_link(
-				    archive_entry_pathname(entry), namespace,
-				    name, value, size);
-			}
-			if (e != (int)size) {
-				archive_strcat(&errlist, name);
-				archive_strappend_char(&errlist, ' ');
-				ret = ARCHIVE_WARN;
-				if (errno != ENOTSUP && errno != ENOSYS)
-					fail = 1;
-			}
-		}
-	}
-
-	if (ret == ARCHIVE_WARN) {
-		if (fail && errlist.length > 0) {
-			errlist.length--;
-			errlist.s[errlist.length] = '\0';
-
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Cannot restore extended attributes: %s",
-			    errlist.s);
-		} else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Cannot restore extended "
-			    "attributes on this file system.");
-	}
-
-	archive_string_free(&errlist);
-	return (ret);
-}
-#else
-/*
- * Restore extended attributes - stub implementation for unsupported systems
- */
-static int
-set_xattrs(struct archive_write_disk *a)
-{
-	static int warning_done = 0;
-
-	/* If there aren't any extended attributes, then it's okay not
-	 * to extract them, otherwise, issue a single warning. */
-	if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
-		warning_done = 1;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Cannot restore extended attributes on this system");
-		return (ARCHIVE_WARN);
-	}
-	/* Warning was already emitted; suppress further warnings. */
-	return (ARCHIVE_OK);
-}
-#endif
-
-/*
- * Test if file on disk is older than entry.
- */
-static int
-older(struct stat *st, struct archive_entry *entry)
-{
-	/* First, test the seconds and return if we have a definite answer. */
-	/* Definitely older. */
-	if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
-		return (1);
-	/* Definitely younger. */
-	if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
-		return (0);
-	/* If this platform supports fractional seconds, try those. */
-#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
-	/* Definitely older. */
-	if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry))
-		return (1);
-#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-	/* Definitely older. */
-	if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry))
-		return (1);
-#elif HAVE_STRUCT_STAT_ST_MTIME_N
-	/* older. */
-	if (st->st_mtime_n < archive_entry_mtime_nsec(entry))
-		return (1);
-#elif HAVE_STRUCT_STAT_ST_UMTIME
-	/* older. */
-	if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry))
-		return (1);
-#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
-	/* older. */
-	if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry))
-		return (1);
-#else
-	/* This system doesn't have high-res timestamps. */
-#endif
-	/* Same age or newer, so not older. */
-	return (0);
-}
-
-#ifndef ARCHIVE_ACL_SUPPORT
-int
-archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
-    struct archive_acl *abstract_acl, __LA_MODE_T mode)
-{
-	(void)a; /* UNUSED */
-	(void)fd; /* UNUSED */
-	(void)name; /* UNUSED */
-	(void)abstract_acl; /* UNUSED */
-	(void)mode; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-#endif
-
-/*
- * Close the file descriptor if one is open.
- */
-static void close_file_descriptor(struct archive_write_disk* a)
-{
-	if (a->fd >= 0) {
-		close(a->fd);
-		a->fd = -1;
-	}
-}
-
-
-#endif /* !_WIN32 || __CYGWIN__ */
-
diff --git a/c/archive_write_disk_private.h b/c/archive_write_disk_private.h
deleted file mode 100644
--- a/c/archive_write_disk_private.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_write_disk_private.h 201086 2009-12-28 02:17:53Z kientzle $
- */
-
-#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
-#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#include "archive_platform_acl.h"
-#include "archive_acl_private.h"
-#include "archive_entry.h"
-
-struct archive_write_disk;
-
-int archive_write_disk_set_acls(struct archive *, int, const char *,
-    struct archive_acl *, __LA_MODE_T);
-
-#endif
diff --git a/c/archive_write_disk_set_standard_lookup.c b/c/archive_write_disk_set_standard_lookup.c
deleted file mode 100644
--- a/c/archive_write_disk_set_standard_lookup.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk_set_standard_lookup.c 201083 2009-12-28 02:09:57Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_read_private.h"
-#include "archive_write_disk_private.h"
-
-struct bucket {
-	char	*name;
-	int	 hash;
-	id_t	 id;
-};
-
-static const size_t cache_size = 127;
-static unsigned int	hash(const char *);
-static int64_t	lookup_gid(void *, const char *uname, int64_t);
-static int64_t	lookup_uid(void *, const char *uname, int64_t);
-static void	cleanup(void *);
-
-/*
- * Installs functions that use getpwnam()/getgrnam()---along with
- * a simple cache to accelerate such lookups---into the archive_write_disk
- * object.  This is in a separate file because getpwnam()/getgrnam()
- * can pull in a LOT of library code (including NIS/LDAP functions, which
- * pull in DNS resolvers, etc).  This can easily top 500kB, which makes
- * it inappropriate for some space-constrained applications.
- *
- * Applications that are size-sensitive may want to just use the
- * real default functions (defined in archive_write_disk.c) that just
- * use the uid/gid without the lookup.  Or define your own custom functions
- * if you prefer.
- *
- * TODO: Replace these hash tables with simpler move-to-front LRU
- * lists with a bounded size (128 items?).  The hash is a bit faster,
- * but has a bad pathology in which it thrashes a single bucket.  Even
- * walking a list of 128 items is a lot faster than calling
- * getpwnam()!
- */
-int
-archive_write_disk_set_standard_lookup(struct archive *a)
-{
-	struct bucket *ucache = calloc(cache_size, sizeof(struct bucket));
-	struct bucket *gcache = calloc(cache_size, sizeof(struct bucket));
-	if (ucache == NULL || gcache == NULL) {
-		free(ucache);
-		free(gcache);
-		return (ARCHIVE_FATAL);
-	}
-	archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
-	archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
-	return (ARCHIVE_OK);
-}
-
-static int64_t
-lookup_gid(void *private_data, const char *gname, int64_t gid)
-{
-	int h;
-	struct bucket *b;
-	struct bucket *gcache = (struct bucket *)private_data;
-
-	/* If no gname, just use the gid provided. */
-	if (gname == NULL || *gname == '\0')
-		return (gid);
-
-	/* Try to find gname in the cache. */
-	h = hash(gname);
-	b = &gcache[h % cache_size ];
-	if (b->name != NULL && b->hash == h && strcmp(gname, b->name) == 0)
-		return ((gid_t)b->id);
-
-	/* Free the cache slot for a new entry. */
-	free(b->name);
-	b->name = strdup(gname);
-	/* Note: If strdup fails, that's okay; we just won't cache. */
-	b->hash = h;
-#if HAVE_GRP_H
-#  if HAVE_GETGRNAM_R
-	{
-		char _buffer[128];
-		size_t bufsize = 128;
-		char *buffer = _buffer;
-		char *allocated = NULL;
-		struct group	grent, *result;
-		int r;
-
-		for (;;) {
-			result = &grent; /* Old getgrnam_r ignores last arg. */
-			r = getgrnam_r(gname, &grent, buffer, bufsize, &result);
-			if (r == 0)
-				break;
-			if (r != ERANGE)
-				break;
-			bufsize *= 2;
-			free(allocated);
-			allocated = malloc(bufsize);
-			if (allocated == NULL)
-				break;
-			buffer = allocated;
-		}
-		if (result != NULL)
-			gid = result->gr_gid;
-		free(allocated);
-	}
-#  else /* HAVE_GETGRNAM_R */
-	{
-		struct group *result;
-
-		result = getgrnam(gname);
-		if (result != NULL)
-			gid = result->gr_gid;
-	}
-#  endif /* HAVE_GETGRNAM_R */
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-	/* TODO: do a gname->gid lookup for Windows. */
-#else
-	#error No way to perform gid lookups on this platform
-#endif
-	b->id = (gid_t)gid;
-
-	return (gid);
-}
-
-static int64_t
-lookup_uid(void *private_data, const char *uname, int64_t uid)
-{
-	int h;
-	struct bucket *b;
-	struct bucket *ucache = (struct bucket *)private_data;
-
-	/* If no uname, just use the uid provided. */
-	if (uname == NULL || *uname == '\0')
-		return (uid);
-
-	/* Try to find uname in the cache. */
-	h = hash(uname);
-	b = &ucache[h % cache_size ];
-	if (b->name != NULL && b->hash == h && strcmp(uname, b->name) == 0)
-		return ((uid_t)b->id);
-
-	/* Free the cache slot for a new entry. */
-	free(b->name);
-	b->name = strdup(uname);
-	/* Note: If strdup fails, that's okay; we just won't cache. */
-	b->hash = h;
-#if HAVE_PWD_H
-#  if HAVE_GETPWNAM_R
-	{
-		char _buffer[128];
-		size_t bufsize = 128;
-		char *buffer = _buffer;
-		char *allocated = NULL;
-		struct passwd	pwent, *result;
-		int r;
-
-		for (;;) {
-			result = &pwent; /* Old getpwnam_r ignores last arg. */
-			r = getpwnam_r(uname, &pwent, buffer, bufsize, &result);
-			if (r == 0)
-				break;
-			if (r != ERANGE)
-				break;
-			bufsize *= 2;
-			free(allocated);
-			allocated = malloc(bufsize);
-			if (allocated == NULL)
-				break;
-			buffer = allocated;
-		}
-		if (result != NULL)
-			uid = result->pw_uid;
-		free(allocated);
-	}
-#  else /* HAVE_GETPWNAM_R */
-	{
-		struct passwd *result;
-
-		result = getpwnam(uname);
-		if (result != NULL)
-			uid = result->pw_uid;
-	}
-#endif	/* HAVE_GETPWNAM_R */
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-	/* TODO: do a uname->uid lookup for Windows. */
-#else
-	#error No way to look up uids on this platform
-#endif
-	b->id = (uid_t)uid;
-
-	return (uid);
-}
-
-static void
-cleanup(void *private)
-{
-	size_t i;
-	struct bucket *cache = (struct bucket *)private;
-
-	for (i = 0; i < cache_size; i++)
-		free(cache[i].name);
-	free(cache);
-}
-
-
-static unsigned int
-hash(const char *p)
-{
-	/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
-	   as used by ELF for hashing function names. */
-	unsigned g, h = 0;
-	while (*p != '\0') {
-		h = (h << 4) + *p++;
-		if ((g = h & 0xF0000000) != 0) {
-			h ^= g >> 24;
-			h &= 0x0FFFFFFF;
-		}
-	}
-	return h;
-}
diff --git a/c/archive_write_disk_windows.c b/c/archive_write_disk_windows.c
deleted file mode 100644
--- a/c/archive_write_disk_windows.c
+++ /dev/null
@@ -1,2911 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <winioctl.h>
-
-/* TODO: Support Mac OS 'quarantine' feature.  This is really just a
- * standard tag to mark files that have been downloaded as "tainted".
- * On Mac OS, we should mark the extracted files as tainted if the
- * archive being read was tainted.  Windows has a similar feature; we
- * should investigate ways to support this generically. */
-
-#include "archive.h"
-#include "archive_acl_private.h"
-#include "archive_string.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef IO_REPARSE_TAG_SYMLINK
-/* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
-#define	IO_REPARSE_TAG_SYMLINK 0xA000000CL
-#endif
-
-static BOOL SetFilePointerEx_perso(HANDLE hFile,
-                             LARGE_INTEGER liDistanceToMove,
-                             PLARGE_INTEGER lpNewFilePointer,
-                             DWORD dwMoveMethod)
-{
-	LARGE_INTEGER li;
-	li.QuadPart = liDistanceToMove.QuadPart;
-	li.LowPart = SetFilePointer(
-	    hFile, li.LowPart, &li.HighPart, dwMoveMethod);
-	if(lpNewFilePointer) {
-		lpNewFilePointer->QuadPart = li.QuadPart;
-	}
-	return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR;
-}
-
-struct fixup_entry {
-	struct fixup_entry	*next;
-	struct archive_acl	 acl;
-	mode_t			 mode;
-	int64_t			 atime;
-	int64_t                  birthtime;
-	int64_t			 mtime;
-	int64_t			 ctime;
-	unsigned long		 atime_nanos;
-	unsigned long            birthtime_nanos;
-	unsigned long		 mtime_nanos;
-	unsigned long		 ctime_nanos;
-	unsigned long		 fflags_set;
-	int			 fixup; /* bitmask of what needs fixing */
-	wchar_t			*name;
-};
-
-/*
- * We use a bitmask to track which operations remain to be done for
- * this file.  In particular, this helps us avoid unnecessary
- * operations when it's possible to take care of one step as a
- * side-effect of another.  For example, mkdir() can specify the mode
- * for the newly-created object but symlink() cannot.  This means we
- * can skip chmod() if mkdir() succeeded, but we must explicitly
- * chmod() if we're trying to create a directory that already exists
- * (mkdir() failed) or if we're restoring a symlink.  Similarly, we
- * need to verify UID/GID before trying to restore SUID/SGID bits;
- * that verification can occur explicitly through a stat() call or
- * implicitly because of a successful chown() call.
- */
-#define	TODO_MODE_FORCE		0x40000000
-#define	TODO_MODE_BASE		0x20000000
-#define	TODO_SUID		0x10000000
-#define	TODO_SUID_CHECK		0x08000000
-#define	TODO_SGID		0x04000000
-#define	TODO_SGID_CHECK		0x02000000
-#define	TODO_MODE		(TODO_MODE_BASE|TODO_SUID|TODO_SGID)
-#define	TODO_TIMES		ARCHIVE_EXTRACT_TIME
-#define	TODO_OWNER		ARCHIVE_EXTRACT_OWNER
-#define	TODO_FFLAGS		ARCHIVE_EXTRACT_FFLAGS
-#define	TODO_ACLS		ARCHIVE_EXTRACT_ACL
-#define	TODO_XATTR		ARCHIVE_EXTRACT_XATTR
-#define	TODO_MAC_METADATA	ARCHIVE_EXTRACT_MAC_METADATA
-
-struct archive_write_disk {
-	struct archive	archive;
-
-	mode_t			 user_umask;
-	struct fixup_entry	*fixup_list;
-	struct fixup_entry	*current_fixup;
-	int64_t			 user_uid;
-	int			 skip_file_set;
-	int64_t			 skip_file_dev;
-	int64_t			 skip_file_ino;
-	time_t			 start_time;
-
-	int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
-	void  (*cleanup_gid)(void *private);
-	void			*lookup_gid_data;
-	int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
-	void  (*cleanup_uid)(void *private);
-	void			*lookup_uid_data;
-
-	/*
-	 * Full path of last file to satisfy symlink checks.
-	 */
-	struct archive_wstring	path_safe;
-
-	/*
-	 * Cached stat data from disk for the current entry.
-	 * If this is valid, pst points to st.  Otherwise,
-	 * pst is null.
-	 */
-	BY_HANDLE_FILE_INFORMATION		 st;
-	BY_HANDLE_FILE_INFORMATION		*pst;
-
-	/* Information about the object being restored right now. */
-	struct archive_entry	*entry; /* Entry being extracted. */
-	wchar_t			*name; /* Name of entry, possibly edited. */
-	struct archive_wstring	 _name_data; /* backing store for 'name' */
-	wchar_t			*tmpname; /* Temporary name */
-	struct archive_wstring	_tmpname_data; /* backing store for 'tmpname' */
-	/* Tasks remaining for this object. */
-	int			 todo;
-	/* Tasks deferred until end-of-archive. */
-	int			 deferred;
-	/* Options requested by the client. */
-	int			 flags;
-	/* Handle for the file we're restoring. */
-	HANDLE		 fh;
-	/* Current offset for writing data to the file. */
-	int64_t			 offset;
-	/* Last offset actually written to disk. */
-	int64_t			 fd_offset;
-	/* Total bytes actually written to files. */
-	int64_t			 total_bytes_written;
-	/* Maximum size of file, -1 if unknown. */
-	int64_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. */
-	mode_t			 mode;
-	/* UID/GID to use in restoring this entry. */
-	int64_t			 uid;
-	int64_t			 gid;
-};
-
-/*
- * Default mode for dirs created automatically (will be modified by umask).
- * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
- * by the process' file creation mask."
- */
-#define	DEFAULT_DIR_MODE 0777
-/*
- * Dir modes are restored in two steps:  During the extraction, the permissions
- * in the archive are modified to match the following limits.  During
- * the post-extract fixup pass, the permissions from the archive are
- * applied.
- */
-#define	MINIMUM_DIR_MODE 0700
-#define	MAXIMUM_DIR_MODE 0775
-
-static int	disk_unlink(const wchar_t *);
-static int	disk_rmdir(const wchar_t *);
-static int	check_symlinks(struct archive_write_disk *);
-static int	create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *,
-		    const wchar_t *pathname);
-static int	cleanup_pathname(struct archive_write_disk *, wchar_t *);
-static int	create_dir(struct archive_write_disk *, wchar_t *);
-static int	create_parent_dir(struct archive_write_disk *, wchar_t *);
-static int	la_chmod(const wchar_t *, mode_t);
-static int	la_mktemp(struct archive_write_disk *);
-static int	older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *);
-static int	permissive_name_w(struct archive_write_disk *);
-static int	restore_entry(struct archive_write_disk *);
-static int	set_acls(struct archive_write_disk *, HANDLE h,
-		    const wchar_t *, struct archive_acl *);
-static int	set_xattrs(struct archive_write_disk *);
-static int	clear_nochange_fflags(struct archive_write_disk *);
-static int	set_fflags(struct archive_write_disk *);
-static int	set_fflags_platform(const wchar_t *, unsigned long,
-		    unsigned long);
-static int	set_ownership(struct archive_write_disk *);
-static int	set_mode(struct archive_write_disk *, int mode);
-static int	set_times(struct archive_write_disk *, HANDLE, int,
-		    const wchar_t *, time_t, long, time_t, long, time_t,
-		    long, time_t, long);
-static int	set_times_from_entry(struct archive_write_disk *);
-static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
-static ssize_t	write_data_block(struct archive_write_disk *,
-		    const char *, size_t);
-
-static int	_archive_write_disk_close(struct archive *);
-static int	_archive_write_disk_free(struct archive *);
-static int	_archive_write_disk_header(struct archive *,
-		    struct archive_entry *);
-static int64_t	_archive_write_disk_filter_bytes(struct archive *, int);
-static int	_archive_write_disk_finish_entry(struct archive *);
-static ssize_t	_archive_write_disk_data(struct archive *, const void *,
-		    size_t);
-static ssize_t	_archive_write_disk_data_block(struct archive *, const void *,
-		    size_t, int64_t);
-
-#define bhfi_dev(bhfi)	((bhfi)->dwVolumeSerialNumber)
-/* Treat FileIndex as i-node. We should remove a sequence number
- * which is high-16-bits of nFileIndexHigh. */
-#define bhfi_ino(bhfi)	\
-	((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \
-    | (bhfi)->nFileIndexLow)
-#define bhfi_size(bhfi)	\
-    ((((int64_t)(bhfi)->nFileSizeHigh) << 32) | (bhfi)->nFileSizeLow)
-
-static int
-file_information(struct archive_write_disk *a, wchar_t *path,
-    BY_HANDLE_FILE_INFORMATION *st, mode_t *mode, int sim_lstat)
-{
-	HANDLE h;
-	int r;
-	DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
-	WIN32_FIND_DATAW	findData;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-	if (sim_lstat || mode != NULL) {
-		h = FindFirstFileW(path, &findData);
-		if (h == INVALID_HANDLE_VALUE &&
-		    GetLastError() == ERROR_INVALID_NAME) {
-			wchar_t *full;
-			full = __la_win_permissive_name_w(path);
-			h = FindFirstFileW(full, &findData);
-			free(full);
-		}
-		if (h == INVALID_HANDLE_VALUE) {
-			la_dosmaperr(GetLastError());
-			return (-1);
-		}
-		FindClose(h);
-	}
-
-	/* Is symlink file ? */
-	if (sim_lstat && 
-	    ((findData.dwFileAttributes
-		        & FILE_ATTRIBUTE_REPARSE_POINT) &&
-		(findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)))
-		flag |= FILE_FLAG_OPEN_REPARSE_POINT;
-
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-	ZeroMemory(&createExParams, sizeof(createExParams));
-	createExParams.dwSize = sizeof(createExParams);
-	createExParams.dwFileFlags = flag;
-	h = CreateFile2(a->name, 0, 0,
-		OPEN_EXISTING, &createExParams);
-#else
-	h = CreateFileW(a->name, 0, 0, NULL,
-	    OPEN_EXISTING, flag, NULL);
-#endif
-	if (h == INVALID_HANDLE_VALUE &&
-	    GetLastError() == ERROR_INVALID_NAME) {
-		wchar_t *full;
-		full = __la_win_permissive_name_w(path);
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		h = CreateFile2(full, 0, 0,
-			OPEN_EXISTING, &createExParams);
-#else
-		h = CreateFileW(full, 0, 0, NULL,
-		    OPEN_EXISTING, flag, NULL);
-#endif
-		free(full);
-	}
-	if (h == INVALID_HANDLE_VALUE) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-	r = GetFileInformationByHandle(h, st);
-	CloseHandle(h);
-	if (r == 0) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-
-	if (mode == NULL)
-		return (0);
-
-	*mode = S_IRUSR | S_IRGRP | S_IROTH;
-	if ((st->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
-		*mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-	if ((st->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
-	    findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)
-		*mode |= S_IFLNK;
-	else if (st->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-		*mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
-	else {
-		const wchar_t *p;
-
-		*mode |= S_IFREG;
-		p = wcsrchr(path, L'.');
-		if (p != NULL && wcslen(p) == 4) {
-			switch (p[1]) {
-			case L'B': case L'b':
-				if ((p[2] == L'A' || p[2] == L'a' ) &&
-				    (p[3] == L'T' || p[3] == L't' ))
-					*mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			case L'C': case L'c':
-				if (((p[2] == L'M' || p[2] == L'm' ) &&
-				    (p[3] == L'D' || p[3] == L'd' )))
-					*mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			case L'E': case L'e':
-				if ((p[2] == L'X' || p[2] == L'x' ) &&
-				    (p[3] == L'E' || p[3] == L'e' ))
-					*mode |= S_IXUSR | S_IXGRP | S_IXOTH;
-				break;
-			default:
-				break;
-			}
-		}
-	}
-	return (0);
-}
-
-/* 
- * Note: The path, for example, "aa/a/../b../c" will be converted to "aa/c"
- * by GetFullPathNameW() W32 API, which __la_win_permissive_name_w uses.
- * It means we cannot handle multiple dirs in one archive_entry.
- * So we have to make the full-pathname in another way, which does not
- * break "../" path string.
- */
-static int
-permissive_name_w(struct archive_write_disk *a)
-{
-	wchar_t *wn, *wnp;
-	wchar_t *ws, *wsp;
-	DWORD l;
-
-	wnp = a->name;
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
-	    wnp[2] == L'?' && wnp[3] == L'\\')
-		/* We have already a permissive name. */
-		return (0);
-
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
-		wnp[2] == L'.' && wnp[3] == L'\\') {
-		/* This is a device name */
-		if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
-		     (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
-			 wnp[5] == L':' && wnp[6] == L'\\') {
-			wnp[2] = L'?';/* Not device name. */
-			return (0);
-		}
-	}
-
-	/*
-	 * A full-pathname starting with a drive name like "C:\abc".
-	 */
-	if (((wnp[0] >= L'a' && wnp[0] <= L'z') ||
-	     (wnp[0] >= L'A' && wnp[0] <= L'Z')) &&
-		 wnp[1] == L':' && wnp[2] == L'\\') {
-		wn = _wcsdup(wnp);
-		if (wn == NULL)
-			return (-1);
-		archive_wstring_ensure(&(a->_name_data), 4 + wcslen(wn) + 1);
-		a->name = a->_name_data.s;
-		/* Prepend "\\?\" */
-		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
-		archive_wstrcat(&(a->_name_data), wn);
-		free(wn);
-		return (0);
-	}
-
-	/*
-	 * A full-pathname pointing to a network drive
-	 * like "\\<server-name>\<share-name>\file". 
-	 */
-	if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
-		const wchar_t *p = &wnp[2];
-
-		/* Skip server-name letters. */
-		while (*p != L'\\' && *p != L'\0')
-			++p;
-		if (*p == L'\\') {
-			const wchar_t *rp = ++p;
-			/* Skip share-name letters. */
-			while (*p != L'\\' && *p != L'\0')
-				++p;
-			if (*p == L'\\' && p != rp) {
-				/* Now, match patterns such as
-				 * "\\server-name\share-name\" */
-				wn = _wcsdup(wnp);
-				if (wn == NULL)
-					return (-1);
-				archive_wstring_ensure(&(a->_name_data),
-					8 + wcslen(wn) + 1);
-				a->name = a->_name_data.s;
-				/* Prepend "\\?\UNC\" */
-				archive_wstrncpy(&(a->_name_data),
-					L"\\\\?\\UNC\\", 8);
-				archive_wstrcat(&(a->_name_data), wn+2);
-				free(wn);
-				return (0);
-			}
-		}
-		return (0);
-	}
-
-	/*
-	 * Get current working directory.
-	 */
-	l = GetCurrentDirectoryW(0, NULL);
-	if (l == 0)
-		return (-1);
-	ws = malloc(l * sizeof(wchar_t));
-	l = GetCurrentDirectoryW(l, ws);
-	if (l == 0) {
-		free(ws);
-		return (-1);
-	}
-	wsp = ws;
-
-	/*
-	 * A full-pathname starting without a drive name like "\abc".
-	 */
-	if (wnp[0] == L'\\') {
-		wn = _wcsdup(wnp);
-		if (wn == NULL)
-			return (-1);
-		archive_wstring_ensure(&(a->_name_data),
-			4 + 2 + wcslen(wn) + 1);
-		a->name = a->_name_data.s;
-		/* Prepend "\\?\" and drive name. */
-		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
-		archive_wstrncat(&(a->_name_data), wsp, 2);
-		archive_wstrcat(&(a->_name_data), wn);
-		free(wsp);
-		free(wn);
-		return (0);
-	}
-
-	wn = _wcsdup(wnp);
-	if (wn == NULL)
-		return (-1);
-	archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1);
-	a->name = a->_name_data.s;
-	/* Prepend "\\?\" and drive name if not already added. */
-	if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' &&
-		wsp[2] == L'?' && wsp[3] == L'\\')
-	{
-		archive_wstrncpy(&(a->_name_data), wsp, l);
-	}
-	else if (l > 2 && wsp[0] == L'\\' && wsp[1] == L'\\' && wsp[2] != L'\\')
-	{
-		archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8);
-		archive_wstrncat(&(a->_name_data), wsp+2, l-2);
-	}
-	else
-	{
-		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
-		archive_wstrncat(&(a->_name_data), wsp, l);
-	}
-	archive_wstrncat(&(a->_name_data), L"\\", 1);
-	archive_wstrcat(&(a->_name_data), wn);
-	a->name = a->_name_data.s;
-	free(wsp);
-	free(wn);
-	return (0);
-}
-
-static int
-la_chmod(const wchar_t *path, mode_t mode)
-{
-	DWORD attr;
-	BOOL r;
-	wchar_t *fullname;
-	int ret = 0;
-
-	fullname = NULL;
-	attr = GetFileAttributesW(path);
-	if (attr == (DWORD)-1 &&
-	    GetLastError() == ERROR_INVALID_NAME) {
-		fullname = __la_win_permissive_name_w(path);
-		attr = GetFileAttributesW(fullname);
-	}
-	if (attr == (DWORD)-1) {
-		la_dosmaperr(GetLastError());
-		ret = -1;
-		goto exit_chmode;
-	}
-	if (mode & _S_IWRITE)
-		attr &= ~FILE_ATTRIBUTE_READONLY;
-	else
-		attr |= FILE_ATTRIBUTE_READONLY;
-	if (fullname != NULL)
-		r = SetFileAttributesW(fullname, attr);
-	else
-		r = SetFileAttributesW(path, attr);
-	if (r == 0) {
-		la_dosmaperr(GetLastError());
-		ret = -1;
-	}
-exit_chmode:
-	free(fullname);
-	return (ret);
-}
-
-static int
-la_mktemp(struct archive_write_disk *a)
-{
-	int fd;
-	mode_t mode;
-
-	archive_wstring_empty(&(a->_tmpname_data));
-	archive_wstrcpy(&(a->_tmpname_data), a->name);
-	archive_wstrcat(&(a->_tmpname_data), L".XXXXXX");
-	a->tmpname = a->_tmpname_data.s;
-
-	fd = __archive_mkstemp(a->tmpname);
-	if (fd == -1)
-		return -1;
-
-	mode = a->mode & 0777 & ~a->user_umask;
-	if (la_chmod(a->tmpname, mode) == -1) {
-		la_dosmaperr(GetLastError());
-		_close(fd);
-		return -1;
-	}
-	return (fd);
-}
-
-#if _WIN32_WINNT < _WIN32_WINNT_VISTA
-static void *
-la_GetFunctionKernel32(const char *name)
-{
-	static HINSTANCE lib;
-	static int set;
-	if (!set) {
-		set = 1;
-		lib = LoadLibrary(TEXT("kernel32.dll"));
-	}
-	if (lib == NULL) {
-		fprintf(stderr, "Can't load kernel32.dll?!\n");
-		exit(1);
-	}
-	return (void *)GetProcAddress(lib, name);
-}
-#endif
-
-static int
-la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
-{
-	static BOOL (WINAPI *f)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
-	BOOL ret;
-
-#if _WIN32_WINNT < _WIN32_WINNT_XP
-	static int set;
-/* CreateHardLinkW is available since XP and always loaded */
-	if (!set) {
-		set = 1;
-		f = la_GetFunctionKernel32("CreateHardLinkW");
-	}
-#else
-	f = CreateHardLinkW;
-#endif
-	if (!f) {
-		errno = ENOTSUP;
-		return (0);
-	}
-	ret = (*f)(linkname, target, NULL);
-	if (!ret) {
-		/* Under windows 2000, it is necessary to remove
-		 * the "\\?\" prefix. */
-#define IS_UNC(name)	((name[0] == L'U' || name[0] == L'u') &&	\
-			 (name[1] == L'N' || name[1] == L'n') &&	\
-			 (name[2] == L'C' || name[2] == L'c') &&	\
-			 name[3] == L'\\')
-		if (!wcsncmp(linkname,L"\\\\?\\", 4)) {
-			linkname += 4;
-			if (IS_UNC(linkname))
-				linkname += 4;
-		}
-		if (!wcsncmp(target,L"\\\\?\\", 4)) {
-			target += 4;
-			if (IS_UNC(target))
-				target += 4;
-		}
-#undef IS_UNC
-		ret = (*f)(linkname, target, NULL);
-	}
-	return (ret);
-}
-
-/*
- * Create file or directory symolic link
- *
- * If linktype is AE_SYMLINK_TYPE_UNDEFINED (or unknown), guess linktype from
- * the link target
- */
-static int
-la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target,
-    int linktype) {
-	static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD);
-	wchar_t *ttarget, *p;
-	size_t len;
-	DWORD attrs = 0;
-	DWORD flags = 0;
-	DWORD newflags = 0;
-	BOOL ret = 0;
-
-#if _WIN32_WINNT < _WIN32_WINNT_VISTA
-/* CreateSymbolicLinkW is available since Vista and always loaded */
-	static int set;
-	if (!set) {
-		set = 1;
-		f = la_GetFunctionKernel32("CreateSymbolicLinkW");
-	}
-#else
-# if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-	f = CreateSymbolicLinkW;
-# else
-	f = NULL;
-# endif
-#endif
-	if (!f)
-		return (0);
-
-	len = wcslen(target);
-	if (len == 0) {
-		errno = EINVAL;
-		return(0);
-	}
-	/*
-	 * When writing path targets, we need to translate slashes
-	 * to backslashes
-	 */
-	ttarget = malloc((len + 1) * sizeof(wchar_t));
-	if (ttarget == NULL)
-		return(0);
-
-	p = ttarget;
-
-	while(*target != L'\0') {
-		if (*target == L'/')
-			*p = L'\\';
-		else
-			*p = *target;
-		target++;
-		p++;
-	}
-	*p = L'\0';
-
-	/*
-	 * In case of undefined symlink type we guess it from the target.
-	 * If the target equals ".", "..", ends with a backslash or a
-	 * backslash followed by "." or ".." we assume it is a directory
-	 * symlink. In all other cases we assume a file symlink.
-	 */
-	if (linktype != AE_SYMLINK_TYPE_FILE && (
-		linktype == AE_SYMLINK_TYPE_DIRECTORY ||
-		*(p - 1) == L'\\' || (*(p - 1) == L'.' && (
-	    len == 1 || *(p - 2) == L'\\' || ( *(p - 2) == L'.' && (
-	    len == 2 || *(p - 3) == L'\\')))))) {
-#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
-		flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
-#else
-		flags |= 0x1;
-#endif
-	}
-
-#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
-	newflags = flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
-#else
-	newflags = flags | 0x2;
-#endif
-
-	/*
-	 * Windows won't overwrite existing links
-	 */
-	attrs = GetFileAttributesW(linkname);
-	if (attrs != INVALID_FILE_ATTRIBUTES) {
-		if (attrs & FILE_ATTRIBUTE_DIRECTORY)
-			disk_rmdir(linkname);
-		else
-			disk_unlink(linkname);
-	}
-
-	ret = (*f)(linkname, ttarget, newflags);
-	/*
-	 * Prior to Windows 10 calling CreateSymbolicLinkW() will fail
-	 * if SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is set
-	 */
-	if (!ret) {
-		ret = (*f)(linkname, ttarget, flags);
-	}
-	free(ttarget);
-	return (ret);
-}
-
-static int
-la_ftruncate(HANDLE handle, int64_t length)
-{
-	LARGE_INTEGER distance;
-
-	if (GetFileType(handle) != FILE_TYPE_DISK) {
-		errno = EBADF;
-		return (-1);
-	}
-	distance.QuadPart = length;
-	if (!SetFilePointerEx_perso(handle, distance, NULL, FILE_BEGIN)) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-	if (!SetEndOfFile(handle)) {
-		la_dosmaperr(GetLastError());
-		return (-1);
-	}
-	return (0);
-}
-
-static int
-lazy_stat(struct archive_write_disk *a)
-{
-	if (a->pst != NULL) {
-		/* Already have stat() data available. */
-		return (ARCHIVE_OK);
-	}
-	if (a->fh != INVALID_HANDLE_VALUE &&
-	    GetFileInformationByHandle(a->fh, &a->st) == 0) {
-		a->pst = &a->st;
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * XXX At this point, symlinks should not be hit, otherwise
-	 * XXX a race occurred.  Do we want to check explicitly for that?
-	 */
-	if (file_information(a, a->name, &a->st, NULL, 1) == 0) {
-		a->pst = &a->st;
-		return (ARCHIVE_OK);
-	}
-	archive_set_error(&a->archive, errno, "Couldn't stat file");
-	return (ARCHIVE_WARN);
-}
-
-static const struct archive_vtable
-archive_write_disk_vtable = {
-	.archive_close = _archive_write_disk_close,
-	.archive_filter_bytes = _archive_write_disk_filter_bytes,
-	.archive_free = _archive_write_disk_free,
-	.archive_write_header = _archive_write_disk_header,
-	.archive_write_finish_entry = _archive_write_disk_finish_entry,
-	.archive_write_data = _archive_write_disk_data,
-	.archive_write_data_block = _archive_write_disk_data_block,
-};
-
-static int64_t
-_archive_write_disk_filter_bytes(struct archive *_a, int n)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	(void)n; /* UNUSED */
-	if (n == -1 || n == 0)
-		return (a->total_bytes_written);
-	return (-1);
-}
-
-
-int
-archive_write_disk_set_options(struct archive *_a, int flags)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-
-	a->flags = flags;
-	return (ARCHIVE_OK);
-}
-
-
-/*
- * Extract this entry to disk.
- *
- * TODO: Validate hardlinks.  According to the standards, we're
- * supposed to check each extracted hardlink and squawk if it refers
- * to a file that we didn't restore.  I'm not entirely convinced this
- * is a good idea, but more importantly: Is there any way to validate
- * hardlinks without keeping a complete list of filenames from the
- * entire archive?? Ugh.
- *
- */
-static int
-_archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	struct fixup_entry *fe;
-	int ret, r;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_disk_header");
-	archive_clear_error(&a->archive);
-	if (a->archive.state & ARCHIVE_STATE_DATA) {
-		r = _archive_write_disk_finish_entry(&a->archive);
-		if (r == ARCHIVE_FATAL)
-			return (r);
-	}
-
-	/* Set up for this particular entry. */
-	a->pst = NULL;
-	a->current_fixup = NULL;
-	a->deferred = 0;
-	archive_entry_free(a->entry);
-	a->entry = NULL;
-	a->entry = archive_entry_clone(entry);
-	a->fh = INVALID_HANDLE_VALUE;
-	a->fd_offset = 0;
-	a->offset = 0;
-	a->restore_pwd = -1;
-	a->uid = a->user_uid;
-	a->mode = archive_entry_mode(a->entry);
-	if (archive_entry_size_is_set(a->entry))
-		a->filesize = archive_entry_size(a->entry);
-	else
-		a->filesize = -1;
-	archive_wstrcpy(&(a->_name_data), archive_entry_pathname_w(a->entry));
-	a->name = a->_name_data.s;
-	archive_clear_error(&a->archive);
-
-	/*
-	 * Clean up the requested path.  This is necessary for correct
-	 * dir restores; the dir restore logic otherwise gets messed
-	 * up by nonsense like "dir/.".
-	 */
-	ret = cleanup_pathname(a, a->name);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	/*
-	 * Generate a full-pathname and use it from here.
-	 */
-	if (permissive_name_w(a) < 0) {
-		errno = EINVAL;
-		return (ARCHIVE_FAILED);
-	}
-
-	/*
-	 * Query the umask so we get predictable mode settings.
-	 * This gets done on every call to _write_header in case the
-	 * user edits their umask during the extraction for some
-	 * reason.
-	 */
-	umask(a->user_umask = umask(0));
-
-	/* Figure out what we need to do for this entry. */
-	a->todo = TODO_MODE_BASE;
-	if (a->flags & ARCHIVE_EXTRACT_PERM) {
-		a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
-		/*
-		 * SGID requires an extra "check" step because we
-		 * cannot easily predict the GID that the system will
-		 * assign.  (Different systems assign GIDs to files
-		 * based on a variety of criteria, including process
-		 * credentials and the gid of the enclosing
-		 * directory.)  We can only restore the SGID bit if
-		 * the file has the right GID, and we only know the
-		 * GID if we either set it (see set_ownership) or if
-		 * we've actually called stat() on the file after it
-		 * was restored.  Since there are several places at
-		 * which we might verify the GID, we need a TODO bit
-		 * to keep track.
-		 */
-		if (a->mode & S_ISGID)
-			a->todo |= TODO_SGID | TODO_SGID_CHECK;
-		/*
-		 * Verifying the SUID is simpler, but can still be
-		 * done in multiple ways, hence the separate "check" bit.
-		 */
-		if (a->mode & S_ISUID)
-			a->todo |= TODO_SUID | TODO_SUID_CHECK;
-	} else {
-		/*
-		 * User didn't request full permissions, so don't
-		 * restore SUID, SGID bits and obey umask.
-		 */
-		a->mode &= ~S_ISUID;
-		a->mode &= ~S_ISGID;
-		a->mode &= ~S_ISVTX;
-		a->mode &= ~a->user_umask;
-	}
-#if 0
-	if (a->flags & ARCHIVE_EXTRACT_OWNER)
-		a->todo |= TODO_OWNER;
-#endif
-	if (a->flags & ARCHIVE_EXTRACT_TIME)
-		a->todo |= TODO_TIMES;
-	if (a->flags & ARCHIVE_EXTRACT_ACL) {
-		if (archive_entry_filetype(a->entry) == AE_IFDIR)
-			a->deferred |= TODO_ACLS;
-		else
-			a->todo |= TODO_ACLS;
-	}
-	if (a->flags & ARCHIVE_EXTRACT_XATTR)
-		a->todo |= TODO_XATTR;
-	if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
-		a->todo |= TODO_FFLAGS;
-	if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
-		ret = check_symlinks(a);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-	}
-
-	ret = restore_entry(a);
-
-	/*
-	 * TODO: There are rumours that some extended attributes must
-	 * be restored before file data is written.  If this is true,
-	 * then we either need to write all extended attributes both
-	 * before and after restoring the data, or find some rule for
-	 * determining which must go first and which last.  Due to the
-	 * many ways people are using xattrs, this may prove to be an
-	 * intractable problem.
-	 */
-
-	/*
-	 * Fixup uses the unedited pathname from archive_entry_pathname(),
-	 * because it is relative to the base dir and the edited path
-	 * might be relative to some intermediate dir as a result of the
-	 * deep restore logic.
-	 */
-	if (a->deferred & TODO_MODE) {
-		fe = current_fixup(a, archive_entry_pathname_w(entry));
-		fe->fixup |= TODO_MODE_BASE;
-		fe->mode = a->mode;
-	}
-
-	if ((a->deferred & TODO_TIMES)
-		&& (archive_entry_mtime_is_set(entry)
-		    || archive_entry_atime_is_set(entry))) {
-		fe = current_fixup(a, archive_entry_pathname_w(entry));
-		fe->mode = a->mode;
-		fe->fixup |= TODO_TIMES;
-		if (archive_entry_atime_is_set(entry)) {
-			fe->atime = archive_entry_atime(entry);
-			fe->atime_nanos = archive_entry_atime_nsec(entry);
-		} else {
-			/* If atime is unset, use start time. */
-			fe->atime = a->start_time;
-			fe->atime_nanos = 0;
-		}
-		if (archive_entry_mtime_is_set(entry)) {
-			fe->mtime = archive_entry_mtime(entry);
-			fe->mtime_nanos = archive_entry_mtime_nsec(entry);
-		} else {
-			/* If mtime is unset, use start time. */
-			fe->mtime = a->start_time;
-			fe->mtime_nanos = 0;
-		}
-		if (archive_entry_birthtime_is_set(entry)) {
-			fe->birthtime = archive_entry_birthtime(entry);
-			fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
-		} else {
-			/* If birthtime is unset, use mtime. */
-			fe->birthtime = fe->mtime;
-			fe->birthtime_nanos = fe->mtime_nanos;
-		}
-	}
-
-	if (a->deferred & TODO_ACLS) {
-		fe = current_fixup(a, archive_entry_pathname_w(entry));
-		archive_acl_copy(&fe->acl, archive_entry_acl(entry));
-	}
-
-	if (a->deferred & TODO_FFLAGS) {
-		unsigned long set, clear;
-
-		fe = current_fixup(a, archive_entry_pathname_w(entry));
-		archive_entry_fflags(entry, &set, &clear);
-		fe->fflags_set = set;
-	}
-
-	/*
-	 * On Windows, A creating sparse file requires a special mark.
-	 */
-	if (a->fh != INVALID_HANDLE_VALUE &&
-	    archive_entry_sparse_count(entry) > 0) {
-		int64_t base = 0, offset, length;
-		int i, cnt = archive_entry_sparse_reset(entry);
-		int sparse = 0;
-
-		for (i = 0; i < cnt; i++) {
-			archive_entry_sparse_next(entry, &offset, &length);
-			if (offset - base >= 4096) {
-				sparse = 1;/* we have a hole. */
-				break;
-			}
-			base = offset + length;
-		}
-		if (sparse) {
-			DWORD dmy;
-			/* Mark this file as sparse. */
-			DeviceIoControl(a->fh, FSCTL_SET_SPARSE,
-			    NULL, 0, NULL, 0, &dmy, NULL);
-		}
-	}
-
-	/* We've created the object and are ready to pour data into it. */
-	if (ret >= ARCHIVE_WARN)
-		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->fh == INVALID_HANDLE_VALUE) {
-		archive_entry_set_size(entry, 0);
-		a->filesize = 0;
-	}
-
-	return (ret);
-}
-
-int
-archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
-	a->skip_file_set = 1;
-	a->skip_file_dev = d;
-	a->skip_file_ino = i;
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
-{
-	OVERLAPPED ol;
-	uint64_t start_size = size;
-	DWORD bytes_written = 0;
-	ssize_t block_size = 0, bytes_to_write;
-
-	if (size == 0)
-		return (ARCHIVE_OK);
-
-	if (a->filesize == 0 || a->fh == INVALID_HANDLE_VALUE) {
-		archive_set_error(&a->archive, 0,
-		    "Attempt to write to an empty file");
-		return (ARCHIVE_WARN);
-	}
-
-	if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
-		/* XXX TODO XXX Is there a more appropriate choice here ? */
-		/* This needn't match the filesystem allocation size. */
-		block_size = 16*1024;
-	}
-
-	/* If this write would run beyond the file size, truncate it. */
-	if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
-		start_size = size = (size_t)(a->filesize - a->offset);
-
-	/* Write the data. */
-	while (size > 0) {
-		if (block_size == 0) {
-			bytes_to_write = size;
-		} else {
-			/* We're sparsifying the file. */
-			const char *p, *end;
-			int64_t block_end;
-
-			/* Skip leading zero bytes. */
-			for (p = buff, end = buff + size; p < end; ++p) {
-				if (*p != '\0')
-					break;
-			}
-			a->offset += p - buff;
-			size -= p - buff;
-			buff = p;
-			if (size == 0)
-				break;
-
-			/* Calculate next block boundary after offset. */
-			block_end
-			    = (a->offset / block_size + 1) * block_size;
-
-			/* If the adjusted write would cross block boundary,
-			 * truncate it to the block boundary. */
-			bytes_to_write = size;
-			if (a->offset + bytes_to_write > block_end)
-				bytes_to_write = (DWORD)(block_end - a->offset);
-		}
-		memset(&ol, 0, sizeof(ol));
-		ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF);
-		ol.OffsetHigh = (DWORD)(a->offset >> 32);
-		if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write,
-		    &bytes_written, &ol)) {
-			DWORD lasterr;
-
-			lasterr = GetLastError();
-			if (lasterr == ERROR_ACCESS_DENIED)
-				errno = EBADF;
-			else
-				la_dosmaperr(lasterr);
-			archive_set_error(&a->archive, errno, "Write failed");
-			return (ARCHIVE_WARN);
-		}
-		buff += bytes_written;
-		size -= bytes_written;
-		a->total_bytes_written += bytes_written;
-		a->offset += bytes_written;
-		a->fd_offset = a->offset;
-	}
-	return ((ssize_t)(start_size - size));
-}
-
-static ssize_t
-_archive_write_disk_data_block(struct archive *_a,
-    const void *buff, size_t size, int64_t offset)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	ssize_t r;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_DATA, "archive_write_data_block");
-
-	a->offset = offset;
-	r = write_data_block(a, buff, size);
-	if (r < ARCHIVE_OK)
-		return (r);
-	if ((size_t)r < size) {
-		archive_set_error(&a->archive, 0,
-		    "Write request too large");
-		return (ARCHIVE_WARN);
-	}
-#if ARCHIVE_VERSION_NUMBER < 3999000
-	return (ARCHIVE_OK);
-#else
-	return (size);
-#endif
-}
-
-static ssize_t
-_archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_DATA, "archive_write_data");
-
-	return (write_data_block(a, buff, size));
-}
-
-static int
-_archive_write_disk_finish_entry(struct archive *_a)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	int ret = ARCHIVE_OK;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_finish_entry");
-	if (a->archive.state & ARCHIVE_STATE_HEADER)
-		return (ARCHIVE_OK);
-	archive_clear_error(&a->archive);
-
-	/* Pad or truncate file to the right size. */
-	if (a->fh == INVALID_HANDLE_VALUE) {
-		/* There's no file. */
-	} else if (a->filesize < 0) {
-		/* File size is unknown, so we can't set the size. */
-	} else if (a->fd_offset == a->filesize) {
-		/* Last write ended at exactly the filesize; we're done. */
-		/* Hopefully, this is the common case. */
-	} else {
-		if (la_ftruncate(a->fh, a->filesize) == -1) {
-			archive_set_error(&a->archive, errno,
-			    "File size could not be restored");
-			CloseHandle(a->fh);
-			a->fh = INVALID_HANDLE_VALUE;
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	/* Restore metadata. */
-
-	/*
-	 * Look up the "real" UID only if we're going to need it.
-	 * TODO: the TODO_SGID condition can be dropped here, can't it?
-	 */
-	if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
-		a->uid = archive_write_disk_uid(&a->archive,
-		    archive_entry_uname(a->entry),
-		    archive_entry_uid(a->entry));
-	}
-	/* Look up the "real" GID only if we're going to need it. */
-	/* TODO: the TODO_SUID condition can be dropped here, can't it? */
-	if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
-		a->gid = archive_write_disk_gid(&a->archive,
-		    archive_entry_gname(a->entry),
-		    archive_entry_gid(a->entry));
-	 }
-
-	/*
-	 * Restore ownership before set_mode tries to restore suid/sgid
-	 * bits.  If we set the owner, we know what it is and can skip
-	 * a stat() call to examine the ownership of the file on disk.
-	 */
-	if (a->todo & TODO_OWNER)
-		ret = set_ownership(a);
-
-	/*
-	 * set_mode must precede ACLs on systems such as Solaris and
-	 * FreeBSD where setting the mode implicitly clears extended ACLs
-	 */
-	if (a->todo & TODO_MODE) {
-		int r2 = set_mode(a, a->mode);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Security-related extended attributes (such as
-	 * security.capability on Linux) have to be restored last,
-	 * since they're implicitly removed by other file changes.
-	 */
-	if (a->todo & TODO_XATTR) {
-		int r2 = set_xattrs(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Some flags prevent file modification; they must be restored after
-	 * file contents are written.
-	 */
-	if (a->todo & TODO_FFLAGS) {
-		int r2 = set_fflags(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * Time must follow most other metadata;
-	 * otherwise atime will get changed.
-	 */
-	if (a->todo & TODO_TIMES) {
-		int r2 = set_times_from_entry(a);
-		if (r2 < ret) ret = r2;
-	}
-
-	/*
-	 * ACLs must be restored after timestamps because there are
-	 * ACLs that prevent attribute changes (including time).
-	 */
-	if (a->todo & TODO_ACLS) {
-		int r2 = set_acls(a, a->fh,
-				  archive_entry_pathname_w(a->entry),
-				  archive_entry_acl(a->entry));
-		if (r2 < ret) ret = r2;
-	}
-
-	/* If there's an fd, we can close it now. */
-	if (a->fh != INVALID_HANDLE_VALUE) {
-		CloseHandle(a->fh);
-		a->fh = INVALID_HANDLE_VALUE;
-		if (a->tmpname) {
-			/* Windows does not support atomic rename */
-			disk_unlink(a->name);
-			if (_wrename(a->tmpname, a->name) != 0) {
-				la_dosmaperr(GetLastError());
-				archive_set_error(&a->archive, errno,
-				    "Failed to rename temporary file");
-				ret = ARCHIVE_FAILED;
-				disk_unlink(a->tmpname);
-			}
-			a->tmpname = NULL;
-		}
-	}
-	/* If there's an entry, we can release it now. */
-	archive_entry_free(a->entry);
-	a->entry = NULL;
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	return (ret);
-}
-
-int
-archive_write_disk_set_group_lookup(struct archive *_a,
-    void *private_data,
-    la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
-    void (*cleanup_gid)(void *private))
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
-
-	if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
-		(a->cleanup_gid)(a->lookup_gid_data);
-
-	a->lookup_gid = lookup_gid;
-	a->cleanup_gid = cleanup_gid;
-	a->lookup_gid_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_disk_set_user_lookup(struct archive *_a,
-    void *private_data,
-    int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
-    void (*cleanup_uid)(void *private))
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
-
-	if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
-		(a->cleanup_uid)(a->lookup_uid_data);
-
-	a->lookup_uid = lookup_uid;
-	a->cleanup_uid = cleanup_uid;
-	a->lookup_uid_data = private_data;
-	return (ARCHIVE_OK);
-}
-
-int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
-{
-       struct archive_write_disk *a = (struct archive_write_disk *)_a;
-       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-           ARCHIVE_STATE_ANY, "archive_write_disk_gid");
-       if (a->lookup_gid)
-               return (a->lookup_gid)(a->lookup_gid_data, name, id);
-       return (id);
-}
- 
-int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
-{
-       struct archive_write_disk *a = (struct archive_write_disk *)_a;
-       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-           ARCHIVE_STATE_ANY, "archive_write_disk_uid");
-       if (a->lookup_uid)
-               return (a->lookup_uid)(a->lookup_uid_data, name, id);
-       return (id);
-}
-
-/*
- * Create a new archive_write_disk object and initialize it with global state.
- */
-struct archive *
-archive_write_disk_new(void)
-{
-	struct archive_write_disk *a;
-
-	a = (struct archive_write_disk *)calloc(1, sizeof(*a));
-	if (a == NULL)
-		return (NULL);
-	a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
-	/* We're ready to write a header immediately. */
-	a->archive.state = ARCHIVE_STATE_HEADER;
-	a->archive.vtable = &archive_write_disk_vtable;
-	a->start_time = time(NULL);
-	/* Query and restore the umask. */
-	umask(a->user_umask = umask(0));
-	if (archive_wstring_ensure(&a->path_safe, 512) == NULL) {
-		free(a);
-		return (NULL);
-	}
-	a->path_safe.s[0] = 0;
-	return (&a->archive);
-}
-
-static int
-disk_unlink(const wchar_t *path)
-{
-	wchar_t *fullname;
-	int r;
-
-	r = _wunlink(path);
-	if (r != 0 && GetLastError() == ERROR_INVALID_NAME) {
-		fullname = __la_win_permissive_name_w(path);
-		r = _wunlink(fullname);
-		free(fullname);
-	}
-	return (r);
-}
-
-static int
-disk_rmdir(const wchar_t *path)
-{
-	wchar_t *fullname;
-	int r;
-
-	r = _wrmdir(path);
-	if (r != 0 && GetLastError() == ERROR_INVALID_NAME) {
-		fullname = __la_win_permissive_name_w(path);
-		r = _wrmdir(fullname);
-		free(fullname);
-	}
-	return (r);
-}
-
-/*
- * The main restore function.
- */
-static int
-restore_entry(struct archive_write_disk *a)
-{
-	int ret = ARCHIVE_OK, en;
-
-	if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
-		/*
-		 * TODO: Fix this.  Apparently, there are platforms
-		 * that still allow root to hose the entire filesystem
-		 * by unlinking a dir.  The S_ISDIR() test above
-		 * prevents us from using unlink() here if the new
-		 * object is a dir, but that doesn't mean the old
-		 * object isn't a dir.
-		 */
-		if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
-			(void)clear_nochange_fflags(a);
-		if (disk_unlink(a->name) == 0) {
-			/* We removed it, reset cached stat. */
-			a->pst = NULL;
-		} else if (errno == ENOENT) {
-			/* File didn't exist, that's just as good. */
-		} else if (disk_rmdir(a->name) == 0) {
-			/* It was a dir, but now it's gone. */
-			a->pst = NULL;
-		} else {
-			/* We tried, but couldn't get rid of it. */
-			archive_set_error(&a->archive, errno,
-			    "Could not unlink");
-			return(ARCHIVE_FAILED);
-		}
-	}
-
-	/* Try creating it first; if this fails, we'll try to recover. */
-	en = create_filesystem_object(a);
-
-	if ((en == ENOTDIR || en == ENOENT)
-	    && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
-		wchar_t *full;
-		/* If the parent dir doesn't exist, try creating it. */
-		create_parent_dir(a, a->name);
-		/* Now try to create the object again. */
-		full = __la_win_permissive_name_w(a->name);
-		if (full == NULL) {
-			en = EINVAL;
-		} else {
-			/* Remove multiple directories such as "a/../b../c" */
-			archive_wstrcpy(&(a->_name_data), full);
-			a->name = a->_name_data.s;
-			free(full);
-			en = create_filesystem_object(a);
-		}
-	}
-
-	if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
-		archive_set_error(&a->archive, en,
-			"Hard-link target '%s' does not exist.",
-			archive_entry_hardlink(a->entry));
-		return (ARCHIVE_FAILED);
-	}
-
-	if ((en == EISDIR || en == EEXIST)
-	    && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
-		/* If we're not overwriting, we're done. */
-		if (S_ISDIR(a->mode)) {
-			/* Don't overwrite any settings on existing directories. */
-			a->todo = 0;
-		}
-		archive_entry_unset_size(a->entry);
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * Some platforms return EISDIR if you call
-	 * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
-	 * return EEXIST.  POSIX is ambiguous, requiring EISDIR
-	 * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
-	 * on an existing item.
-	 */
-	if (en == EISDIR) {
-		/* A dir is in the way of a non-dir, rmdir it. */
-		if (disk_rmdir(a->name) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't remove already-existing dir");
-			return (ARCHIVE_FAILED);
-		}
-		a->pst = NULL;
-		/* Try again. */
-		en = create_filesystem_object(a);
-	} else if (en == EEXIST) {
-		mode_t st_mode;
-		mode_t lst_mode;
-		BY_HANDLE_FILE_INFORMATION lst;
-		/*
-		 * We know something is in the way, but we don't know what;
-		 * we need to find out before we go any further.
-		 */
-		int r = 0;
-		int dirlnk = 0;
-
-		/*
-		 * The SECURE_SYMLINK logic has already removed a
-		 * symlink to a dir if the client wants that.  So
-		 * follow the symlink if we're creating a dir.
-		 * If it's not a dir (or it's a broken symlink),
-		 * then don't follow it.
-		 *
-		 * Windows distinguishes file and directory symlinks.
-		 * A file symlink may erroneously point to a directory
-		 * and a directory symlink to a file. Windows does not follow
-		 * such symlinks. We always need both source and target
-		 * information.
-		 */
-		r = file_information(a, a->name, &lst, &lst_mode, 1);
-		if (r != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't stat existing object");
-			return (ARCHIVE_FAILED);
-		} else if (S_ISLNK(lst_mode)) {
-			if (lst.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-				dirlnk = 1;
-			/* In case of a symlink we need target information */
-			r = file_information(a, a->name, &a->st, &st_mode, 0);
-			if (r != 0) {
-				a->st = lst;
-				st_mode = lst_mode;
-			}
-		} else {
-			a->st = lst;
-			st_mode = lst_mode;
-		}
-
-		/*
-		 * NO_OVERWRITE_NEWER doesn't apply to directories.
-		 */
-		if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
-		    &&  !S_ISDIR(st_mode)) {
-			if (!older(&(a->st), a->entry)) {
-				archive_entry_unset_size(a->entry);
-				return (ARCHIVE_OK);
-			}
-		}
-
-		/* If it's our archive, we're done. */
-		if (a->skip_file_set &&
-		    bhfi_dev(&a->st) == a->skip_file_dev &&
-		    bhfi_ino(&a->st) == a->skip_file_ino) {
-			archive_set_error(&a->archive, 0,
-			    "Refusing to overwrite archive");
-			return (ARCHIVE_FAILED);
-		}
-
-		if (!S_ISDIR(st_mode)) {
-			if (a->flags &
-			    ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) {
-				(void)clear_nochange_fflags(a);
-			}
-			if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
-				S_ISREG(st_mode)) {
-				int fd = la_mktemp(a);
-
-				if (fd == -1) {
-					la_dosmaperr(GetLastError());
-					archive_set_error(&a->archive, errno,
-					    "Can't create temporary file");
-					return (ARCHIVE_FAILED);
-				}
-				a->fh = (HANDLE)_get_osfhandle(fd);
-				if (a->fh == INVALID_HANDLE_VALUE) {
-					la_dosmaperr(GetLastError());
-					return (ARCHIVE_FAILED);
-				}
-				a->pst = NULL;
-				en = 0;
-			} else {
-				if (dirlnk) {
-					/* Edge case: dir symlink pointing
-					 * to a file */
-					if (disk_rmdir(a->name) != 0) {
-						archive_set_error(&a->archive,
-						    errno, "Can't unlink "
-						    "directory symlink");
-						return (ARCHIVE_FAILED);
-					}
-				} else {
-					if (disk_unlink(a->name) != 0) {
-						/* A non-dir is in the way,
-						 * unlink it. */
-						archive_set_error(&a->archive,
-						    errno, "Can't unlink "
-						    "already-existing object");
-						return (ARCHIVE_FAILED);
-					}
-				}
-				a->pst = NULL;
-				/* Try again. */
-				en = create_filesystem_object(a);
-			}
-		} else if (!S_ISDIR(a->mode)) {
-			/* A dir is in the way of a non-dir, rmdir it. */
-			if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
-				(void)clear_nochange_fflags(a);
-			if (disk_rmdir(a->name) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Can't remove already-existing dir");
-				return (ARCHIVE_FAILED);
-			}
-			/* Try again. */
-			en = create_filesystem_object(a);
-		} else {
-			/*
-			 * There's a dir in the way of a dir.  Don't
-			 * waste time with rmdir()/mkdir(), just fix
-			 * up the permissions on the existing dir.
-			 * Note that we don't change perms on existing
-			 * dirs unless _EXTRACT_PERM is specified.
-			 */
-			if ((a->mode != st_mode)
-			    && (a->todo & TODO_MODE_FORCE))
-				a->deferred |= (a->todo & TODO_MODE);
-			/* Ownership doesn't need deferred fixup. */
-			en = 0; /* Forget the EEXIST. */
-		}
-	}
-
-	if (en) {
-		/* Everything failed; give up here. */
-		archive_set_error(&a->archive, en, "Can't create '%ls'",
-		    a->name);
-		return (ARCHIVE_FAILED);
-	}
-
-	a->pst = NULL; /* Cached stat data no longer valid. */
-	return (ret);
-}
-
-/*
- * Returns 0 if creation succeeds, or else returns errno value from
- * the failed system call.   Note:  This function should only ever perform
- * a single system call.
- */
-static int
-create_filesystem_object(struct archive_write_disk *a)
-{
-	/* Create the entry. */
-	const wchar_t *linkname;
-	wchar_t *fullname;
-	mode_t final_mode, mode;
-	int r;
-	DWORD attrs = 0;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-	/* 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_w(a->entry);
-	if (linkname != NULL) {
-		wchar_t *linksanitized, *linkfull, *namefull;
-		size_t l = (wcslen(linkname) + 1) * sizeof(wchar_t);
-		linksanitized = malloc(l);
-		if (linksanitized == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for hardlink target");
-			return (-1);
-		}
-		memcpy(linksanitized, linkname, l);
-		r = cleanup_pathname(a, linksanitized);
-		if (r != ARCHIVE_OK) {
-			free(linksanitized);
-			return (r);
-		}
-		linkfull = __la_win_permissive_name_w(linksanitized);
-		free(linksanitized);
-		namefull = __la_win_permissive_name_w(a->name);
-		if (linkfull == NULL || namefull == NULL) {
-			errno = EINVAL;
-			r = -1;
-		} else {
-			/*
-			 * Unlinking and linking here is really not atomic,
-			 * but doing it right, would require us to construct
-			 * an mktemplink() function, and then use _wrename().
-			 */
-			if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) {
-				attrs = GetFileAttributesW(namefull);
-				if (attrs != INVALID_FILE_ATTRIBUTES) {
-					if (attrs & FILE_ATTRIBUTE_DIRECTORY)
-						disk_rmdir(namefull);
-					else
-						disk_unlink(namefull);
-				}
-			}
-			r = la_CreateHardLinkW(namefull, linkfull);
-			if (r == 0) {
-				la_dosmaperr(GetLastError());
-				r = errno;
-			} else
-				r = 0;
-		}
-		/*
-		 * New cpio and pax formats allow hardlink entries
-		 * to carry data, so we may have to open the file
-		 * for hardlink entries.
-		 *
-		 * If the hardlink was successfully created and
-		 * the archive doesn't have carry data for it,
-		 * consider it to be non-authoritative for meta data.
-		 * This is consistent with GNU tar and BSD pax.
-		 * If the hardlink does carry data, let the last
-		 * archive entry decide ownership.
-		 */
-		if (r == 0 && a->filesize <= 0) {
-			a->todo = 0;
-			a->deferred = 0;
-		} else if (r == 0 && a->filesize > 0) {
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-			ZeroMemory(&createExParams, sizeof(createExParams));
-			createExParams.dwSize = sizeof(createExParams);
-			createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
-			a->fh = CreateFile2(namefull, GENERIC_WRITE, 0,
-			    TRUNCATE_EXISTING, &createExParams);
-#else
-			a->fh = CreateFileW(namefull, GENERIC_WRITE, 0, NULL,
-			    TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-#endif
-			if (a->fh == INVALID_HANDLE_VALUE) {
-				la_dosmaperr(GetLastError());
-				r = errno;
-			}
-		}
-		free(linkfull);
-		free(namefull);
-		return (r);
-	}
-	linkname = archive_entry_symlink_w(a->entry);
-	if (linkname != NULL) {
-		/*
-		 * Unlinking and linking here is really not atomic,
-		 * but doing it right, would require us to construct
-		 * an mktemplink() function, and then use _wrename().
-		 */
-		attrs = GetFileAttributesW(a->name);
-		if (attrs != INVALID_FILE_ATTRIBUTES) {
-			if (attrs & FILE_ATTRIBUTE_DIRECTORY)
-				disk_rmdir(a->name);
-			else
-				disk_unlink(a->name);
-		}
-#if HAVE_SYMLINK
-		return symlink(linkname, a->name) ? errno : 0;
-#else
-		errno = 0;
-		r = la_CreateSymbolicLinkW((const wchar_t *)a->name, linkname,
-		    archive_entry_symlink_type(a->entry));
-		if (r == 0) {
-			if (errno == 0)
-				la_dosmaperr(GetLastError());
-			r = errno;
-		} else
-			r = 0;
-		return (r);
-#endif
-	}
-
-	/*
-	 * The remaining system calls all set permissions, so let's
-	 * try to take advantage of that to avoid an extra chmod()
-	 * call.  (Recall that umask is set to zero right now!)
-	 */
-
-	/* Mode we want for the final restored object (w/o file type bits). */
-	final_mode = a->mode & 07777;
-	/*
-	 * The mode that will actually be restored in this step.  Note
-	 * that SUID, SGID, etc, require additional work to ensure
-	 * security, so we never restore them at this point.
-	 */
-	mode = final_mode & 0777 & ~a->user_umask;
-
-	switch (a->mode & AE_IFMT) {
-	default:
-		/* POSIX requires that we fall through here. */
-		/* FALLTHROUGH */
-	case AE_IFREG:
-		a->tmpname = NULL;
-		fullname = a->name;
-		/* O_WRONLY | O_CREAT | O_EXCL */
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		ZeroMemory(&createExParams, sizeof(createExParams));
-		createExParams.dwSize = sizeof(createExParams);
-		createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
-		a->fh = CreateFile2(fullname, GENERIC_WRITE, 0,
-		    CREATE_NEW, &createExParams);
-#else
-		a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
-		    CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
-#endif
-		if (a->fh == INVALID_HANDLE_VALUE &&
-		    GetLastError() == ERROR_INVALID_NAME &&
-		    fullname == a->name) {
-			fullname = __la_win_permissive_name_w(a->name);
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-			a->fh = CreateFile2(fullname, GENERIC_WRITE, 0,
-			    CREATE_NEW, &createExParams);
-#else
-			a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
-			    CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
-#endif
-		}
-		if (a->fh == INVALID_HANDLE_VALUE) {
-			if (GetLastError() == ERROR_ACCESS_DENIED) {
-				DWORD attr;
-				/* Simulate an errno of POSIX system. */
-				attr = GetFileAttributesW(fullname);
-				if (attr == (DWORD)-1)
-					la_dosmaperr(GetLastError());
-				else if (attr & FILE_ATTRIBUTE_DIRECTORY)
-					errno = EISDIR;
-				else
-					errno = EACCES;
-			} else
-				la_dosmaperr(GetLastError());
-			r = 1;
-		} else
-			r = 0;
-		if (fullname != a->name)
-			free(fullname);
-		break;
-	case AE_IFCHR:
-	case AE_IFBLK:
-		/* TODO: Find a better way to warn about our inability
-		 * to restore a block device node. */
-		return (EINVAL);
-	case AE_IFDIR:
-		mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
-		fullname = a->name;
-		r = CreateDirectoryW(fullname, NULL);
-		if (r == 0 && GetLastError() == ERROR_INVALID_NAME &&
-			fullname == a->name) {
-			fullname = __la_win_permissive_name_w(a->name);
-			r = CreateDirectoryW(fullname, NULL);
-		}
-		if (r != 0) {
-			r = 0;
-			/* Defer setting dir times. */
-			a->deferred |= (a->todo & TODO_TIMES);
-			a->todo &= ~TODO_TIMES;
-			/* Never use an immediate chmod(). */
-			/* We can't avoid the chmod() entirely if EXTRACT_PERM
-			 * because of SysV SGID inheritance. */
-			if ((mode != final_mode)
-			    || (a->flags & ARCHIVE_EXTRACT_PERM))
-				a->deferred |= (a->todo & TODO_MODE);
-			a->todo &= ~TODO_MODE;
-		} else {
-			la_dosmaperr(GetLastError());
-			r = -1;
-		}
-		if (fullname != a->name)
-			free(fullname);
-		break;
-	case AE_IFIFO:
-		/* TODO: Find a better way to warn about our inability
-		 * to restore a fifo. */
-		return (EINVAL);
-	}
-
-	/* All the system calls above set errno on failure. */
-	if (r)
-		return (errno);
-
-	/* If we managed to set the final mode, we've avoided a chmod(). */
-	if (mode == final_mode)
-		a->todo &= ~TODO_MODE;
-	return (0);
-}
-
-/*
- * Cleanup function for archive_extract.  Mostly, this involves processing
- * the fixup list, which is used to address a number of problems:
- *   * Dir permissions might prevent us from restoring a file in that
- *     dir, so we restore the dir with minimum 0700 permissions first,
- *     then correct the mode at the end.
- *   * Similarly, the act of restoring a file touches the directory
- *     and changes the timestamp on the dir, so we have to touch-up dir
- *     timestamps at the end as well.
- *   * Some file flags can interfere with the restore by, for example,
- *     preventing the creation of hardlinks to those files.
- *   * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
- *
- * Note that tar/cpio do not require that archives be in a particular
- * order; there is no way to know when the last file has been restored
- * within a directory, so there's no way to optimize the memory usage
- * here by fixing up the directory any earlier than the
- * end-of-archive.
- *
- * XXX TODO: Directory ACLs should be restored here, for the same
- * reason we set directory perms here. XXX
- */
-static int
-_archive_write_disk_close(struct archive *_a)
-{
-	struct archive_write_disk *a = (struct archive_write_disk *)_a;
-	struct fixup_entry *next, *p;
-	int ret;
-
-	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-	    "archive_write_disk_close");
-	ret = _archive_write_disk_finish_entry(&a->archive);
-
-	/* Sort dir list so directories are fixed up in depth-first order. */
-	p = sort_dir_list(a->fixup_list);
-
-	while (p != NULL) {
-		a->pst = NULL; /* Mark stat cache as out-of-date. */
-		if (p->fixup & TODO_TIMES) {
-			set_times(a, INVALID_HANDLE_VALUE, p->mode, p->name,
-			    p->atime, p->atime_nanos,
-			    p->birthtime, p->birthtime_nanos,
-			    p->mtime, p->mtime_nanos,
-			    p->ctime, p->ctime_nanos);
-		}
-		if (p->fixup & TODO_MODE_BASE)
-			la_chmod(p->name, p->mode);
-		if (p->fixup & TODO_ACLS)
-			set_acls(a, INVALID_HANDLE_VALUE, p->name, &p->acl);
-		if (p->fixup & TODO_FFLAGS)
-			set_fflags_platform(p->name, p->fflags_set, 0);
-		next = p->next;
-		archive_acl_clear(&p->acl);
-		free(p->name);
-		free(p);
-		p = next;
-	}
-	a->fixup_list = NULL;
-	return (ret);
-}
-
-static int
-_archive_write_disk_free(struct archive *_a)
-{
-	struct archive_write_disk *a;
-	int ret;
-	if (_a == NULL)
-		return (ARCHIVE_OK);
-	archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
-	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
-	a = (struct archive_write_disk *)_a;
-	ret = _archive_write_disk_close(&a->archive);
-	archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
-	archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
-	archive_entry_free(a->entry);
-	archive_wstring_free(&a->_name_data);
-	archive_wstring_free(&a->_tmpname_data);
-	archive_string_free(&a->archive.error_string);
-	archive_wstring_free(&a->path_safe);
-	a->archive.magic = 0;
-	__archive_clean(&a->archive);
-	free(a);
-	return (ret);
-}
-
-/*
- * Simple O(n log n) merge sort to order the fixup list.  In
- * particular, we want to restore dir timestamps depth-first.
- */
-static struct fixup_entry *
-sort_dir_list(struct fixup_entry *p)
-{
-	struct fixup_entry *a, *b, *t;
-
-	if (p == NULL)
-		return (NULL);
-	/* A one-item list is already sorted. */
-	if (p->next == NULL)
-		return (p);
-
-	/* Step 1: split the list. */
-	t = p;
-	a = p->next->next;
-	while (a != NULL) {
-		/* Step a twice, t once. */
-		a = a->next;
-		if (a != NULL)
-			a = a->next;
-		t = t->next;
-	}
-	/* Now, t is at the mid-point, so break the list here. */
-	b = t->next;
-	t->next = NULL;
-	a = p;
-
-	/* Step 2: Recursively sort the two sub-lists. */
-	a = sort_dir_list(a);
-	b = sort_dir_list(b);
-
-	/* Step 3: Merge the returned lists. */
-	/* Pick the first element for the merged list. */
-	if (wcscmp(a->name, b->name) > 0) {
-		t = p = a;
-		a = a->next;
-	} else {
-		t = p = b;
-		b = b->next;
-	}
-
-	/* Always put the later element on the list first. */
-	while (a != NULL && b != NULL) {
-		if (wcscmp(a->name, b->name) > 0) {
-			t->next = a;
-			a = a->next;
-		} else {
-			t->next = b;
-			b = b->next;
-		}
-		t = t->next;
-	}
-
-	/* Only one list is non-empty, so just splice it on. */
-	if (a != NULL)
-		t->next = a;
-	if (b != NULL)
-		t->next = b;
-
-	return (p);
-}
-
-/*
- * Returns a new, initialized fixup entry.
- *
- * TODO: Reduce the memory requirements for this list by using a tree
- * structure rather than a simple list of names.
- */
-static struct fixup_entry *
-new_fixup(struct archive_write_disk *a, const wchar_t *pathname)
-{
-	struct fixup_entry *fe;
-
-	fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
-	if (fe == NULL)
-		return (NULL);
-	fe->next = a->fixup_list;
-	a->fixup_list = fe;
-	fe->fixup = 0;
-	fe->name = _wcsdup(pathname);
-	fe->fflags_set = 0;
-	return (fe);
-}
-
-/*
- * Returns a fixup structure for the current entry.
- */
-static struct fixup_entry *
-current_fixup(struct archive_write_disk *a, const wchar_t *pathname)
-{
-	if (a->current_fixup == NULL)
-		a->current_fixup = new_fixup(a, pathname);
-	return (a->current_fixup);
-}
-
-/*
- * TODO: The deep-directory support bypasses this; disable deep directory
- * support if we're doing symlink checks.
- */
-/*
- * TODO: Someday, integrate this with the deep dir support; they both
- * scan the path and both can be optimized by comparing against other
- * recent paths.
- */
-static int
-check_symlinks(struct archive_write_disk *a)
-{
-	wchar_t *pn, *p;
-	wchar_t c;
-	int r;
-	BY_HANDLE_FILE_INFORMATION st;
-	mode_t st_mode;
-
-	/*
-	 * Guard against symlink tricks.  Reject any archive entry whose
-	 * destination would be altered by a symlink.
-	 */
-	/* Whatever we checked last time doesn't need to be re-checked. */
-	pn = a->name;
-	p = a->path_safe.s;
-	while ((*pn != '\0') && (*p == *pn))
-		++p, ++pn;
-	/* Skip leading backslashes */
-	while (*pn == '\\')
-		++pn;
-	c = pn[0];
-	/* Keep going until we've checked the entire name. */
-	while (pn[0] != '\0' && (pn[0] != '\\' || pn[1] != '\0')) {
-		/* Skip the next path element. */
-		while (*pn != '\0' && *pn != '\\')
-			++pn;
-		c = pn[0];
-		pn[0] = '\0';
-		/* Check that we haven't hit a symlink. */
-		r = file_information(a, a->name, &st, &st_mode, 1);
-		if (r != 0) {
-			/* We've hit a dir that doesn't exist; stop now. */
-			if (errno == ENOENT)
-				break;
-		} else if (S_ISLNK(st_mode)) {
-			if (c == '\0') {
-				/*
-				 * Last element is a file or directory symlink.
-				 * Remove it so we can overwrite it with the
-				 * item being extracted.
-				 */
-				if (a->flags &
-				    ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) {
-					(void)clear_nochange_fflags(a);
-				}
-				if (st.dwFileAttributes &
-				    FILE_ATTRIBUTE_DIRECTORY) {
-					r = disk_rmdir(a->name);
-				} else {
-					r = disk_unlink(a->name);
-				}
-				if (r) {
-					archive_set_error(&a->archive, errno,
-					    "Could not remove symlink %ls",
-					    a->name);
-					pn[0] = c;
-					return (ARCHIVE_FAILED);
-				}
-				a->pst = NULL;
-				/*
-				 * Even if we did remove it, a warning
-				 * is in order.  The warning is silly,
-				 * though, if we're just replacing one
-				 * symlink with another symlink.
-				 */
-				if (!S_ISLNK(a->mode)) {
-					archive_set_error(&a->archive, 0,
-					    "Removing symlink %ls",
-					    a->name);
-				}
-				/* Symlink gone.  No more problem! */
-				pn[0] = c;
-				return (0);
-			} else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
-				/* User asked us to remove problems. */
-				if (a->flags &
-				    ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) {
-					(void)clear_nochange_fflags(a);
-				}
-				if (st.dwFileAttributes &
-				    FILE_ATTRIBUTE_DIRECTORY) {
-					r = disk_rmdir(a->name);
-				} else {
-					r = disk_unlink(a->name);
-				}
-				if (r != 0) {
-					archive_set_error(&a->archive, 0,
-					    "Cannot remove intervening "
-					    "symlink %ls", a->name);
-					pn[0] = c;
-					return (ARCHIVE_FAILED);
-				}
-				a->pst = NULL;
-			} else {
-				archive_set_error(&a->archive, 0,
-				    "Cannot extract through symlink %ls",
-				    a->name);
-				pn[0] = c;
-				return (ARCHIVE_FAILED);
-			}
-		}
-		if (!c)
-			break;
-		pn[0] = c;
-		pn++;
-	}
-	pn[0] = c;
-	/* We've checked and/or cleaned the whole path, so remember it. */
-	archive_wstrcpy(&a->path_safe, a->name);
-	return (ARCHIVE_OK);
-}
-
-static int
-guidword(wchar_t *p, int n)
-{
-	int i;
-
-	for (i = 0; i < n; i++) {
-		if ((*p >= L'0' && *p <= L'9') ||
-		    (*p >= L'a' && *p <= L'f') ||
-		    (*p >= L'A' && *p <= L'F'))
-			p++;
-		else
-			return (-1);
-	}
-	return (0);
-}
-
-/*
- * Canonicalize the pathname.  In particular, this strips duplicate
- * '\' characters, '.' elements, and trailing '\'.  It also raises an
- * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is
- * set) any '..' in the path.
- */
-static int
-cleanup_pathname(struct archive_write_disk *a, wchar_t *name)
-{
-	wchar_t *dest, *src, *p, *top;
-	wchar_t separator = L'\0';
-
-	p = name;
-	if (*p == L'\0') {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid empty pathname");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Replace '/' by '\' */
-	for (; *p != L'\0'; p++) {
-		if (*p == L'/')
-			*p = L'\\';
-	}
-	p = name;
-
-	/* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or
-	 * "\\?\Volume{GUID}\"
-	 * (absolute path prefixes used by Windows API) */
-	if (p[0] == L'\\' && p[1] == L'\\' &&
-	    (p[2] == L'.' || p[2] == L'?') && p[3] ==  L'\\')
-	{
-		/* A path begin with "\\?\UNC\" */
-		if (p[2] == L'?' &&
-		    (p[4] == L'U' || p[4] == L'u') &&
-		    (p[5] == L'N' || p[5] == L'n') &&
-		    (p[6] == L'C' || p[6] == L'c') &&
-		    p[7] == L'\\')
-			p += 8;
-		/* A path begin with "\\?\Volume{GUID}\" */
-		else if (p[2] == L'?' &&
-		    (p[4] == L'V' || p[4] == L'v') &&
-		    (p[5] == L'O' || p[5] == L'o') &&
-		    (p[6] == L'L' || p[6] == L'l') &&
-		    (p[7] == L'U' || p[7] == L'u') &&
-		    (p[8] == L'M' || p[8] == L'm') &&
-		    (p[9] == L'E' || p[9] == L'e') &&
-		    p[10] == L'{') {
-			if (guidword(p+11, 8) == 0 && p[19] == L'-' &&
-			    guidword(p+20, 4) == 0 && p[24] == L'-' &&
-			    guidword(p+25, 4) == 0 && p[29] == L'-' &&
-			    guidword(p+30, 4) == 0 && p[34] == L'-' &&
-			    guidword(p+35, 12) == 0 && p[47] == L'}' &&
-			    p[48] == L'\\')
-				p += 49;
-			else
-				p += 4;
-		/* A path begin with "\\.\PhysicalDriveX" */
-		} else if (p[2] == L'.' &&
-		    (p[4] == L'P' || p[4] == L'p') &&
-		    (p[5] == L'H' || p[5] == L'h') &&
-		    (p[6] == L'Y' || p[6] == L'y') &&
-		    (p[7] == L'S' || p[7] == L's') &&
-		    (p[8] == L'I' || p[8] == L'i') &&
-		    (p[9] == L'C' || p[9] == L'c') &&
-		    (p[9] == L'A' || p[9] == L'a') &&
-		    (p[9] == L'L' || p[9] == L'l') &&
-		    (p[9] == L'D' || p[9] == L'd') &&
-		    (p[9] == L'R' || p[9] == L'r') &&
-		    (p[9] == L'I' || p[9] == L'i') &&
-		    (p[9] == L'V' || p[9] == L'v') &&
-		    (p[9] == L'E' || p[9] == L'e') &&
-		    (p[10] >= L'0' && p[10] <= L'9') &&
-		    p[11] == L'\0') {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Path is a physical drive name");
-			return (ARCHIVE_FAILED);
-		} else
-			p += 4;
-    /* Network drive path like "\\<server-name>\<share-name>\file" */
-    } else if (p[0] == L'\\' && p[1] == L'\\') {
-        p += 2;
-	}
-
-	/* Skip leading drive letter from archives created
-	 * on Windows. */
-	if (((p[0] >= L'a' && p[0] <= L'z') ||
-	     (p[0] >= L'A' && p[0] <= L'Z')) &&
-		 p[1] == L':') {
-		if (p[2] == L'\0') {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Path is a drive name");
-			return (ARCHIVE_FAILED);
-		}
-		if (p[2] == L'\\')
-			p += 2;
-	}
-
-	top = dest = src = p;
-	/* Rewrite the path name if its character is a unusable. */
-	for (; *p != L'\0'; p++) {
-		if (*p == L':' || *p == L'*' || *p == L'?' || *p == L'"' ||
-		    *p == L'<' || *p == L'>' || *p == L'|')
-			*p = L'_';
-	}
-	/* Skip leading '\'. */
-	if (*src == L'\\')
-		separator = *src++;
-
-	/* Scan the pathname one element at a time. */
-	for (;;) {
-		/* src points to first char after '\' */
-		if (src[0] == L'\0') {
-			break;
-		} else if (src[0] == L'\\') {
-			/* Found '\\'('//'), ignore second one. */
-			src++;
-			continue;
-		} else if (src[0] == L'.') {
-			if (src[1] == L'\0') {
-				/* Ignore trailing '.' */
-				break;
-			} else if (src[1] == L'\\') {
-				/* Skip '.\'. */
-				src += 2;
-				continue;
-			} else if (src[1] == L'.') {
-				if (src[2] == L'\\' || src[2] == L'\0') {
-					/* Conditionally warn about '..' */
-					if (a->flags &
-					    ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_MISC,
-						    "Path contains '..'");
-						return (ARCHIVE_FAILED);
-					}
-				}
-				/*
-				 * Note: Under no circumstances do we
-				 * remove '..' elements.  In
-				 * particular, restoring
-				 * '\foo\..\bar\' should create the
-				 * 'foo' dir as a side-effect.
-				 */
-			}
-		}
-
-		/* Copy current element, including leading '\'. */
-		if (separator)
-			*dest++ = L'\\';
-		while (*src != L'\0' && *src != L'\\') {
-			*dest++ = *src++;
-		}
-
-		if (*src == L'\0')
-			break;
-
-		/* Skip '\' separator. */
-		separator = *src++;
-	}
-	/*
-	 * We've just copied zero or more path elements, not including the
-	 * final '\'.
-	 */
-	if (dest == top) {
-		/*
-		 * Nothing got copied.  The path must have been something
-		 * like '.' or '\' or './' or '/././././/./'.
-		 */
-		if (separator)
-			*dest++ = L'\\';
-		else
-			*dest++ = L'.';
-	}
-	/* Terminate the result. */
-	*dest = L'\0';
-	return (ARCHIVE_OK);
-}
-
-/*
- * Create the parent directory of the specified path, assuming path
- * is already in mutable storage.
- */
-static int
-create_parent_dir(struct archive_write_disk *a, wchar_t *path)
-{
-	wchar_t *slash;
-	int r;
-
-	/* Remove tail element to obtain parent name. */
-	slash = wcsrchr(path, L'\\');
-	if (slash == NULL)
-		return (ARCHIVE_OK);
-	*slash = L'\0';
-	r = create_dir(a, path);
-	*slash = L'\\';
-	return (r);
-}
-
-/*
- * Create the specified dir, recursing to create parents as necessary.
- *
- * Returns ARCHIVE_OK if the path exists when we're done here.
- * Otherwise, returns ARCHIVE_FAILED.
- * Assumes path is in mutable storage; path is unchanged on exit.
- */
-static int
-create_dir(struct archive_write_disk *a, wchar_t *path)
-{
-	BY_HANDLE_FILE_INFORMATION st;
-	struct fixup_entry *le;
-	wchar_t *slash, *base, *full;
-	mode_t mode_final, mode, st_mode;
-	int r;
-
-	/* Check for special names and just skip them. */
-	slash = wcsrchr(path, L'\\');
-	if (slash == NULL)
-		base = path;
-	else
-		base = slash + 1;
-
-	if (base[0] == L'\0' ||
-	    (base[0] == L'.' && base[1] == L'\0') ||
-	    (base[0] == L'.' && base[1] == L'.' && base[2] == L'\0')) {
-		/* Don't bother trying to create null path, '.', or '..'. */
-		if (slash != NULL) {
-			*slash = L'\0';
-			r = create_dir(a, path);
-			*slash = L'\\';
-			return (r);
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/*
-	 * Yes, this should be stat() and not lstat().  Using lstat()
-	 * here loses the ability to extract through symlinks.  Also note
-	 * that this should not use the a->st cache.
-	 */
-	if (file_information(a, path, &st, &st_mode, 0) == 0) {
-		if (S_ISDIR(st_mode))
-			return (ARCHIVE_OK);
-		if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
-			archive_set_error(&a->archive, EEXIST,
-			    "Can't create directory '%ls'", path);
-			return (ARCHIVE_FAILED);
-		}
-		if (disk_unlink(path) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't create directory '%ls': "
-			    "Conflicting file cannot be removed",
-			    path);
-			return (ARCHIVE_FAILED);
-		}
-	} else if (errno != ENOENT && errno != ENOTDIR) {
-		/* Stat failed? */
-		archive_set_error(&a->archive, errno,
-		    "Can't test directory '%ls'", path);
-		return (ARCHIVE_FAILED);
-	} else if (slash != NULL) {
-		*slash = '\0';
-		r = create_dir(a, path);
-		*slash = '\\';
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-
-	/*
-	 * Mode we want for the final restored directory.  Per POSIX,
-	 * implicitly-created dirs must be created obeying the umask.
-	 * There's no mention whether this is different for privileged
-	 * restores (which the rest of this code handles by pretending
-	 * umask=0).  I've chosen here to always obey the user's umask for
-	 * implicit dirs, even if _EXTRACT_PERM was specified.
-	 */
-	mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
-	/* Mode we want on disk during the restore process. */
-	mode = mode_final;
-	mode |= MINIMUM_DIR_MODE;
-	mode &= MAXIMUM_DIR_MODE;
-	/*
-	 * Apply __la_win_permissive_name_w to path in order to
-	 * remove '../' path string.
-	 */
-	full = __la_win_permissive_name_w(path);
-	if (full == NULL)
-		errno = EINVAL;
-	else if (CreateDirectoryW(full, NULL) != 0) {
-		if (mode != mode_final) {
-			le = new_fixup(a, path);
-			le->fixup |=TODO_MODE_BASE;
-			le->mode = mode_final;
-		}
-		free(full);
-		return (ARCHIVE_OK);
-	} else {
-		la_dosmaperr(GetLastError());
-	}
-	free(full);
-
-	/*
-	 * Without the following check, a/b/../b/c/d fails at the
-	 * second visit to 'b', so 'd' can't be created.  Note that we
-	 * don't add it to the fixup list here, as it's already been
-	 * added.
-	 */
-	if (file_information(a, path, &st, &st_mode, 0) == 0 &&
-	    S_ISDIR(st_mode))
-		return (ARCHIVE_OK);
-
-	archive_set_error(&a->archive, errno, "Failed to create dir '%ls'",
-	    path);
-	return (ARCHIVE_FAILED);
-}
-
-/*
- * Note: Although we can skip setting the user id if the desired user
- * id matches the current user, we cannot skip setting the group, as
- * many systems set the gid based on the containing directory.  So
- * we have to perform a chown syscall if we want to set the SGID
- * bit.  (The alternative is to stat() and then possibly chown(); it's
- * more efficient to skip the stat() and just always chown().)  Note
- * that a successful chown() here clears the TODO_SGID_CHECK bit, which
- * allows set_mode to skip the stat() check for the GID.
- */
-static int
-set_ownership(struct archive_write_disk *a)
-{
-/* unfortunately, on win32 there is no 'root' user with uid 0,
-   so we just have to try the chown and see if it works */
-
-	/* If we know we can't change it, don't bother trying. */
-	if (a->user_uid != 0  &&  a->user_uid != a->uid) {
-		archive_set_error(&a->archive, errno,
-		    "Can't set UID=%jd", (intmax_t)a->uid);
-		return (ARCHIVE_WARN);
-	}
-
-	archive_set_error(&a->archive, errno,
-	    "Can't set user=%jd/group=%jd for %ls",
-	    (intmax_t)a->uid, (intmax_t)a->gid, a->name);
-	return (ARCHIVE_WARN);
-}
-
-static int
-set_times(struct archive_write_disk *a,
-    HANDLE h, int mode, const wchar_t *name,
-    time_t atime, long atime_nanos,
-    time_t birthtime, long birthtime_nanos,
-    time_t mtime, long mtime_nanos,
-    time_t ctime_sec, long ctime_nanos)
-{
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
-	 + (((nsec)/1000)*10))
-
-	HANDLE hw = 0;
-	ULARGE_INTEGER wintm;
-	FILETIME *pfbtime;
-	FILETIME fatime, fbtime, fmtime;
-
-	(void)ctime_sec; /* UNUSED */
-	(void)ctime_nanos; /* UNUSED */
-
-	if (h != INVALID_HANDLE_VALUE) {
-		hw = NULL;
-	} else {
-		wchar_t *ws;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		CREATEFILE2_EXTENDED_PARAMETERS createExParams;
-#endif
-
-		if (S_ISLNK(mode))
-			return (ARCHIVE_OK);
-		ws = __la_win_permissive_name_w(name);
-		if (ws == NULL)
-			goto settimes_failed;
-# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
-		ZeroMemory(&createExParams, sizeof(createExParams));
-		createExParams.dwSize = sizeof(createExParams);
-		createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
-		hw = CreateFile2(ws, FILE_WRITE_ATTRIBUTES, 0,
-		    OPEN_EXISTING, &createExParams);
-#else
-		hw = CreateFileW(ws, FILE_WRITE_ATTRIBUTES,
-		    0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-#endif
-		free(ws);
-		if (hw == INVALID_HANDLE_VALUE)
-			goto settimes_failed;
-		h = hw;
-	}
-
-	wintm.QuadPart = WINTIME(atime, atime_nanos);
-	fatime.dwLowDateTime = wintm.LowPart;
-	fatime.dwHighDateTime = wintm.HighPart;
-	wintm.QuadPart = WINTIME(mtime, mtime_nanos);
-	fmtime.dwLowDateTime = wintm.LowPart;
-	fmtime.dwHighDateTime = wintm.HighPart;
-	/*
-	 * SetFileTime() supports birthtime.
-	 */
-	if (birthtime > 0 || birthtime_nanos > 0) {
-		wintm.QuadPart = WINTIME(birthtime, birthtime_nanos);
-		fbtime.dwLowDateTime = wintm.LowPart;
-		fbtime.dwHighDateTime = wintm.HighPart;
-		pfbtime = &fbtime;
-	} else
-		pfbtime = NULL;
-	if (SetFileTime(h, pfbtime, &fatime, &fmtime) == 0)
-		goto settimes_failed;
-	CloseHandle(hw);
-	return (ARCHIVE_OK);
-
-settimes_failed:
-	CloseHandle(hw);
-	archive_set_error(&a->archive, EINVAL, "Can't restore time");
-	return (ARCHIVE_WARN);
-}
-
-static int
-set_times_from_entry(struct archive_write_disk *a)
-{
-	time_t atime, birthtime, mtime, ctime_sec;
-	long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
-
-	/* Suitable defaults. */
-	atime = birthtime = mtime = ctime_sec = a->start_time;
-	atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
-
-	/* If no time was provided, we're done. */
-	if (!archive_entry_atime_is_set(a->entry)
-	    && !archive_entry_birthtime_is_set(a->entry)
-	    && !archive_entry_mtime_is_set(a->entry))
-		return (ARCHIVE_OK);
-
-	if (archive_entry_atime_is_set(a->entry)) {
-		atime = archive_entry_atime(a->entry);
-		atime_nsec = archive_entry_atime_nsec(a->entry);
-	}
-	if (archive_entry_birthtime_is_set(a->entry)) {
-		birthtime = archive_entry_birthtime(a->entry);
-		birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
-	}
-	if (archive_entry_mtime_is_set(a->entry)) {
-		mtime = archive_entry_mtime(a->entry);
-		mtime_nsec = archive_entry_mtime_nsec(a->entry);
-	}
-	if (archive_entry_ctime_is_set(a->entry)) {
-		ctime_sec = archive_entry_ctime(a->entry);
-		ctime_nsec = archive_entry_ctime_nsec(a->entry);
-	}
-
-	return set_times(a, a->fh, a->mode, a->name,
-			 atime, atime_nsec,
-			 birthtime, birthtime_nsec,
-			 mtime, mtime_nsec,
-			 ctime_sec, ctime_nsec);
-}
-
-static int
-set_mode(struct archive_write_disk *a, int mode)
-{
-	int r = ARCHIVE_OK;
-	mode &= 07777; /* Strip off file type bits. */
-
-	if (a->todo & TODO_SGID_CHECK) {
-		/*
-		 * If we don't know the GID is right, we must stat()
-		 * to verify it.  We can't just check the GID of this
-		 * process, since systems sometimes set GID from
-		 * the enclosing dir or based on ACLs.
-		 */
-		if ((r = lazy_stat(a)) != ARCHIVE_OK)
-			return (r);
-		if (0 != a->gid) {
-			mode &= ~ S_ISGID;
-		}
-		/* While we're here, double-check the UID. */
-		if (0 != a->uid
-		    && (a->todo & TODO_SUID)) {
-			mode &= ~ S_ISUID;
-		}
-		a->todo &= ~TODO_SGID_CHECK;
-		a->todo &= ~TODO_SUID_CHECK;
-	} else if (a->todo & TODO_SUID_CHECK) {
-		/*
-		 * If we don't know the UID is right, we can just check
-		 * the user, since all systems set the file UID from
-		 * the process UID.
-		 */
-		if (a->user_uid != a->uid) {
-			mode &= ~ S_ISUID;
-		}
-		a->todo &= ~TODO_SUID_CHECK;
-	}
-
-	if (S_ISLNK(a->mode)) {
-#ifdef HAVE_LCHMOD
-		/*
-		 * If this is a symlink, use lchmod().  If the
-		 * platform doesn't support lchmod(), just skip it.  A
-		 * platform that doesn't provide a way to set
-		 * permissions on symlinks probably ignores
-		 * permissions on symlinks, so a failure here has no
-		 * impact.
-		 */
-		if (lchmod(a->name, mode) != 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't set permissions to 0%o", (int)mode);
-			r = ARCHIVE_WARN;
-		}
-#endif
-	} else if (!S_ISDIR(a->mode)) {
-		/*
-		 * If it's not a symlink and not a dir, then use
-		 * fchmod() or chmod(), depending on whether we have
-		 * an fd.  Dirs get their perms set during the
-		 * post-extract fixup, which is handled elsewhere.
-		 */
-#ifdef HAVE_FCHMOD
-		if (a->fd >= 0) {
-			if (fchmod(a->fd, mode) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Can't set permissions to 0%o", (int)mode);
-				r = ARCHIVE_WARN;
-			}
-		} else
-#endif
-			/* If this platform lacks fchmod(), then
-			 * we'll just use chmod(). */
-			if (la_chmod(a->name, mode) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Can't set permissions to 0%o", (int)mode);
-				r = ARCHIVE_WARN;
-			}
-	}
-	return (r);
-}
-
-static int set_fflags_platform(const wchar_t *name, unsigned long fflags_set,
-    unsigned long fflags_clear)
-{
-	DWORD oldflags, newflags;
-	wchar_t *fullname;
-
-	const DWORD settable_flags =
-	    FILE_ATTRIBUTE_ARCHIVE |
-	    FILE_ATTRIBUTE_HIDDEN |
-	    FILE_ATTRIBUTE_NORMAL |
-	    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
-	    FILE_ATTRIBUTE_OFFLINE |
-	    FILE_ATTRIBUTE_READONLY |
-	    FILE_ATTRIBUTE_SYSTEM |
-	    FILE_ATTRIBUTE_TEMPORARY;
-
-	oldflags = GetFileAttributesW(name);
-	if (oldflags == (DWORD)-1 &&
-	    GetLastError() == ERROR_INVALID_NAME) {
-		fullname = __la_win_permissive_name_w(name);
-		oldflags = GetFileAttributesW(fullname);
-	}
-	if (oldflags == (DWORD)-1) {
-		la_dosmaperr(GetLastError());
-		return (ARCHIVE_WARN);
-	}
-	newflags = ((oldflags & ~fflags_clear) | fflags_set) & settable_flags;
-	if(SetFileAttributesW(name, newflags) == 0)
-		return (ARCHIVE_WARN);
-	return (ARCHIVE_OK);
-}
-
-static int
-clear_nochange_fflags(struct archive_write_disk *a)
-{
-	return (set_fflags_platform(a->name, 0, FILE_ATTRIBUTE_READONLY));
-}
-
-static int
-set_fflags(struct archive_write_disk *a)
-{
-	unsigned long	set, clear;
-
-	if (a->todo & TODO_FFLAGS) {
-		archive_entry_fflags(a->entry, &set, &clear);
-		if (set == 0  && clear == 0)
-			return (ARCHIVE_OK);
-		return (set_fflags_platform(a->name, set, clear));
-
-        }
-	return (ARCHIVE_OK);
-}
-
-/* Default empty function body to satisfy mainline code. */
-static int
-set_acls(struct archive_write_disk *a, HANDLE h, const wchar_t *name,
-	 struct archive_acl *acl)
-{
-	(void)a; /* UNUSED */
-	(void)h; /* UNUSED */
-	(void)name; /* UNUSED */
-	(void)acl; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-/*
- * Restore extended attributes - stub implementation for unsupported systems
- */
-static int
-set_xattrs(struct archive_write_disk *a)
-{
-	static int warning_done = 0;
-
-	/* If there aren't any extended attributes, then it's okay not
-	 * to extract them, otherwise, issue a single warning. */
-	if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
-		warning_done = 1;
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Cannot restore extended attributes on this system");
-		return (ARCHIVE_WARN);
-	}
-	/* Warning was already emitted; suppress further warnings. */
-	return (ARCHIVE_OK);
-}
-
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		/* milli seconds base */
-		*t = (time_t)(utc.QuadPart / 10000000);
-		/* nano seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-/*
- * Test if file on disk is older than entry.
- */
-static int
-older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
-{
-	time_t sec;
-	long nsec;
-
-	fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec);
-	/* First, test the seconds and return if we have a definite answer. */
-	/* Definitely older. */
-	if (sec < archive_entry_mtime(entry))
-		return (1);
-	/* Definitely younger. */
-	if (sec > archive_entry_mtime(entry))
-		return (0);
-	if (nsec < archive_entry_mtime_nsec(entry))
-		return (1);
-	/* Same age or newer, so not older. */
-	return (0);
-}
-
-#endif /* _WIN32 && !__CYGWIN__ */
-
diff --git a/c/archive_write_open_fd.c b/c/archive_write_open_fd.c
deleted file mode 100644
--- a/c/archive_write_open_fd.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_fd.c 201093 2009-12-28 02:28:44Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-
-struct write_fd_data {
-	int		fd;
-};
-
-static int	file_free(struct archive *, void *);
-static int	file_open(struct archive *, void *);
-static ssize_t	file_write(struct archive *, void *, const void *buff, size_t);
-
-int
-archive_write_open_fd(struct archive *a, int fd)
-{
-	struct write_fd_data *mine;
-
-	mine = (struct write_fd_data *)malloc(sizeof(*mine));
-	if (mine == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	mine->fd = fd;
-#if defined(__CYGWIN__) || defined(_WIN32)
-	setmode(mine->fd, O_BINARY);
-#endif
-	return (archive_write_open2(a, mine,
-		    file_open, file_write, NULL, file_free));
-}
-
-static int
-file_open(struct archive *a, void *client_data)
-{
-	struct write_fd_data *mine;
-	struct stat st;
-
-	mine = (struct write_fd_data *)client_data;
-
-	if (fstat(mine->fd, &st) != 0) {
-		archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd);
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * If this is a regular file, don't add it to itself.
-	 */
-	if (S_ISREG(st.st_mode))
-		archive_write_set_skip_file(a, st.st_dev, st.st_ino);
-
-	/*
-	 * If client hasn't explicitly set the last block handling,
-	 * then set it here.
-	 */
-	if (archive_write_get_bytes_in_last_block(a) < 0) {
-		/* If the output is a block or character device, fifo,
-		 * or stdout, pad the last block, otherwise leave it
-		 * unpadded. */
-		if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
-		    S_ISFIFO(st.st_mode) || (mine->fd == 1))
-			/* Last block will be fully padded. */
-			archive_write_set_bytes_in_last_block(a, 0);
-		else
-			archive_write_set_bytes_in_last_block(a, 1);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-file_write(struct archive *a, void *client_data, const void *buff, size_t length)
-{
-	struct write_fd_data	*mine;
-	ssize_t	bytesWritten;
-
-	mine = (struct write_fd_data *)client_data;
-	for (;;) {
-		bytesWritten = write(mine->fd, buff, length);
-		if (bytesWritten <= 0) {
-			if (errno == EINTR)
-				continue;
-			archive_set_error(a, errno, "Write error");
-			return (-1);
-		}
-		return (bytesWritten);
-	}
-}
-
-static int
-file_free(struct archive *a, void *client_data)
-{
-	struct write_fd_data	*mine = (struct write_fd_data *)client_data;
-
-	(void)a; /* UNUSED */
-	if (mine == NULL)
-		return (ARCHIVE_OK);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_open_file.c b/c/archive_write_open_file.c
deleted file mode 100644
--- a/c/archive_write_open_file.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_file.c,v 1.19 2007/01/09 08:05:56 kientzle Exp $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-
-struct write_FILE_data {
-	FILE		*f;
-};
-
-static int	file_free(struct archive *, void *);
-static int	file_open(struct archive *, void *);
-static ssize_t	file_write(struct archive *, void *, const void *buff, size_t);
-
-int
-archive_write_open_FILE(struct archive *a, FILE *f)
-{
-	struct write_FILE_data *mine;
-
-	mine = (struct write_FILE_data *)malloc(sizeof(*mine));
-	if (mine == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	mine->f = f;
-	return (archive_write_open2(a, mine, file_open, file_write,
-	    NULL, file_free));
-}
-
-static int
-file_open(struct archive *a, void *client_data)
-{
-	(void)a; /* UNUSED */
-	(void)client_data; /* UNUSED */
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-file_write(struct archive *a, void *client_data, const void *buff, size_t length)
-{
-	struct write_FILE_data	*mine;
-	size_t	bytesWritten;
-
-	mine = client_data;
-	for (;;) {
-		bytesWritten = fwrite(buff, 1, length, mine->f);
-		if (bytesWritten <= 0) {
-			if (errno == EINTR)
-				continue;
-			archive_set_error(a, errno, "Write error");
-			return (-1);
-		}
-		return (bytesWritten);
-	}
-}
-
-static int
-file_free(struct archive *a, void *client_data)
-{
-	struct write_FILE_data	*mine = client_data;
-
-	(void)a; /* UNUSED */
-	if (mine == NULL)
-		return (ARCHIVE_OK);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_open_filename.c b/c/archive_write_open_filename.c
deleted file mode 100644
--- a/c/archive_write_open_filename.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_filename.c 191165 2009-04-17 00:39:35Z kientzle $");
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_string.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_CLOEXEC
-#define O_CLOEXEC	0
-#endif
-
-struct write_file_data {
-	int		fd;
-	struct archive_mstring filename;
-};
-
-static int	file_close(struct archive *, void *);
-static int	file_free(struct archive *, void *);
-static int	file_open(struct archive *, void *);
-static ssize_t	file_write(struct archive *, void *, const void *buff, size_t);
-static int	open_filename(struct archive *, int, const void *);
-
-int
-archive_write_open_file(struct archive *a, const char *filename)
-{
-	return (archive_write_open_filename(a, filename));
-}
-
-int
-archive_write_open_filename(struct archive *a, const char *filename)
-{
-
-	if (filename == NULL || filename[0] == '\0')
-		return (archive_write_open_fd(a, 1));
-
-	return (open_filename(a, 1, filename));
-}
-
-int
-archive_write_open_filename_w(struct archive *a, const wchar_t *filename)
-{
-
-	if (filename == NULL || filename[0] == L'\0')
-		return (archive_write_open_fd(a, 1));
-
-	return (open_filename(a, 0, filename));
-}
-
-static int
-open_filename(struct archive *a, int mbs_fn, const void *filename)
-{
-	struct write_file_data *mine;
-	int r;
-
-	mine = (struct write_file_data *)calloc(1, sizeof(*mine));
-	if (mine == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	if (mbs_fn)
-		r = archive_mstring_copy_mbs(&mine->filename, filename);
-	else
-		r = archive_mstring_copy_wcs(&mine->filename, filename);
-	if (r < 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(a, ENOMEM, "No memory");
-			return (ARCHIVE_FATAL);
-		}
-		if (mbs_fn)
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Can't convert '%s' to WCS",
-			    (const char *)filename);
-		else
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "Can't convert '%S' to MBS",
-			    (const wchar_t *)filename);
-		return (ARCHIVE_FAILED);
-	}
-	mine->fd = -1;
-	return (archive_write_open2(a, mine,
-		    file_open, file_write, file_close, file_free));
-}
-
-static int
-file_open(struct archive *a, void *client_data)
-{
-	int flags;
-	struct write_file_data *mine;
-	struct stat st;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	wchar_t *fullpath;
-#endif
-	const wchar_t *wcs;
-	const char *mbs;
-
-	mine = (struct write_file_data *)client_data;
-	flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC;
-
-	/*
-	 * Open the file.
-	 */
-	mbs = NULL; wcs = NULL;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	if (archive_mstring_get_wcs(a, &mine->filename, &wcs) != 0) {
-		if (errno == ENOMEM)
-			archive_set_error(a, errno, "No memory");
-		else {
-			archive_mstring_get_mbs(a, &mine->filename, &mbs);
-			archive_set_error(a, errno,
-			    "Can't convert '%s' to WCS", mbs);
-		}
-		return (ARCHIVE_FATAL);
-	}
-	fullpath = __la_win_permissive_name_w(wcs);
-	if (fullpath != NULL) {
-		mine->fd = _wopen(fullpath, flags, 0666);
-		free(fullpath);
-	} else
-		mine->fd = _wopen(wcs, flags, 0666);
-#else
-	if (archive_mstring_get_mbs(a, &mine->filename, &mbs) != 0) {
-		if (errno == ENOMEM)
-			archive_set_error(a, errno, "No memory");
-		else {
-			archive_mstring_get_wcs(a, &mine->filename, &wcs);
-			archive_set_error(a, errno,
-			    "Can't convert '%S' to MBS", wcs);
-		}
-		return (ARCHIVE_FATAL);
-	}
-	mine->fd = open(mbs, flags, 0666);
-	__archive_ensure_cloexec_flag(mine->fd);
-#endif
-	if (mine->fd < 0) {
-		if (mbs != NULL)
-			archive_set_error(a, errno, "Failed to open '%s'", mbs);
-		else
-			archive_set_error(a, errno, "Failed to open '%S'", wcs);
-		return (ARCHIVE_FATAL);
-	}
-
-	if (fstat(mine->fd, &st) != 0) {
-		if (mbs != NULL)
-			archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
-		else
-			archive_set_error(a, errno, "Couldn't stat '%S'", wcs);
-		return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Set up default last block handling.
-	 */
-	if (archive_write_get_bytes_in_last_block(a) < 0) {
-		if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
-		    S_ISFIFO(st.st_mode))
-			/* Pad last block when writing to device or FIFO. */
-			archive_write_set_bytes_in_last_block(a, 0);
-		else
-			/* Don't pad last block otherwise. */
-			archive_write_set_bytes_in_last_block(a, 1);
-	}
-
-	/*
-	 * If the output file is a regular file, don't add it to
-	 * itself.  If it's a device file, it's okay to add the device
-	 * entry to the output archive.
-	 */
-	if (S_ISREG(st.st_mode))
-		archive_write_set_skip_file(a, st.st_dev, st.st_ino);
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-file_write(struct archive *a, void *client_data, const void *buff,
-    size_t length)
-{
-	struct write_file_data	*mine;
-	ssize_t	bytesWritten;
-
-	mine = (struct write_file_data *)client_data;
-	for (;;) {
-		bytesWritten = write(mine->fd, buff, length);
-		if (bytesWritten <= 0) {
-			if (errno == EINTR)
-				continue;
-			archive_set_error(a, errno, "Write error");
-			return (-1);
-		}
-		return (bytesWritten);
-	}
-}
-
-static int
-file_close(struct archive *a, void *client_data)
-{
-	struct write_file_data	*mine = (struct write_file_data *)client_data;
-
-	(void)a; /* UNUSED */
-
-	if (mine == NULL)
-		return (ARCHIVE_FATAL);
-
-	if (mine->fd >= 0)
-		close(mine->fd);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-file_free(struct archive *a, void *client_data)
-{
-	struct write_file_data	*mine = (struct write_file_data *)client_data;
-
-	(void)a; /* UNUSED */
-
-	if (mine == NULL)
-		return (ARCHIVE_OK);
-
-	archive_mstring_clean(&mine->filename);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_open_memory.c b/c/archive_write_open_memory.c
deleted file mode 100644
--- a/c/archive_write_open_memory.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_memory.c,v 1.3 2007/01/09 08:05:56 kientzle Exp $");
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "archive.h"
-
-struct write_memory_data {
-	size_t	used;
-	size_t  size;
-	size_t * client_size;
-	unsigned char * buff;
-};
-
-static int	memory_write_free(struct archive *, void *);
-static int	memory_write_open(struct archive *, void *);
-static ssize_t	memory_write(struct archive *, void *, const void *buff, size_t);
-
-/*
- * Client provides a pointer to a block of memory to receive
- * the data.  The 'size' param both tells us the size of the
- * client buffer and lets us tell the client the final size.
- */
-int
-archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t *used)
-{
-	struct write_memory_data *mine;
-
-	mine = (struct write_memory_data *)calloc(1, sizeof(*mine));
-	if (mine == NULL) {
-		archive_set_error(a, ENOMEM, "No memory");
-		return (ARCHIVE_FATAL);
-	}
-	mine->buff = buff;
-	mine->size = buffSize;
-	mine->client_size = used;
-	return (archive_write_open2(a, mine,
-		    memory_write_open, memory_write, NULL, memory_write_free));
-}
-
-static int
-memory_write_open(struct archive *a, void *client_data)
-{
-	struct write_memory_data *mine;
-	mine = client_data;
-	mine->used = 0;
-	if (mine->client_size != NULL)
-		*mine->client_size = mine->used;
-	/* Disable padding if it hasn't been set explicitly. */
-	if (-1 == archive_write_get_bytes_in_last_block(a))
-		archive_write_set_bytes_in_last_block(a, 1);
-	return (ARCHIVE_OK);
-}
-
-/*
- * Copy the data into the client buffer.
- * Note that we update mine->client_size on every write.
- * In particular, this means the client can follow exactly
- * how much has been written into their buffer at any time.
- */
-static ssize_t
-memory_write(struct archive *a, void *client_data, const void *buff, size_t length)
-{
-	struct write_memory_data *mine;
-	mine = client_data;
-
-	if (mine->used + length > mine->size) {
-		archive_set_error(a, ENOMEM, "Buffer exhausted");
-		return (ARCHIVE_FATAL);
-	}
-	memcpy(mine->buff + mine->used, buff, length);
-	mine->used += length;
-	if (mine->client_size != NULL)
-		*mine->client_size = mine->used;
-	return (length);
-}
-
-static int
-memory_write_free(struct archive *a, void *client_data)
-{
-	struct write_memory_data *mine;
-	(void)a; /* UNUSED */
-	mine = client_data;
-	if (mine == NULL)
-		return (ARCHIVE_OK);
-	free(mine);
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_private.h b/c/archive_write_private.h
deleted file mode 100644
--- a/c/archive_write_private.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/archive_write_private.h 201155 2009-12-29 05:20:12Z kientzle $
- */
-
-#ifndef ARCHIVE_WRITE_PRIVATE_H_INCLUDED
-#define ARCHIVE_WRITE_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-#include "archive.h"
-#include "archive_string.h"
-#include "archive_private.h"
-
-#define	ARCHIVE_WRITE_FILTER_STATE_NEW		1U
-#define	ARCHIVE_WRITE_FILTER_STATE_OPEN		2U
-#define	ARCHIVE_WRITE_FILTER_STATE_CLOSED	4U
-#define	ARCHIVE_WRITE_FILTER_STATE_FATAL	0x8000U
-
-struct archive_write;
-
-struct archive_write_filter {
-	int64_t bytes_written;
-	struct archive *archive; /* Associated archive. */
-	struct archive_write_filter *next_filter; /* Who I write to. */
-	int	(*options)(struct archive_write_filter *,
-	    const char *key, const char *value);
-	int	(*open)(struct archive_write_filter *);
-	int	(*write)(struct archive_write_filter *, const void *, size_t);
-	int	(*flush)(struct archive_write_filter *);
-	int	(*close)(struct archive_write_filter *);
-	int	(*free)(struct archive_write_filter *);
-	void	 *data;
-	const char *name;
-	int	  code;
-	int	  bytes_per_block;
-	int	  bytes_in_last_block;
-	int	  state;
-};
-
-#if ARCHIVE_VERSION < 4000000
-void __archive_write_filters_free(struct archive *);
-#endif
-
-struct archive_write_filter *__archive_write_allocate_filter(struct archive *);
-
-int __archive_write_output(struct archive_write *, const void *, size_t);
-int __archive_write_nulls(struct archive_write *, size_t);
-int __archive_write_filter(struct archive_write_filter *, const void *, size_t);
-
-struct archive_write {
-	struct archive	archive;
-
-	/* Dev/ino of the archive being written. */
-	int		  skip_file_set;
-	int64_t		  skip_file_dev;
-	int64_t		  skip_file_ino;
-
-	/* Utility:  Pointer to a block of nulls. */
-	const unsigned char	*nulls;
-	size_t			 null_length;
-
-	/* Callbacks to open/read/write/close archive stream. */
-	archive_open_callback	*client_opener;
-	archive_write_callback	*client_writer;
-	archive_close_callback	*client_closer;
-	archive_free_callback	*client_freer;
-	void			*client_data;
-
-	/*
-	 * Blocking information.  Note that bytes_in_last_block is
-	 * misleadingly named; I should find a better name.  These
-	 * control the final output from all compressors, including
-	 * compression_none.
-	 */
-	int		  bytes_per_block;
-	int		  bytes_in_last_block;
-
-	/*
-	 * First and last write filters in the pipeline.
-	 */
-	struct archive_write_filter *filter_first;
-	struct archive_write_filter *filter_last;
-
-	/*
-	 * Pointers to format-specific functions for writing.  They're
-	 * initialized by archive_write_set_format_XXX() calls.
-	 */
-	void	 *format_data;
-	const char *format_name;
-	int	(*format_init)(struct archive_write *);
-	int	(*format_options)(struct archive_write *,
-		    const char *key, const char *value);
-	int	(*format_finish_entry)(struct archive_write *);
-	int 	(*format_write_header)(struct archive_write *,
-		    struct archive_entry *);
-	ssize_t	(*format_write_data)(struct archive_write *,
-		    const void *buff, size_t);
-	int	(*format_close)(struct archive_write *);
-	int	(*format_free)(struct archive_write *);
-
-
-	/*
-	 * Encryption passphrase.
-	 */
-	char		*passphrase;
-	archive_passphrase_callback *passphrase_callback;
-	void		*passphrase_client_data;
-};
-
-/*
- * Utility function to format a USTAR header into a buffer.  If
- * "strict" is set, this tries to create the absolutely most portable
- * version of a ustar header.  If "strict" is set to 0, then it will
- * relax certain requirements.
- *
- * Generally, format-specific declarations don't belong in this
- * header; this is a rare example of a function that is shared by
- * two very similar formats (ustar and pax).
- */
-int
-__archive_write_format_header_ustar(struct archive_write *, char buff[512],
-    struct archive_entry *, int tartype, int strict,
-    struct archive_string_conv *);
-
-struct archive_write_program_data;
-struct archive_write_program_data * __archive_write_program_allocate(const char *program_name);
-int	__archive_write_program_free(struct archive_write_program_data *);
-int	__archive_write_program_open(struct archive_write_filter *,
-	    struct archive_write_program_data *, const char *);
-int	__archive_write_program_close(struct archive_write_filter *,
-	    struct archive_write_program_data *);
-int	__archive_write_program_write(struct archive_write_filter *,
-	    struct archive_write_program_data *, const void *, size_t);
-
-/*
- * Get a encryption passphrase.
- */
-const char * __archive_write_get_passphrase(struct archive_write *a);
-#endif
diff --git a/c/archive_write_set_format.c b/c/archive_write_set_format.c
deleted file mode 100644
--- a/c/archive_write_set_format.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format.c 201168 2009-12-29 06:15:32Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-#include "archive_write_set_format_private.h"
-
-/* A table that maps format codes to functions. */
-static const
-struct { int code; int (*setter)(struct archive *); } codes[] =
-{
-	{ ARCHIVE_FORMAT_7ZIP,		archive_write_set_format_7zip },
-	{ ARCHIVE_FORMAT_CPIO,		archive_write_set_format_cpio },
-	{ ARCHIVE_FORMAT_CPIO_BIN_LE,	archive_write_set_format_cpio_bin },
-	{ ARCHIVE_FORMAT_CPIO_PWB,	archive_write_set_format_cpio_pwb },
-	{ ARCHIVE_FORMAT_CPIO_POSIX,	archive_write_set_format_cpio_odc },
-	{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC,	archive_write_set_format_cpio_newc },
-	{ ARCHIVE_FORMAT_ISO9660,	archive_write_set_format_iso9660 },
-	{ ARCHIVE_FORMAT_MTREE,		archive_write_set_format_mtree },
-	{ ARCHIVE_FORMAT_RAW,		archive_write_set_format_raw },
-	{ ARCHIVE_FORMAT_SHAR,		archive_write_set_format_shar },
-	{ ARCHIVE_FORMAT_SHAR_BASE,	archive_write_set_format_shar },
-	{ ARCHIVE_FORMAT_SHAR_DUMP,	archive_write_set_format_shar_dump },
-	{ ARCHIVE_FORMAT_TAR,	archive_write_set_format_pax_restricted },
-	{ ARCHIVE_FORMAT_TAR_GNUTAR,	archive_write_set_format_gnutar },
-	{ ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, archive_write_set_format_pax },
-	{ ARCHIVE_FORMAT_TAR_PAX_RESTRICTED,
-				archive_write_set_format_pax_restricted },
-	{ ARCHIVE_FORMAT_TAR_USTAR,	archive_write_set_format_ustar },
-	{ ARCHIVE_FORMAT_WARC,		archive_write_set_format_warc },
-	{ ARCHIVE_FORMAT_XAR,		archive_write_set_format_xar },
-	{ ARCHIVE_FORMAT_ZIP,		archive_write_set_format_zip },
-	{ 0,		NULL }
-};
-
-int
-archive_write_set_format(struct archive *a, int code)
-{
-	int i;
-
-	for (i = 0; codes[i].code != 0; i++) {
-		if (code == codes[i].code)
-			return ((codes[i].setter)(a));
-	}
-
-	archive_set_error(a, EINVAL, "No such format");
-	return (ARCHIVE_FATAL);
-}
-
-void
-__archive_write_entry_filetype_unsupported(struct archive *a,
-    struct archive_entry *entry, const char *format)
-{
-	const char *name = NULL;
-
-	switch (archive_entry_filetype(entry)) {
-	/*
-	 * All formats should be able to archive regular files (AE_IFREG)
-	 */
-	case AE_IFDIR:
-		name = "directories";
-		break;
-	case AE_IFLNK:
-		name = "symbolic links";
-		break;
-	case AE_IFCHR:
-		name = "character devices";
-		break;
-	case AE_IFBLK:
-		name = "block devices";
-		break;
-	case AE_IFIFO:
-		name = "named pipes";
-		break;
-	case AE_IFSOCK:
-		name = "sockets";
-		break;
-	default:
-		break;
-	}
-
-	if (name != NULL) {
-		archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "%s: %s format cannot archive %s",
-		    archive_entry_pathname(entry), format, name);
-	} else {
-		archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "%s: %s format cannot archive files with mode 0%lo",
-		    archive_entry_pathname(entry), format,
-		    (unsigned long)archive_entry_mode(entry));
-	}
-}
diff --git a/c/archive_write_set_format_7zip.c b/c/archive_write_set_format_7zip.c
deleted file mode 100644
--- a/c/archive_write_set_format_7zip.c
+++ /dev/null
@@ -1,2322 +0,0 @@
-/*-
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdlib.h>
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#if HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_ppmd7_private.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-/*
- * Codec ID
- */
-#define _7Z_COPY	0
-#define _7Z_LZMA1	0x030101
-#define _7Z_LZMA2	0x21
-#define _7Z_DEFLATE	0x040108
-#define _7Z_BZIP2	0x040202
-#define _7Z_PPMD	0x030401
-
-/*
- * 7-Zip header property IDs.
- */
-#define kEnd			0x00
-#define kHeader			0x01
-#define kArchiveProperties	0x02
-#define kAdditionalStreamsInfo	0x03
-#define kMainStreamsInfo	0x04
-#define kFilesInfo		0x05
-#define kPackInfo		0x06
-#define kUnPackInfo		0x07
-#define kSubStreamsInfo		0x08
-#define kSize			0x09
-#define kCRC			0x0A
-#define kFolder			0x0B
-#define kCodersUnPackSize	0x0C
-#define kNumUnPackStream	0x0D
-#define kEmptyStream		0x0E
-#define kEmptyFile		0x0F
-#define kAnti			0x10
-#define kName			0x11
-#define kCTime			0x12
-#define kATime			0x13
-#define kMTime			0x14
-#define kAttributes		0x15
-#define kEncodedHeader		0x17
-
-enum la_zaction {
-	ARCHIVE_Z_FINISH,
-	ARCHIVE_Z_RUN
-};
-
-/*
- * A stream object of universal compressor.
- */
-struct la_zstream {
-	const uint8_t		*next_in;
-	size_t			 avail_in;
-	uint64_t		 total_in;
-
-	uint8_t			*next_out;
-	size_t			 avail_out;
-	uint64_t		 total_out;
-
-	uint32_t		 prop_size;
-	uint8_t			*props;
-
-	int			 valid;
-	void			*real_stream;
-	int			 (*code) (struct archive *a,
-				    struct la_zstream *lastrm,
-				    enum la_zaction action);
-	int			 (*end)(struct archive *a,
-				    struct la_zstream *lastrm);
-};
-
-#define PPMD7_DEFAULT_ORDER	6
-#define PPMD7_DEFAULT_MEM_SIZE	(1 << 24)
-
-struct ppmd_stream {
-	int			 stat;
-	CPpmd7			 ppmd7_context;
-	CPpmd7z_RangeEnc	 range_enc;
-	IByteOut		 byteout;
-	uint8_t			*buff;
-	uint8_t			*buff_ptr;
-	uint8_t			*buff_end;
-	size_t			 buff_bytes;
-};
-
-struct coder {
-	unsigned		 codec;
-	size_t			 prop_size;
-	uint8_t			*props;
-};
-
-struct file {
-	struct archive_rb_node	 rbnode;
-
-	struct file		*next;
-	unsigned		 name_len;
-	uint8_t			*utf16name;/* UTF16-LE name. */
-	uint64_t		 size;
-	unsigned		 flg;
-#define MTIME_IS_SET	(1<<0)
-#define ATIME_IS_SET	(1<<1)
-#define CTIME_IS_SET	(1<<2)
-#define CRC32_IS_SET	(1<<3)
-#define HAS_STREAM	(1<<4)
-
-	struct {
-		time_t		 time;
-		long		 time_ns;
-	}			 times[3];
-#define MTIME 0
-#define ATIME 1
-#define CTIME 2
-
-	mode_t			 mode;
-	uint32_t		 crc32;
-
-	unsigned		 dir:1;
-};
-
-struct _7zip {
-	int			 temp_fd;
-	uint64_t		 temp_offset;
-
-	struct file		*cur_file;
-	size_t			 total_number_entry;
-	size_t			 total_number_nonempty_entry;
-	size_t			 total_number_empty_entry;
-	size_t			 total_number_dir_entry;
-	size_t			 total_bytes_entry_name;
-	size_t			 total_number_time_defined[3];
-	uint64_t		 total_bytes_compressed;
-	uint64_t		 total_bytes_uncompressed;
-	uint64_t		 entry_bytes_remaining;
-	uint32_t		 entry_crc32;
-	uint32_t		 precode_crc32;
-	uint32_t		 encoded_crc32;
-	int			 crc32flg;
-#define	PRECODE_CRC32	1
-#define	ENCODED_CRC32	2
-
-	unsigned		 opt_compression;
-	int			 opt_compression_level;
-
-	struct la_zstream	 stream;
-	struct coder		 coder;
-
-	struct archive_string_conv *sconv;
-
-	/*
-	 * Compressed data buffer.
-	 */
-	unsigned char		 wbuff[512 * 20 * 6];
-	size_t			 wbuff_remaining;
-
-	/*
-	 * The list of the file entries which has its contents is used to
-	 * manage struct file objects.
-	 * We use 'next' (a member of struct file) to chain.
-	 */
-	struct {
-		struct file	*first;
-		struct file	**last;
-	}			 file_list, empty_list;
-	struct archive_rb_tree	 rbtree;/* for empty files */
-};
-
-static int	_7z_options(struct archive_write *,
-		    const char *, const char *);
-static int	_7z_write_header(struct archive_write *,
-		    struct archive_entry *);
-static ssize_t	_7z_write_data(struct archive_write *,
-		    const void *, size_t);
-static int	_7z_finish_entry(struct archive_write *);
-static int	_7z_close(struct archive_write *);
-static int	_7z_free(struct archive_write *);
-static int	file_cmp_node(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static int	file_cmp_key(const struct archive_rb_node *, const void *);
-static int	file_new(struct archive_write *a, struct archive_entry *,
-		    struct file **);
-static void	file_free(struct file *);
-static void	file_register(struct _7zip *, struct file *);
-static void	file_register_empty(struct _7zip *, struct file *);
-static void	file_init_register(struct _7zip *);
-static void	file_init_register_empty(struct _7zip *);
-static void	file_free_register(struct _7zip *);
-static ssize_t	compress_out(struct archive_write *, const void *, size_t ,
-		    enum la_zaction);
-static int	compression_init_encoder_copy(struct archive *,
-		    struct la_zstream *);
-static int	compression_code_copy(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_copy(struct archive *, struct la_zstream *);
-static int	compression_init_encoder_deflate(struct archive *,
-		    struct la_zstream *, int, int);
-#ifdef HAVE_ZLIB_H
-static int	compression_code_deflate(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_deflate(struct archive *, struct la_zstream *);
-#endif
-static int	compression_init_encoder_bzip2(struct archive *,
-		    struct la_zstream *, int);
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-static int	compression_code_bzip2(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_bzip2(struct archive *, struct la_zstream *);
-#endif
-static int	compression_init_encoder_lzma1(struct archive *,
-		    struct la_zstream *, int);
-static int	compression_init_encoder_lzma2(struct archive *,
-		    struct la_zstream *, int);
-#if defined(HAVE_LZMA_H)
-static int	compression_code_lzma(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_lzma(struct archive *, struct la_zstream *);
-#endif
-static int	compression_init_encoder_ppmd(struct archive *,
-		    struct la_zstream *, unsigned, uint32_t);
-static int	compression_code_ppmd(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_ppmd(struct archive *, struct la_zstream *);
-static int	_7z_compression_init_encoder(struct archive_write *, unsigned,
-		    int);
-static int	compression_code(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end(struct archive *,
-		    struct la_zstream *);
-static int	enc_uint64(struct archive_write *, uint64_t);
-static int	make_header(struct archive_write *, uint64_t, uint64_t,
-		    uint64_t, int, struct coder *);
-static int	make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
-		    	uint64_t, int, struct coder *, int, uint32_t);
-
-int
-archive_write_set_format_7zip(struct archive *_a)
-{
-	static const struct archive_rb_tree_ops rb_ops = {
-		file_cmp_node, file_cmp_key
-	};
-	struct archive_write *a = (struct archive_write *)_a;
-	struct _7zip *zip;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_7zip");
-
-	/* If another format was already registered, unregister it. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	zip = calloc(1, sizeof(*zip));
-	if (zip == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate 7-Zip data");
-		return (ARCHIVE_FATAL);
-	}
-	zip->temp_fd = -1;
-	__archive_rb_tree_init(&(zip->rbtree), &rb_ops);
-	file_init_register(zip);
-	file_init_register_empty(zip);
-
-	/* Set default compression type and its level. */
-#if HAVE_LZMA_H
-	zip->opt_compression = _7Z_LZMA1;
-#elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-	zip->opt_compression = _7Z_BZIP2;
-#elif defined(HAVE_ZLIB_H)
-	zip->opt_compression = _7Z_DEFLATE;
-#else
-	zip->opt_compression = _7Z_COPY;
-#endif
-	zip->opt_compression_level = 6;
-
-	a->format_data = zip;
-
-	a->format_name = "7zip";
-	a->format_options = _7z_options;
-	a->format_write_header = _7z_write_header;
-	a->format_write_data = _7z_write_data;
-	a->format_finish_entry = _7z_finish_entry;
-	a->format_close = _7z_close;
-	a->format_free = _7z_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
-	a->archive.archive_format_name = "7zip";
-
-	return (ARCHIVE_OK);
-}
-
-static int
-_7z_options(struct archive_write *a, const char *key, const char *value)
-{
-	struct _7zip *zip;
-
-	zip = (struct _7zip *)a->format_data;
-
-	if (strcmp(key, "compression") == 0) {
-		const char *name = NULL;
-
-		if (value == NULL || strcmp(value, "copy") == 0 ||
-		    strcmp(value, "COPY") == 0 ||
-		    strcmp(value, "store") == 0 ||
-		    strcmp(value, "STORE") == 0)
-			zip->opt_compression = _7Z_COPY;
-		else if (strcmp(value, "deflate") == 0 ||
-		    strcmp(value, "DEFLATE") == 0)
-#if HAVE_ZLIB_H
-			zip->opt_compression = _7Z_DEFLATE;
-#else
-			name = "deflate";
-#endif
-		else if (strcmp(value, "bzip2") == 0 ||
-		    strcmp(value, "BZIP2") == 0)
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-			zip->opt_compression = _7Z_BZIP2;
-#else
-			name = "bzip2";
-#endif
-		else if (strcmp(value, "lzma1") == 0 ||
-		    strcmp(value, "LZMA1") == 0)
-#if HAVE_LZMA_H
-			zip->opt_compression = _7Z_LZMA1;
-#else
-			name = "lzma1";
-#endif
-		else if (strcmp(value, "lzma2") == 0 ||
-		    strcmp(value, "LZMA2") == 0)
-#if HAVE_LZMA_H
-			zip->opt_compression = _7Z_LZMA2;
-#else
-			name = "lzma2";
-#endif
-		else if (strcmp(value, "ppmd") == 0 ||
-		    strcmp(value, "PPMD") == 0 ||
-		    strcmp(value, "PPMd") == 0)
-			zip->opt_compression = _7Z_PPMD;
-		else {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Unknown compression name: `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		if (name != NULL) {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "`%s' compression not supported "
-			    "on this platform",
-			    name);
-			return (ARCHIVE_FAILED);
-		}
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL ||
-		    !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0') {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Illegal value `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		zip->opt_compression_level = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-_7z_write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct _7zip *zip;
-	struct file *file;
-	int r;
-
-	zip = (struct _7zip *)a->format_data;
-	zip->cur_file = NULL;
-	zip->entry_bytes_remaining = 0;
-
-	if (zip->sconv == NULL) {
-		zip->sconv = archive_string_conversion_to_charset(
-		    &a->archive, "UTF-16LE", 1);
-		if (zip->sconv == NULL)
-			return (ARCHIVE_FATAL);
-	}
-
-	r = file_new(a, entry, &file);
-	if (r < ARCHIVE_WARN) {
-		if (file != NULL)
-			file_free(file);
-		return (r);
-	}
-	if (file->size == 0 && file->dir) {
-		if (!__archive_rb_tree_insert_node(&(zip->rbtree),
-		    (struct archive_rb_node *)file)) {
-			/* We have already had the same file. */
-			file_free(file);
-			return (ARCHIVE_OK);
-		}
-	}
-
-	if (file->flg & MTIME_IS_SET)
-		zip->total_number_time_defined[MTIME]++;
-	if (file->flg & CTIME_IS_SET)
-		zip->total_number_time_defined[CTIME]++;
-	if (file->flg & ATIME_IS_SET)
-		zip->total_number_time_defined[ATIME]++;
-
-	zip->total_number_entry++;
-	zip->total_bytes_entry_name += file->name_len + 2;
-	if (file->size == 0) {
-		/* Count up the number of empty files. */
-		zip->total_number_empty_entry++;
-		if (file->dir)
-			zip->total_number_dir_entry++;
-		else
-			file_register_empty(zip, file);
-		return (r);
-	}
-
-	/*
-	 * Init compression.
-	 */
-	if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
-		r = _7z_compression_init_encoder(a, zip->opt_compression,
-			zip->opt_compression_level);
-		if (r < 0) {
-			file_free(file);
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	/* Register a non-empty file. */
-	file_register(zip, file);
-
-	/*
-	 * Set the current file to cur_file to read its contents.
-	 */
-	zip->cur_file = file;
-
-
-	/* Save a offset of current file in temporary file. */
-	zip->entry_bytes_remaining = file->size;
-	zip->entry_crc32 = 0;
-
-	/*
-	 * Store a symbolic link name as file contents.
-	 */
-	if (archive_entry_filetype(entry) == AE_IFLNK) {
-		ssize_t bytes;
-		const void *p = (const void *)archive_entry_symlink(entry);
-		bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
-		if (bytes < 0)
-			return ((int)bytes);
-		zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
-		zip->entry_bytes_remaining -= bytes;
-	}
-
-	return (r);
-}
-
-/*
- * Write data to a temporary file.
- */
-static int
-write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	struct _7zip *zip;
-	const unsigned char *p;
-	ssize_t ws;
-
-	zip = (struct _7zip *)a->format_data;
-
-	/*
-	 * Open a temporary file.
-	 */
-	if (zip->temp_fd == -1) {
-		zip->temp_offset = 0;
-		zip->temp_fd = __archive_mktemp(NULL);
-		if (zip->temp_fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't create temporary file");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	p = (const unsigned char *)buff;
-	while (s) {
-		ws = write(zip->temp_fd, p, s);
-		if (ws < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "fwrite function failed");
-			return (ARCHIVE_FATAL);
-		}
-		s -= ws;
-		p += ws;
-		zip->temp_offset += ws;
-	}
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-compress_out(struct archive_write *a, const void *buff, size_t s,
-    enum la_zaction run)
-{
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-	int r;
-
-	if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
-		return (0);
-
-	if ((zip->crc32flg & PRECODE_CRC32) && s)
-		zip->precode_crc32 = crc32(zip->precode_crc32, buff,
-		    (unsigned)s);
-	zip->stream.next_in = (const unsigned char *)buff;
-	zip->stream.avail_in = s;
-	for (;;) {
-		/* Compress file data. */
-		r = compression_code(&(a->archive), &(zip->stream), run);
-		if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
-			return (ARCHIVE_FATAL);
-		if (zip->stream.avail_out == 0) {
-			if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
-			    != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			zip->stream.next_out = zip->wbuff;
-			zip->stream.avail_out = sizeof(zip->wbuff);
-			if (zip->crc32flg & ENCODED_CRC32)
-				zip->encoded_crc32 = crc32(zip->encoded_crc32,
-				    zip->wbuff, sizeof(zip->wbuff));
-			if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
-				continue;
-		}
-		if (zip->stream.avail_in == 0)
-			break;
-	}
-	if (run == ARCHIVE_Z_FINISH) {
-		uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
-		if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		if ((zip->crc32flg & ENCODED_CRC32) && bytes)
-			zip->encoded_crc32 = crc32(zip->encoded_crc32,
-			    zip->wbuff, (unsigned)bytes);
-	}
-
-	return (s);
-}
-
-static ssize_t
-_7z_write_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct _7zip *zip;
-	ssize_t bytes;
-
-	zip = (struct _7zip *)a->format_data;
-
-	if (s > zip->entry_bytes_remaining)
-		s = (size_t)zip->entry_bytes_remaining;
-	if (s == 0 || zip->cur_file == NULL)
-		return (0);
-	bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
-	if (bytes < 0)
-		return (bytes);
-	zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
-	zip->entry_bytes_remaining -= bytes;
-	return (bytes);
-}
-
-static int
-_7z_finish_entry(struct archive_write *a)
-{
-	struct _7zip *zip;
-	size_t s;
-	ssize_t r;
-
-	zip = (struct _7zip *)a->format_data;
-	if (zip->cur_file == NULL)
-		return (ARCHIVE_OK);
-
-	while (zip->entry_bytes_remaining > 0) {
-		s = (size_t)zip->entry_bytes_remaining;
-		if (s > a->null_length)
-			s = a->null_length;
-		r = _7z_write_data(a, a->nulls, s);
-		if (r < 0)
-			return ((int)r);
-	}
-	zip->total_bytes_compressed += zip->stream.total_in;
-	zip->total_bytes_uncompressed += zip->stream.total_out;
-	zip->cur_file->crc32 = zip->entry_crc32;
-	zip->cur_file = NULL;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-flush_wbuff(struct archive_write *a)
-{
-	struct _7zip *zip;
-	int r;
-	size_t s;
-
-	zip = (struct _7zip *)a->format_data;
-	s = sizeof(zip->wbuff) - zip->wbuff_remaining;
-	r = __archive_write_output(a, zip->wbuff, s);
-	if (r != ARCHIVE_OK)
-		return (r);
-	zip->wbuff_remaining = sizeof(zip->wbuff);
-	return (r);
-}
-
-static int
-copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
-{
-	struct _7zip *zip;
-	int r;
-
-	zip = (struct _7zip *)a->format_data;
-	if (zip->temp_offset > 0 &&
-	    lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
-		archive_set_error(&(a->archive), errno, "lseek failed");
-		return (ARCHIVE_FATAL);
-	}
-	while (length) {
-		size_t rsize;
-		ssize_t rs;
-		unsigned char *wb;
-
-		if (length > zip->wbuff_remaining)
-			rsize = zip->wbuff_remaining;
-		else
-			rsize = (size_t)length;
-		wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
-		rs = read(zip->temp_fd, wb, rsize);
-		if (rs < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Can't read temporary file(%jd)",
-			    (intmax_t)rs);
-			return (ARCHIVE_FATAL);
-		}
-		if (rs == 0) {
-			archive_set_error(&(a->archive), 0,
-			    "Truncated 7-Zip archive");
-			return (ARCHIVE_FATAL);
-		}
-		zip->wbuff_remaining -= rs;
-		length -= rs;
-		if (zip->wbuff_remaining == 0) {
-			r = flush_wbuff(a);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-_7z_close(struct archive_write *a)
-{
-	struct _7zip *zip;
-	unsigned char *wb;
-	uint64_t header_offset, header_size, header_unpacksize;
-	uint64_t length;
-	uint32_t header_crc32;
-	int r;
-
-	zip = (struct _7zip *)a->format_data;
-
-	if (zip->total_number_entry > 0) {
-		struct archive_rb_node *n;
-		uint64_t data_offset, data_size, data_unpacksize;
-		unsigned header_compression;
-
-		r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
-		if (r < 0)
-			return (r);
-		data_offset = 0;
-		data_size = zip->stream.total_out;
-		data_unpacksize = zip->stream.total_in;
-		zip->coder.codec = zip->opt_compression;
-		zip->coder.prop_size = zip->stream.prop_size;
-		zip->coder.props = zip->stream.props;
-		zip->stream.prop_size = 0;
-		zip->stream.props = NULL;
-		zip->total_number_nonempty_entry =
-		    zip->total_number_entry - zip->total_number_empty_entry;
-
-		/* Connect an empty file list. */
-		if (zip->empty_list.first != NULL) {
-			*zip->file_list.last = zip->empty_list.first;
-			zip->file_list.last = zip->empty_list.last;
-		}
-		/* Connect a directory file list. */
-		ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
-			file_register(zip, (struct file *)n);
-		}
-
-		/*
-		 * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
-		 * the compression type for encoding the header.
-		 */
-#if HAVE_LZMA_H
-		header_compression = _7Z_LZMA1;
-		if(zip->opt_compression == _7Z_LZMA2 ||
-		   zip->opt_compression == _7Z_COPY)
-			header_compression = zip->opt_compression;
-
-		/* If the stored file is only one, do not encode the header.
-		 * This is the same way 7z command does. */
-		if (zip->total_number_entry == 1)
-			header_compression = _7Z_COPY;
-#else
-		header_compression = _7Z_COPY;
-#endif
-		r = _7z_compression_init_encoder(a, header_compression,
-		                                 zip->opt_compression_level);
-		if (r < 0)
-			return (r);
-		zip->crc32flg = PRECODE_CRC32;
-		zip->precode_crc32 = 0;
-		r = make_header(a, data_offset, data_size, data_unpacksize,
-			1, &(zip->coder));
-		if (r < 0)
-			return (r);
-		r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
-		if (r < 0)
-			return (r);
-		header_offset = data_offset + data_size;
-		header_size = zip->stream.total_out;
-		header_crc32 = zip->precode_crc32;
-		header_unpacksize = zip->stream.total_in;
-
-		if (header_compression != _7Z_COPY) {
-			/*
-			 * Encode the header in order to reduce the size
-			 * of the archive.
-			 */
-			free(zip->coder.props);
-			zip->coder.codec = header_compression;
-			zip->coder.prop_size = zip->stream.prop_size;
-			zip->coder.props = zip->stream.props;
-			zip->stream.prop_size = 0;
-			zip->stream.props = NULL;
-
-			r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
-			if (r < 0)
-				return (r);
-			zip->crc32flg = ENCODED_CRC32;
-			zip->encoded_crc32 = 0;
-
-			/*
-			 * Make EncodedHeader.
-			 */
-			r = enc_uint64(a, kEncodedHeader);
-			if (r < 0)
-				return (r);
-			r = make_streamsInfo(a, header_offset, header_size,
-			      header_unpacksize, 1, &(zip->coder), 0,
-			      header_crc32);
-			if (r < 0)
-				return (r);
-			r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
-			if (r < 0)
-				return (r);
-			header_offset = header_offset + header_size;
-			header_size = zip->stream.total_out;
-			header_crc32 = zip->encoded_crc32;
-		}
-		zip->crc32flg = 0;
-	} else {
-		header_offset = header_size = 0;
-		header_crc32 = 0;
-	}
-	
-	length = zip->temp_offset;
-
-	/*
-	 * Make the zip header on wbuff(write buffer).
-	 */
-	wb = zip->wbuff;
-	zip->wbuff_remaining = sizeof(zip->wbuff);
-	memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
-	wb[6] = 0;/* Major version. */
-	wb[7] = 3;/* Minor version. */
-	archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
-	archive_le64enc(&wb[20], header_size);/* Next Header Size */
-	archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
-	archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
-	zip->wbuff_remaining -= 32;
-
-	/*
-	 * Read all file contents and an encoded header from the temporary
-	 * file and write out it.
-	 */
-	r = copy_out(a, 0, length);
-	if (r != ARCHIVE_OK)
-		return (r);
-	r = flush_wbuff(a);
-	return (r);
-}
-
-/*
- * Encode 64 bits value into 7-Zip's encoded UINT64 value.
- */
-static int
-enc_uint64(struct archive_write *a, uint64_t val)
-{
-	unsigned mask = 0x80;
-	uint8_t numdata[9];
-	int i;
-
-	numdata[0] = 0;
-	for (i = 1; i < (int)sizeof(numdata); i++) {
-		if (val < mask) {
-			numdata[0] |= (uint8_t)val;
-			break;
-		}
-		numdata[i] = (uint8_t)val;
-		val >>= 8;
-		numdata[0] |= mask;
-		mask >>= 1;
-	}
-	return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
-}
-
-static int
-make_substreamsInfo(struct archive_write *a, struct coder *coders)
-{
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-	struct file *file;
-	int r;
-
-	/*
-	 * Make SubStreamsInfo.
-	 */
-	r = enc_uint64(a, kSubStreamsInfo);
-	if (r < 0)
-		return (r);
-
-	if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
-		/*
-		 * Make NumUnPackStream.
-		 */
-		r = enc_uint64(a, kNumUnPackStream);
-		if (r < 0)
-			return (r);
-
-		/* Write numUnpackStreams */
-		r = enc_uint64(a, zip->total_number_nonempty_entry);
-		if (r < 0)
-			return (r);
-
-		/*
-		 * Make kSize.
-		 */
-		r = enc_uint64(a, kSize);
-		if (r < 0)
-			return (r);
-		file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->next == NULL ||
-			    file->next->size == 0)
-				break;
-			r = enc_uint64(a, file->size);
-			if (r < 0)
-				return (r);
-		}
-	}
-
-	/*
-	 * Make CRC.
-	 */
-	r = enc_uint64(a, kCRC);
-	if (r < 0)
-		return (r);
-
-
-	/* All are defined */
-	r = enc_uint64(a, 1);
-	if (r < 0)
-		return (r);
-	file = zip->file_list.first;
-	for (;file != NULL; file = file->next) {
-		uint8_t crc[4];
-		if (file->size == 0)
-			break;
-		archive_le32enc(crc, file->crc32);
-		r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Write End. */
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-	return (ARCHIVE_OK);
-}
-
-static int
-make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
-    uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
-    uint32_t header_crc)
-{
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-	uint8_t codec_buff[8];
-	int numFolders, fi;
-	int codec_size;
-	int i, r;
-
-	if (coders->codec == _7Z_COPY)
-		numFolders = (int)zip->total_number_nonempty_entry;
-	else
-		numFolders = 1;
-
-	/*
-	 * Make PackInfo.
-	 */
-	r = enc_uint64(a, kPackInfo);
-	if (r < 0)
-		return (r);
-
-	/* Write PackPos. */
-	r = enc_uint64(a, offset);
-	if (r < 0)
-		return (r);
-
-	/* Write NumPackStreams. */
-	r = enc_uint64(a, numFolders);
-	if (r < 0)
-		return (r);
-
-	/* Make Size. */
-	r = enc_uint64(a, kSize);
-	if (r < 0)
-		return (r);
-
-	if (numFolders > 1) {
-		struct file *file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->size == 0)
-				break;
-			r = enc_uint64(a, file->size);
-			if (r < 0)
-				return (r);
-		}
-	} else {
-		/* Write size. */
-		r = enc_uint64(a, pack_size);
-		if (r < 0)
-			return (r);
-	}
-
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-
-	/*
-	 * Make UnPackInfo.
-	 */
-	r = enc_uint64(a, kUnPackInfo);
-	if (r < 0)
-		return (r);
-
-	/*
-	 * Make Folder.
-	 */
-	r = enc_uint64(a, kFolder);
-	if (r < 0)
-		return (r);
-
-	/* Write NumFolders. */
-	r = enc_uint64(a, numFolders);
-	if (r < 0)
-		return (r);
-
-	/* Write External. */
-	r = enc_uint64(a, 0);
-	if (r < 0)
-		return (r);
-
-	for (fi = 0; fi < numFolders; fi++) {
-		/* Write NumCoders. */
-		r = enc_uint64(a, num_coder);
-		if (r < 0)
-			return (r);
-
-		for (i = 0; i < num_coder; i++) {
-			unsigned codec_id = coders[i].codec;
-
-			/* Write Codec flag. */
-			archive_be64enc(codec_buff, codec_id);
-			for (codec_size = 8; codec_size > 0; codec_size--) {
-				if (codec_buff[8 - codec_size])
-					break;
-			}
-			if (codec_size == 0)
-				codec_size = 1;
-			if (coders[i].prop_size)
-				r = enc_uint64(a, codec_size | 0x20);
-			else
-				r = enc_uint64(a, codec_size);
-			if (r < 0)
-				return (r);
-
-			/* Write Codec ID. */
-			codec_size &= 0x0f;
-			r = (int)compress_out(a, &codec_buff[8-codec_size],
-				codec_size, ARCHIVE_Z_RUN);
-			if (r < 0)
-				return (r);
-
-			if (coders[i].prop_size) {
-				/* Write Codec property size. */
-				r = enc_uint64(a, coders[i].prop_size);
-				if (r < 0)
-					return (r);
-
-				/* Write Codec properties. */
-				r = (int)compress_out(a, coders[i].props,
-					coders[i].prop_size, ARCHIVE_Z_RUN);
-				if (r < 0)
-					return (r);
-			}
-		}
-	}
-
-	/*
-	 * Make CodersUnPackSize.
-	 */
-	r = enc_uint64(a, kCodersUnPackSize);
-	if (r < 0)
-		return (r);
-
-	if (numFolders > 1) {
-		struct file *file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->size == 0)
-				break;
-			r = enc_uint64(a, file->size);
-			if (r < 0)
-				return (r);
-		}
-
-	} else {
-		/* Write UnPackSize. */
-		r = enc_uint64(a, unpack_size);
-		if (r < 0)
-			return (r);
-	}
-
-	if (!substrm) {
-		uint8_t crc[4];
-		/*
-		 * Make CRC.
-		 */
-		r = enc_uint64(a, kCRC);
-		if (r < 0)
-			return (r);
-
-		/* All are defined */
-		r = enc_uint64(a, 1);
-		if (r < 0)
-			return (r);
-		archive_le32enc(crc, header_crc);
-		r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Write End. */
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-
-	if (substrm) {
-		/*
-		 * Make SubStreamsInfo.
-		 */
-		r = make_substreamsInfo(a, coders);
-		if (r < 0)
-			return (r);
-	}
-
-
-	/* Write End. */
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-
-	return (ARCHIVE_OK);
-}
-
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static uint64_t
-utcToFiletime(time_t t, long ns)
-{
-	uint64_t fileTime;
-
-	fileTime = t;
-	fileTime *= 10000000;
-	fileTime += ns / 100;
-	fileTime += EPOC_TIME;
-	return (fileTime);
-}
-
-static int
-make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
-{
-	uint8_t filetime[8];
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-	struct file *file;
-	int r;
-	uint8_t b, mask;
-
-	/*
-	 * Make Time Bools.
-	 */
-	if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
-		/* Write Time Type. */
-		r = enc_uint64(a, type);
-		if (r < 0)
-			return (r);
-		/* Write EmptyStream Size. */
-		r = enc_uint64(a, 2 + zip->total_number_entry * 8);
-		if (r < 0)
-			return (r);
-		/* All are defined. */
-		r = enc_uint64(a, 1);
-		if (r < 0)
-			return (r);
-	} else {
-		if (zip->total_number_time_defined[ti] == 0)
-			return (ARCHIVE_OK);
-
-		/* Write Time Type. */
-		r = enc_uint64(a, type);
-		if (r < 0)
-			return (r);
-		/* Write EmptyStream Size. */
-		r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
-			+ zip->total_number_time_defined[ti] * 8);
-		if (r < 0)
-			return (r);
-
-		/* All are not defined. */
-		r = enc_uint64(a, 0);
-		if (r < 0)
-			return (r);
-
-		b = 0;
-		mask = 0x80;
-		file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->flg & flg)
-				b |= mask;
-			mask >>= 1;
-			if (mask == 0) {
-				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-				if (r < 0)
-					return (r);
-				mask = 0x80;
-				b = 0;
-			}
-		}
-		if (mask != 0x80) {
-			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-			if (r < 0)
-				return (r);
-		}
-	}
-
-	/* External. */
-	r = enc_uint64(a, 0);
-	if (r < 0)
-		return (r);
-
-
-	/*
-	 * Make Times.
-	 */
-	file = zip->file_list.first;
-	for (;file != NULL; file = file->next) {
-		if ((file->flg & flg) == 0)
-			continue;
-		archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
-			file->times[ti].time_ns));
-		r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
-		if (r < 0)
-			return (r);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
-    uint64_t unpack_size, int codernum, struct coder *coders)
-{
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-	struct file *file;
-	int r;
-	uint8_t b, mask;
-
-	/*
-	 * Make FilesInfo.
-	 */
-	r = enc_uint64(a, kHeader);
-	if (r < 0)
-		return (r);
-
-	/*
-	 * If there are empty files only, do not write MainStreamInfo.
-	 */
-	if (zip->total_number_nonempty_entry) {
-		/*
-		 * Make MainStreamInfo.
-		 */
-		r = enc_uint64(a, kMainStreamsInfo);
-		if (r < 0)
-			return (r);
-		r = make_streamsInfo(a, offset, pack_size, unpack_size,
-		      codernum, coders, 1, 0);
-		if (r < 0)
-			return (r);
-	}
-
-	/*
-	 * Make FilesInfo.
-	 */
-	r = enc_uint64(a, kFilesInfo);
-	if (r < 0)
-		return (r);
-
-	/* Write numFiles. */
-	r = enc_uint64(a, zip->total_number_entry);
-	if (r < 0)
-		return (r);
-
-	if (zip->total_number_empty_entry > 0) {
-		/* Make EmptyStream. */
-		r = enc_uint64(a, kEmptyStream);
-		if (r < 0)
-			return (r);
-
-		/* Write EmptyStream Size. */
-		r = enc_uint64(a, (zip->total_number_entry+7)>>3);
-		if (r < 0)
-			return (r);
-
-		b = 0;
-		mask = 0x80;
-		file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->size == 0)
-				b |= mask;
-			mask >>= 1;
-			if (mask == 0) {
-				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-				if (r < 0)
-					return (r);
-				mask = 0x80;
-				b = 0;
-			}
-		}
-		if (mask != 0x80) {
-			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-			if (r < 0)
-				return (r);
-		}
-	}
-
-	if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
-		/* Make EmptyFile. */
-		r = enc_uint64(a, kEmptyFile);
-		if (r < 0)
-			return (r);
-
-		/* Write EmptyFile Size. */
-		r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
-		if (r < 0)
-			return (r);
-
-		b = 0;
-		mask = 0x80;
-		file = zip->file_list.first;
-		for (;file != NULL; file = file->next) {
-			if (file->size)
-				continue;
-			if (!file->dir)
-				b |= mask;
-			mask >>= 1;
-			if (mask == 0) {
-				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-				if (r < 0)
-					return (r);
-				mask = 0x80;
-				b = 0;
-			}
-		}
-		if (mask != 0x80) {
-			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
-			if (r < 0)
-				return (r);
-		}
-	}
-
-	/* Make Name. */
-	r = enc_uint64(a, kName);
-	if (r < 0)
-		return (r);
-
-	/* Write Name size. */
-	r = enc_uint64(a, zip->total_bytes_entry_name+1);
-	if (r < 0)
-		return (r);
-
-	/* Write dmy byte. */
-	r = enc_uint64(a, 0);
-	if (r < 0)
-		return (r);
-
-	file = zip->file_list.first;
-	for (;file != NULL; file = file->next) {
-		r = (int)compress_out(a, file->utf16name, file->name_len+2,
-			ARCHIVE_Z_RUN);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Make MTime. */
-	r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
-	if (r < 0)
-		return (r);
-
-	/* Make CTime. */
-	r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
-	if (r < 0)
-		return (r);
-
-	/* Make ATime. */
-	r = make_time(a, kATime, ATIME_IS_SET, ATIME);
-	if (r < 0)
-		return (r);
-
-	/* Make Attributes. */
-	r = enc_uint64(a, kAttributes);
-	if (r < 0)
-		return (r);
-
-	/* Write Attributes size. */
-	r = enc_uint64(a, 2 + zip->total_number_entry * 4);
-	if (r < 0)
-		return (r);
-
-	/* Write "All Are Defined". */
-	r = enc_uint64(a, 1);
-	if (r < 0)
-		return (r);
-
-	/* Write dmy byte. */
-	r = enc_uint64(a, 0);
-	if (r < 0)
-		return (r);
-
-	file = zip->file_list.first;
-	for (;file != NULL; file = file->next) {
-		/*
-		 * High 16bits is unix mode.
-		 * Low 16bits is Windows attributes.
-		 */
-		uint32_t encattr, attr;
-		if (file->dir)
-			attr = 0x8010;
-		else
-			attr = 0x8020;
-		if ((file->mode & 0222) == 0)
-			attr |= 1;/* Read Only. */
-		attr |= ((uint32_t)file->mode) << 16;
-		archive_le32enc(&encattr, attr);
-		r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Write End. */
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-
-	/* Write End. */
-	r = enc_uint64(a, kEnd);
-	if (r < 0)
-		return (r);
-
-	return (ARCHIVE_OK);
-}
-
-
-static int
-_7z_free(struct archive_write *a)
-{
-	struct _7zip *zip = (struct _7zip *)a->format_data;
-
-	/* Close the temporary file. */
-	if (zip->temp_fd >= 0)
-		close(zip->temp_fd);
-
-	file_free_register(zip);
-	compression_end(&(a->archive), &(zip->stream));
-	free(zip->coder.props);
-	free(zip);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-file_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct file *f1 = (const struct file *)n1;
-	const struct file *f2 = (const struct file *)n2;
-
-	if (f1->name_len == f2->name_len)
-		return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
-	return (f1->name_len > f2->name_len)?1:-1;
-}
-        
-static int
-file_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct file *f = (const struct file *)n;
-
-	return (f->name_len - *(const char *)key);
-}
-
-static int
-file_new(struct archive_write *a, struct archive_entry *entry,
-    struct file **newfile)
-{
-	struct _7zip *zip;
-	struct file *file;
-	const char *u16;
-	size_t u16len;
-	int ret = ARCHIVE_OK;
-
-	zip = (struct _7zip *)a->format_data;
-	*newfile = NULL;
-
-	file = calloc(1, sizeof(*file));
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
-		if (errno == ENOMEM) {
-			free(file);
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for UTF-16LE");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "A filename cannot be converted to UTF-16LE;"
-		    "You should disable making Joliet extension");
-		ret = ARCHIVE_WARN;
-	}
-	file->utf16name = malloc(u16len + 2);
-	if (file->utf16name == NULL) {
-		free(file);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for Name");
-		return (ARCHIVE_FATAL);
-	}
-	memcpy(file->utf16name, u16, u16len);
-	file->utf16name[u16len+0] = 0;
-	file->utf16name[u16len+1] = 0;
-	file->name_len = (unsigned)u16len;
-	file->mode = archive_entry_mode(entry);
-	if (archive_entry_filetype(entry) == AE_IFREG)
-		file->size = archive_entry_size(entry);
-	else
-		archive_entry_set_size(entry, 0);
-	if (archive_entry_filetype(entry) == AE_IFDIR)
-		file->dir = 1;
-	else if (archive_entry_filetype(entry) == AE_IFLNK)
-		file->size = strlen(archive_entry_symlink(entry));
-	if (archive_entry_mtime_is_set(entry)) {
-		file->flg |= MTIME_IS_SET;
-		file->times[MTIME].time = archive_entry_mtime(entry);
-		file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
-	}
-	if (archive_entry_atime_is_set(entry)) {
-		file->flg |= ATIME_IS_SET;
-		file->times[ATIME].time = archive_entry_atime(entry);
-		file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
-	}
-	if (archive_entry_ctime_is_set(entry)) {
-		file->flg |= CTIME_IS_SET;
-		file->times[CTIME].time = archive_entry_ctime(entry);
-		file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
-	}
-
-	*newfile = file;
-	return (ret);
-}
-
-static void
-file_free(struct file *file)
-{
-	free(file->utf16name);
-	free(file);
-}
-
-static void
-file_register(struct _7zip *zip, struct file *file)
-{
-	file->next = NULL;
-	*zip->file_list.last = file;
-	zip->file_list.last = &(file->next);
-}
-
-static void
-file_init_register(struct _7zip *zip)
-{
-	zip->file_list.first = NULL;
-	zip->file_list.last = &(zip->file_list.first);
-}
-
-static void
-file_free_register(struct _7zip *zip)
-{
-	struct file *file, *file_next;
-
-	file = zip->file_list.first;
-	while (file != NULL) {
-		file_next = file->next;
-		file_free(file);
-		file = file_next;
-	}
-}
-
-static void
-file_register_empty(struct _7zip *zip, struct file *file)
-{
-	file->next = NULL;
-	*zip->empty_list.last = file;
-	zip->empty_list.last = &(file->next);
-}
-
-static void
-file_init_register_empty(struct _7zip *zip)
-{
-	zip->empty_list.first = NULL;
-	zip->empty_list.last = &(zip->empty_list.first);
-}
-
-#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
-	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
-static int
-compression_unsupported_encoder(struct archive *a,
-    struct la_zstream *lastrm, const char *name)
-{
-
-	archive_set_error(a, ARCHIVE_ERRNO_MISC,
-	    "%s compression not supported on this platform", name);
-	lastrm->valid = 0;
-	lastrm->real_stream = NULL;
-	return (ARCHIVE_FAILED);
-}
-#endif
-
-/*
- * _7_COPY compressor.
- */
-static int
-compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
-{
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	lastrm->valid = 1;
-	lastrm->code = compression_code_copy;
-	lastrm->end = compression_end_copy;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_copy(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	size_t bytes;
-
-	(void)a; /* UNUSED */
-	if (lastrm->avail_out > lastrm->avail_in)
-		bytes = lastrm->avail_in;
-	else
-		bytes = lastrm->avail_out;
-	if (bytes) {
-		memcpy(lastrm->next_out, lastrm->next_in, bytes);
-		lastrm->next_in += bytes;
-		lastrm->avail_in -= bytes;
-		lastrm->total_in += bytes;
-		lastrm->next_out += bytes;
-		lastrm->avail_out -= bytes;
-		lastrm->total_out += bytes;
-	}
-	if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
-		return (ARCHIVE_EOF);
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_end_copy(struct archive *a, struct la_zstream *lastrm)
-{
-	(void)a; /* UNUSED */
-	lastrm->valid = 0;
-	return (ARCHIVE_OK);
-}
-
-/*
- * _7_DEFLATE compressor.
- */
-#ifdef HAVE_ZLIB_H
-static int
-compression_init_encoder_deflate(struct archive *a,
-    struct la_zstream *lastrm, int level, int withheader)
-{
-	z_stream *strm;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for gzip stream");
-		return (ARCHIVE_FATAL);
-	}
-	/* zlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = (uInt)lastrm->avail_in;
-	strm->total_in = (uLong)lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = (uInt)lastrm->avail_out;
-	strm->total_out = (uLong)lastrm->total_out;
-	if (deflateInit2(strm, level, Z_DEFLATED,
-	    (withheader)?15:-15,
-	    8, Z_DEFAULT_STRATEGY) != Z_OK) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lastrm->real_stream = strm;
-	lastrm->valid = 1;
-	lastrm->code = compression_code_deflate;
-	lastrm->end = compression_end_deflate;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_deflate(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	z_stream *strm;
-	int r;
-
-	strm = (z_stream *)lastrm->real_stream;
-	/* zlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = (uInt)lastrm->avail_in;
-	strm->total_in = (uLong)lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = (uInt)lastrm->avail_out;
-	strm->total_out = (uLong)lastrm->total_out;
-	r = deflate(strm,
-	    (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
-	lastrm->next_in = strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in = strm->total_in;
-	lastrm->next_out = strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out = strm->total_out;
-	switch (r) {
-	case Z_OK:
-		return (ARCHIVE_OK);
-	case Z_STREAM_END:
-		return (ARCHIVE_EOF);
-	default:
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "GZip compression failed:"
-		    " deflate() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
-{
-	z_stream *strm;
-	int r;
-
-	strm = (z_stream *)lastrm->real_stream;
-	r = deflateEnd(strm);
-	free(strm);
-	lastrm->real_stream = NULL;
-	lastrm->valid = 0;
-	if (r != Z_OK) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-#else
-static int
-compression_init_encoder_deflate(struct archive *a,
-    struct la_zstream *lastrm, int level, int withheader)
-{
-
-	(void) level; /* UNUSED */
-	(void) withheader; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "deflate"));
-}
-#endif
-
-/*
- * _7_BZIP2 compressor.
- */
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-static int
-compression_init_encoder_bzip2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-	bz_stream *strm;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for bzip2 stream");
-		return (ARCHIVE_FATAL);
-	}
-	/* bzlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = (uint32_t)lastrm->avail_in;
-	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
-	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
-	strm->next_out = (char *)lastrm->next_out;
-	strm->avail_out = (uint32_t)lastrm->avail_out;
-	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
-	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
-	if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lastrm->real_stream = strm;
-	lastrm->valid = 1;
-	lastrm->code = compression_code_bzip2;
-	lastrm->end = compression_end_bzip2;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_bzip2(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	bz_stream *strm;
-	int r;
-
-	strm = (bz_stream *)lastrm->real_stream;
-	/* bzlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = (uint32_t)lastrm->avail_in;
-	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
-	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
-	strm->next_out = (char *)lastrm->next_out;
-	strm->avail_out = (uint32_t)lastrm->avail_out;
-	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
-	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
-	r = BZ2_bzCompress(strm,
-	    (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
-	lastrm->next_in = (const unsigned char *)strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in =
-	    (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
-	    + (uint64_t)(uint32_t)strm->total_in_lo32;
-	lastrm->next_out = (unsigned char *)strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out =
-	    (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
-	    + (uint64_t)(uint32_t)strm->total_out_lo32;
-	switch (r) {
-	case BZ_RUN_OK:     /* Non-finishing */
-	case BZ_FINISH_OK:  /* Finishing: There's more work to do */
-		return (ARCHIVE_OK);
-	case BZ_STREAM_END: /* Finishing: all done */
-		/* Only occurs in finishing case */
-		return (ARCHIVE_EOF);
-	default:
-		/* Any other return value indicates an error */
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Bzip2 compression failed:"
-		    " BZ2_bzCompress() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
-{
-	bz_stream *strm;
-	int r;
-
-	strm = (bz_stream *)lastrm->real_stream;
-	r = BZ2_bzCompressEnd(strm);
-	free(strm);
-	lastrm->real_stream = NULL;
-	lastrm->valid = 0;
-	if (r != BZ_OK) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-#else
-static int
-compression_init_encoder_bzip2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-
-	(void) level; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "bzip2"));
-}
-#endif
-
-/*
- * _7_LZMA1, _7_LZMA2 compressor.
- */
-#if defined(HAVE_LZMA_H)
-static int
-compression_init_encoder_lzma(struct archive *a,
-    struct la_zstream *lastrm, int level, uint64_t filter_id)
-{
-	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
-	lzma_stream *strm;
-	lzma_filter *lzmafilters;
-	lzma_options_lzma lzma_opt;
-	int r;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for lzma stream");
-		return (ARCHIVE_FATAL);
-	}
-	lzmafilters = (lzma_filter *)(strm+1);
-	if (level > 9)
-		level = 9;
-	if (lzma_lzma_preset(&lzma_opt, level)) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lzmafilters[0].id = filter_id;
-	lzmafilters[0].options = &lzma_opt;
-	lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
-
-	r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
-	if (r != LZMA_OK) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "lzma_properties_size failed");
-		return (ARCHIVE_FATAL);
-	}
-	if (lastrm->prop_size) {
-		lastrm->props = malloc(lastrm->prop_size);
-		if (lastrm->props == NULL) {
-			free(strm);
-			lastrm->real_stream = NULL;
-			archive_set_error(a, ENOMEM,
-			    "Cannot allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		r = lzma_properties_encode(lzmafilters,  lastrm->props);
-		if (r != LZMA_OK) {
-			free(strm);
-			lastrm->real_stream = NULL;
-			archive_set_error(a, ARCHIVE_ERRNO_MISC,
-			    "lzma_properties_encode failed");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	*strm = lzma_init_data;
-	r = lzma_raw_encoder(strm, lzmafilters);
-	switch (r) {
-	case LZMA_OK:
-		lastrm->real_stream = strm;
-		lastrm->valid = 1;
-		lastrm->code = compression_code_lzma;
-		lastrm->end = compression_end_lzma;
-		r = ARCHIVE_OK;
-		break;
-	case LZMA_MEM_ERROR:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "Cannot allocate memory");
-		r =  ARCHIVE_FATAL;
-		break;
-        default:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "It's a bug in liblzma");
-		r =  ARCHIVE_FATAL;
-		break;
-	}
-	return (r);
-}
-
-static int
-compression_init_encoder_lzma1(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-	return compression_init_encoder_lzma(a, lastrm, level,
-		    LZMA_FILTER_LZMA1);
-}
-
-static int
-compression_init_encoder_lzma2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-	return compression_init_encoder_lzma(a, lastrm, level,
-		    LZMA_FILTER_LZMA2);
-}
-
-static int
-compression_code_lzma(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	lzma_stream *strm;
-	int r;
-
-	strm = (lzma_stream *)lastrm->real_stream;
-	strm->next_in = lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in = lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out = lastrm->total_out;
-	r = lzma_code(strm,
-	    (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
-	lastrm->next_in = strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in = strm->total_in;
-	lastrm->next_out = strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out = strm->total_out;
-	switch (r) {
-	case LZMA_OK:
-		/* Non-finishing case */
-		return (ARCHIVE_OK);
-	case LZMA_STREAM_END:
-		/* This return can only occur in finishing case. */
-		return (ARCHIVE_EOF);
-	case LZMA_MEMLIMIT_ERROR:
-		archive_set_error(a, ENOMEM,
-		    "lzma compression error:"
-		    " %ju MiB would have been needed",
-		    (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
-			/ (1024 * 1024)));
-		return (ARCHIVE_FATAL);
-	default:
-		/* Any other return value indicates an error */
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "lzma compression failed:"
-		    " lzma_code() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
-{
-	lzma_stream *strm;
-
-	(void)a; /* UNUSED */
-	strm = (lzma_stream *)lastrm->real_stream;
-	lzma_end(strm);
-	free(strm);
-	lastrm->valid = 0;
-	lastrm->real_stream = NULL;
-	return (ARCHIVE_OK);
-}
-#else
-static int
-compression_init_encoder_lzma1(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-
-	(void) level; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "lzma"));
-}
-static int
-compression_init_encoder_lzma2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-
-	(void) level; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "lzma"));
-}
-#endif
-
-/*
- * _7_PPMD compressor.
- */
-static void
-ppmd_write(void *p, Byte b)
-{
-	struct archive_write *a = ((IByteOut *)p)->a;
-	struct _7zip *zip = (struct _7zip *)(a->format_data);
-	struct la_zstream *lastrm = &(zip->stream);
-	struct ppmd_stream *strm;
-
-	if (lastrm->avail_out) {
-		*lastrm->next_out++ = b;
-		lastrm->avail_out--;
-		lastrm->total_out++;
-		return;
-	}
-	strm = (struct ppmd_stream *)lastrm->real_stream;
-	if (strm->buff_ptr < strm->buff_end) {
-		*strm->buff_ptr++ = b;
-		strm->buff_bytes++;
-	}
-}
-
-static int
-compression_init_encoder_ppmd(struct archive *a,
-    struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
-{
-	struct ppmd_stream *strm;
-	uint8_t *props;
-	int r;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for PPMd");
-		return (ARCHIVE_FATAL);
-	}
-	strm->buff = malloc(32);
-	if (strm->buff == NULL) {
-		free(strm);
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for PPMd");
-		return (ARCHIVE_FATAL);
-	}
-	strm->buff_ptr = strm->buff;
-	strm->buff_end = strm->buff + 32;
-
-	props = malloc(1+4);
-	if (props == NULL) {
-		free(strm->buff);
-		free(strm);
-		archive_set_error(a, ENOMEM,
-		    "Coludn't allocate memory for PPMd");
-		return (ARCHIVE_FATAL);
-	}
-	props[0] = maxOrder;
-	archive_le32enc(props+1, msize);
-	__archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
-	r = __archive_ppmd7_functions.Ppmd7_Alloc(
-		&strm->ppmd7_context, msize);
-	if (r == 0) {
-		free(strm->buff);
-		free(strm);
-		free(props);
-		archive_set_error(a, ENOMEM,
-		    "Coludn't allocate memory for PPMd");
-		return (ARCHIVE_FATAL);
-	}
-	__archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder);
-	strm->byteout.a = (struct archive_write *)a;
-	strm->byteout.Write = ppmd_write;
-	strm->range_enc.Stream = &(strm->byteout);
-	__archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc));
-	strm->stat = 0;
-
-	lastrm->real_stream = strm;
-	lastrm->valid = 1;
-	lastrm->code = compression_code_ppmd;
-	lastrm->end = compression_end_ppmd;
-	lastrm->prop_size = 5;
-	lastrm->props = props;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_ppmd(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	struct ppmd_stream *strm;
-
-	(void)a; /* UNUSED */
-
-	strm = (struct ppmd_stream *)lastrm->real_stream;
-
-	/* Copy encoded data if there are remaining bytes from previous call. */
-	if (strm->buff_bytes) {
-		uint8_t *p = strm->buff_ptr - strm->buff_bytes;
-		while (lastrm->avail_out && strm->buff_bytes) {
-			*lastrm->next_out++ = *p++;
-			lastrm->avail_out--;
-			lastrm->total_out++;
-			strm->buff_bytes--;
-		}
-		if (strm->buff_bytes)
-			return (ARCHIVE_OK);
-		if (strm->stat == 1)
-			return (ARCHIVE_EOF);
-		strm->buff_ptr = strm->buff;
-	}
-	while (lastrm->avail_in && lastrm->avail_out) {
-		__archive_ppmd7_functions.Ppmd7_EncodeSymbol(
-			&(strm->ppmd7_context), &(strm->range_enc),
-			*lastrm->next_in++);
-		lastrm->avail_in--;
-		lastrm->total_in++;
-	}
-	if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
-		__archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
-			&(strm->range_enc));
-		strm->stat = 1;
-		/* Return EOF if there are no remaining bytes. */
-		if (strm->buff_bytes == 0)
-			return (ARCHIVE_EOF);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
-{
-	struct ppmd_stream *strm;
-
-	(void)a; /* UNUSED */
-
-	strm = (struct ppmd_stream *)lastrm->real_stream;
-	__archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
-	free(strm->buff);
-	free(strm);
-	lastrm->real_stream = NULL;
-	lastrm->valid = 0;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Universal compressor initializer.
- */
-static int
-_7z_compression_init_encoder(struct archive_write *a, unsigned compression,
-    int compression_level)
-{
-	struct _7zip *zip;
-	int r;
-
-	zip = (struct _7zip *)a->format_data;
-	switch (compression) {
-	case _7Z_DEFLATE:
-		r = compression_init_encoder_deflate(
-		    &(a->archive), &(zip->stream),
-		    compression_level, 0);
-		break;
-	case _7Z_BZIP2:
-		r = compression_init_encoder_bzip2(
-		    &(a->archive), &(zip->stream),
-		    compression_level);
-		break;
-	case _7Z_LZMA1:
-		r = compression_init_encoder_lzma1(
-		    &(a->archive), &(zip->stream),
-		    compression_level);
-		break;
-	case _7Z_LZMA2:
-		r = compression_init_encoder_lzma2(
-		    &(a->archive), &(zip->stream),
-		    compression_level);
-		break;
-	case _7Z_PPMD:
-		r = compression_init_encoder_ppmd(
-		    &(a->archive), &(zip->stream),
-		    PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
-		break;
-	case _7Z_COPY:
-	default:
-		r = compression_init_encoder_copy(
-		    &(a->archive), &(zip->stream));
-		break;
-	}
-	if (r == ARCHIVE_OK) {
-		zip->stream.total_in = 0;
-		zip->stream.next_out = zip->wbuff;
-		zip->stream.avail_out = sizeof(zip->wbuff);
-		zip->stream.total_out = 0;
-	}
-
-	return (r);
-}
-
-static int
-compression_code(struct archive *a, struct la_zstream *lastrm,
-    enum la_zaction action)
-{
-	if (lastrm->valid)
-		return (lastrm->code(a, lastrm, action));
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_end(struct archive *a, struct la_zstream *lastrm)
-{
-	if (lastrm->valid) {
-		lastrm->prop_size = 0;
-		free(lastrm->props);
-		lastrm->props = NULL;
-		return (lastrm->end(a, lastrm));
-	}
-	return (ARCHIVE_OK);
-}
-
-
diff --git a/c/archive_write_set_format_ar.c b/c/archive_write_set_format_ar.c
deleted file mode 100644
--- a/c/archive_write_set_format_ar.c
+++ /dev/null
@@ -1,570 +0,0 @@
-/*-
- * Copyright (c) 2007 Kai Wang
- * Copyright (c) 2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ar.c 201108 2009-12-28 03:28:21Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct ar_w {
-	uint64_t	 entry_bytes_remaining;
-	uint64_t	 entry_padding;
-	int		 is_strtab;
-	int		 has_strtab;
-	char		 wrote_global_header;
-	char		*strtab;
-};
-
-/*
- * Define structure of the "ar" header.
- */
-#define AR_name_offset 0
-#define AR_name_size 16
-#define AR_date_offset 16
-#define AR_date_size 12
-#define AR_uid_offset 28
-#define AR_uid_size 6
-#define AR_gid_offset 34
-#define AR_gid_size 6
-#define AR_mode_offset 40
-#define AR_mode_size 8
-#define AR_size_offset 48
-#define AR_size_size 10
-#define AR_fmag_offset 58
-#define AR_fmag_size 2
-
-static int		 archive_write_set_format_ar(struct archive_write *);
-static int		 archive_write_ar_header(struct archive_write *,
-			     struct archive_entry *);
-static ssize_t		 archive_write_ar_data(struct archive_write *,
-			     const void *buff, size_t s);
-static int		 archive_write_ar_free(struct archive_write *);
-static int		 archive_write_ar_close(struct archive_write *);
-static int		 archive_write_ar_finish_entry(struct archive_write *);
-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);
-
-int
-archive_write_set_format_ar_bsd(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_ar_bsd");
-	r = archive_write_set_format_ar(a);
-	if (r == ARCHIVE_OK) {
-		a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
-		a->archive.archive_format_name = "ar (BSD)";
-	}
-	return (r);
-}
-
-int
-archive_write_set_format_ar_svr4(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_ar_svr4");
-	r = archive_write_set_format_ar(a);
-	if (r == ARCHIVE_OK) {
-		a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
-		a->archive.archive_format_name = "ar (GNU/SVR4)";
-	}
-	return (r);
-}
-
-/*
- * Generic initialization.
- */
-static int
-archive_write_set_format_ar(struct archive_write *a)
-{
-	struct ar_w *ar;
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	ar = (struct ar_w *)calloc(1, sizeof(*ar));
-	if (ar == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = ar;
-
-	a->format_name = "ar";
-	a->format_write_header = archive_write_ar_header;
-	a->format_write_data = archive_write_ar_data;
-	a->format_close = archive_write_ar_close;
-	a->format_free = archive_write_ar_free;
-	a->format_finish_entry = archive_write_ar_finish_entry;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
-{
-	int ret, append_fn;
-	char buff[60];
-	char *ss, *se;
-	struct ar_w *ar;
-	const char *pathname;
-	const char *filename;
-	int64_t size;
-
-	append_fn = 0;
-	ar = (struct ar_w *)a->format_data;
-	ar->is_strtab = 0;
-	filename = NULL;
-	size = archive_entry_size(entry);
-
-
-	/*
-	 * Reject files with empty name.
-	 */
-	pathname = archive_entry_pathname(entry);
-	if (pathname == NULL || *pathname == '\0') {
-		archive_set_error(&a->archive, EINVAL,
-		    "Invalid filename");
-		return (ARCHIVE_WARN);
-	}
-
-	/*
-	 * If we are now at the beginning of the archive,
-	 * we need first write the ar global header.
-	 */
-	if (!ar->wrote_global_header) {
-		__archive_write_output(a, "!<arch>\n", 8);
-		ar->wrote_global_header = 1;
-	}
-
-	memset(buff, ' ', 60);
-	memcpy(&buff[AR_fmag_offset], "`\n", 2);
-
-	if (strcmp(pathname, "/") == 0 ) {
-		/* Entry is archive symbol table in GNU format */
-		buff[AR_name_offset] = '/';
-		goto stat;
-	}
-	if (strcmp(pathname, "/SYM64/") == 0) {
-		/* Entry is archive symbol table in GNU 64-bit format */
-		memcpy(buff + AR_name_offset, "/SYM64/", 7);
-		goto stat;
-	}
-	if (strcmp(pathname, "__.SYMDEF") == 0) {
-		/* Entry is archive symbol table in BSD format */
-		memcpy(buff + AR_name_offset, "__.SYMDEF", 9);
-		goto stat;
-	}
-	if (strcmp(pathname, "//") == 0) {
-		/*
-		 * Entry is archive filename table, inform that we should
-		 * collect strtab in next _data call.
-		 */
-		ar->is_strtab = 1;
-		buff[AR_name_offset] = buff[AR_name_offset + 1] = '/';
-		/*
-		 * For archive string table, only ar_size field should
-		 * be set.
-		 */
-		goto size;
-	}
-
-	/*
-	 * Otherwise, entry is a normal archive member.
-	 * Strip leading paths from filenames, if any.
-	 */
-	if ((filename = ar_basename(pathname)) == NULL) {
-		/* Reject filenames with trailing "/" */
-		archive_set_error(&a->archive, EINVAL,
-		    "Invalid filename");
-		return (ARCHIVE_WARN);
-	}
-
-	if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) {
-		/*
-		 * SVR4/GNU variant use a "/" to mark then end of the filename,
-		 * make it possible to have embedded spaces in the filename.
-		 * So, the longest filename here (without extension) is
-		 * actually 15 bytes.
-		 */
-		if (strlen(filename) <= 15) {
-			memcpy(&buff[AR_name_offset],
-			    filename, strlen(filename));
-			buff[AR_name_offset + strlen(filename)] = '/';
-		} else {
-			/*
-			 * For filename longer than 15 bytes, GNU variant
-			 * makes use of a string table and instead stores the
-			 * offset of the real filename to in the ar_name field.
-			 * The string table should have been written before.
-			 */
-			if (ar->has_strtab <= 0) {
-				archive_set_error(&a->archive, EINVAL,
-				    "Can't find string table");
-				return (ARCHIVE_WARN);
-			}
-
-			se = (char *)malloc(strlen(filename) + 3);
-			if (se == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate filename buffer");
-				return (ARCHIVE_FATAL);
-			}
-
-			memcpy(se, filename, strlen(filename));
-			strcpy(se + strlen(filename), "/\n");
-
-			ss = strstr(ar->strtab, se);
-			free(se);
-
-			if (ss == NULL) {
-				archive_set_error(&a->archive, EINVAL,
-				    "Invalid string table");
-				return (ARCHIVE_WARN);
-			}
-
-			/*
-			 * GNU variant puts "/" followed by digits into
-			 * ar_name field. These digits indicates the real
-			 * filename string's offset to the string table.
-			 */
-			buff[AR_name_offset] = '/';
-			if (format_decimal(ss - ar->strtab,
-			    buff + AR_name_offset + 1,
-			    AR_name_size - 1)) {
-				archive_set_error(&a->archive, ERANGE,
-				    "string table offset too large");
-				return (ARCHIVE_WARN);
-			}
-		}
-	} else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) {
-		/*
-		 * BSD variant: for any file name which is more than
-		 * 16 chars or contains one or more embedded space(s), the
-		 * string "#1/" followed by the ASCII length of the name is
-		 * put into the ar_name field. The file size (stored in the
-		 * ar_size field) is incremented by the length of the name.
-		 * The name is then written immediately following the
-		 * archive header.
-		 */
-		if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) {
-			memcpy(&buff[AR_name_offset], filename, strlen(filename));
-			buff[AR_name_offset + strlen(filename)] = ' ';
-		}
-		else {
-			memcpy(buff + AR_name_offset, "#1/", 3);
-			if (format_decimal(strlen(filename),
-			    buff + AR_name_offset + 3,
-			    AR_name_size - 3)) {
-				archive_set_error(&a->archive, ERANGE,
-				    "File name too long");
-				return (ARCHIVE_WARN);
-			}
-			append_fn = 1;
-			size += strlen(filename);
-		}
-	}
-
-stat:
-	if (format_decimal(archive_entry_mtime(entry), buff + AR_date_offset, AR_date_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File modification time too large");
-		return (ARCHIVE_WARN);
-	}
-	if (format_decimal(archive_entry_uid(entry), buff + AR_uid_offset, AR_uid_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric user ID too large");
-		return (ARCHIVE_WARN);
-	}
-	if (format_decimal(archive_entry_gid(entry), buff + AR_gid_offset, AR_gid_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric group ID too large");
-		return (ARCHIVE_WARN);
-	}
-	if (format_octal(archive_entry_mode(entry), buff + AR_mode_offset, AR_mode_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric mode too large");
-		return (ARCHIVE_WARN);
-	}
-	/*
-	 * Sanity Check: A non-pseudo archive member should always be
-	 * a regular file.
-	 */
-	if (filename != NULL && archive_entry_filetype(entry) != AE_IFREG) {
-		archive_set_error(&a->archive, EINVAL,
-		    "Regular file required for non-pseudo member");
-		return (ARCHIVE_WARN);
-	}
-
-size:
-	if (format_decimal(size, buff + AR_size_offset, AR_size_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File size out of range");
-		return (ARCHIVE_WARN);
-	}
-
-	ret = __archive_write_output(a, buff, 60);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	ar->entry_bytes_remaining = size;
-	ar->entry_padding = ar->entry_bytes_remaining % 2;
-
-	if (append_fn > 0) {
-		ret = __archive_write_output(a, filename, strlen(filename));
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		ar->entry_bytes_remaining -= strlen(filename);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct ar_w *ar;
-	int ret;
-
-	ar = (struct ar_w *)a->format_data;
-	if (s > ar->entry_bytes_remaining)
-		s = (size_t)ar->entry_bytes_remaining;
-
-	if (ar->is_strtab > 0) {
-		if (ar->has_strtab > 0) {
-			archive_set_error(&a->archive, EINVAL,
-			    "More than one string tables exist");
-			return (ARCHIVE_WARN);
-		}
-
-		ar->strtab = (char *)malloc(s + 1);
-		if (ar->strtab == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate strtab buffer");
-			return (ARCHIVE_FATAL);
-		}
-		memcpy(ar->strtab, buff, s);
-		ar->strtab[s] = '\0';
-		ar->has_strtab = 1;
-	}
-
-	ret = __archive_write_output(a, buff, s);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-
-	ar->entry_bytes_remaining -= s;
-	return (s);
-}
-
-static int
-archive_write_ar_free(struct archive_write *a)
-{
-	struct ar_w *ar;
-
-	ar = (struct ar_w *)a->format_data;
-
-	if (ar == NULL)
-		return (ARCHIVE_OK);
-
-	if (ar->has_strtab > 0) {
-		free(ar->strtab);
-		ar->strtab = NULL;
-	}
-
-	free(ar);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_ar_close(struct archive_write *a)
-{
-	struct ar_w *ar;
-	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.
-	 */
-	ar = (struct ar_w *)a->format_data;
-	if (!ar->wrote_global_header) {
-		ar->wrote_global_header = 1;
-		ret = __archive_write_output(a, "!<arch>\n", 8);
-		return (ret);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_ar_finish_entry(struct archive_write *a)
-{
-	struct ar_w *ar;
-	int ret;
-
-	ar = (struct ar_w *)a->format_data;
-
-	if (ar->entry_bytes_remaining != 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Entry remaining bytes larger than 0");
-		return (ARCHIVE_WARN);
-	}
-
-	if (ar->entry_padding == 0) {
-		return (ARCHIVE_OK);
-	}
-
-	if (ar->entry_padding != 1) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Padding wrong size: %ju should be 1 or 0",
-		    (uintmax_t)ar->entry_padding);
-		return (ARCHIVE_WARN);
-	}
-
-	ret = __archive_write_output(a, "\n", 1);
-	return (ret);
-}
-
-/*
- * Format a number into the specified field using base-8.
- * NB: This version is slightly different from the one in
- * _ustar.c
- */
-static int
-format_octal(int64_t v, char *p, int s)
-{
-	int len;
-	char *h;
-
-	len = s;
-	h = p;
-
-	/* Octal values can't be negative, so use 0. */
-	if (v < 0) {
-		while (len-- > 0)
-			*p++ = '0';
-		return (-1);
-	}
-
-	p += s;		/* Start at the end and work backwards. */
-	do {
-		*--p = (char)('0' + (v & 7));
-		v >>= 3;
-	} while (--s > 0 && v > 0);
-
-	if (v == 0) {
-		memmove(h, p, len - s);
-		p = h + len - s;
-		while (s-- > 0)
-			*p++ = ' ';
-		return (0);
-	}
-	/* If it overflowed, fill field with max value. */
-	while (len-- > 0)
-		*p++ = '7';
-
-	return (-1);
-}
-
-/*
- * Format a number into the specified field using base-10.
- */
-static int
-format_decimal(int64_t v, char *p, int s)
-{
-	int len;
-	char *h;
-
-	len = s;
-	h = p;
-
-	/* Negative values in ar header are meaningless, so use 0. */
-	if (v < 0) {
-		while (len-- > 0)
-			*p++ = '0';
-		return (-1);
-	}
-
-	p += s;
-	do {
-		*--p = (char)('0' + (v % 10));
-		v /= 10;
-	} while (--s > 0 && v > 0);
-
-	if (v == 0) {
-		memmove(h, p, len - s);
-		p = h + len - s;
-		while (s-- > 0)
-			*p++ = ' ';
-		return (0);
-	}
-	/* If it overflowed, fill field with max value. */
-	while (len-- > 0)
-		*p++ = '9';
-
-	return (-1);
-}
-
-static const char *
-ar_basename(const char *path)
-{
-	const char *endp, *startp;
-
-	endp = path + strlen(path) - 1;
-	/*
-	 * For filename with trailing slash(es), we return
-	 * NULL indicating an error.
-	 */
-	if (*endp == '/')
-		return (NULL);
-
-	/* Find the start of the base */
-	startp = endp;
-	while (startp > path && *(startp - 1) != '/')
-		startp--;
-	
-	return (startp);
-}
diff --git a/c/archive_write_set_format_by_name.c b/c/archive_write_set_format_by_name.c
deleted file mode 100644
--- a/c/archive_write_set_format_by_name.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-/* A table that maps names to functions. */
-static const
-struct { const char *name; int (*setter)(struct archive *); } names[] =
-{
-	{ "7zip",	archive_write_set_format_7zip },
-	{ "ar",		archive_write_set_format_ar_bsd },
-	{ "arbsd",	archive_write_set_format_ar_bsd },
-	{ "argnu",	archive_write_set_format_ar_svr4 },
-	{ "arsvr4",	archive_write_set_format_ar_svr4 },
-	{ "bin",	archive_write_set_format_cpio_bin },
-	{ "bsdtar",	archive_write_set_format_pax_restricted },
-	{ "cd9660",	archive_write_set_format_iso9660 },
-	{ "cpio",	archive_write_set_format_cpio },
-	{ "gnutar",	archive_write_set_format_gnutar },
-	{ "iso",	archive_write_set_format_iso9660 },
-	{ "iso9660",	archive_write_set_format_iso9660 },
-	{ "mtree",	archive_write_set_format_mtree },
-	{ "mtree-classic",	archive_write_set_format_mtree_classic },
-	{ "newc",	archive_write_set_format_cpio_newc },
-	{ "odc",	archive_write_set_format_cpio_odc },
-	{ "oldtar",	archive_write_set_format_v7tar },
-	{ "pax",	archive_write_set_format_pax },
-	{ "paxr",	archive_write_set_format_pax_restricted },
-	{ "posix",	archive_write_set_format_pax },
-	{ "pwb",	archive_write_set_format_cpio_pwb },
-	{ "raw",	archive_write_set_format_raw },
-	{ "rpax",	archive_write_set_format_pax_restricted },
-	{ "shar",	archive_write_set_format_shar },
-	{ "shardump",	archive_write_set_format_shar_dump },
-	{ "ustar",	archive_write_set_format_ustar },
-	{ "v7tar",	archive_write_set_format_v7tar },
-	{ "v7",		archive_write_set_format_v7tar },
-	{ "warc",	archive_write_set_format_warc },
-	{ "xar",	archive_write_set_format_xar },
-	{ "zip",	archive_write_set_format_zip },
-	{ NULL,		NULL }
-};
-
-int
-archive_write_set_format_by_name(struct archive *a, const char *name)
-{
-	int i;
-
-	for (i = 0; names[i].name != NULL; i++) {
-		if (strcmp(name, names[i].name) == 0)
-			return ((names[i].setter)(a));
-	}
-
-	archive_set_error(a, EINVAL, "No such format '%s'", name);
-	a->state = ARCHIVE_STATE_FATAL;
-	return (ARCHIVE_FATAL);
-}
diff --git a/c/archive_write_set_format_cpio.c b/c/archive_write_set_format_cpio.c
deleted file mode 100644
--- a/c/archive_write_set_format_cpio.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "archive_platform.h"
-#include "archive.h"
-
-/*
- * Set output format to the default 'cpio' format.
- */
-int
-archive_write_set_format_cpio(struct archive *_a)
-{
-	return archive_write_set_format_cpio_odc(_a);
-}
diff --git a/c/archive_write_set_format_cpio_binary.c b/c/archive_write_set_format_cpio_binary.c
deleted file mode 100644
--- a/c/archive_write_set_format_cpio_binary.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-static ssize_t	archive_write_binary_data(struct archive_write *,
-		    const void *buff, size_t s);
-static int	archive_write_binary_close(struct archive_write *);
-static int	archive_write_binary_free(struct archive_write *);
-static int	archive_write_binary_finish_entry(struct archive_write *);
-static int	archive_write_binary_header(struct archive_write *,
-		    struct archive_entry *);
-static int	archive_write_binary_options(struct archive_write *,
-		    const char *, const char *);
-static int	write_header(struct archive_write *, struct archive_entry *);
-
-struct cpio {
-	uint64_t	  entry_bytes_remaining;
-
-	int64_t		  ino_next;
-
-	struct		 { int64_t old; int new;} *ino_list;
-	size_t		  ino_list_size;
-	size_t		  ino_list_next;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int		  init_default_conversion;
-};
-
-/* This struct needs to be packed to get the header right */
-
-#if defined(__GNUC__)
-#define PACKED(x) x __attribute__((packed))
-#elif defined(_MSC_VER)
-#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
-#else
-#define PACKED(x) x
-#endif
-
-#define HSIZE 26
-
-PACKED(struct cpio_binary_header {
-	uint16_t	h_magic;
-	uint16_t	h_dev;
-	uint16_t	h_ino;
-	uint16_t	h_mode;
-	uint16_t	h_uid;
-	uint16_t	h_gid;
-	uint16_t	h_nlink;
-	uint16_t	h_majmin;
-	uint32_t	h_mtime;
-	uint16_t	h_namesize;
-	uint32_t	h_filesize;
-});
-
-/* Back in the day, the 7th Edition cpio.c had this, to
- * adapt to, as the comment said, "VAX, Interdata, ...":
- *
- * union { long l; short s[2]; char c[4]; } U;
- * #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}
- * long mklong(v)
- * short v[];
- * {
- *         U.l = 1;
- *         if(U.c[0])
- *                 U.s[0] = v[1], U.s[1] = v[0];
- *         else
- *                 U.s[0] = v[0], U.s[1] = v[1];
- *         return U.l;
- * }
- *
- * Of course, that assumes that all machines have little-endian shorts,
- * and just adapts the others to the special endianness of the PDP-11.
- *
- * Now, we could do this:
- *
- * union { uint32_t l; uint16_t s[2]; uint8_t c[4]; } U;
- * #define PUTI16(v,sv) {U.s[0]=1;if(U.c[0]) v=sv; else U.s[0]=sv,U.c[2]=U.c[1],U.c[3]=U.c[0],v=U.s[1];}
- * #define PUTI32(v,lv) {char_t Ut;U.l=1;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,Ut=U.c[0],U.c[0]=U.c[1],U.c[1]=Ut,Ut=U.c[2],U.c[2]=U.c[3],U.c[3]=Ut,v[0]=U.s[0],v[1]=U.s[1];}
- *
- * ...but it feels a little better to do it like this:
- */
-
-static uint16_t la_swap16(uint16_t in) {
-	union {
-		uint16_t s[2];
-		uint8_t c[4];
-	} U;
-	U.s[0] = 1;
-	if (U.c[0])
-		return in;
-	else {
-		U.s[0] = in;
-		U.c[2] = U.c[1];
-		U.c[3] = U.c[0];
-		return U.s[1];
-	}
-	/* NOTREACHED */
-}
-
-static uint32_t la_swap32(uint32_t in) {
-	union {
-		uint32_t l;
-		uint16_t s[2];
-		uint8_t c[4];
-	} U;
-	U.l = 1;
-	if (U.c[0]) {		/* Little-endian */
-		uint16_t t;
-		U.l = in;
-		t = U.s[0];
-		U.s[0] = U.s[1];
-		U.s[1] = t;
-	} else if (U.c[3]) {	/* Big-endian */
-		U.l = in;
-		U.s[0] = la_swap16(U.s[0]);
-		U.s[1] = la_swap16(U.s[1]);
-	} else {		/* PDP-endian */
-		U.l = in;
-	}
-	return U.l;
-}
-
-/*
- * Set output format to the selected binary variant
- */
-static int
-archive_write_set_format_cpio_binary(struct archive *_a, int format)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct cpio *cpio;
-
-	if (sizeof(struct cpio_binary_header) != HSIZE) {
-		archive_set_error(&a->archive, EINVAL,
-				  "Binary cpio format not supported on this platform");
-		return (ARCHIVE_FATAL);
-	}
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_binary");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
-	if (cpio == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = cpio;
-	a->format_name = "cpio";
-	a->format_options = archive_write_binary_options;
-	a->format_write_header = archive_write_binary_header;
-	a->format_write_data = archive_write_binary_data;
-	a->format_finish_entry = archive_write_binary_finish_entry;
-	a->format_close = archive_write_binary_close;
-	a->format_free = archive_write_binary_free;
-	a->archive.archive_format = format;
-	switch (format) {
-	case ARCHIVE_FORMAT_CPIO_PWB:
-		a->archive.archive_format_name = "PWB cpio";
-		break;
-	case ARCHIVE_FORMAT_CPIO_BIN_LE:
-		a->archive.archive_format_name = "7th Edition cpio";
-		break;
-	default:
-		archive_set_error(&a->archive, EINVAL, "binary format must be 'pwb' or 'bin'");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Set output format to PWB (6th Edition) binary format
- */
-int
-archive_write_set_format_cpio_pwb(struct archive *_a)
-{
-	return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_PWB);
-}
-
-/*
- * Set output format to 7th Edition binary format
- */
-int
-archive_write_set_format_cpio_bin(struct archive *_a)
-{
-	return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_BIN_LE);
-}
-
-static int
-archive_write_binary_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct cpio *cpio = (struct cpio *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			cpio->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (cpio->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Ino values are as long as 64 bits on some systems; cpio format
- * only allows 16 bits and relies on the ino values to identify hardlinked
- * files.  So, we can't merely "hash" the ino numbers since collisions
- * would corrupt the archive.  Instead, we generate synthetic ino values
- * to store in the archive and maintain a map of original ino values to
- * synthetic ones so we can preserve hardlink information.
- *
- * TODO: Make this more efficient.  It's not as bad as it looks (most
- * files don't have any hardlinks and we don't do any work here for those),
- * but it wouldn't be hard to do better.
- *
- * TODO: Work with dev/ino pairs here instead of just ino values.
- */
-static int
-synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
-{
-	int64_t ino = archive_entry_ino64(entry);
-	int ino_new;
-	size_t i;
-
-	/*
-	 * If no index number was given, don't assign one.  In
-	 * particular, this handles the end-of-archive marker
-	 * correctly by giving it a zero index value.  (This is also
-	 * why we start our synthetic index numbers with one below.)
-	 */
-	if (ino == 0)
-		return (0);
-
-	/* Don't store a mapping if we don't need to. */
-	if (archive_entry_nlink(entry) < 2) {
-		return (int)(++cpio->ino_next);
-	}
-
-	/* Look up old ino; if we have it, this is a hardlink
-	 * and we reuse the same value. */
-	for (i = 0; i < cpio->ino_list_next; ++i) {
-		if (cpio->ino_list[i].old == ino)
-			return (cpio->ino_list[i].new);
-	}
-
-	/* Assign a new index number. */
-	ino_new = (int)(++cpio->ino_next);
-
-	/* Ensure space for the new mapping. */
-	if (cpio->ino_list_size <= cpio->ino_list_next) {
-		size_t newsize = cpio->ino_list_size < 512
-		    ? 512 : cpio->ino_list_size * 2;
-		void *newlist = realloc(cpio->ino_list,
-		    sizeof(cpio->ino_list[0]) * newsize);
-		if (newlist == NULL)
-			return (-1);
-
-		cpio->ino_list_size = newsize;
-		cpio->ino_list = newlist;
-	}
-
-	/* Record and return the new value. */
-	cpio->ino_list[cpio->ino_list_next].old = ino;
-	cpio->ino_list[cpio->ino_list_next].new = ino_new;
-	++cpio->ino_list_next;
-	return (ino_new);
-}
-
-
-static struct archive_string_conv *
-get_sconv(struct archive_write *a)
-{
-	struct cpio *cpio;
-	struct archive_string_conv *sconv;
-
-	cpio = (struct cpio *)a->format_data;
-	sconv = cpio->opt_sconv;
-	if (sconv == NULL) {
-		if (!cpio->init_default_conversion) {
-			cpio->sconv_default =
-			    archive_string_default_conversion_for_write(
-			      &(a->archive));
-			cpio->init_default_conversion = 1;
-		}
-		sconv = cpio->sconv_default;
-	}
-	return (sconv);
-}
-
-static int
-archive_write_binary_header(struct archive_write *a, struct archive_entry *entry)
-{
-	const char *path;
-	size_t len;
-
-	if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
-		archive_set_error(&a->archive, -1, "Filetype required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
-	    && errno == ENOMEM) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for Pathname");
-		return (ARCHIVE_FATAL);
-	}
-	if (len == 0 || path == NULL || path[0] == '\0') {
-		archive_set_error(&a->archive, -1, "Pathname required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
-		archive_set_error(&a->archive, -1, "Size required");
-		return (ARCHIVE_FAILED);
-	}
-	return write_header(a, entry);
-}
-
-static int
-write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct cpio *cpio;
-	const char *p, *path;
-	int pathlength, ret, ret_final;
-	int64_t	ino;
-	struct cpio_binary_header h;
-	struct archive_string_conv *sconv;
-	struct archive_entry *entry_main;
-	size_t len;
-
-	cpio = (struct cpio *)a->format_data;
-	ret_final = ARCHIVE_OK;
-	sconv = get_sconv(a);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-
-	ret = archive_entry_pathname_l(entry, &path, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    archive_entry_pathname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-	/* Include trailing null */
-	pathlength = (int)len + 1;
-
-	h.h_magic = la_swap16(070707);
-	h.h_dev = la_swap16(archive_entry_dev(entry));
-
-	ino = synthesize_ino_value(cpio, entry);
-	if (ino < 0) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for ino translation table");
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	} else if (ino > 077777) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Too many files for this cpio format");
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-	h.h_ino = la_swap16((uint16_t)ino);
-
-	h.h_mode = archive_entry_mode(entry);
-	if (((h.h_mode & AE_IFMT) == AE_IFSOCK) || ((h.h_mode & AE_IFMT) == AE_IFIFO)) {
-		archive_set_error(&a->archive, EINVAL,
-				  "sockets and fifos cannot be represented in the binary cpio formats");
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-	if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
-		if ((h.h_mode & AE_IFMT) == AE_IFLNK) {
-			archive_set_error(&a->archive, EINVAL,
-					  "symbolic links cannot be represented in the PWB cpio format");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		/* we could turn off AE_IFREG here, but it does no harm, */
-		/* and allows v7 cpio to read the entry without confusion */
-	}
-	h.h_mode = la_swap16(h.h_mode);
-
-	h.h_uid = la_swap16((uint16_t)archive_entry_uid(entry));
-	h.h_gid = la_swap16((uint16_t)archive_entry_gid(entry));
-	h.h_nlink = la_swap16((uint16_t)archive_entry_nlink(entry));
-
-	if (archive_entry_filetype(entry) == AE_IFBLK
-	    || archive_entry_filetype(entry) == AE_IFCHR)
-		h.h_majmin = la_swap16(archive_entry_rdev(entry));
-	else
-		h.h_majmin = 0;
-
-	h.h_mtime = la_swap32((uint32_t)archive_entry_mtime(entry));
-	h.h_namesize = la_swap16(pathlength);
-
-	/* Non-regular files don't store bodies. */
-	if (archive_entry_filetype(entry) != AE_IFREG)
-		archive_entry_set_size(entry, 0);
-
-	/* Symlinks get the link written as the body of the entry. */
-	ret = archive_entry_symlink_l(entry, &p, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    archive_entry_symlink(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-
-	if (len > 0 && p != NULL  &&  *p != '\0') {
-		if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
-			archive_set_error(&a->archive, EINVAL,
-					  "symlinks are not supported by UNIX V6 or by PWB cpio");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		h.h_filesize = la_swap32((uint32_t)strlen(p)); /* symlink */
-	} else {
-		if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) &&
-		    (archive_entry_size(entry) > 256*256*256-1)) {
-			archive_set_error(&a->archive, ERANGE,
-					  "File is too large for PWB binary cpio format.");
-			ret_final = ARCHIVE_FAILED;
-			goto exit_write_header;
-		} else if (archive_entry_size(entry) > INT32_MAX) {
-			archive_set_error(&a->archive, ERANGE,
-					  "File is too large for binary cpio format.");
-			ret_final = ARCHIVE_FAILED;
-			goto exit_write_header;
-		}
-		h.h_filesize = la_swap32((uint32_t)archive_entry_size(entry)); /* file */
-	}
-
-	ret = __archive_write_output(a, &h, HSIZE);
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-
-	ret = __archive_write_output(a, path, pathlength);
-	if ((ret == ARCHIVE_OK) && ((pathlength % 2) != 0))
-		ret = __archive_write_nulls(a, 1);
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-
-	cpio->entry_bytes_remaining = archive_entry_size(entry);
-	if ((cpio->entry_bytes_remaining % 2) != 0)
-		cpio->entry_bytes_remaining++;
-
-	/* Write the symlink now. */
-	if (p != NULL  &&  *p != '\0') {
-		ret = __archive_write_output(a, p, strlen(p));
-		if ((ret == ARCHIVE_OK) && ((strlen(p) % 2) != 0))
-			ret = __archive_write_nulls(a, 1);
-		if (ret != ARCHIVE_OK) {
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-	}
-
-exit_write_header:
-	archive_entry_free(entry_main);
-	return (ret_final);
-}
-
-static ssize_t
-archive_write_binary_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct cpio *cpio;
-	int ret;
-
-	cpio = (struct cpio *)a->format_data;
-	if (s > cpio->entry_bytes_remaining)
-		s = (size_t)cpio->entry_bytes_remaining;
-
-	ret = __archive_write_output(a, buff, s);
-	cpio->entry_bytes_remaining -= s;
-	if (ret >= 0)
-		return (s);
-	else
-		return (ret);
-}
-
-static int
-archive_write_binary_close(struct archive_write *a)
-{
-	int er;
-	struct archive_entry *trailer;
-
-	trailer = archive_entry_new2(NULL);
-	/* nlink = 1 here for GNU cpio compat. */
-	archive_entry_set_nlink(trailer, 1);
-	archive_entry_set_size(trailer, 0);
-	archive_entry_set_pathname(trailer, "TRAILER!!!");
-	er = write_header(a, trailer);
-	archive_entry_free(trailer);
-	return (er);
-}
-
-static int
-archive_write_binary_free(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	free(cpio->ino_list);
-	free(cpio);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_binary_finish_entry(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	return (__archive_write_nulls(a,
-		(size_t)cpio->entry_bytes_remaining));
-}
diff --git a/c/archive_write_set_format_cpio_newc.c b/c/archive_write_set_format_cpio_newc.c
deleted file mode 100644
--- a/c/archive_write_set_format_cpio_newc.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o.
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio_newc.c 201160 2009-12-29 05:41:57Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-static ssize_t	archive_write_newc_data(struct archive_write *,
-		    const void *buff, size_t s);
-static int	archive_write_newc_close(struct archive_write *);
-static int	archive_write_newc_free(struct archive_write *);
-static int	archive_write_newc_finish_entry(struct archive_write *);
-static int	archive_write_newc_header(struct archive_write *,
-		    struct archive_entry *);
-static int      archive_write_newc_options(struct archive_write *,
-		    const char *, const char *);
-static int	format_hex(int64_t, void *, int);
-static int64_t	format_hex_recursive(int64_t, char *, int);
-static int	write_header(struct archive_write *, struct archive_entry *);
-
-struct cpio {
-	uint64_t	  entry_bytes_remaining;
-	int		  padding;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int		  init_default_conversion;
-};
-
-#define	c_magic_offset 0
-#define	c_magic_size 6
-#define	c_ino_offset 6
-#define	c_ino_size 8
-#define	c_mode_offset 14
-#define	c_mode_size 8
-#define	c_uid_offset 22
-#define	c_uid_size 8
-#define	c_gid_offset 30
-#define	c_gid_size 8
-#define	c_nlink_offset 38
-#define	c_nlink_size 8
-#define	c_mtime_offset 46
-#define	c_mtime_size 8
-#define	c_filesize_offset 54
-#define	c_filesize_size 8
-#define	c_devmajor_offset 62
-#define	c_devmajor_size 8
-#define	c_devminor_offset 70
-#define	c_devminor_size 8
-#define	c_rdevmajor_offset 78
-#define	c_rdevmajor_size 8
-#define	c_rdevminor_offset 86
-#define	c_rdevminor_size 8
-#define	c_namesize_offset 94
-#define	c_namesize_size 8
-#define	c_checksum_offset 102
-#define	c_checksum_size 8
-#define	c_header_size 110
-
-/* Logic trick: difference between 'n' and next multiple of 4 */
-#define PAD4(n)	(3 & (1 + ~(n)))
-
-/*
- * Set output format to 'cpio' format.
- */
-int
-archive_write_set_format_cpio_newc(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct cpio *cpio;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_newc");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
-	if (cpio == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = cpio;
-	a->format_name = "cpio";
-	a->format_options = archive_write_newc_options;
-	a->format_write_header = archive_write_newc_header;
-	a->format_write_data = archive_write_newc_data;
-	a->format_finish_entry = archive_write_newc_finish_entry;
-	a->format_close = archive_write_newc_close;
-	a->format_free = archive_write_newc_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
-	a->archive.archive_format_name = "SVR4 cpio nocrc";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_newc_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct cpio *cpio = (struct cpio *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			cpio->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (cpio->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static struct archive_string_conv *
-get_sconv(struct archive_write *a)
-{
-	struct cpio *cpio;
-	struct archive_string_conv *sconv;
-
-	cpio = (struct cpio *)a->format_data;
-	sconv = cpio->opt_sconv;
-	if (sconv == NULL) {
-		if (!cpio->init_default_conversion) {
-			cpio->sconv_default =
-			    archive_string_default_conversion_for_write(
-			      &(a->archive));
-			cpio->init_default_conversion = 1;
-		}
-		sconv = cpio->sconv_default;
-	}
-	return (sconv);
-}
-
-static int
-archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
-{
-	const char *path;
-	size_t len;
-
-	if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
-		archive_set_error(&a->archive, -1, "Filetype required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
-	    && errno == ENOMEM) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for Pathname");
-		return (ARCHIVE_FATAL);
-	}
-	if (len == 0 || path == NULL || path[0] == '\0') {
-		archive_set_error(&a->archive, -1, "Pathname required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (archive_entry_hardlink(entry) == NULL
-	    && (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0)) {
-		archive_set_error(&a->archive, -1, "Size required");
-		return (ARCHIVE_FAILED);
-	}
-	return write_header(a, entry);
-}
-
-static int
-write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	int64_t ino;
-	struct cpio *cpio;
-	const char *p, *path;
-	int pathlength, ret, ret_final;
-	char h[c_header_size];
-	struct archive_string_conv *sconv;
-	struct archive_entry *entry_main;
-	size_t len;
-	int pad;
-
-	cpio = (struct cpio *)a->format_data;
-	ret_final = ARCHIVE_OK;
-	sconv = get_sconv(a);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-
-	ret = archive_entry_pathname_l(entry, &path, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    archive_entry_pathname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-	pathlength = (int)len + 1; /* Include trailing null. */
-
-	memset(h, 0, c_header_size);
-	format_hex(0x070701, h + c_magic_offset, c_magic_size);
-	format_hex(archive_entry_devmajor(entry), h + c_devmajor_offset,
-	    c_devmajor_size);
-	format_hex(archive_entry_devminor(entry), h + c_devminor_offset,
-	    c_devminor_size);
-
-	ino = archive_entry_ino64(entry);
-	if (ino > 0xffffffff) {
-		archive_set_error(&a->archive, ERANGE,
-		    "large inode number truncated");
-		ret_final = ARCHIVE_WARN;
-	}
-
-	/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
-	format_hex(ino & 0xffffffff, h + c_ino_offset, c_ino_size);
-	format_hex(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
-	format_hex(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
-	format_hex(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
-	format_hex(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
-	if (archive_entry_filetype(entry) == AE_IFBLK
-	    || archive_entry_filetype(entry) == AE_IFCHR) {
-	    format_hex(archive_entry_rdevmajor(entry), h + c_rdevmajor_offset, c_rdevmajor_size);
-	    format_hex(archive_entry_rdevminor(entry), h + c_rdevminor_offset, c_rdevminor_size);
-	} else {
-	    format_hex(0, h + c_rdevmajor_offset, c_rdevmajor_size);
-	    format_hex(0, h + c_rdevminor_offset, c_rdevminor_size);
-	}
-	format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
-	format_hex(pathlength, h + c_namesize_offset, c_namesize_size);
-	format_hex(0, h + c_checksum_offset, c_checksum_size);
-
-	/* Non-regular files don't store bodies. */
-	if (archive_entry_filetype(entry) != AE_IFREG)
-		archive_entry_set_size(entry, 0);
-
-	/* Symlinks get the link written as the body of the entry. */
-	ret = archive_entry_symlink_l(entry, &p, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Likname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    archive_entry_symlink(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-	if (len > 0 && p != NULL  &&  *p != '\0')
-		ret = format_hex(strlen(p), h + c_filesize_offset,
-		    c_filesize_size);
-	else
-		ret = format_hex(archive_entry_size(entry),
-		    h + c_filesize_offset, c_filesize_size);
-	if (ret) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File is too large for this format.");
-		ret_final = ARCHIVE_FAILED;
-		goto exit_write_header;
-	}
-
-	ret = __archive_write_output(a, h, c_header_size);
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-
-	/* Pad pathname to even length. */
-	ret = __archive_write_output(a, path, pathlength);
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-	pad = PAD4(pathlength + c_header_size);
-	if (pad) {
-		ret = __archive_write_output(a, "\0\0\0", pad);
-		if (ret != ARCHIVE_OK) {
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-	}
-
-	cpio->entry_bytes_remaining = archive_entry_size(entry);
-	cpio->padding = (int)PAD4(cpio->entry_bytes_remaining);
-
-	/* Write the symlink now. */
-	if (p != NULL  &&  *p != '\0') {
-		ret = __archive_write_output(a, p, strlen(p));
-		if (ret != ARCHIVE_OK) {
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		pad = PAD4(strlen(p));
-		ret = __archive_write_output(a, "\0\0\0", pad);
-		if (ret != ARCHIVE_OK) {
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-	}
-exit_write_header:
-	archive_entry_free(entry_main);
-	return (ret_final);
-}
-
-static ssize_t
-archive_write_newc_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct cpio *cpio;
-	int ret;
-
-	cpio = (struct cpio *)a->format_data;
-	if (s > cpio->entry_bytes_remaining)
-		s = (size_t)cpio->entry_bytes_remaining;
-
-	ret = __archive_write_output(a, buff, s);
-	cpio->entry_bytes_remaining -= s;
-	if (ret >= 0)
-		return (s);
-	else
-		return (ret);
-}
-
-/*
- * Format a number into the specified field.
- */
-static int
-format_hex(int64_t v, void *p, int digits)
-{
-	int64_t	max;
-	int	ret;
-
-	max = (((int64_t)1) << (digits * 4)) - 1;
-	if (v >= 0  &&  v <= max) {
-	    format_hex_recursive(v, (char *)p, digits);
-	    ret = 0;
-	} else {
-	    format_hex_recursive(max, (char *)p, digits);
-	    ret = -1;
-	}
-	return (ret);
-}
-
-static int64_t
-format_hex_recursive(int64_t v, char *p, int s)
-{
-	if (s == 0)
-		return (v);
-	v = format_hex_recursive(v, p+1, s-1);
-	*p = "0123456789abcdef"[v & 0xf];
-	return (v >> 4);
-}
-
-static int
-archive_write_newc_close(struct archive_write *a)
-{
-	int er;
-	struct archive_entry *trailer;
-
-	trailer = archive_entry_new();
-	archive_entry_set_nlink(trailer, 1);
-	archive_entry_set_size(trailer, 0);
-	archive_entry_set_pathname(trailer, "TRAILER!!!");
-	/* Bypass the required data checks. */
-	er = write_header(a, trailer);
-	archive_entry_free(trailer);
-	return (er);
-}
-
-static int
-archive_write_newc_free(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	free(cpio);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_newc_finish_entry(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	return (__archive_write_nulls(a,
-		(size_t)cpio->entry_bytes_remaining + cpio->padding));
-}
diff --git a/c/archive_write_set_format_cpio_odc.c b/c/archive_write_set_format_cpio_odc.c
deleted file mode 100644
--- a/c/archive_write_set_format_cpio_odc.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-static ssize_t	archive_write_odc_data(struct archive_write *,
-		    const void *buff, size_t s);
-static int	archive_write_odc_close(struct archive_write *);
-static int	archive_write_odc_free(struct archive_write *);
-static int	archive_write_odc_finish_entry(struct archive_write *);
-static int	archive_write_odc_header(struct archive_write *,
-		    struct archive_entry *);
-static int	archive_write_odc_options(struct archive_write *,
-		    const char *, const char *);
-static int	format_octal(int64_t, void *, int);
-static int64_t	format_octal_recursive(int64_t, char *, int);
-static int	write_header(struct archive_write *, struct archive_entry *);
-
-struct cpio {
-	uint64_t	  entry_bytes_remaining;
-
-	int64_t		  ino_next;
-
-	struct		 { int64_t old; int new;} *ino_list;
-	size_t		  ino_list_size;
-	size_t		  ino_list_next;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int		  init_default_conversion;
-};
-
-#define	c_magic_offset 0
-#define	c_magic_size 6
-#define	c_dev_offset 6
-#define	c_dev_size 6
-#define	c_ino_offset 12
-#define	c_ino_size 6
-#define	c_mode_offset 18
-#define	c_mode_size 6
-#define	c_uid_offset 24
-#define	c_uid_size 6
-#define	c_gid_offset 30
-#define	c_gid_size 6
-#define	c_nlink_offset 36
-#define	c_nlink_size 6
-#define	c_rdev_offset 42
-#define	c_rdev_size 6
-#define	c_mtime_offset 48
-#define	c_mtime_size 11
-#define	c_namesize_offset 59
-#define	c_namesize_size 6
-#define	c_filesize_offset 65
-#define	c_filesize_size 11
-
-/*
- * Set output format to 'cpio' format.
- */
-int
-archive_write_set_format_cpio_odc(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct cpio *cpio;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_odc");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
-	if (cpio == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = cpio;
-	a->format_name = "cpio";
-	a->format_options = archive_write_odc_options;
-	a->format_write_header = archive_write_odc_header;
-	a->format_write_data = archive_write_odc_data;
-	a->format_finish_entry = archive_write_odc_finish_entry;
-	a->format_close = archive_write_odc_close;
-	a->format_free = archive_write_odc_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
-	a->archive.archive_format_name = "POSIX cpio";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_odc_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct cpio *cpio = (struct cpio *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			cpio->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (cpio->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Ino values are as long as 64 bits on some systems; cpio format
- * only allows 18 bits and relies on the ino values to identify hardlinked
- * files.  So, we can't merely "hash" the ino numbers since collisions
- * would corrupt the archive.  Instead, we generate synthetic ino values
- * to store in the archive and maintain a map of original ino values to
- * synthetic ones so we can preserve hardlink information.
- *
- * TODO: Make this more efficient.  It's not as bad as it looks (most
- * files don't have any hardlinks and we don't do any work here for those),
- * but it wouldn't be hard to do better.
- *
- * TODO: Work with dev/ino pairs here instead of just ino values.
- */
-static int
-synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
-{
-	int64_t ino = archive_entry_ino64(entry);
-	int ino_new;
-	size_t i;
-
-	/*
-	 * If no index number was given, don't assign one.  In
-	 * particular, this handles the end-of-archive marker
-	 * correctly by giving it a zero index value.  (This is also
-	 * why we start our synthetic index numbers with one below.)
-	 */
-	if (ino == 0)
-		return (0);
-
-	/* Don't store a mapping if we don't need to. */
-	if (archive_entry_nlink(entry) < 2) {
-		return (int)(++cpio->ino_next);
-	}
-
-	/* Look up old ino; if we have it, this is a hardlink
-	 * and we reuse the same value. */
-	for (i = 0; i < cpio->ino_list_next; ++i) {
-		if (cpio->ino_list[i].old == ino)
-			return (cpio->ino_list[i].new);
-	}
-
-	/* Assign a new index number. */
-	ino_new = (int)(++cpio->ino_next);
-
-	/* Ensure space for the new mapping. */
-	if (cpio->ino_list_size <= cpio->ino_list_next) {
-		size_t newsize = cpio->ino_list_size < 512
-		    ? 512 : cpio->ino_list_size * 2;
-		void *newlist = realloc(cpio->ino_list,
-		    sizeof(cpio->ino_list[0]) * newsize);
-		if (newlist == NULL)
-			return (-1);
-
-		cpio->ino_list_size = newsize;
-		cpio->ino_list = newlist;
-	}
-
-	/* Record and return the new value. */
-	cpio->ino_list[cpio->ino_list_next].old = ino;
-	cpio->ino_list[cpio->ino_list_next].new = ino_new;
-	++cpio->ino_list_next;
-	return (ino_new);
-}
-
-
-static struct archive_string_conv *
-get_sconv(struct archive_write *a)
-{
-	struct cpio *cpio;
-	struct archive_string_conv *sconv;
-
-	cpio = (struct cpio *)a->format_data;
-	sconv = cpio->opt_sconv;
-	if (sconv == NULL) {
-		if (!cpio->init_default_conversion) {
-			cpio->sconv_default =
-			    archive_string_default_conversion_for_write(
-			      &(a->archive));
-			cpio->init_default_conversion = 1;
-		}
-		sconv = cpio->sconv_default;
-	}
-	return (sconv);
-}
-
-static int
-archive_write_odc_header(struct archive_write *a, struct archive_entry *entry)
-{
-	const char *path;
-	size_t len;
-
-	if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
-		archive_set_error(&a->archive, -1, "Filetype required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
-	    && errno == ENOMEM) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for Pathname");
-		return (ARCHIVE_FATAL);
-	}
-	if (len == 0 || path == NULL || path[0] == '\0') {
-		archive_set_error(&a->archive, -1, "Pathname required");
-		return (ARCHIVE_FAILED);
-	}
-
-	if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
-		archive_set_error(&a->archive, -1, "Size required");
-		return (ARCHIVE_FAILED);
-	}
-	return write_header(a, entry);
-}
-
-static int
-write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct cpio *cpio;
-	const char *p, *path;
-	int pathlength, ret, ret_final;
-	int64_t	ino;
-	char h[76];
-	struct archive_string_conv *sconv;
-	struct archive_entry *entry_main;
-	size_t len;
-
-	cpio = (struct cpio *)a->format_data;
-	ret_final = ARCHIVE_OK;
-	sconv = get_sconv(a);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-
-	ret = archive_entry_pathname_l(entry, &path, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    archive_entry_pathname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-	/* Include trailing null. */
-	pathlength = (int)len + 1;
-
-	memset(h, 0, sizeof(h));
-	format_octal(070707, h + c_magic_offset, c_magic_size);
-	format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
-
-	ino = synthesize_ino_value(cpio, entry);
-	if (ino < 0) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "No memory for ino translation table");
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	} else if (ino > 0777777) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Too many files for this cpio format");
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-	format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
-
-	/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
-	format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
-	format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
-	format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
-	format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
-	if (archive_entry_filetype(entry) == AE_IFBLK
-	    || archive_entry_filetype(entry) == AE_IFCHR)
-	    format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
-	else
-	    format_octal(0, h + c_rdev_offset, c_rdev_size);
-	format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
-	format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
-
-	/* Non-regular files don't store bodies. */
-	if (archive_entry_filetype(entry) != AE_IFREG)
-		archive_entry_set_size(entry, 0);
-
-	/* Symlinks get the link written as the body of the entry. */
-	ret = archive_entry_symlink_l(entry, &p, &len, sconv);
-	if (ret != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    archive_entry_symlink(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret_final = ARCHIVE_WARN;
-	}
-	if (len > 0 && p != NULL  &&  *p != '\0')
-		ret = format_octal(strlen(p), h + c_filesize_offset,
-		    c_filesize_size);
-	else
-		ret = format_octal(archive_entry_size(entry),
-		    h + c_filesize_offset, c_filesize_size);
-	if (ret) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File is too large for cpio format.");
-		ret_final = ARCHIVE_FAILED;
-		goto exit_write_header;
-	}
-
-	ret = __archive_write_output(a, h, sizeof(h));
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-
-	ret = __archive_write_output(a, path, pathlength);
-	if (ret != ARCHIVE_OK) {
-		ret_final = ARCHIVE_FATAL;
-		goto exit_write_header;
-	}
-
-	cpio->entry_bytes_remaining = archive_entry_size(entry);
-
-	/* Write the symlink now. */
-	if (p != NULL  &&  *p != '\0') {
-		ret = __archive_write_output(a, p, strlen(p));
-		if (ret != ARCHIVE_OK) {
-			ret_final = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-	}
-exit_write_header:
-	archive_entry_free(entry_main);
-	return (ret_final);
-}
-
-static ssize_t
-archive_write_odc_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct cpio *cpio;
-	int ret;
-
-	cpio = (struct cpio *)a->format_data;
-	if (s > cpio->entry_bytes_remaining)
-		s = (size_t)cpio->entry_bytes_remaining;
-
-	ret = __archive_write_output(a, buff, s);
-	cpio->entry_bytes_remaining -= s;
-	if (ret >= 0)
-		return (s);
-	else
-		return (ret);
-}
-
-/*
- * Format a number into the specified field.
- */
-static int
-format_octal(int64_t v, void *p, int digits)
-{
-	int64_t	max;
-	int	ret;
-
-	max = (((int64_t)1) << (digits * 3)) - 1;
-	if (v >= 0  &&  v <= max) {
-	    format_octal_recursive(v, (char *)p, digits);
-	    ret = 0;
-	} else {
-	    format_octal_recursive(max, (char *)p, digits);
-	    ret = -1;
-	}
-	return (ret);
-}
-
-static int64_t
-format_octal_recursive(int64_t v, char *p, int s)
-{
-	if (s == 0)
-		return (v);
-	v = format_octal_recursive(v, p+1, s-1);
-	*p = '0' + ((char)v & 7);
-	return (v >> 3);
-}
-
-static int
-archive_write_odc_close(struct archive_write *a)
-{
-	int er;
-	struct archive_entry *trailer;
-
-	trailer = archive_entry_new2(NULL);
-	/* nlink = 1 here for GNU cpio compat. */
-	archive_entry_set_nlink(trailer, 1);
-	archive_entry_set_size(trailer, 0);
-	archive_entry_set_pathname(trailer, "TRAILER!!!");
-	er = write_header(a, trailer);
-	archive_entry_free(trailer);
-	return (er);
-}
-
-static int
-archive_write_odc_free(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	free(cpio->ino_list);
-	free(cpio);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_odc_finish_entry(struct archive_write *a)
-{
-	struct cpio *cpio;
-
-	cpio = (struct cpio *)a->format_data;
-	return (__archive_write_nulls(a,
-		(size_t)cpio->entry_bytes_remaining));
-}
diff --git a/c/archive_write_set_format_filter_by_ext.c b/c/archive_write_set_format_filter_by_ext.c
deleted file mode 100644
--- a/c/archive_write_set_format_filter_by_ext.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2015 Okhotnikov Kirill
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_private.h"
-
-/* A table that maps names to functions. */
-static const
-struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *);  } names[] =
-{
-	{ ".7z",	archive_write_set_format_7zip,            archive_write_add_filter_none},
-	{ ".zip",	archive_write_set_format_zip,             archive_write_add_filter_none},
-	{ ".jar",	archive_write_set_format_zip,             archive_write_add_filter_none},
-	{ ".cpio",	archive_write_set_format_cpio,            archive_write_add_filter_none},
-	{ ".iso",	archive_write_set_format_iso9660,         archive_write_add_filter_none},
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
-	{ ".a",	        archive_write_set_format_ar_bsd,          archive_write_add_filter_none},
-	{ ".ar",	archive_write_set_format_ar_bsd,          archive_write_add_filter_none},
-#else         
-	{ ".a",	        archive_write_set_format_ar_svr4,         archive_write_add_filter_none},
-	{ ".ar",	archive_write_set_format_ar_svr4,         archive_write_add_filter_none},
-#endif        
-	{ ".tar",	archive_write_set_format_pax_restricted,  archive_write_add_filter_none},
-	{ ".tgz",	archive_write_set_format_pax_restricted,  archive_write_add_filter_gzip},
-	{ ".tar.gz",	archive_write_set_format_pax_restricted,  archive_write_add_filter_gzip},
-	{ ".tar.bz2",	archive_write_set_format_pax_restricted,  archive_write_add_filter_bzip2},
-	{ ".tar.xz",	archive_write_set_format_pax_restricted,  archive_write_add_filter_xz},
-	{ NULL,		NULL,                             NULL }
-};
-
-static 
-int cmpsuff(const char *str, const char *suffix)
-{
-  size_t length_str, length_suffix;
-
-  if ((str == NULL) || (suffix == NULL))
-    return -1;
-
-  length_str = strlen(str);
-  length_suffix = strlen(suffix);
-
-  if (length_str >= length_suffix) {
-    return strcmp(str + (length_str - length_suffix), suffix);
-  } else {
-    return -1;
-  }
-}
-
-static int get_array_index(const char *name)
-{
-  int i;
-
-  for (i = 0; names[i].name != NULL; i++) 
-  {
-    if (cmpsuff(name, names[i].name) == 0)
-      return i;
-  }    
-  return -1;
-  
-}
-
-int
-archive_write_set_format_filter_by_ext(struct archive *a, const char *filename)
-{
-  int names_index = get_array_index(filename);
-  
-  if (names_index >= 0)
-  {  
-    int format_state = (names[names_index].format)(a);
-    if (format_state == ARCHIVE_OK)
-      return ((names[names_index].filter)(a));
-    else
-      return format_state;
-  }    
-
-  archive_set_error(a, EINVAL, "No such format '%s'", filename);
-  a->state = ARCHIVE_STATE_FATAL;
-  return (ARCHIVE_FATAL);
-}
-
-int
-archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext)
-{
-  int names_index = get_array_index(filename);
-  
-  if (names_index < 0)
-    names_index = get_array_index(def_ext);
-  
-  if (names_index >= 0)
-  {  
-    int format_state = (names[names_index].format)(a);
-    if (format_state == ARCHIVE_OK)
-      return ((names[names_index].filter)(a));
-    else
-      return format_state;
-  }    
-
-  archive_set_error(a, EINVAL, "No such format '%s'", filename);
-  a->state = ARCHIVE_STATE_FATAL;
-  return (ARCHIVE_FATAL);
-}
-
-
-
-
diff --git a/c/archive_write_set_format_gnutar.c b/c/archive_write_set_format_gnutar.c
deleted file mode 100644
--- a/c/archive_write_set_format_gnutar.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/*-
- * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * Author: Jonas Gastal <jgastal@profusion.mobi>
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_gnu_tar.c 191579 2009-04-27 18:35:03Z gastal $");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct gnutar {
-	uint64_t	entry_bytes_remaining;
-	uint64_t	entry_padding;
-	const char *	linkname;
-	size_t		linkname_length;
-	const char *	pathname;
-	size_t		pathname_length;
-	const char *	uname;
-	size_t		uname_length;
-	const char *	gname;
-	size_t		gname_length;
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int init_default_conversion;
-};
-
-/*
- * Define structure of GNU tar header.
- */
-#define	GNUTAR_name_offset 0
-#define	GNUTAR_name_size 100
-#define	GNUTAR_mode_offset 100
-#define	GNUTAR_mode_size 7
-#define	GNUTAR_mode_max_size 8
-#define	GNUTAR_uid_offset 108
-#define	GNUTAR_uid_size 7
-#define	GNUTAR_uid_max_size 8
-#define	GNUTAR_gid_offset 116
-#define	GNUTAR_gid_size 7
-#define	GNUTAR_gid_max_size 8
-#define	GNUTAR_size_offset 124
-#define	GNUTAR_size_size 11
-#define	GNUTAR_size_max_size 12
-#define	GNUTAR_mtime_offset 136
-#define	GNUTAR_mtime_size 11
-#define	GNUTAR_mtime_max_size 11
-#define	GNUTAR_checksum_offset 148
-#define	GNUTAR_checksum_size 8
-#define	GNUTAR_typeflag_offset 156
-#define	GNUTAR_typeflag_size 1
-#define	GNUTAR_linkname_offset 157
-#define	GNUTAR_linkname_size 100
-#define	GNUTAR_magic_offset 257
-#define	GNUTAR_magic_size 6
-#define	GNUTAR_version_offset 263
-#define	GNUTAR_version_size 2
-#define	GNUTAR_uname_offset 265
-#define	GNUTAR_uname_size 32
-#define	GNUTAR_gname_offset 297
-#define	GNUTAR_gname_size 32
-#define	GNUTAR_rdevmajor_offset 329
-#define	GNUTAR_rdevmajor_size 6
-#define	GNUTAR_rdevmajor_max_size 8
-#define	GNUTAR_rdevminor_offset 337
-#define	GNUTAR_rdevminor_size 6
-#define	GNUTAR_rdevminor_max_size 8
-
-/*
- * A filled-in copy of the header for initialization.
- */
-static const char template_header[] = {
-	/* name: 100 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,
-	/* Mode, null termination: 8 bytes */
-	'0','0','0','0','0','0', '0','\0',
-	/* uid, null termination: 8 bytes */
-	'0','0','0','0','0','0', '0','\0',
-	/* gid, null termination: 8 bytes */
-	'0','0','0','0','0','0', '0','\0',
-	/* size, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', '\0',
-	/* mtime, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', '\0',
-	/* Initial checksum value: 8 spaces */
-	' ',' ',' ',' ',' ',' ',' ',' ',
-	/* Typeflag: 1 byte */
-	'0',			/* '0' = regular file */
-	/* Linkname: 100 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,
-	/* Magic: 8 bytes */
-	'u','s','t','a','r',' ', ' ','\0',
-	/* Uname: 32 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,
-	/* Gname: 32 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,
-	/* rdevmajor + null padding: 8 bytes */
-	'\0','\0','\0','\0','\0','\0', '\0','\0',
-	/* rdevminor + null padding: 8 bytes */
-	'\0','\0','\0','\0','\0','\0', '\0','\0',
-	/* Padding: 167 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
-};
-
-static int      archive_write_gnutar_options(struct archive_write *,
-		    const char *, const char *);
-static int	archive_format_gnutar_header(struct archive_write *, char h[512],
-		    struct archive_entry *, int tartype);
-static int      archive_write_gnutar_header(struct archive_write *,
-		    struct archive_entry *entry);
-static ssize_t	archive_write_gnutar_data(struct archive_write *a, const void *buff,
-		    size_t s);
-static int	archive_write_gnutar_free(struct archive_write *);
-static int	archive_write_gnutar_close(struct archive_write *);
-static int	archive_write_gnutar_finish_entry(struct archive_write *);
-static int	format_256(int64_t, char *, int);
-static int	format_number(int64_t, char *, int size, int maxsize);
-static int	format_octal(int64_t, char *, int);
-
-/*
- * Set output format to 'GNU tar' format.
- */
-int
-archive_write_set_format_gnutar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct gnutar *gnutar;
-
-	gnutar = (struct gnutar *)calloc(1, sizeof(*gnutar));
-	if (gnutar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate gnutar data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = gnutar;
-	a->format_name = "gnutar";
-	a->format_options = archive_write_gnutar_options;
-	a->format_write_header = archive_write_gnutar_header;
-	a->format_write_data = archive_write_gnutar_data;
-	a->format_close = archive_write_gnutar_close;
-	a->format_free = archive_write_gnutar_free;
-	a->format_finish_entry = archive_write_gnutar_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
-	a->archive.archive_format_name = "GNU tar";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_gnutar_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct gnutar *gnutar = (struct gnutar *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			gnutar->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (gnutar->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_gnutar_close(struct archive_write *a)
-{
-	return (__archive_write_nulls(a, 512*2));
-}
-
-static int
-archive_write_gnutar_free(struct archive_write *a)
-{
-	struct gnutar *gnutar;
-
-	gnutar = (struct gnutar *)a->format_data;
-	free(gnutar);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_gnutar_finish_entry(struct archive_write *a)
-{
-	struct gnutar *gnutar;
-	int ret;
-
-	gnutar = (struct gnutar *)a->format_data;
-	ret = __archive_write_nulls(a, (size_t)
-	    (gnutar->entry_bytes_remaining + gnutar->entry_padding));
-	gnutar->entry_bytes_remaining = gnutar->entry_padding = 0;
-	return (ret);
-}
-
-static ssize_t
-archive_write_gnutar_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct gnutar *gnutar;
-	int ret;
-
-	gnutar = (struct gnutar *)a->format_data;
-	if (s > gnutar->entry_bytes_remaining)
-		s = (size_t)gnutar->entry_bytes_remaining;
-	ret = __archive_write_output(a, buff, s);
-	gnutar->entry_bytes_remaining -= s;
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	return (s);
-}
-
-static int
-archive_write_gnutar_header(struct archive_write *a,
-     struct archive_entry *entry)
-{
-	char buff[512];
-	int r, ret, ret2 = ARCHIVE_OK;
-	int tartype;
-	struct gnutar *gnutar;
-	struct archive_string_conv *sconv;
-	struct archive_entry *entry_main;
-
-	gnutar = (struct gnutar *)a->format_data;
-
-	/* Setup default string conversion. */
-	if (gnutar->opt_sconv == NULL) {
-		if (!gnutar->init_default_conversion) {
-			gnutar->sconv_default =
-			    archive_string_default_conversion_for_write(
-				&(a->archive));
-			gnutar->init_default_conversion = 1;
-		}
-		sconv = gnutar->sconv_default;
-	} else
-		sconv = gnutar->opt_sconv;
-
-	/* Only regular files (not hardlinks) have data. */
-	if (archive_entry_hardlink(entry) != NULL ||
-	    archive_entry_symlink(entry) != NULL ||
-	    !(archive_entry_filetype(entry) == AE_IFREG))
-		archive_entry_set_size(entry, 0);
-
-	if (AE_IFDIR == archive_entry_filetype(entry)) {
-		const char *p;
-		size_t path_length;
-		/*
-		 * Ensure a trailing '/'.  Modify the entry so
-		 * the client sees the change.
-		 */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		const wchar_t *wp;
-
-		wp = archive_entry_pathname_w(entry);
-		if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
-			struct archive_wstring ws;
-
-			archive_string_init(&ws);
-			path_length = wcslen(wp);
-			if (archive_wstring_ensure(&ws,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate ustar data");
-				archive_wstring_free(&ws);
-				return(ARCHIVE_FATAL);
-			}
-			/* Should we keep '\' ? */
-			if (wp[path_length -1] == L'\\')
-				path_length--;
-			archive_wstrncpy(&ws, wp, path_length);
-			archive_wstrappend_wchar(&ws, L'/');
-			archive_entry_copy_pathname_w(entry, ws.s);
-			archive_wstring_free(&ws);
-			p = NULL;
-		} else
-#endif
-			p = archive_entry_pathname(entry);
-		/*
-		 * On Windows, this is a backup operation just in
-		 * case getting WCS failed. On POSIX, this is a
-		 * normal operation.
-		 */
-		if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
-			struct archive_string as;
-
-			archive_string_init(&as);
-			path_length = strlen(p);
-			if (archive_string_ensure(&as,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate ustar data");
-				archive_string_free(&as);
-				return(ARCHIVE_FATAL);
-			}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-			/* NOTE: This might break the pathname
-			 * if the current code page is CP932 and
-			 * the pathname includes a character '\'
-			 * as a part of its multibyte pathname. */
-			if (p[strlen(p) -1] == '\\')
-				path_length--;
-			else
-#endif
-			archive_strncpy(&as, p, path_length);
-			archive_strappend_char(&as, '/');
-			archive_entry_copy_pathname(entry, as.s);
-			archive_string_free(&as);
-		}
-	}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-	r = archive_entry_pathname_l(entry, &(gnutar->pathname),
-	    &(gnutar->pathname_length), sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathame");
-			ret = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    archive_entry_pathname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret2 = ARCHIVE_WARN;
-	}
-	r = archive_entry_uname_l(entry, &(gnutar->uname),
-	    &(gnutar->uname_length), sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Uname");
-			ret = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate uname '%s' to %s",
-		    archive_entry_uname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret2 = ARCHIVE_WARN;
-	}
-	r = archive_entry_gname_l(entry, &(gnutar->gname),
-	    &(gnutar->gname_length), sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Gname");
-			ret = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate gname '%s' to %s",
-		    archive_entry_gname(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret2 = ARCHIVE_WARN;
-	}
-
-	/* If linkname is longer than 100 chars we need to add a 'K' header. */
-	r = archive_entry_hardlink_l(entry, &(gnutar->linkname),
-	    &(gnutar->linkname_length), sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			ret = ARCHIVE_FATAL;
-			goto exit_write_header;
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    archive_entry_hardlink(entry),
-		    archive_string_conversion_charset_name(sconv));
-		ret2 = ARCHIVE_WARN;
-	}
-	if (gnutar->linkname_length == 0) {
-		r = archive_entry_symlink_l(entry, &(gnutar->linkname),
-		    &(gnutar->linkname_length), sconv);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				ret = ARCHIVE_FATAL;
-				goto exit_write_header;
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate linkname '%s' to %s",
-			    archive_entry_hardlink(entry),
-			    archive_string_conversion_charset_name(sconv));
-			ret2 = ARCHIVE_WARN;
-		}
-	}
-	if (gnutar->linkname_length > GNUTAR_linkname_size) {
-		size_t length = gnutar->linkname_length + 1;
-		struct archive_entry *temp = archive_entry_new2(&a->archive);
-
-		/* Uname/gname here don't really matter since no one reads them;
-		 * these are the values that GNU tar happens to use on FreeBSD. */
-		archive_entry_set_uname(temp, "root");
-		archive_entry_set_gname(temp, "wheel");
-
-		archive_entry_set_pathname(temp, "././@LongLink");
-		archive_entry_set_size(temp, length);
-		ret = archive_format_gnutar_header(a, buff, temp, 'K');
-		archive_entry_free(temp);
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		ret = __archive_write_output(a, buff, 512);
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		/* Write name and trailing null byte. */
-		ret = __archive_write_output(a, gnutar->linkname, length);
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		/* Pad to 512 bytes */
-		ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-	}
-
-	/* If pathname is longer than 100 chars we need to add an 'L' header. */
-	if (gnutar->pathname_length > GNUTAR_name_size) {
-		const char *pathname = gnutar->pathname;
-		size_t length = gnutar->pathname_length + 1;
-		struct archive_entry *temp = archive_entry_new2(&a->archive);
-
-		/* Uname/gname here don't really matter since no one reads them;
-		 * these are the values that GNU tar happens to use on FreeBSD. */
-		archive_entry_set_uname(temp, "root");
-		archive_entry_set_gname(temp, "wheel");
-
-		archive_entry_set_pathname(temp, "././@LongLink");
-		archive_entry_set_size(temp, length);
-		ret = archive_format_gnutar_header(a, buff, temp, 'L');
-		archive_entry_free(temp);
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		ret = __archive_write_output(a, buff, 512);
-		if(ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		/* Write pathname + trailing null byte. */
-		ret = __archive_write_output(a, pathname, length);
-		if(ret < ARCHIVE_WARN)
-			goto exit_write_header;
-		/* Pad to multiple of 512 bytes. */
-		ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
-		if (ret < ARCHIVE_WARN)
-			goto exit_write_header;
-	}
-
-	if (archive_entry_hardlink(entry) != NULL) {
-		tartype = '1';
-	} else
-		switch (archive_entry_filetype(entry)) {
-		case AE_IFREG: tartype = '0' ; break;
-		case AE_IFLNK: tartype = '2' ; break;
-		case AE_IFCHR: tartype = '3' ; break;
-		case AE_IFBLK: tartype = '4' ; break;
-		case AE_IFDIR: tartype = '5' ; break;
-		case AE_IFIFO: tartype = '6' ; break;
-		default: /* AE_IFSOCK and unknown */
-			__archive_write_entry_filetype_unsupported(
-                            &a->archive, entry, "gnutar");
-			ret = ARCHIVE_FAILED;
-			goto exit_write_header;
-		}
-
-	ret = archive_format_gnutar_header(a, buff, entry, tartype);
-	if (ret < ARCHIVE_WARN)
-		goto exit_write_header;
-	if (ret2 < ret)
-		ret = ret2;
-	ret2 = __archive_write_output(a, buff, 512);
-	if (ret2 < ARCHIVE_WARN) {
-		ret = ret2;
-		goto exit_write_header;
-	}
-	if (ret2 < ret)
-		ret = ret2;
-
-	gnutar->entry_bytes_remaining = archive_entry_size(entry);
-	gnutar->entry_padding = 0x1ff & (-(int64_t)gnutar->entry_bytes_remaining);
-exit_write_header:
-	archive_entry_free(entry_main);
-	return (ret);
-}
-
-static int
-archive_format_gnutar_header(struct archive_write *a, char h[512],
-    struct archive_entry *entry, int tartype)
-{
-	unsigned int checksum;
-	int i, ret;
-	size_t copy_length;
-	const char *p;
-	struct gnutar *gnutar;
-
-	gnutar = (struct gnutar *)a->format_data;
-
-	ret = 0;
-
-	/*
-	 * The "template header" already includes the signature,
-	 * various end-of-field markers, and other required elements.
-	 */
-	memcpy(h, &template_header, 512);
-
-	/*
-	 * Because the block is already null-filled, and strings
-	 * are allowed to exactly fill their destination (without null),
-	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
-	 */
-
-	if (tartype == 'K' || tartype == 'L') {
-		p = archive_entry_pathname(entry);
-		copy_length = strlen(p);
-	} else {
-		p = gnutar->pathname;
-		copy_length = gnutar->pathname_length;
-	}
-	if (copy_length > GNUTAR_name_size)
-		copy_length = GNUTAR_name_size;
-	memcpy(h + GNUTAR_name_offset, p, copy_length);
-
-	if ((copy_length = gnutar->linkname_length) > 0) {
-		if (copy_length > GNUTAR_linkname_size)
-			copy_length = GNUTAR_linkname_size;
-		memcpy(h + GNUTAR_linkname_offset, gnutar->linkname,
-		    copy_length);
-	}
-
-	/* TODO: How does GNU tar handle unames longer than GNUTAR_uname_size? */
-	if (tartype == 'K' || tartype == 'L') {
-		p = archive_entry_uname(entry);
-		copy_length = strlen(p);
-	} else {
-		p = gnutar->uname;
-		copy_length = gnutar->uname_length;
-	}
-	if (copy_length > 0) {
-		if (copy_length > GNUTAR_uname_size)
-			copy_length = GNUTAR_uname_size;
-		memcpy(h + GNUTAR_uname_offset, p, copy_length);
-	}
-
-	/* TODO: How does GNU tar handle gnames longer than GNUTAR_gname_size? */
-	if (tartype == 'K' || tartype == 'L') {
-		p = archive_entry_gname(entry);
-		copy_length = strlen(p);
-	} else {
-		p = gnutar->gname;
-		copy_length = gnutar->gname_length;
-	}
-	if (copy_length > 0) {
-		if (strlen(p) > GNUTAR_gname_size)
-			copy_length = GNUTAR_gname_size;
-		memcpy(h + GNUTAR_gname_offset, p, copy_length);
-	}
-
-	/* By truncating the mode here, we ensure it always fits. */
-	format_octal(archive_entry_mode(entry) & 07777,
-	    h + GNUTAR_mode_offset, GNUTAR_mode_size);
-
-	/* GNU tar supports base-256 here, so should never overflow. */
-	if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
-		GNUTAR_uid_size, GNUTAR_uid_max_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric user ID %jd too large",
-		    (intmax_t)archive_entry_uid(entry));
-		ret = ARCHIVE_FAILED;
-	}
-
-	/* GNU tar supports base-256 here, so should never overflow. */
-	if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
-		GNUTAR_gid_size, GNUTAR_gid_max_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric group ID %jd too large",
-		    (intmax_t)archive_entry_gid(entry));
-		ret = ARCHIVE_FAILED;
-	}
-
-	/* GNU tar supports base-256 here, so should never overflow. */
-	if (format_number(archive_entry_size(entry), h + GNUTAR_size_offset,
-		GNUTAR_size_size, GNUTAR_size_max_size)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File size out of range");
-		ret = ARCHIVE_FAILED;
-	}
-
-	/* Shouldn't overflow before 2106, since mtime field is 33 bits. */
-	format_octal(archive_entry_mtime(entry),
-	    h + GNUTAR_mtime_offset, GNUTAR_mtime_size);
-
-	if (archive_entry_filetype(entry) == AE_IFBLK
-	    || archive_entry_filetype(entry) == AE_IFCHR) {
-		if (format_octal(archive_entry_rdevmajor(entry),
-		    h + GNUTAR_rdevmajor_offset,
-			GNUTAR_rdevmajor_size)) {
-			archive_set_error(&a->archive, ERANGE,
-			    "Major device number too large");
-			ret = ARCHIVE_FAILED;
-		}
-
-		if (format_octal(archive_entry_rdevminor(entry),
-		    h + GNUTAR_rdevminor_offset,
-			GNUTAR_rdevminor_size)) {
-			archive_set_error(&a->archive, ERANGE,
-			    "Minor device number too large");
-			ret = ARCHIVE_FAILED;
-		}
-	}
-
-	h[GNUTAR_typeflag_offset] = tartype;
-
-	checksum = 0;
-	for (i = 0; i < 512; i++)
-		checksum += 255 & (unsigned int)h[i];
-	h[GNUTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
-	/* h[GNUTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
-	format_octal(checksum, h + GNUTAR_checksum_offset, 6);
-	return (ret);
-}
-
-/*
- * Format a number into a field, falling back to base-256 if necessary.
- */
-static int
-format_number(int64_t v, char *p, int s, int maxsize)
-{
-	int64_t limit = ((int64_t)1 << (s*3));
-
-	if (v < limit)
-		return (format_octal(v, p, s));
-	return (format_256(v, p, maxsize));
-}
-
-/*
- * Format a number into the specified field using base-256.
- */
-static int
-format_256(int64_t v, char *p, int s)
-{
-	p += s;
-	while (s-- > 0) {
-		*--p = (char)(v & 0xff);
-		v >>= 8;
-	}
-	*p |= 0x80; /* Set the base-256 marker bit. */
-	return (0);
-}
-
-/*
- * Format a number into the specified field using octal.
- */
-static int
-format_octal(int64_t v, char *p, int s)
-{
-	int len = s;
-
-	/* Octal values can't be negative, so use 0. */
-	if (v < 0)
-		v = 0;
-
-	p += s;		/* Start at the end and work backwards. */
-	while (s-- > 0) {
-		*--p = (char)('0' + (v & 7));
-		v >>= 3;
-	}
-
-	if (v == 0)
-		return (0);
-
-	/* If it overflowed, fill field with max value. */
-	while (len-- > 0)
-		*p++ = '7';
-
-	return (-1);
-}
diff --git a/c/archive_write_set_format_iso9660.c b/c/archive_write_set_format_iso9660.c
deleted file mode 100644
--- a/c/archive_write_set_format_iso9660.c
+++ /dev/null
@@ -1,8161 +0,0 @@
-/*-
- * Copyright (c) 2009-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#include <stdio.h>
-#include <stdarg.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_write_private.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define getuid()			0
-#define getgid()			0
-#endif
-
-/*#define DEBUG 1*/
-#ifdef DEBUG
-/* To compare to the ISO image file made by mkisofs. */
-#define COMPAT_MKISOFS		1
-#endif
-
-#define LOGICAL_BLOCK_BITS			11
-#define LOGICAL_BLOCK_SIZE			2048
-#define PATH_TABLE_BLOCK_SIZE			4096
-
-#define SYSTEM_AREA_BLOCK			16
-#define PRIMARY_VOLUME_DESCRIPTOR_BLOCK 	1
-#define SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK 	1
-#define BOOT_RECORD_DESCRIPTOR_BLOCK	 	1
-#define VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK	1
-#define NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK	1
-#define RRIP_ER_BLOCK				1
-#define PADDING_BLOCK				150
-
-#define FD_1_2M_SIZE		(1024 * 1200)
-#define FD_1_44M_SIZE		(1024 * 1440)
-#define FD_2_88M_SIZE		(1024 * 2880)
-#define MULTI_EXTENT_SIZE	(ARCHIVE_LITERAL_LL(1) << 32)	/* 4Gi bytes. */
-#define MAX_DEPTH		8
-#define RR_CE_SIZE		28		/* SUSP "CE" extension size */
-
-#define FILE_FLAG_EXISTENCE	0x01
-#define FILE_FLAG_DIRECTORY	0x02
-#define FILE_FLAG_ASSOCIATED	0x04
-#define FILE_FLAG_RECORD	0x08
-#define FILE_FLAG_PROTECTION	0x10
-#define FILE_FLAG_MULTI_EXTENT	0x80
-
-static const char rrip_identifier[] =
-	"RRIP_1991A";
-static const char rrip_descriptor[] =
-	"THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR "
-	"POSIX FILE SYSTEM SEMANTICS";
-static const char rrip_source[] =
-	"PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE.  "
-	"SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR "
-	"CONTACT INFORMATION.";
-#define RRIP_ER_ID_SIZE		(sizeof(rrip_identifier)-1)
-#define RRIP_ER_DSC_SIZE	(sizeof(rrip_descriptor)-1)
-#define RRIP_ER_SRC_SIZE	(sizeof(rrip_source)-1)
-#define RRIP_ER_SIZE		(8 + RRIP_ER_ID_SIZE + \
-				RRIP_ER_DSC_SIZE + RRIP_ER_SRC_SIZE)
-
-static const unsigned char zisofs_magic[8] = {
-	0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
-};
-
-#define ZF_HEADER_SIZE	16	/* zisofs header size. */
-#define ZF_LOG2_BS	15	/* log2 block size; 32K bytes. */
-#define ZF_BLOCK_SIZE	(1UL << ZF_LOG2_BS)
-
-/*
- * Manage extra records.
- */
-struct extr_rec {
-	int		 location;
-	int		 offset;
-	unsigned char	 buf[LOGICAL_BLOCK_SIZE];
-	struct extr_rec	*next;
-};
-
-struct ctl_extr_rec {
-	int		 use_extr;
-	unsigned char	*bp;
-	struct isoent	*isoent;
-	unsigned char	*ce_ptr;
-	int		 cur_len;
-	int		 dr_len;
-	int		 limit;
-	int		 extr_off;
-	int		 extr_loc;
-};
-#define DR_SAFETY	RR_CE_SIZE
-#define DR_LIMIT	(254 - DR_SAFETY)
-
-/*
- * The relation of struct isofile and isoent and archive_entry.
- *
- * Primary volume tree  --> struct isoent
- *                                |
- *                                v
- *                          struct isofile --> archive_entry
- *                                ^
- *                                |
- * Joliet volume tree   --> struct isoent
- *
- * struct isoent has specific information for volume.
- */
-
-struct isofile {
-	/* Used for managing struct isofile list. */
-	struct isofile		*allnext;
-	struct isofile		*datanext;
-	/* Used for managing a hardlinked struct isofile list. */
-	struct isofile		*hlnext;
-	struct isofile		*hardlink_target;
-
-	struct archive_entry	*entry;
-
-	/*
-	 * Used for making a directory tree.
-	 */
-	struct archive_string	 parentdir;
-	struct archive_string	 basename;
-	struct archive_string	 basename_utf16;
-	struct archive_string	 symlink;
-	int			 dircnt;	/* The number of elements of
-						 * its parent directory */
-
-	/*
-	 * Used for a Directory Record.
-	 */
-	struct content {
-		int64_t		 offset_of_temp;
-		int64_t		 size;
-		int		 blocks;
-		uint32_t 	 location;
-		/*
-		 * One extent equals one content.
-		 * If this entry has multi extent, `next' variable points
-		 * next content data.
-		 */
-		struct content	*next;		/* next content	*/
-	} content, *cur_content;
-	int			 write_content;
-
-	enum {
-		NO = 0,
-		BOOT_CATALOG,
-		BOOT_IMAGE
-	} boot;
-
-	/*
-	 * Used for a zisofs.
-	 */
-	struct {
-		unsigned char	 header_size;
-		unsigned char	 log2_bs;
-		uint32_t	 uncompressed_size;
-	} zisofs;
-};
-
-struct isoent {
-	/* Keep `rbnode' at the first member of struct isoent. */
-	struct archive_rb_node	 rbnode;
-
-	struct isofile		*file;
-
-	struct isoent		*parent;
-	/* A list of children.(use chnext) */
-	struct {
-		struct isoent	*first;
-		struct isoent	**last;
-		int		 cnt;
-	}			 children;
-	struct archive_rb_tree	 rbtree;
-
-	/* A list of sub directories.(use drnext) */
-	struct {
-		struct isoent	*first;
-		struct isoent	**last;
-		int		 cnt;
-	}			 subdirs;
-	/* A sorted list of sub directories. */
-	struct isoent		**children_sorted;
-	/* Used for managing struct isoent list. */
-	struct isoent		*chnext;
-	struct isoent		*drnext;
-	struct isoent		*ptnext;
-
-	/*
-	 * Used for making a Directory Record.
-	 */
-	int			 dir_number;
-	struct {
-		int		 vd;
-		int		 self;
-		int		 parent;
-		int		 normal;
-	}			 dr_len;
-	uint32_t 		 dir_location;
-	int			 dir_block;
-
-	/*
-	 * Identifier:
-	 *   on primary, ISO9660 file/directory name.
-	 *   on joliet, UCS2 file/directory name.
-	 * ext_off   : offset of identifier extension.
-	 * ext_len   : length of identifier extension.
-	 * id_len    : byte size of identifier.
-	 *   on primary, this is ext_off + ext_len + version length.
-	 *   on joliet, this is ext_off + ext_len.
-	 * mb_len    : length of multibyte-character of identifier.
-	 *   on primary, mb_len and id_len are always the same.
-	 *   on joliet, mb_len and id_len are different.
-	 */
-	char			*identifier;
-	int			 ext_off;
-	int			 ext_len;
-	int			 id_len;
-	int			 mb_len;
-
-	/*
-	 * Used for making a Rockridge extension.
-	 * This is a part of Directory Records.
-	 */
-	struct isoent		*rr_parent;
-	struct isoent		*rr_child;
-
-	/* Extra Record.(which we call in this source file)
-	 * A maximum size of the Directory Record is 254.
-	 * so, if generated RRIP data of a file cannot into a Directory
-	 * Record because of its size, that surplus data relocate this
-	 * Extra Record.
-	 */
-	struct {
-		struct extr_rec	*first;
-		struct extr_rec	**last;
-		struct extr_rec	*current;
-	}			 extr_rec_list;
-
-	unsigned int		 virtual:1;
-	/* If set to one, this file type is a directory.
-	 * A convenience flag to be used as
-	 * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
-	 */
-	unsigned int		 dir:1;
-};
-
-struct hardlink {
-	struct archive_rb_node	 rbnode;
-	int			 nlink;
-	struct {
-		struct isofile	*first;
-		struct isofile	**last;
-	}			 file_list;
-};
-
-/*
- * ISO writer options
- */
-struct iso_option {
-	/*
-	 * Usage  : abstract-file=<value>
-	 * Type   : string, max 37 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -abstract <value>
-	 *
-	 * Specifies Abstract Filename.
-	 * This file shall be described in the Root Directory
-	 * and containing a abstract statement.
-	 */
-	unsigned int	 abstract_file:1;
-#define OPT_ABSTRACT_FILE_DEFAULT	0	/* Not specified */
-#define ABSTRACT_FILE_SIZE		37
-
-	/*
-	 * Usage  : application-id=<value>
-	 * Type   : string, max 128 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -A/-appid <value>.
-	 *
-	 * Specifies Application Identifier.
-	 * If the first byte is set to '_'(5F), the remaining
-	 * bytes of this option shall specify an identifier
-	 * for a file containing the identification of the
-	 * application.
-	 * This file shall be described in the Root Directory.
-	 */
-	unsigned int	 application_id:1;
-#define OPT_APPLICATION_ID_DEFAULT	0	/* Use default identifier */
-#define APPLICATION_IDENTIFIER_SIZE	128
-
-	/*
-	 * Usage : !allow-vernum
-	 * Type  : boolean
-	 * Default: Enabled
-	 *	  : Violates the ISO9660 standard if disable.
-	 * COMPAT: mkisofs -N
-	 *
-	 * Allow filenames to use version numbers.
-	 */
-	unsigned int	 allow_vernum:1;
-#define OPT_ALLOW_VERNUM_DEFAULT	1	/* Enabled */
-
-	/*
-	 * Usage  : biblio-file=<value>
-	 * Type   : string, max 37 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -biblio <value>
-	 *
-	 * Specifies Bibliographic Filename.
-	 * This file shall be described in the Root Directory
-	 * and containing bibliographic records.
-	 */
-	unsigned int	 biblio_file:1;
-#define OPT_BIBLIO_FILE_DEFAULT		0	/* Not specified */
-#define BIBLIO_FILE_SIZE		37
-
-	/*
-	 * Usage  : boot=<value>
-	 * Type   : string
-	 * Default: Not specified
-	 * COMPAT : mkisofs -b/-eltorito-boot <value>
-	 *
-	 * Specifies "El Torito" boot image file to make
-	 * a bootable CD.
-	 */
-	unsigned int	 boot:1;
-#define OPT_BOOT_DEFAULT		0	/* Not specified */
-
-	/*
-	 * Usage  : boot-catalog=<value>
-	 * Type   : string
-	 * Default: "boot.catalog"
-	 * COMPAT : mkisofs -c/-eltorito-catalog <value>
-	 *
-	 * Specifies a fullpath of El Torito boot catalog.
-	 */
-	unsigned int	 boot_catalog:1;
-#define OPT_BOOT_CATALOG_DEFAULT	0	/* Not specified */
-
-	/*
-	 * Usage  : boot-info-table
-	 * Type   : boolean
-	 * Default: Disabled
-	 * COMPAT : mkisofs -boot-info-table
-	 *
-	 * Modify the boot image file specified by `boot'
-	 * option; ISO writer stores boot file information
-	 * into the boot file in ISO image at offset 8
-	 * through offset 64.
-	 */
-	unsigned int	 boot_info_table:1;
-#define OPT_BOOT_INFO_TABLE_DEFAULT	0	/* Disabled */
-
-	/*
-	 * Usage  : boot-load-seg=<value>
-	 * Type   : hexadecimal
-	 * Default: Not specified
-	 * COMPAT : mkisofs -boot-load-seg <value>
-	 *
-	 * Specifies a load segment for boot image.
-	 * This is used with no-emulation mode.
-	 */
-	unsigned int	 boot_load_seg:1;
-#define OPT_BOOT_LOAD_SEG_DEFAULT	0	/* Not specified */
-
-	/*
-	 * Usage  : boot-load-size=<value>
-	 * Type   : decimal
-	 * Default: Not specified
-	 * COMPAT : mkisofs -boot-load-size <value>
-	 *
-	 * Specifies a sector count for boot image.
-	 * This is used with no-emulation mode.
-	 */
-	unsigned int	 boot_load_size:1;
-#define OPT_BOOT_LOAD_SIZE_DEFAULT	0	/* Not specified */
-
-	/*
-	 * Usage  : boot-type=<boot-media-type>
-	 *        : 'no-emulation' : 'no emulation' image
-	 *        :           'fd' : floppy disk image
-	 *        :    'hard-disk' : hard disk image
-	 * Type   : string
-	 * Default: Auto detect
-	 *        : We check a size of boot image;
-	 *        : If the size is just 1.22M/1.44M/2.88M,
-	 *        : we assume boot_type is 'fd';
-	 *        : otherwise boot_type is 'no-emulation'.
-	 * COMPAT :
-	 *    boot=no-emulation
-	 *	mkisofs -no-emul-boot
-	 *    boot=fd
-	 *	This is a default on the mkisofs.
-	 *    boot=hard-disk
-	 *	mkisofs -hard-disk-boot
-	 *
-	 * Specifies a type of "El Torito" boot image.
-	 */
-	unsigned int	 boot_type:2;
-#define OPT_BOOT_TYPE_AUTO		0	/* auto detect		  */
-#define OPT_BOOT_TYPE_NO_EMU		1	/* ``no emulation'' image */
-#define OPT_BOOT_TYPE_FD		2	/* floppy disk image	  */
-#define OPT_BOOT_TYPE_HARD_DISK		3	/* hard disk image	  */
-#define OPT_BOOT_TYPE_DEFAULT		OPT_BOOT_TYPE_AUTO
-
-	/*
-	 * Usage  : compression-level=<value>
-	 * Type   : decimal
-	 * Default: Not specified
-	 * COMPAT : NONE
-	 *
-	 * Specifies compression level for option zisofs=direct.
-	 */
-	unsigned int	 compression_level:1;
-#define OPT_COMPRESSION_LEVEL_DEFAULT	0	/* Not specified */
-
-	/*
-	 * Usage  : copyright-file=<value>
-	 * Type   : string, max 37 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -copyright <value>
-	 *
-	 * Specifies Copyright Filename.
-	 * This file shall be described in the Root Directory
-	 * and containing a copyright statement.
-	 */
-	unsigned int	 copyright_file:1;
-#define OPT_COPYRIGHT_FILE_DEFAULT	0	/* Not specified */
-#define COPYRIGHT_FILE_SIZE		37
-
-	/*
-	 * Usage  : gid=<value>
-	 * Type   : decimal
-	 * Default: Not specified
-	 * COMPAT : mkisofs -gid <value>
-	 *
-	 * Specifies a group id to rewrite the group id of all files.
-	 */
-	unsigned int	 gid:1;
-#define OPT_GID_DEFAULT			0	/* Not specified */
-
-	/*
-	 * Usage  : iso-level=[1234]
-	 * Type   : decimal
-	 * Default: 1
-	 * COMPAT : mkisofs -iso-level <value>
-	 *
-	 * Specifies ISO9600 Level.
-	 * Level 1: [DEFAULT]
-	 *   - limits each file size less than 4Gi bytes;
-	 *   - a File Name shall not contain more than eight
-	 *     d-characters or eight d1-characters;
-	 *   - a File Name Extension shall not contain more than
-	 *     three d-characters or three d1-characters;
-	 *   - a Directory Identifier shall not contain more
-	 *     than eight d-characters or eight d1-characters.
-	 * Level 2:
-	 *   - limits each file size less than 4Giga bytes;
-	 *   - a File Name shall not contain more than thirty
-	 *     d-characters or thirty d1-characters;
-	 *   - a File Name Extension shall not contain more than
-	 *     thirty d-characters or thirty d1-characters;
-	 *   - a Directory Identifier shall not contain more
-	 *     than thirty-one d-characters or thirty-one
-	 *     d1-characters.
-	 * Level 3:
-	 *   - no limit of file size; use multi extent.
-	 * Level 4:
-	 *   - this level 4 simulates mkisofs option
-	 *     '-iso-level 4';
-	 *   - crate a enhanced volume as mkisofs doing;
-	 *   - allow a File Name to have leading dot;
-	 *   - allow a File Name to have all ASCII letters;
-	 *   - allow a File Name to have multiple dots;
-	 *   - allow more then 8 depths of directory trees;
-	 *   - disable a version number to a File Name;
-	 *   - disable a forced period to the tail of a File Name;
-	 *   - the maximum length of files and directories is raised to 193.
-	 *     if rockridge option is disabled, raised to 207.
-	 */
-	unsigned int	 iso_level:3;
-#define OPT_ISO_LEVEL_DEFAULT		1	/* ISO Level 1 */
-
-	/*
-	 * Usage  : joliet[=long]
-	 *        : !joliet
-	 *        :   Do not generate Joliet Volume and Records.
-	 *        : joliet [DEFAULT]
-	 *        :   Generates Joliet Volume and Directory Records.
-	 *        :   [COMPAT: mkisofs -J/-joliet]
-	 *        : joliet=long
-	 *        :   The joliet filenames are up to 103 Unicode
-	 *        :   characters.
-	 *        :   This option breaks the Joliet specification.
-	 *        :   [COMPAT: mkisofs -J -joliet-long]
-	 * Type   : boolean/string
-	 * Default: Enabled
-	 * COMPAT : mkisofs -J / -joliet-long
-	 *
-	 * Generates Joliet Volume and Directory Records.
-	 */
-	unsigned int	 joliet:2;
-#define OPT_JOLIET_DISABLE		0	/* Not generate Joliet Records. */
-#define OPT_JOLIET_ENABLE		1	/* Generate Joliet Records.  */
-#define OPT_JOLIET_LONGNAME		2	/* Use long joliet filenames.*/
-#define OPT_JOLIET_DEFAULT		OPT_JOLIET_ENABLE
-
-	/*
-	 * Usage  : !limit-depth
-	 * Type   : boolean
-	 * Default: Enabled
-	 *	  : Violates the ISO9660 standard if disable.
-	 * COMPAT : mkisofs -D/-disable-deep-relocation
-	 *
-	 * The number of levels in hierarchy cannot exceed eight.
-	 */
-	unsigned int	 limit_depth:1;
-#define OPT_LIMIT_DEPTH_DEFAULT		1	/* Enabled */
-
-	/*
-	 * Usage  : !limit-dirs
-	 * Type   : boolean
-	 * Default: Enabled
-	 *	  : Violates the ISO9660 standard if disable.
-	 * COMPAT : mkisofs -no-limit-pathtables
-	 *
-	 * Limits the number of directories less than 65536 due
-	 * to the size of the Parent Directory Number of Path
-	 * Table.
-	 */
-	unsigned int	 limit_dirs:1;
-#define OPT_LIMIT_DIRS_DEFAULT		1	/* Enabled */
-
-	/*
-	 * Usage  : !pad
-	 * Type   : boolean
-	 * Default: Enabled
-	 * COMPAT : -pad/-no-pad
-	 *
-	 * Pads the end of the ISO image by null of 300Ki bytes.
-	 */
-	unsigned int	 pad:1;
-#define OPT_PAD_DEFAULT			1	/* Enabled */
-
-	/*
-	 * Usage  : publisher=<value>
-	 * Type   : string, max 128 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -publisher <value>
-	 *
-	 * Specifies Publisher Identifier.
-	 * If the first byte is set to '_'(5F), the remaining
-	 * bytes of this option shall specify an identifier
-	 * for a file containing the identification of the user.
-	 * This file shall be described in the Root Directory.
-	 */
-	unsigned int	 publisher:1;
-#define OPT_PUBLISHER_DEFAULT		0	/* Not specified */
-#define PUBLISHER_IDENTIFIER_SIZE	128
-
-	/*
-	 * Usage  : rockridge
-	 *        : !rockridge
-	 *        :    disable to generate SUSP and RR records.
-	 *        : rockridge
-	 *        :    the same as 'rockridge=useful'.
-	 *        : rockridge=strict
-	 *        :    generate SUSP and RR records.
-	 *        :    [COMPAT: mkisofs -R]
-	 *        : rockridge=useful [DEFAULT]
-	 *        :    generate SUSP and RR records.
-	 *        :    [COMPAT: mkisofs -r]
-	 *        :    NOTE  Our rockridge=useful option does not set a zero
-	 *        :          to uid and gid, you should use application
-	 *        :          option such as --gid,--gname,--uid and --uname
-	 *        :          bsdtar options instead.
-	 * Type   : boolean/string
-	 * Default: Enabled as rockridge=useful
-	 * COMPAT : mkisofs -r / -R
-	 *
-	 * Generates SUSP and RR records.
-	 */
-	unsigned int	 rr:2;
-#define OPT_RR_DISABLED			0
-#define OPT_RR_STRICT			1
-#define OPT_RR_USEFUL			2
-#define OPT_RR_DEFAULT			OPT_RR_USEFUL
-
-	/*
-	 * Usage  : volume-id=<value>
-	 * Type   : string, max 32 bytes
-	 * Default: Not specified
-	 * COMPAT : mkisofs -V <value>
-	 *
-	 * Specifies Volume Identifier.
-	 */
-	unsigned int	 volume_id:1;
-#define OPT_VOLUME_ID_DEFAULT		0	/* Use default identifier */
-#define VOLUME_IDENTIFIER_SIZE		32
-
-	/*
-	 * Usage  : !zisofs [DEFAULT]
-	 *        :    Disable to generate RRIP 'ZF' extension.
-	 *        : zisofs
-	 *        :    Make files zisofs file and generate RRIP 'ZF'
- 	 *        :    extension. So you do not need mkzftree utility
-	 *        :    for making zisofs.
-	 *        :    When the file size is less than one Logical Block
-	 *        :    size, that file will not zisofs'ed since it does
-	 *        :    reduce an ISO-image size.
-	 *        :
-	 *        :    When you specify option 'boot=<boot-image>', that
-	 *        :    'boot-image' file won't be converted to zisofs file.
-	 * Type   : boolean
-	 * Default: Disabled
-	 *
-	 * Generates RRIP 'ZF' System Use Entry.
-	 */
-	unsigned int	 zisofs:1;
-#define OPT_ZISOFS_DISABLED		0
-#define OPT_ZISOFS_DIRECT		1
-#define OPT_ZISOFS_DEFAULT		OPT_ZISOFS_DISABLED
-
-};
-
-struct iso9660 {
-	/* The creation time of ISO image. */
-	time_t			 birth_time;
-	/* A file stream of a temporary file, which file contents
-	 * save to until ISO image can be created. */
-	int			 temp_fd;
-
-	struct isofile		*cur_file;
-	struct isoent		*cur_dirent;
-	struct archive_string	 cur_dirstr;
-	uint64_t		 bytes_remaining;
-	int			 need_multi_extent;
-
-	/* Temporary string buffer for Joliet extension. */
-	struct archive_string	 utf16be;
-	struct archive_string	 mbs;
-
-	struct archive_string_conv *sconv_to_utf16be;
-	struct archive_string_conv *sconv_from_utf16be;
-
-	/* A list of all of struct isofile entries. */
-	struct {
-		struct isofile	*first;
-		struct isofile	**last;
-	}			 all_file_list;
-
-	/* A list of struct isofile entries which have its
-	 * contents and are not a directory, a hardlinked file
-	 * and a symlink file. */
-	struct {
-		struct isofile	*first;
-		struct isofile	**last;
-	}			 data_file_list;
-
-	/* Used for managing to find hardlinking files. */
-	struct archive_rb_tree	 hardlink_rbtree;
-
-	/* Used for making the Path Table Record. */
-	struct vdd {
-		/* the root of entry tree. */
-		struct isoent	*rootent;
-		enum vdd_type {
-			VDD_PRIMARY,
-			VDD_JOLIET,
-			VDD_ENHANCED
-		} vdd_type;
-
-		struct path_table {
-			struct isoent		*first;
-			struct isoent		**last;
-			struct isoent		**sorted;
-			int			 cnt;
-		} *pathtbl;
-		int				 max_depth;
-
-		int		 path_table_block;
-		int		 path_table_size;
-		int		 location_type_L_path_table;
-		int		 location_type_M_path_table;
-		int		 total_dir_block;
-	} primary, joliet;
-
-	/* Used for making a Volume Descriptor. */
-	int			 volume_space_size;
-	int			 volume_sequence_number;
-	int			 total_file_block;
-	struct archive_string	 volume_identifier;
-	struct archive_string	 publisher_identifier;
-	struct archive_string	 data_preparer_identifier;
-	struct archive_string	 application_identifier;
-	struct archive_string	 copyright_file_identifier;
-	struct archive_string	 abstract_file_identifier;
-	struct archive_string	 bibliographic_file_identifier;
-
-	/* Used for making rockridge extensions. */
-	int			 location_rrip_er;
-
-	/* Used for making zisofs. */
-	struct {
-		unsigned int	 detect_magic:1;
-		unsigned int	 making:1;
-		unsigned int	 allzero:1;
-		unsigned char	 magic_buffer[64];
-		int		 magic_cnt;
-
-#ifdef HAVE_ZLIB_H
-		/*
-		 * Copy a compressed file to iso9660.zisofs.temp_fd
-		 * and also copy a uncompressed file(original file) to
-		 * iso9660.temp_fd . If the number of logical block
-		 * of the compressed file is less than the number of
-		 * logical block of the uncompressed file, use it and
-		 * remove the copy of the uncompressed file.
-		 * but if not, we use uncompressed file and remove
-		 * the copy of the compressed file.
-		 */
-		uint32_t	*block_pointers;
-		size_t		 block_pointers_allocated;
-		int		 block_pointers_cnt;
-		int		 block_pointers_idx;
-		int64_t		 total_size;
-		int64_t		 block_offset;
-
-		z_stream	 stream;
-		int		 stream_valid;
-		int64_t		 remaining;
-		int		 compression_level;
-#endif
-	} zisofs;
-
-	struct isoent		*directories_too_deep;
-	int			 dircnt_max;
-
-	/* Write buffer. */
-#define wb_buffmax()	(LOGICAL_BLOCK_SIZE * 32)
-#define wb_remaining(a)	(((struct iso9660 *)(a)->format_data)->wbuff_remaining)
-#define wb_offset(a)	(((struct iso9660 *)(a)->format_data)->wbuff_offset \
-		+ wb_buffmax() - wb_remaining(a))
-	unsigned char		 wbuff[LOGICAL_BLOCK_SIZE * 32];
-	size_t			 wbuff_remaining;
-	enum {
-		WB_TO_STREAM,
-		WB_TO_TEMP
-	} 			 wbuff_type;
-	int64_t			 wbuff_offset;
-	int64_t			 wbuff_written;
-	int64_t			 wbuff_tail;
-
-	/* 'El Torito' boot data. */
-	struct {
-		/* boot catalog file */
-		struct archive_string	 catalog_filename;
-		struct isoent		*catalog;
-		/* boot image file */
-		struct archive_string	 boot_filename;
-		struct isoent		*boot;
-
-		unsigned char		 platform_id;
-#define BOOT_PLATFORM_X86	0
-#define BOOT_PLATFORM_PPC	1
-#define BOOT_PLATFORM_MAC	2
-		struct archive_string	 id;
-		unsigned char		 media_type;
-#define BOOT_MEDIA_NO_EMULATION		0
-#define BOOT_MEDIA_1_2M_DISKETTE	1
-#define BOOT_MEDIA_1_44M_DISKETTE	2
-#define BOOT_MEDIA_2_88M_DISKETTE	3
-#define BOOT_MEDIA_HARD_DISK		4
-		unsigned char		 system_type;
-		uint16_t		 boot_load_seg;
-		uint16_t		 boot_load_size;
-#define BOOT_LOAD_SIZE		4
-	} el_torito;
-
-	struct iso_option	 opt;
-};
-
-/*
- * Types of Volume Descriptor
- */
-enum VD_type {
-	VDT_BOOT_RECORD=0,	/* Boot Record Volume Descriptor 	*/
-	VDT_PRIMARY=1,		/* Primary Volume Descriptor		*/
-	VDT_SUPPLEMENTARY=2,	/* Supplementary Volume Descriptor	*/
-	VDT_TERMINATOR=255	/* Volume Descriptor Set Terminator	*/
-};
-
-/*
- * Types of Directory Record
- */
-enum dir_rec_type {
-	DIR_REC_VD,		/* Stored in Volume Descriptor.	*/
-	DIR_REC_SELF,		/* Stored as Current Directory.	*/
-	DIR_REC_PARENT,		/* Stored as Parent Directory.	*/
-	DIR_REC_NORMAL 		/* Stored as Child.		*/
-};
-
-/*
- * Kinds of Volume Descriptor Character
- */
-enum vdc {
-	VDC_STD,
-	VDC_LOWERCASE,
-	VDC_UCS2,
-	VDC_UCS2_DIRECT
-};
-
-/*
- * IDentifier Resolver.
- * Used for resolving duplicated filenames.
- */
-struct idr {
-	struct idrent {
-		struct archive_rb_node	rbnode;
-		/* Used in wait_list. */
-		struct idrent		*wnext;
-		struct idrent		*avail;
-
-		struct isoent		*isoent;
-		int			 weight;
-		int			 noff;
-		int			 rename_num;
-	} *idrent_pool;
-
-	struct archive_rb_tree		 rbtree;
-
-	struct {
-		struct idrent		*first;
-		struct idrent		**last;
-	} wait_list;
-
-	int				 pool_size;
-	int				 pool_idx;
-	int				 num_size;
-	int				 null_size;
-
-	char				 char_map[0x80];
-};
-
-enum char_type {
-	A_CHAR,
-	D_CHAR
-};
-
-
-static int	iso9660_options(struct archive_write *,
-		    const char *, const char *);
-static int	iso9660_write_header(struct archive_write *,
-		    struct archive_entry *);
-static ssize_t	iso9660_write_data(struct archive_write *,
-		    const void *, size_t);
-static int	iso9660_finish_entry(struct archive_write *);
-static int	iso9660_close(struct archive_write *);
-static int	iso9660_free(struct archive_write *);
-
-static void	get_system_identitier(char *, size_t);
-static void	set_str(unsigned char *, const char *, size_t, char,
-		    const char *);
-static inline int joliet_allowed_char(unsigned char, unsigned char);
-static int	set_str_utf16be(struct archive_write *, unsigned char *,
-			const char *, size_t, uint16_t, enum vdc);
-static int	set_str_a_characters_bp(struct archive_write *,
-			unsigned char *, int, int, const char *, enum vdc);
-static int	set_str_d_characters_bp(struct archive_write *,
-			unsigned char *, int, int, const char *, enum  vdc);
-static void	set_VD_bp(unsigned char *, enum VD_type, unsigned char);
-static inline void set_unused_field_bp(unsigned char *, int, int);
-
-static unsigned char *extra_open_record(unsigned char *, int,
-		    struct isoent *, struct ctl_extr_rec *);
-static void	extra_close_record(struct ctl_extr_rec *, int);
-static unsigned char * extra_next_record(struct ctl_extr_rec *, int);
-static unsigned char *extra_get_record(struct isoent *, int *, int *, int *);
-static void	extra_tell_used_size(struct ctl_extr_rec *, int);
-static int	extra_setup_location(struct isoent *, int);
-static int	set_directory_record_rr(unsigned char *, int,
-		    struct isoent *, struct iso9660 *, enum dir_rec_type);
-static int	set_directory_record(unsigned char *, size_t,
-		    struct isoent *, struct iso9660 *, enum dir_rec_type,
-		    enum vdd_type);
-static inline int get_dir_rec_size(struct iso9660 *, struct isoent *,
-		    enum dir_rec_type, enum vdd_type);
-static inline unsigned char *wb_buffptr(struct archive_write *);
-static int	wb_write_out(struct archive_write *);
-static int	wb_consume(struct archive_write *, size_t);
-#ifdef HAVE_ZLIB_H
-static int	wb_set_offset(struct archive_write *, int64_t);
-#endif
-static int	write_null(struct archive_write *, size_t);
-static int	write_VD_terminator(struct archive_write *);
-static int	set_file_identifier(unsigned char *, int, int, enum vdc,
-		    struct archive_write *, struct vdd *,
-		    struct archive_string *, const char *, int,
-		    enum char_type);
-static int	write_VD(struct archive_write *, struct vdd *);
-static int	write_VD_boot_record(struct archive_write *);
-static int	write_information_block(struct archive_write *);
-static int	write_path_table(struct archive_write *, int,
-		    struct vdd *);
-static int	write_directory_descriptors(struct archive_write *,
-		    struct vdd *);
-static int	write_file_descriptors(struct archive_write *);
-static int	write_rr_ER(struct archive_write *);
-static void	calculate_path_table_size(struct vdd *);
-
-static void	isofile_init_entry_list(struct iso9660 *);
-static void	isofile_add_entry(struct iso9660 *, struct isofile *);
-static void	isofile_free_all_entries(struct iso9660 *);
-static void	isofile_init_entry_data_file_list(struct iso9660 *);
-static void	isofile_add_data_file(struct iso9660 *, struct isofile *);
-static struct isofile * isofile_new(struct archive_write *,
-		    struct archive_entry *);
-static void	isofile_free(struct isofile *);
-static int	isofile_gen_utility_names(struct archive_write *,
-		    struct isofile *);
-static int	isofile_register_hardlink(struct archive_write *,
-		    struct isofile *);
-static void	isofile_connect_hardlink_files(struct iso9660 *);
-static void	isofile_init_hardlinks(struct iso9660 *);
-static void	isofile_free_hardlinks(struct iso9660 *);
-
-static struct isoent *isoent_new(struct isofile *);
-static int	isoent_clone_tree(struct archive_write *,
-		    struct isoent **, struct isoent *);
-static void	_isoent_free(struct isoent *isoent);
-static void	isoent_free_all(struct isoent *);
-static struct isoent * isoent_create_virtual_dir(struct archive_write *,
-		    struct iso9660 *, const char *);
-static int	isoent_cmp_node(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static int	isoent_cmp_key(const struct archive_rb_node *,
-		    const void *);
-static int	isoent_add_child_head(struct isoent *, struct isoent *);
-static int	isoent_add_child_tail(struct isoent *, struct isoent *);
-static void	isoent_remove_child(struct isoent *, struct isoent *);
-static void	isoent_setup_directory_location(struct iso9660 *,
-		    int, struct vdd *);
-static void	isoent_setup_file_location(struct iso9660 *, int);
-static int	get_path_component(char *, size_t, const char *);
-static int	isoent_tree(struct archive_write *, struct isoent **);
-static struct isoent *isoent_find_child(struct isoent *, const char *);
-static struct isoent *isoent_find_entry(struct isoent *, const char *);
-static void	idr_relaxed_filenames(char *);
-static void	idr_init(struct iso9660 *, struct vdd *, struct idr *);
-static void	idr_cleanup(struct idr *);
-static int	idr_ensure_poolsize(struct archive_write *, struct idr *,
-		    int);
-static int	idr_start(struct archive_write *, struct idr *,
-		    int, int, int, int, const struct archive_rb_tree_ops *);
-static void	idr_register(struct idr *, struct isoent *, int,
-		    int);
-static void	idr_extend_identifier(struct idrent *, int, int);
-static void	idr_resolve(struct idr *, void (*)(unsigned char *, int));
-static void	idr_set_num(unsigned char *, int);
-static void	idr_set_num_beutf16(unsigned char *, int);
-static int	isoent_gen_iso9660_identifier(struct archive_write *,
-		    struct isoent *, struct idr *);
-static int	isoent_gen_joliet_identifier(struct archive_write *,
-		    struct isoent *, struct idr *);
-static int	isoent_cmp_iso9660_identifier(const struct isoent *,
-		    const struct isoent *);
-static int	isoent_cmp_node_iso9660(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static int	isoent_cmp_key_iso9660(const struct archive_rb_node *,
-		    const void *);
-static int	isoent_cmp_joliet_identifier(const struct isoent *,
-		    const struct isoent *);
-static int	isoent_cmp_node_joliet(const struct archive_rb_node *,
-		    const struct archive_rb_node *);
-static int	isoent_cmp_key_joliet(const struct archive_rb_node *,
-		    const void *);
-static inline void path_table_add_entry(struct path_table *, struct isoent *);
-static inline struct isoent * path_table_last_entry(struct path_table *);
-static int	isoent_make_path_table(struct archive_write *);
-static int	isoent_find_out_boot_file(struct archive_write *,
-		    struct isoent *);
-static int	isoent_create_boot_catalog(struct archive_write *,
-		    struct isoent *);
-static size_t	fd_boot_image_size(int);
-static int	make_boot_catalog(struct archive_write *);
-static int	setup_boot_information(struct archive_write *);
-
-static int	zisofs_init(struct archive_write *, struct isofile *);
-static void	zisofs_detect_magic(struct archive_write *,
-		    const void *, size_t);
-static int	zisofs_write_to_temp(struct archive_write *,
-		    const void *, size_t);
-static int	zisofs_finish_entry(struct archive_write *);
-static int	zisofs_rewind_boot_file(struct archive_write *);
-static int	zisofs_free(struct archive_write *);
-
-int
-archive_write_set_format_iso9660(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct iso9660 *iso9660;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_iso9660");
-
-	/* If another format was already registered, unregister it. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	iso9660 = calloc(1, sizeof(*iso9660));
-	if (iso9660 == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate iso9660 data");
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->birth_time = 0;
-	iso9660->temp_fd = -1;
-	iso9660->cur_file = NULL;
-	iso9660->primary.max_depth = 0;
-	iso9660->primary.vdd_type = VDD_PRIMARY;
-	iso9660->primary.pathtbl = NULL;
-	iso9660->joliet.rootent = NULL;
-	iso9660->joliet.max_depth = 0;
-	iso9660->joliet.vdd_type = VDD_JOLIET;
-	iso9660->joliet.pathtbl = NULL;
-	isofile_init_entry_list(iso9660);
-	isofile_init_entry_data_file_list(iso9660);
-	isofile_init_hardlinks(iso9660);
-	iso9660->directories_too_deep = NULL;
-	iso9660->dircnt_max = 1;
-	iso9660->wbuff_remaining = wb_buffmax();
-	iso9660->wbuff_type = WB_TO_TEMP;
-	iso9660->wbuff_offset = 0;
-	iso9660->wbuff_written = 0;
-	iso9660->wbuff_tail = 0;
-	archive_string_init(&(iso9660->utf16be));
-	archive_string_init(&(iso9660->mbs));
-
-	/*
-	 * Init Identifiers used for PVD and SVD.
-	 */
-	archive_string_init(&(iso9660->volume_identifier));
-	archive_strcpy(&(iso9660->volume_identifier), "CDROM");
-	archive_string_init(&(iso9660->publisher_identifier));
-	archive_string_init(&(iso9660->data_preparer_identifier));
-	archive_string_init(&(iso9660->application_identifier));
-	archive_strcpy(&(iso9660->application_identifier),
-	    archive_version_string());
-	archive_string_init(&(iso9660->copyright_file_identifier));
-	archive_string_init(&(iso9660->abstract_file_identifier));
-	archive_string_init(&(iso9660->bibliographic_file_identifier));
-
-	/*
-	 * Init El Torito bootable CD variables.
-	 */
-	archive_string_init(&(iso9660->el_torito.catalog_filename));
-	iso9660->el_torito.catalog = NULL;
-	/* Set default file name of boot catalog  */
-	archive_strcpy(&(iso9660->el_torito.catalog_filename),
-	    "boot.catalog");
-	archive_string_init(&(iso9660->el_torito.boot_filename));
-	iso9660->el_torito.boot = NULL;
-	iso9660->el_torito.platform_id = BOOT_PLATFORM_X86;
-	archive_string_init(&(iso9660->el_torito.id));
-	iso9660->el_torito.boot_load_seg = 0;
-	iso9660->el_torito.boot_load_size = BOOT_LOAD_SIZE;
-
-	/*
-	 * Init zisofs variables.
-	 */
-#ifdef HAVE_ZLIB_H
-	iso9660->zisofs.block_pointers = NULL;
-	iso9660->zisofs.block_pointers_allocated = 0;
-	iso9660->zisofs.stream_valid = 0;
-	iso9660->zisofs.compression_level = 9;
-	memset(&(iso9660->zisofs.stream), 0,
-	    sizeof(iso9660->zisofs.stream));
-#endif
-
-	/*
-	 * Set default value of iso9660 options.
-	 */
-	iso9660->opt.abstract_file = OPT_ABSTRACT_FILE_DEFAULT;
-	iso9660->opt.application_id = OPT_APPLICATION_ID_DEFAULT;
-	iso9660->opt.allow_vernum = OPT_ALLOW_VERNUM_DEFAULT;
-	iso9660->opt.biblio_file = OPT_BIBLIO_FILE_DEFAULT;
-	iso9660->opt.boot = OPT_BOOT_DEFAULT;
-	iso9660->opt.boot_catalog = OPT_BOOT_CATALOG_DEFAULT;
-	iso9660->opt.boot_info_table = OPT_BOOT_INFO_TABLE_DEFAULT;
-	iso9660->opt.boot_load_seg = OPT_BOOT_LOAD_SEG_DEFAULT;
-	iso9660->opt.boot_load_size = OPT_BOOT_LOAD_SIZE_DEFAULT;
-	iso9660->opt.boot_type = OPT_BOOT_TYPE_DEFAULT;
-	iso9660->opt.compression_level = OPT_COMPRESSION_LEVEL_DEFAULT;
-	iso9660->opt.copyright_file = OPT_COPYRIGHT_FILE_DEFAULT;
-	iso9660->opt.iso_level = OPT_ISO_LEVEL_DEFAULT;
-	iso9660->opt.joliet = OPT_JOLIET_DEFAULT;
-	iso9660->opt.limit_depth = OPT_LIMIT_DEPTH_DEFAULT;
-	iso9660->opt.limit_dirs = OPT_LIMIT_DIRS_DEFAULT;
-	iso9660->opt.pad = OPT_PAD_DEFAULT;
-	iso9660->opt.publisher = OPT_PUBLISHER_DEFAULT;
-	iso9660->opt.rr = OPT_RR_DEFAULT;
-	iso9660->opt.volume_id = OPT_VOLUME_ID_DEFAULT;
-	iso9660->opt.zisofs = OPT_ZISOFS_DEFAULT;
-
-	/* Create the root directory. */
-	iso9660->primary.rootent =
-	    isoent_create_virtual_dir(a, iso9660, "");
-	if (iso9660->primary.rootent == NULL) {
-		free(iso9660);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->primary.rootent->parent = iso9660->primary.rootent;
-	iso9660->cur_dirent = iso9660->primary.rootent;
-	archive_string_init(&(iso9660->cur_dirstr));
-	archive_string_ensure(&(iso9660->cur_dirstr), 1);
-	iso9660->cur_dirstr.s[0] = 0;
-	iso9660->sconv_to_utf16be = NULL;
-	iso9660->sconv_from_utf16be = NULL;
-
-	a->format_data = iso9660;
-	a->format_name = "iso9660";
-	a->format_options = iso9660_options;
-	a->format_write_header = iso9660_write_header;
-	a->format_write_data = iso9660_write_data;
-	a->format_finish_entry = iso9660_finish_entry;
-	a->format_close = iso9660_close;
-	a->format_free = iso9660_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
-	a->archive.archive_format_name = "ISO9660";
-
-	return (ARCHIVE_OK);
-}
-
-static int
-get_str_opt(struct archive_write *a, struct archive_string *s,
-    size_t maxsize, const char *key, const char *value)
-{
-
-	if (strlen(value) > maxsize) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Value is longer than %zu characters "
-		    "for option ``%s''", maxsize, key);
-		return (ARCHIVE_FATAL);
-	}
-	archive_strcpy(s, value);
-	return (ARCHIVE_OK);
-}
-
-static int
-get_num_opt(struct archive_write *a, int *num, int high, int low,
-    const char *key, const char *value)
-{
-	const char *p = value;
-	int data = 0;
-	int neg = 0;
-
-	if (p == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid value(empty) for option ``%s''", key);
-		return (ARCHIVE_FATAL);
-	}
-	if (*p == '-') {
-		neg = 1;
-		p++;
-	}
-	while (*p) {
-		if (*p >= '0' && *p <= '9')
-			data = data * 10 + *p - '0';
-		else {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid value for option ``%s''", key);
-			return (ARCHIVE_FATAL);
-		}
-		if (data > high) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid value(over %d) for "
-			    "option ``%s''", high, key);
-			return (ARCHIVE_FATAL);
-		}
-		if (data < low) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Invalid value(under %d) for "
-			    "option ``%s''", low, key);
-			return (ARCHIVE_FATAL);
-		}
-		p++;
-	}
-	if (neg)
-		data *= -1;
-	*num = data;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-iso9660_options(struct archive_write *a, const char *key, const char *value)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	const char *p;
-	int r;
-
-	switch (key[0]) {
-	case 'a':
-		if (strcmp(key, "abstract-file") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->abstract_file_identifier),
-			    ABSTRACT_FILE_SIZE, key, value);
-			iso9660->opt.abstract_file = r == ARCHIVE_OK;
-			return (r);
-		}
-		if (strcmp(key, "application-id") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->application_identifier),
-			    APPLICATION_IDENTIFIER_SIZE, key, value);
-			iso9660->opt.application_id = r == ARCHIVE_OK;
-			return (r);
-		}
-		if (strcmp(key, "allow-vernum") == 0) {
-			iso9660->opt.allow_vernum = value != NULL;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'b':
-		if (strcmp(key, "biblio-file") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->bibliographic_file_identifier),
-			    BIBLIO_FILE_SIZE, key, value);
-			iso9660->opt.biblio_file = r == ARCHIVE_OK;
-			return (r);
-		}
-		if (strcmp(key, "boot") == 0) {
-			if (value == NULL)
-				iso9660->opt.boot = 0;
-			else {
-				iso9660->opt.boot = 1;
-				archive_strcpy(
-				    &(iso9660->el_torito.boot_filename),
-				    value);
-			}
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "boot-catalog") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->el_torito.catalog_filename),
-			    1024, key, value);
-			iso9660->opt.boot_catalog = r == ARCHIVE_OK;
-			return (r);
-		}
-		if (strcmp(key, "boot-info-table") == 0) {
-			iso9660->opt.boot_info_table = value != NULL;
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "boot-load-seg") == 0) {
-			uint32_t seg;
-
-			iso9660->opt.boot_load_seg = 0;
-			if (value == NULL)
-				goto invalid_value;
-			seg = 0;
-			p = value;
-			if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
-				p += 2;
-			while (*p) {
-				if (seg)
-					seg <<= 4;
-				if (*p >= 'A' && *p <= 'F')
-					seg += *p - 'A' + 0x0a;
-				else if (*p >= 'a' && *p <= 'f')
-					seg += *p - 'a' + 0x0a;
-				else if (*p >= '0' && *p <= '9')
-					seg += *p - '0';
-				else
-					goto invalid_value;
-				if (seg > 0xffff) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "Invalid value(over 0xffff) for "
-					    "option ``%s''", key);
-					return (ARCHIVE_FATAL);
-				}
-				p++;
-			}
-			iso9660->el_torito.boot_load_seg = (uint16_t)seg;
-			iso9660->opt.boot_load_seg = 1;
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "boot-load-size") == 0) {
-			int num = 0;
-			r = get_num_opt(a, &num, 0xffff, 1, key, value);
-			iso9660->opt.boot_load_size = r == ARCHIVE_OK;
-			if (r != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			iso9660->el_torito.boot_load_size = (uint16_t)num;
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "boot-type") == 0) {
-			if (value == NULL)
-				goto invalid_value;
-			if (strcmp(value, "no-emulation") == 0)
-				iso9660->opt.boot_type = OPT_BOOT_TYPE_NO_EMU;
-			else if (strcmp(value, "fd") == 0)
-				iso9660->opt.boot_type = OPT_BOOT_TYPE_FD;
-			else if (strcmp(value, "hard-disk") == 0)
-				iso9660->opt.boot_type = OPT_BOOT_TYPE_HARD_DISK;
-			else
-				goto invalid_value;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'c':
-		if (strcmp(key, "compression-level") == 0) {
-#ifdef HAVE_ZLIB_H
-			if (value == NULL ||
-			    !(value[0] >= '0' && value[0] <= '9') ||
-			    value[1] != '\0')
-				goto invalid_value;
-                	iso9660->zisofs.compression_level = value[0] - '0';
-			iso9660->opt.compression_level = 1;
-                	return (ARCHIVE_OK);
-#else
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Option ``%s'' "
-			    "is not supported on this platform.", key);
-			return (ARCHIVE_FATAL);
-#endif
-		}
-		if (strcmp(key, "copyright-file") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->copyright_file_identifier),
-			    COPYRIGHT_FILE_SIZE, key, value);
-			iso9660->opt.copyright_file = r == ARCHIVE_OK;
-			return (r);
-		}
-#ifdef DEBUG
-		/* Specifies Volume creation date and time;
-		 * year(4),month(2),day(2),hour(2),minute(2),second(2).
-		 * e.g. "20090929033757"
-		 */
-		if (strcmp(key, "creation") == 0) {
-			struct tm tm;
-			char buf[5];
-
-			p = value;
-			if (p == NULL || strlen(p) < 14)
-				goto invalid_value;
-			memset(&tm, 0, sizeof(tm));
-			memcpy(buf, p, 4); buf[4] = '\0'; p += 4;
-			tm.tm_year = strtol(buf, NULL, 10) - 1900;
-			memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
-			tm.tm_mon = strtol(buf, NULL, 10) - 1;
-			memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
-			tm.tm_mday = strtol(buf, NULL, 10);
-			memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
-			tm.tm_hour = strtol(buf, NULL, 10);
-			memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
-			tm.tm_min = strtol(buf, NULL, 10);
-			memcpy(buf, p, 2); buf[2] = '\0';
-			tm.tm_sec = strtol(buf, NULL, 10);
-			iso9660->birth_time = mktime(&tm);
-			return (ARCHIVE_OK);
-		}
-#endif
-		break;
-	case 'i':
-		if (strcmp(key, "iso-level") == 0) {
-			if (value != NULL && value[1] == '\0' &&
-			    (value[0] >= '1' && value[0] <= '4')) {
-				iso9660->opt.iso_level = value[0]-'0';
-				return (ARCHIVE_OK);
-			}
-			goto invalid_value;
-		}
-		break;
-	case 'j':
-		if (strcmp(key, "joliet") == 0) {
-			if (value == NULL)
-				iso9660->opt.joliet = OPT_JOLIET_DISABLE;
-			else if (strcmp(value, "1") == 0)
-				iso9660->opt.joliet = OPT_JOLIET_ENABLE;
-			else if (strcmp(value, "long") == 0)
-				iso9660->opt.joliet = OPT_JOLIET_LONGNAME;
-			else
-				goto invalid_value;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'l':
-		if (strcmp(key, "limit-depth") == 0) {
-			iso9660->opt.limit_depth = value != NULL;
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "limit-dirs") == 0) {
-			iso9660->opt.limit_dirs = value != NULL;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'p':
-		if (strcmp(key, "pad") == 0) {
-			iso9660->opt.pad = value != NULL;
-			return (ARCHIVE_OK);
-		}
-		if (strcmp(key, "publisher") == 0) {
-			r = get_str_opt(a,
-			    &(iso9660->publisher_identifier),
-			    PUBLISHER_IDENTIFIER_SIZE, key, value);
-			iso9660->opt.publisher = r == ARCHIVE_OK;
-			return (r);
-		}
-		break;
-	case 'r':
-		if (strcmp(key, "rockridge") == 0 ||
-		    strcmp(key, "Rockridge") == 0) {
-			if (value == NULL)
-				iso9660->opt.rr = OPT_RR_DISABLED;
-			else if (strcmp(value, "1") == 0)
-				iso9660->opt.rr = OPT_RR_USEFUL;
-			else if (strcmp(value, "strict") == 0)
-				iso9660->opt.rr = OPT_RR_STRICT;
-			else if (strcmp(value, "useful") == 0)
-				iso9660->opt.rr = OPT_RR_USEFUL;
-			else
-				goto invalid_value;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'v':
-		if (strcmp(key, "volume-id") == 0) {
-			r = get_str_opt(a, &(iso9660->volume_identifier),
-			    VOLUME_IDENTIFIER_SIZE, key, value);
-			iso9660->opt.volume_id = r == ARCHIVE_OK;
-			return (r);
-		}
-		break;
-	case 'z':
-		if (strcmp(key, "zisofs") == 0) {
-			if (value == NULL)
-				iso9660->opt.zisofs = OPT_ZISOFS_DISABLED;
-			else {
-#ifdef HAVE_ZLIB_H
-				iso9660->opt.zisofs = OPT_ZISOFS_DIRECT;
-#else
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "``zisofs'' "
-				    "is not supported on this platform.");
-				return (ARCHIVE_FATAL);
-#endif
-			}
-			return (ARCHIVE_OK);
-		}
-		break;
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-
-invalid_value:
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Invalid value for option ``%s''", key);
-	return (ARCHIVE_FAILED);
-}
-
-static int
-iso9660_write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct iso9660 *iso9660;
-	struct isofile *file;
-	struct isoent *isoent;
-	int r, ret = ARCHIVE_OK;
-
-	iso9660 = a->format_data;
-
-	iso9660->cur_file = NULL;
-	iso9660->bytes_remaining = 0;
-	iso9660->need_multi_extent = 0;
-	if (archive_entry_filetype(entry) == AE_IFLNK
-	    && iso9660->opt.rr == OPT_RR_DISABLED) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Ignore symlink file.");
-		iso9660->cur_file = NULL;
-		return (ARCHIVE_WARN);
-	}
-	if (archive_entry_filetype(entry) == AE_IFREG &&
-	    archive_entry_size(entry) >= MULTI_EXTENT_SIZE) {
-		if (iso9660->opt.iso_level < 3) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Ignore over %lld bytes file. "
-			    "This file too large.",
-			    MULTI_EXTENT_SIZE);
-				iso9660->cur_file = NULL;
-			return (ARCHIVE_WARN);
-		}
-		iso9660->need_multi_extent = 1;
-	}
-
-	file = isofile_new(a, entry);
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate data");
-		return (ARCHIVE_FATAL);
-	}
-	r = isofile_gen_utility_names(a, file);
-	if (r < ARCHIVE_WARN) {
-		isofile_free(file);
-		return (r);
-	}
-	else if (r < ret)
-		ret = r;
-
-	/*
-	 * Ignore a path which looks like the top of directory name
-	 * since we have already made the root directory of an ISO image.
-	 */
-	if (archive_strlen(&(file->parentdir)) == 0 &&
-	    archive_strlen(&(file->basename)) == 0) {
-		isofile_free(file);
-		return (r);
-	}
-
-	isofile_add_entry(iso9660, file);
-	isoent = isoent_new(file);
-	if (isoent == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate data");
-		return (ARCHIVE_FATAL);
-	}
-	if (isoent->file->dircnt > iso9660->dircnt_max)
-		iso9660->dircnt_max = isoent->file->dircnt;
-
-	/* Add the current file into tree */
-	r = isoent_tree(a, &isoent);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	/* If there is the same file in tree and
-	 * the current file is older than the file in tree.
-	 * So we don't need the current file data anymore. */
-	if (isoent->file != file)
-		return (ARCHIVE_OK);
-
-	/* Non regular files contents are unneeded to be saved to
-	 * temporary files. */
-	if (archive_entry_filetype(file->entry) != AE_IFREG)
-		return (ret);
-
-	/*
-	 * Set the current file to cur_file to read its contents.
-	 */
-	iso9660->cur_file = file;
-
-	if (archive_entry_nlink(file->entry) > 1) {
-		r = isofile_register_hardlink(a, file);
-		if (r != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Prepare to save the contents of the file.
-	 */
-	if (iso9660->temp_fd < 0) {
-		iso9660->temp_fd = __archive_mktemp(NULL);
-		if (iso9660->temp_fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't create temporary file");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	/* Save an offset of current file in temporary file. */
-	file->content.offset_of_temp = wb_offset(a);
-	file->cur_content = &(file->content);
-	r = zisofs_init(a, file);
-	if (r < ret)
-		ret = r;
-	iso9660->bytes_remaining =  archive_entry_size(file->entry);
-
-	return (ret);
-}
-
-static int
-write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	ssize_t written;
-	const unsigned char *b;
-
-	b = (const unsigned char *)buff;
-	while (s) {
-		written = write(iso9660->temp_fd, b, s);
-		if (written < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't write to temporary file");
-			return (ARCHIVE_FATAL);
-		}
-		s -= written;
-		b += written;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-wb_write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	const char *xp = buff;
-	size_t xs = s;
-
-	/*
-	 * If a written data size is big enough to use system-call
-	 * and there is no waiting data, this calls write_to_temp() in
-	 * order to reduce a extra memory copy.
-	 */
-	if (wb_remaining(a) == wb_buffmax() && s > (1024 * 16)) {
-		struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
-		xs = s % LOGICAL_BLOCK_SIZE;
-		iso9660->wbuff_offset += s - xs;
-		if (write_to_temp(a, buff, s - xs) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		if (xs == 0)
-			return (ARCHIVE_OK);
-		xp += s - xs;
-	}
-
-	while (xs) {
-		size_t size = xs;
-		if (size > wb_remaining(a))
-			size = wb_remaining(a);
-		memcpy(wb_buffptr(a), xp, size);
-		if (wb_consume(a, size) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		xs -= size;
-		xp += size;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-wb_write_padding_to_temp(struct archive_write *a, int64_t csize)
-{
-	size_t ns;
-	int ret;
-
-	ns = (size_t)(csize % LOGICAL_BLOCK_SIZE);
-	if (ns != 0)
-		ret = write_null(a, LOGICAL_BLOCK_SIZE - ns);
-	else
-		ret = ARCHIVE_OK;
-	return (ret);
-}
-
-static ssize_t
-write_iso9660_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	size_t ws;
-
-	if (iso9660->temp_fd < 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Couldn't create temporary file");
-		return (ARCHIVE_FATAL);
-	}
-
-	ws = s;
-	if (iso9660->need_multi_extent &&
-	    (iso9660->cur_file->cur_content->size + ws) >=
-	      (MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE)) {
-		struct content *con;
-		size_t ts;
-
-		ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE -
-		    iso9660->cur_file->cur_content->size);
-
-		if (iso9660->zisofs.detect_magic)
-			zisofs_detect_magic(a, buff, ts);
-
-		if (iso9660->zisofs.making) {
-			if (zisofs_write_to_temp(a, buff, ts) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		} else {
-			if (wb_write_to_temp(a, buff, ts) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			iso9660->cur_file->cur_content->size += ts;
-		}
-
-		/* Write padding. */
-		if (wb_write_padding_to_temp(a,
-		    iso9660->cur_file->cur_content->size) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-
-		/* Compute the logical block number. */
-		iso9660->cur_file->cur_content->blocks = (int)
-		    ((iso9660->cur_file->cur_content->size
-		     + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
-
-		/*
-		 * Make next extent.
-		 */
-		ws -= ts;
-		buff = (const void *)(((const unsigned char *)buff) + ts);
-		/* Make a content for next extent. */
-		con = calloc(1, sizeof(*con));
-		if (con == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate content data");
-			return (ARCHIVE_FATAL);
-		}
-		con->offset_of_temp = wb_offset(a);
-		iso9660->cur_file->cur_content->next = con;
-		iso9660->cur_file->cur_content = con;
-#ifdef HAVE_ZLIB_H
-		iso9660->zisofs.block_offset = 0;
-#endif
-	}
-
-	if (iso9660->zisofs.detect_magic)
-		zisofs_detect_magic(a, buff, ws);
-
-	if (iso9660->zisofs.making) {
-		if (zisofs_write_to_temp(a, buff, ws) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	} else {
-		if (wb_write_to_temp(a, buff, ws) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		iso9660->cur_file->cur_content->size += ws;
-	}
-
-	return (s);
-}
-
-static ssize_t
-iso9660_write_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	ssize_t r;
-
-	if (iso9660->cur_file == NULL)
-		return (0);
-	if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
-		return (0);
-	if (s > iso9660->bytes_remaining)
-		s = (size_t)iso9660->bytes_remaining;
-	if (s == 0)
-		return (0);
-
-	r = write_iso9660_data(a, buff, s);
-	if (r > 0)
-		iso9660->bytes_remaining -= r;
-	return (r);
-}
-
-static int
-iso9660_finish_entry(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-
-	if (iso9660->cur_file == NULL)
-		return (ARCHIVE_OK);
-	if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
-		return (ARCHIVE_OK);
-	if (iso9660->cur_file->content.size == 0)
-		return (ARCHIVE_OK);
-
-	/* If there are unwritten data, write null data instead. */
-	while (iso9660->bytes_remaining > 0) {
-		size_t s;
-
-		s = (iso9660->bytes_remaining > a->null_length)?
-		    a->null_length: (size_t)iso9660->bytes_remaining;
-		if (write_iso9660_data(a, a->nulls, s) < 0)
-			return (ARCHIVE_FATAL);
-		iso9660->bytes_remaining -= s;
-	}
-
-	if (iso9660->zisofs.making && zisofs_finish_entry(a) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write padding. */
-	if (wb_write_padding_to_temp(a, iso9660->cur_file->cur_content->size)
-	    != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Compute the logical block number. */
-	iso9660->cur_file->cur_content->blocks = (int)
-	    ((iso9660->cur_file->cur_content->size
-	     + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
-
-	/* Add the current file to data file list. */
-	isofile_add_data_file(iso9660, iso9660->cur_file);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-iso9660_close(struct archive_write *a)
-{
-	struct iso9660 *iso9660;
-	int ret, blocks;
-
-	iso9660 = a->format_data;
-
-	/*
-	 * Write remaining data out to the temporary file.
-	 */
-	if (wb_remaining(a) > 0) {
-		ret = wb_write_out(a);
-		if (ret < 0)
-			return (ret);
-	}
-
-	/*
-	 * Preparations...
-	 */
-#ifdef DEBUG
-	if (iso9660->birth_time == 0)
-#endif
-		time(&(iso9660->birth_time));
-
-	/*
-	 * Prepare a bootable ISO image.
-	 */
-	if (iso9660->opt.boot) {
-		/* Find out the boot file entry. */
-		ret = isoent_find_out_boot_file(a, iso9660->primary.rootent);
-		if (ret < 0)
-			return (ret);
-		/* Reconvert the boot file from zisofs'ed form to
-		 * plain form. */
-		ret = zisofs_rewind_boot_file(a);
-		if (ret < 0)
-			return (ret);
-		/* Write remaining data out to the temporary file. */
-		if (wb_remaining(a) > 0) {
-			ret = wb_write_out(a);
-			if (ret < 0)
-				return (ret);
-		}
-		/* Create the boot catalog. */
-		ret = isoent_create_boot_catalog(a, iso9660->primary.rootent);
-		if (ret < 0)
-			return (ret);
-	}
-
-	/*
-	 * Prepare joliet extensions.
-	 */
-	if (iso9660->opt.joliet) {
-		/* Make a new tree for joliet. */
-		ret = isoent_clone_tree(a, &(iso9660->joliet.rootent),
-		    iso9660->primary.rootent);
-		if (ret < 0)
-			return (ret);
-		/* Make sure we have UTF-16BE converters.
-		 * if there is no file entry, converters are still
-		 * uninitialized. */
-		if (iso9660->sconv_to_utf16be == NULL) {
-			iso9660->sconv_to_utf16be =
-			    archive_string_conversion_to_charset(
-				&(a->archive), "UTF-16BE", 1);
-			if (iso9660->sconv_to_utf16be == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FATAL);
-			iso9660->sconv_from_utf16be =
-			    archive_string_conversion_from_charset(
-				&(a->archive), "UTF-16BE", 1);
-			if (iso9660->sconv_from_utf16be == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FATAL);
-		}
-	}
-
-	/*
-	 * Make Path Tables.
-	 */
-	ret = isoent_make_path_table(a);
-	if (ret < 0)
-		return (ret);
-
-	/*
-	 * Calculate a total volume size and setup all locations of
-	 * contents of an iso9660 image.
-	 */
-	blocks = SYSTEM_AREA_BLOCK
-		+ PRIMARY_VOLUME_DESCRIPTOR_BLOCK
-		+ VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK
-		+ NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
-	if (iso9660->opt.boot)
-		blocks += BOOT_RECORD_DESCRIPTOR_BLOCK;
-	if (iso9660->opt.joliet)
-		blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
-	if (iso9660->opt.iso_level == 4)
-		blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
-
-	/* Setup the locations of Path Table. */
-	iso9660->primary.location_type_L_path_table = blocks;
-	blocks += iso9660->primary.path_table_block;
-	iso9660->primary.location_type_M_path_table = blocks;
-	blocks += iso9660->primary.path_table_block;
-	if (iso9660->opt.joliet) {
-		iso9660->joliet.location_type_L_path_table = blocks;
-		blocks += iso9660->joliet.path_table_block;
-		iso9660->joliet.location_type_M_path_table = blocks;
-		blocks += iso9660->joliet.path_table_block;
-	}
-
-	/* Setup the locations of directories. */
-	isoent_setup_directory_location(iso9660, blocks,
-	    &(iso9660->primary));
-	blocks += iso9660->primary.total_dir_block;
-	if (iso9660->opt.joliet) {
-		isoent_setup_directory_location(iso9660, blocks,
-		    &(iso9660->joliet));
-		blocks += iso9660->joliet.total_dir_block;
-	}
-
-	if (iso9660->opt.rr) {
-		iso9660->location_rrip_er = blocks;
-		blocks += RRIP_ER_BLOCK;
-	}
-
-	/* Setup the locations of all file contents. */
- 	isoent_setup_file_location(iso9660, blocks);
-	blocks += iso9660->total_file_block;
-	if (iso9660->opt.boot && iso9660->opt.boot_info_table) {
-		ret = setup_boot_information(a);
-		if (ret < 0)
-			return (ret);
-	}
-
-	/* Now we have a total volume size. */
-	iso9660->volume_space_size = blocks;
-	if (iso9660->opt.pad)
-		iso9660->volume_space_size += PADDING_BLOCK;
-	iso9660->volume_sequence_number = 1;
-
-
-	/*
-	 * Write an ISO 9660 image.
-	 */
-
-	/* Switch to start using wbuff as file buffer. */
-	iso9660->wbuff_remaining = wb_buffmax();
-	iso9660->wbuff_type = WB_TO_STREAM;
-	iso9660->wbuff_offset = 0;
-	iso9660->wbuff_written = 0;
-	iso9660->wbuff_tail = 0;
-
-	/* Write The System Area */
-	ret = write_null(a, SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write Primary Volume Descriptor */
-	ret = write_VD(a, &(iso9660->primary));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	if (iso9660->opt.boot) {
-		/* Write Boot Record Volume Descriptor */
-		ret = write_VD_boot_record(a);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	if (iso9660->opt.iso_level == 4) {
-		/* Write Enhanced Volume Descriptor */
-		iso9660->primary.vdd_type = VDD_ENHANCED;
-		ret = write_VD(a, &(iso9660->primary));
-		iso9660->primary.vdd_type = VDD_PRIMARY;
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	if (iso9660->opt.joliet) {
-		ret = write_VD(a, &(iso9660->joliet));
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Write Volume Descriptor Set Terminator */
-	ret = write_VD_terminator(a);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write Non-ISO File System Information */
-	ret = write_information_block(a);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write Type L Path Table */
-	ret = write_path_table(a, 0, &(iso9660->primary));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write Type M Path Table */
-	ret = write_path_table(a, 1, &(iso9660->primary));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	if (iso9660->opt.joliet) {
-		/* Write Type L Path Table */
-		ret = write_path_table(a, 0, &(iso9660->joliet));
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-
-		/* Write Type M Path Table */
-		ret = write_path_table(a, 1, &(iso9660->joliet));
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Write Directory Descriptors */
-	ret = write_directory_descriptors(a, &(iso9660->primary));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	if (iso9660->opt.joliet) {
-		ret = write_directory_descriptors(a, &(iso9660->joliet));
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	if (iso9660->opt.rr) {
-		/* Write Rockridge ER(Extensions Reference) */
-		ret = write_rr_ER(a);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Write File Descriptors */
-	ret = write_file_descriptors(a);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Write Padding  */
-	if (iso9660->opt.pad) {
-		ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	if (iso9660->directories_too_deep != NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "%s: Directories too deep.",
-		    archive_entry_pathname(
-			iso9660->directories_too_deep->file->entry));
-		return (ARCHIVE_WARN);
-	}
-
-	/* Write remaining data out. */
-	ret = wb_write_out(a);
-
-	return (ret);
-}
-
-static int
-iso9660_free(struct archive_write *a)
-{
-	struct iso9660 *iso9660;
-	int i, ret;
-
-	iso9660 = a->format_data;
-
-	/* Close the temporary file. */
-	if (iso9660->temp_fd >= 0)
-		close(iso9660->temp_fd);
-
-	/* Free some stuff for zisofs operations. */
-	ret = zisofs_free(a);
-
-	/* Remove directory entries in tree which includes file entries. */
-	isoent_free_all(iso9660->primary.rootent);
-	for (i = 0; i < iso9660->primary.max_depth; i++)
-		free(iso9660->primary.pathtbl[i].sorted);
-	free(iso9660->primary.pathtbl);
-
-	if (iso9660->opt.joliet) {
-		isoent_free_all(iso9660->joliet.rootent);
-		for (i = 0; i < iso9660->joliet.max_depth; i++)
-			free(iso9660->joliet.pathtbl[i].sorted);
-		free(iso9660->joliet.pathtbl);
-	}
-
-	/* Remove isofile entries. */
-	isofile_free_all_entries(iso9660);
-	isofile_free_hardlinks(iso9660);
-
-	archive_string_free(&(iso9660->cur_dirstr));
-	archive_string_free(&(iso9660->volume_identifier));
-	archive_string_free(&(iso9660->publisher_identifier));
-	archive_string_free(&(iso9660->data_preparer_identifier));
-	archive_string_free(&(iso9660->application_identifier));
-	archive_string_free(&(iso9660->copyright_file_identifier));
-	archive_string_free(&(iso9660->abstract_file_identifier));
-	archive_string_free(&(iso9660->bibliographic_file_identifier));
-	archive_string_free(&(iso9660->el_torito.catalog_filename));
-	archive_string_free(&(iso9660->el_torito.boot_filename));
-	archive_string_free(&(iso9660->el_torito.id));
-	archive_string_free(&(iso9660->utf16be));
-	archive_string_free(&(iso9660->mbs));
-
-	free(iso9660);
-	a->format_data = NULL;
-
-	return (ret);
-}
-
-/*
- * Get the System Identifier
- */
-static void
-get_system_identitier(char *system_id, size_t size)
-{
-#if defined(HAVE_SYS_UTSNAME_H)
-	struct utsname u;
-
-	uname(&u);
-	strncpy(system_id, u.sysname, size-1);
-	system_id[size-1] = '\0';
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-	strncpy(system_id, "Windows", size-1);
-	system_id[size-1] = '\0';
-#else
-	strncpy(system_id, "Unknown", size-1);
-	system_id[size-1] = '\0';
-#endif
-}
-
-static void
-set_str(unsigned char *p, const char *s, size_t l, char f, const char *map)
-{
-	unsigned char c;
-
-	if (s == NULL)
-		s = "";
-	while ((c = *s++) != 0 && l > 0) {
-		if (c >= 0x80 || map[c] == 0)
-		 {
-			/* illegal character */
-			if (c >= 'a' && c <= 'z') {
-				/* convert c from a-z to A-Z */
-				c -= 0x20;
-			} else
-				c = 0x5f;
-		}
-		*p++ = c;
-		l--;
-	}
-	/* If l isn't zero, fill p buffer by the character
-	 * which indicated by f. */
-	if (l > 0)
-		memset(p , f, l);
-}
-
-static inline int
-joliet_allowed_char(unsigned char high, unsigned char low)
-{
-	int utf16 = (high << 8) | low;
-
-	if (utf16 <= 0x001F)
-		return (0);
-
-	switch (utf16) {
-	case 0x002A: /* '*' */
-	case 0x002F: /* '/' */
-	case 0x003A: /* ':' */
-	case 0x003B: /* ';' */
-	case 0x003F: /* '?' */
-	case 0x005C: /* '\' */
-		return (0);/* Not allowed. */
-	}
-	return (1);
-}
-
-static int
-set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
-    size_t l, uint16_t uf, enum vdc vdc)
-{
-	size_t size, i;
-	int onepad;
-
-	if (s == NULL)
-		s = "";
-	if (l & 0x01) {
-		onepad = 1;
-		l &= ~1;
-	} else
-		onepad = 0;
-	if (vdc == VDC_UCS2) {
-		struct iso9660 *iso9660 = a->format_data;
-		if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s),
-		    iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for UTF-16BE");
-			return (ARCHIVE_FATAL);
-		}
-		size = iso9660->utf16be.length;
-		if (size > l)
-			size = l;
-		memcpy(p, iso9660->utf16be.s, size);
-	} else {
-		const uint16_t *u16 = (const uint16_t *)s;
-
-		size = 0;
-		while (*u16++)
-			size += 2;
-		if (size > l)
-			size = l;
-		memcpy(p, s, size);
-	}
-	for (i = 0; i < size; i += 2, p += 2) {
-		if (!joliet_allowed_char(p[0], p[1]))
-			archive_be16enc(p, 0x005F);/* '_' */
-	}
-	l -= size;
-	while (l > 0) {
-		archive_be16enc(p, uf);
-		p += 2;
-		l -= 2;
-	}
-	if (onepad)
-		*p = 0;
-	return (ARCHIVE_OK);
-}
-
-static const char a_characters_map[0x80] = {
-/*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
-    1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
-};
-
-static const char a1_characters_map[0x80] = {
-/*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
-    1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
-};
-
-static const char d_characters_map[0x80] = {
-/*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
-};
-
-static const char d1_characters_map[0x80] = {
-/*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
-};
-
-static int
-set_str_a_characters_bp(struct archive_write *a, unsigned char *bp,
-    int from, int to, const char *s, enum vdc vdc)
-{
-	int r;
-
-	switch (vdc) {
-	case VDC_STD:
-		set_str(bp+from, s, to - from + 1, 0x20,
-		    a_characters_map);
-		r = ARCHIVE_OK;
-		break;
-	case VDC_LOWERCASE:
-		set_str(bp+from, s, to - from + 1, 0x20,
-		    a1_characters_map);
-		r = ARCHIVE_OK;
-		break;
-	case VDC_UCS2:
-	case VDC_UCS2_DIRECT:
-		r = set_str_utf16be(a, bp+from, s, to - from + 1,
-		    0x0020, vdc);
-		break;
-	default:
-		r = ARCHIVE_FATAL;
-	}
-	return (r);
-}
-
-static int
-set_str_d_characters_bp(struct archive_write *a, unsigned char *bp,
-    int from, int to, const char *s, enum  vdc vdc)
-{
-	int r;
-
-	switch (vdc) {
-	case VDC_STD:
-		set_str(bp+from, s, to - from + 1, 0x20,
-		    d_characters_map);
-		r = ARCHIVE_OK;
-		break;
-	case VDC_LOWERCASE:
-		set_str(bp+from, s, to - from + 1, 0x20,
-		    d1_characters_map);
-		r = ARCHIVE_OK;
-		break;
-	case VDC_UCS2:
-	case VDC_UCS2_DIRECT:
-		r = set_str_utf16be(a, bp+from, s, to - from + 1,
-		    0x0020, vdc);
-		break;
-	default:
-		r = ARCHIVE_FATAL;
-	}
-	return (r);
-}
-
-static void
-set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver)
-{
-
-	/* Volume Descriptor Type */
-	bp[1] = (unsigned char)type;
-	/* Standard Identifier */
-	memcpy(bp + 2, "CD001", 5);
-	/* Volume Descriptor Version */
-	bp[7] = ver;
-}
-
-static inline void
-set_unused_field_bp(unsigned char *bp, int from, int to)
-{
-	memset(bp + from, 0, to - from + 1);
-}
-
-/*
- * 8-bit unsigned numerical values.
- * ISO9660 Standard 7.1.1
- */
-static inline void
-set_num_711(unsigned char *p, unsigned char value)
-{
-	*p = value;
-}
-
-/*
- * 8-bit signed numerical values.
- * ISO9660 Standard 7.1.2
- */
-static inline void
-set_num_712(unsigned char *p, char value)
-{
-	*((char *)p) = value;
-}
-
-/*
- * Least significant byte first.
- * ISO9660 Standard 7.2.1
- */
-static inline void
-set_num_721(unsigned char *p, uint16_t value)
-{
-	archive_le16enc(p, value);
-}
-
-/*
- * Most significant byte first.
- * ISO9660 Standard 7.2.2
- */
-static inline void
-set_num_722(unsigned char *p, uint16_t value)
-{
-	archive_be16enc(p, value);
-}
-
-/*
- * Both-byte orders.
- * ISO9660 Standard 7.2.3
- */
-static void
-set_num_723(unsigned char *p, uint16_t value)
-{
-	archive_le16enc(p, value);
-	archive_be16enc(p+2, value);
-}
-
-/*
- * Least significant byte first.
- * ISO9660 Standard 7.3.1
- */
-static inline void
-set_num_731(unsigned char *p, uint32_t value)
-{
-	archive_le32enc(p, value);
-}
-
-/*
- * Most significant byte first.
- * ISO9660 Standard 7.3.2
- */
-static inline void
-set_num_732(unsigned char *p, uint32_t value)
-{
-	archive_be32enc(p, value);
-}
-
-/*
- * Both-byte orders.
- * ISO9660 Standard 7.3.3
- */
-static inline void
-set_num_733(unsigned char *p, uint32_t value)
-{
-	archive_le32enc(p, value);
-	archive_be32enc(p+4, value);
-}
-
-static void
-set_digit(unsigned char *p, size_t s, int value)
-{
-
-	while (s--) {
-		p[s] = '0' + (value % 10);
-		value /= 10;
-	}
-}
-
-#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
-#define get_gmoffset(tm)	((tm)->tm_gmtoff)
-#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
-#define get_gmoffset(tm)	((tm)->__tm_gmtoff)
-#else
-static long
-get_gmoffset(struct tm *tm)
-{
-	long offset;
-
-#if defined(HAVE__GET_TIMEZONE)
-	_get_timezone(&offset);
-#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-	offset = _timezone;
-#else
-	offset = timezone;
-#endif
-	offset *= -1;
-	if (tm->tm_isdst)
-		offset += 3600;
-	return (offset);
-}
-#endif
-
-static void
-get_tmfromtime(struct tm *tm, time_t *t)
-{
-#if HAVE_LOCALTIME_S
-	localtime_s(tm, t);
-#elif HAVE_LOCALTIME_R
-	tzset();
-	localtime_r(t, tm);
-#else
-	memcpy(tm, localtime(t), sizeof(*tm));
-#endif
-}
-
-/*
- * Date and Time Format.
- * ISO9660 Standard 8.4.26.1
- */
-static void
-set_date_time(unsigned char *p, time_t t)
-{
-	struct tm tm;
-
-	get_tmfromtime(&tm, &t);
-	set_digit(p, 4, tm.tm_year + 1900);
-	set_digit(p+4, 2, tm.tm_mon + 1);
-	set_digit(p+6, 2, tm.tm_mday);
-	set_digit(p+8, 2, tm.tm_hour);
-	set_digit(p+10, 2, tm.tm_min);
-	set_digit(p+12, 2, tm.tm_sec);
-	set_digit(p+14, 2, 0);
-	set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
-}
-
-static void
-set_date_time_null(unsigned char *p)
-{
-	memset(p, (int)'0', 16);
-	p[16] = 0;
-}
-
-static void
-set_time_915(unsigned char *p, time_t t)
-{
-	struct tm tm;
-
-	get_tmfromtime(&tm, &t);
-	set_num_711(p+0, tm.tm_year);
-	set_num_711(p+1, tm.tm_mon+1);
-	set_num_711(p+2, tm.tm_mday);
-	set_num_711(p+3, tm.tm_hour);
-	set_num_711(p+4, tm.tm_min);
-	set_num_711(p+5, tm.tm_sec);
-	set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
-}
-
-
-/*
- * Write SUSP "CE" System Use Entry.
- */
-static int
-set_SUSP_CE(unsigned char *p, int location, int offset, int size)
-{
-	unsigned char *bp = p -1;
-	/*  Extend the System Use Area
-	 *   "CE" Format:
-	 *               len  ver
-	 *    +----+----+----+----+-----------+-----------+
-	 *    | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
-	 *    +----+----+----+----+-----------+-----------+
-	 *    0    1    2    3    4          12          20
-	 *    +-----------+
-	 *    | LOCATION3 |
-	 *    +-----------+
-	 *   20          28
-	 *   LOCATION1 : Location of Continuation of System Use Area.
-	 *   LOCATION2 : Offset to Start of Continuation.
-	 *   LOCATION3 : Length of the Continuation.
-	 */
-
-	bp[1] = 'C';
-	bp[2] = 'E';
-	bp[3] = RR_CE_SIZE;	/* length	*/
-	bp[4] = 1;		/* version	*/
-	set_num_733(bp+5, location);
-	set_num_733(bp+13, offset);
-	set_num_733(bp+21, size);
-	return (RR_CE_SIZE);
-}
-
-/*
- * The functions, which names are beginning with extra_, are used to
- * control extra records.
- * The maximum size of a Directory Record is 254. When a filename is
- * very long, all of RRIP data of a file won't stored to the Directory
- * Record and so remaining RRIP data store to an extra record instead.
- */
-static unsigned char *
-extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
-    struct ctl_extr_rec *ctl)
-{
-	ctl->bp = bp;
-	if (bp != NULL)
-		bp += dr_len;
-	ctl->use_extr = 0;
-	ctl->isoent = isoent;
-	ctl->ce_ptr = NULL;
-	ctl->cur_len = ctl->dr_len = dr_len;
-	ctl->limit = DR_LIMIT;
-
-	return (bp);
-}
-
-static void
-extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
-{
-	int padding = 0;
-
-	if (ce_size > 0)
-		extra_tell_used_size(ctl, ce_size);
-	/* Padding. */
-	if (ctl->cur_len & 0x01) {
-		ctl->cur_len++;
-		if (ctl->bp != NULL)
-			ctl->bp[ctl->cur_len] = 0;
-		padding = 1;
-	}
-	if (ctl->use_extr) {
-		if (ctl->ce_ptr != NULL)
-			set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
-			    ctl->extr_off, ctl->cur_len - padding);
-	} else
-		ctl->dr_len = ctl->cur_len;
-}
-
-#define extra_space(ctl)	((ctl)->limit - (ctl)->cur_len)
-
-static unsigned char *
-extra_next_record(struct ctl_extr_rec *ctl, int length)
-{
-	int cur_len = ctl->cur_len;/* save cur_len */
-
-	/* Close the current extra record or Directory Record. */
-	extra_close_record(ctl, RR_CE_SIZE);
-
-	/* Get a next extra record. */
-	ctl->use_extr = 1;
-	if (ctl->bp != NULL) {
-		/* Storing data into an extra record. */
-		unsigned char *p;
-
-		/* Save the pointer where a CE extension will be
-		 * stored to. */
-		ctl->ce_ptr = &ctl->bp[cur_len+1];
-		p = extra_get_record(ctl->isoent,
-		    &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
-		ctl->bp = p - 1;/* the base of bp offset is 1. */
-	} else
-		/* Calculating the size of an extra record. */
-		(void)extra_get_record(ctl->isoent,
-		    &ctl->limit, NULL, NULL);
-	ctl->cur_len = 0;
-	/* Check if an extra record is almost full.
-	 * If so, get a next one. */
-	if (extra_space(ctl) < length)
-		(void)extra_next_record(ctl, length);
-
-	return (ctl->bp);
-}
-
-static inline struct extr_rec *
-extra_last_record(struct isoent *isoent)
-{
-	if (isoent->extr_rec_list.first == NULL)
-		return (NULL);
-	return ((struct extr_rec *)(void *)
-		((char *)(isoent->extr_rec_list.last)
-		    - offsetof(struct extr_rec, next)));
-}
-
-static unsigned char *
-extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
-{
-	struct extr_rec *rec;
-
-	isoent = isoent->parent;
-	if (off != NULL) {
-		/* Storing data into an extra record. */
-		rec = isoent->extr_rec_list.current;
-		if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
-			rec = rec->next;
-	} else {
-		/* Calculating the size of an extra record. */
-		rec = extra_last_record(isoent);
-		if (rec == NULL ||
-		    DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
-			rec = malloc(sizeof(*rec));
-			if (rec == NULL)
-				return (NULL);
-			rec->location = 0;
-			rec->offset = 0;
-			/* Insert `rec` into the tail of isoent->extr_rec_list */
-			rec->next = NULL;
-			/*
-			 * Note: testing isoent->extr_rec_list.last == NULL
-			 * here is really unneeded since it has been already
-			 * initialized at isoent_new function but Clang Static
-			 * Analyzer claims that it is dereference of null
-			 * pointer.
-			 */
-			if (isoent->extr_rec_list.last == NULL)
-				isoent->extr_rec_list.last =
-					&(isoent->extr_rec_list.first);
-			*isoent->extr_rec_list.last = rec;
-			isoent->extr_rec_list.last = &(rec->next);
-		}
-	}
-	*space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
-	if (*space & 0x01)
-		*space -= 1;/* Keep padding space. */
-	if (off != NULL)
-		*off = rec->offset;
-	if (loc != NULL)
-		*loc = rec->location;
-	isoent->extr_rec_list.current = rec;
-
-	return (&rec->buf[rec->offset]);
-}
-
-static void
-extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
-{
-	struct isoent *isoent;
-	struct extr_rec *rec;
-
-	if (ctl->use_extr) {
-		isoent = ctl->isoent->parent;
-		rec = isoent->extr_rec_list.current;
-		if (rec != NULL)
-			rec->offset += size;
-	}
-	ctl->cur_len += size;
-}
-
-static int
-extra_setup_location(struct isoent *isoent, int location)
-{
-	struct extr_rec *rec;
-	int cnt;
-
-	cnt = 0;
-	rec = isoent->extr_rec_list.first;
-	isoent->extr_rec_list.current = rec;
-	while (rec) {
-		cnt++;
-		rec->location = location++;
-		rec->offset = 0;
-		rec = rec->next;
-	}
-	return (cnt);
-}
-
-/*
- * Create the RRIP entries.
- */
-static int
-set_directory_record_rr(unsigned char *bp, int dr_len,
-    struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
-{
-	/* Flags(BP 5) of the Rockridge "RR" System Use Field */
-	unsigned char rr_flag;
-#define RR_USE_PX	0x01
-#define RR_USE_PN	0x02
-#define RR_USE_SL	0x04
-#define RR_USE_NM	0x08
-#define RR_USE_CL	0x10
-#define RR_USE_PL	0x20
-#define RR_USE_RE	0x40
-#define RR_USE_TF	0x80
-	int length;
-	struct ctl_extr_rec ctl;
-	struct isoent *rr_parent, *pxent;
-	struct isofile *file;
-
-	bp = extra_open_record(bp, dr_len, isoent, &ctl);
-
-	if (t == DIR_REC_PARENT) {
-		rr_parent = isoent->rr_parent;
-		pxent = isoent->parent;
-		if (rr_parent != NULL)
-			isoent = rr_parent;
-		else
-			isoent = isoent->parent;
-	} else {
-		rr_parent = NULL;
-		pxent = isoent;
-	}
-	file = isoent->file;
-
-	if (t != DIR_REC_NORMAL) {
-		rr_flag = RR_USE_PX | RR_USE_TF;
-		if (rr_parent != NULL)
-			rr_flag |= RR_USE_PL;
-	} else {
-		rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
-		if (archive_entry_filetype(file->entry) == AE_IFLNK)
-			rr_flag |= RR_USE_SL;
-		if (isoent->rr_parent != NULL)
-			rr_flag |= RR_USE_RE;
-		if (isoent->rr_child != NULL)
-			rr_flag |= RR_USE_CL;
-		if (archive_entry_filetype(file->entry) == AE_IFCHR ||
-		    archive_entry_filetype(file->entry) == AE_IFBLK)
-			rr_flag |= RR_USE_PN;
-#ifdef COMPAT_MKISOFS
-		/*
-		 * mkisofs 2.01.01a63 records "RE" extension to
-		 * the entry of "rr_moved" directory.
-		 * I don't understand this behavior.
-		 */
-		if (isoent->virtual &&
-		    isoent->parent == iso9660->primary.rootent &&
-		    strcmp(isoent->file->basename.s, "rr_moved") == 0)
-			rr_flag |= RR_USE_RE;
-#endif
-	}
-
-	/* Write "SP" System Use Entry. */
-	if (t == DIR_REC_SELF && isoent == isoent->parent) {
-		length = 7;
-		if (bp != NULL) {
-			bp[1] = 'S';
-			bp[2] = 'P';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			bp[5] = 0xBE;  /* Check Byte	*/
-			bp[6] = 0xEF;  /* Check Byte	*/
-			bp[7] = 0;
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "RR" System Use Entry. */
-	length = 5;
-	if (extra_space(&ctl) < length)
-		bp = extra_next_record(&ctl, length);
-	if (bp != NULL) {
-		bp[1] = 'R';
-		bp[2] = 'R';
-		bp[3] = length;
-		bp[4] = 1;	/* version */
-		bp[5] = rr_flag;
-		bp += length;
-	}
-	extra_tell_used_size(&ctl, length);
-
-	/* Write "NM" System Use Entry. */
-	if (rr_flag & RR_USE_NM) {
-		/*
-		 *   "NM" Format:
-		 *     e.g. a basename is 'foo'
-		 *               len  ver  flg
-		 *    +----+----+----+----+----+----+----+----+
-		 *    | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
-		 *    +----+----+----+----+----+----+----+----+
-		 *    <----------------- len ----------------->
-		 */
-		size_t nmlen = file->basename.length;
-		const char *nm = file->basename.s;
-		size_t nmmax;
-
-		if (extra_space(&ctl) < 6)
-			bp = extra_next_record(&ctl, 6);
-		if (bp != NULL) {
-			bp[1] = 'N';
-			bp[2] = 'M';
-			bp[4] = 1;	    /* version	*/
-		}
-		nmmax = extra_space(&ctl);
-		if (nmmax > 0xff)
-			nmmax = 0xff;
-		while (nmlen + 5 > nmmax) {
-			length = (int)nmmax;
-			if (bp != NULL) {
-				bp[3] = length;
-				bp[5] = 0x01;/* Alternate Name continues
-					       * in next "NM" field */
-				memcpy(bp+6, nm, length - 5);
-				bp += length;
-			}
-			nmlen -= length - 5;
-			nm += length - 5;
-			extra_tell_used_size(&ctl, length);
-			if (extra_space(&ctl) < 6) {
-				bp = extra_next_record(&ctl, 6);
-				nmmax = extra_space(&ctl);
-				if (nmmax > 0xff)
-					nmmax = 0xff;
-			}
-			if (bp != NULL) {
-				bp[1] = 'N';
-				bp[2] = 'M';
-				bp[4] = 1;    /* version */
-			}
-		}
-		length = 5 + (int)nmlen;
-		if (bp != NULL) {
-			bp[3] = length;
-			bp[5] = 0;
-			memcpy(bp+6, nm, nmlen);
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "PX" System Use Entry. */
-	if (rr_flag & RR_USE_PX) {
-		/*
-		 *   "PX" Format:
-		 *               len  ver
-		 *    +----+----+----+----+-----------+-----------+
-		 *    | 'P'| 'X'| 2C | 01 | FILE MODE |   LINKS   |
-		 *    +----+----+----+----+-----------+-----------+
-		 *    0    1    2    3    4          12          20
-		 *    +-----------+-----------+------------------+
-		 *    |  USER ID  | GROUP ID  |FILE SERIAL NUMBER|
-		 *    +-----------+-----------+------------------+
-		 *   20          28          36                 44
-		 */
-		length = 44;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			mode_t mode;
-			int64_t uid;
-			int64_t gid;
-
-			mode = archive_entry_mode(file->entry);
-			uid = archive_entry_uid(file->entry);
-			gid = archive_entry_gid(file->entry);
-			if (iso9660->opt.rr == OPT_RR_USEFUL) {
-				/*
-				 * This action is similar to mkisofs -r option
-				 * but our rockridge=useful option does not
-				 * set a zero to uid and gid.
-				 */
-				/* set all read bit ON */
-				mode |= 0444;
-#if !defined(_WIN32) && !defined(__CYGWIN__)
-				if (mode & 0111)
-#endif
-					/* set all exec bit ON */
-					mode |= 0111;
-				/* clear all write bits. */
-				mode &= ~0222;
-				/* clear setuid,setgid,sticky bits. */
-				mode &= ~07000;
-			}
-
-			bp[1] = 'P';
-			bp[2] = 'X';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			/* file mode */
-			set_num_733(bp+5, mode);
-			/* file links (stat.st_nlink) */
-			set_num_733(bp+13,
-			    archive_entry_nlink(file->entry));
-			set_num_733(bp+21, (uint32_t)uid);
-			set_num_733(bp+29, (uint32_t)gid);
-			/* File Serial Number */
-			if (pxent->dir)
-				set_num_733(bp+37, pxent->dir_location);
-			else if (file->hardlink_target != NULL)
-				set_num_733(bp+37,
-				    file->hardlink_target->cur_content->location);
-			else
-				set_num_733(bp+37,
-				    file->cur_content->location);
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "SL" System Use Entry. */
-	if (rr_flag & RR_USE_SL) {
-		/*
-		 *   "SL" Format:
-		 *     e.g. a symbolic name is 'foo/bar'
-		 *               len  ver  flg
-		 *    +----+----+----+----+----+------------+
-		 *    | 'S'| 'L'| 0F | 01 | 00 | components |
-		 *    +----+----+----+----+----+-----+------+
-		 *    0    1    2    3    4    5  ...|...  15
-		 *    <----------------- len --------+------>
-		 *    components :                   |
-		 *     cflg clen                     |
-		 *    +----+----+----+----+----+     |
-		 *    | 00 | 03 | 'f'| 'o'| 'o'| <---+
-		 *    +----+----+----+----+----+     |
-		 *    5    6    7    8    9   10     |
-		 *     cflg clen                     |
-		 *    +----+----+----+----+----+     |
-		 *    | 00 | 03 | 'b'| 'a'| 'r'| <---+
-		 *    +----+----+----+----+----+
-		 *   10   11   12   13   14   15
-		 *
-		 *    - cflg : flag of component
-		 *    - clen : length of component
-		 */
-		const char *sl;
-		char sl_last;
-
-		if (extra_space(&ctl) < 7)
-			bp = extra_next_record(&ctl, 7);
-		sl = file->symlink.s;
-		sl_last = '\0';
-		if (bp != NULL) {
-			bp[1] = 'S';
-			bp[2] = 'L';
-			bp[4] = 1;	/* version	*/
-		}
-		for (;;) {
-			unsigned char *nc, *cf,  *cl, cldmy = 0;
-			int sllen, slmax;
-
-			slmax = extra_space(&ctl);
-			if (slmax > 0xff)
-				slmax = 0xff;
-			if (bp != NULL)
-				nc = &bp[6];
-			else
-				nc = NULL;
-			cf = cl = NULL;
-			sllen = 0;
-			while (*sl && sllen + 11 < slmax) {
-				if (sl_last == '\0' && sl[0] == '/') {
-					/*
-					 *     flg  len
-					 *    +----+----+
-					 *    | 08 | 00 | ROOT component.
-					 *    +----+----+ ("/")
-					 *
-				 	 * Root component has to appear
-				 	 * at the first component only.
-					 */
-					if (nc != NULL) {
-						cf = nc++;
-						*cf = 0x08; /* ROOT */
-						*nc++ = 0;
-					}
-					sllen += 2;
-					sl++;
-					sl_last = '/';
-					cl = NULL;
-					continue;
-				}
-				if (((sl_last == '\0' || sl_last == '/') &&
-				      sl[0] == '.' && sl[1] == '.' &&
-				     (sl[2] == '/' || sl[2] == '\0')) ||
-				    (sl[0] == '/' &&
-				      sl[1] == '.' && sl[2] == '.' &&
-				     (sl[3] == '/' || sl[3] == '\0'))) {
-					/*
-					 *     flg  len
-					 *    +----+----+
-					 *    | 04 | 00 | PARENT component.
-					 *    +----+----+ ("..")
-					 */
-					if (nc != NULL) {
-						cf = nc++;
-						*cf = 0x04; /* PARENT */
-						*nc++ = 0;
-					}
-					sllen += 2;
-					if (sl[0] == '/')
-						sl += 3;/* skip "/.." */
-					else
-						sl += 2;/* skip ".." */
-					sl_last = '.';
-					cl = NULL;
-					continue;
-				}
-				if (((sl_last == '\0' || sl_last == '/') &&
-				      sl[0] == '.' &&
-				     (sl[1] == '/' || sl[1] == '\0')) ||
-				    (sl[0] == '/' && sl[1] == '.' &&
-				     (sl[2] == '/' || sl[2] == '\0'))) {
-					/*
-					 *     flg  len
-					 *    +----+----+
-					 *    | 02 | 00 | CURRENT component.
-					 *    +----+----+ (".")
-					 */
-					if (nc != NULL) {
-						cf = nc++;
-						*cf = 0x02; /* CURRENT */
-						*nc++ = 0;
-					}
-					sllen += 2;
-					if (sl[0] == '/')
-						sl += 2;/* skip "/." */
-					else
-						sl ++;  /* skip "." */
-					sl_last = '.';
-					cl = NULL;
-					continue;
-				}
-				if (sl[0] == '/' || cl == NULL) {
-					if (nc != NULL) {
-						cf = nc++;
-						*cf = 0;
-						cl = nc++;
-						*cl = 0;
-					} else
-						cl = &cldmy;
-					sllen += 2;
-					if (sl[0] == '/') {
-						sl_last = *sl++;
-						continue;
-					}
-				}
-				sl_last = *sl++;
-				if (nc != NULL) {
-					*nc++ = sl_last;
-					(*cl) ++;
-				}
-				sllen++;
-			}
-			if (*sl) {
-				length = 5 + sllen;
-				if (bp != NULL) {
-					/*
-					 * Mark flg as CONTINUE component.
-					 */
-					*cf |= 0x01;
-					/*
-					 *               len  ver  flg
-					 *    +----+----+----+----+----+-
-					 *    | 'S'| 'L'| XX | 01 | 01 |
-					 *    +----+----+----+----+----+-
-					 *                           ^
-					 *           continues in next "SL"
-					 */
-					bp[3] = length;
-					bp[5] = 0x01;/* This Symbolic Link
-						      * continues in next
-						      * "SL" field */
-					bp += length;
-				}
-				extra_tell_used_size(&ctl, length);
-				if (extra_space(&ctl) < 11)
-					bp = extra_next_record(&ctl, 11);
-				if (bp != NULL) {
-					/* Next 'SL' */
-					bp[1] = 'S';
-					bp[2] = 'L';
-					bp[4] = 1;    /* version */
-				}
-			} else {
-				length = 5 + sllen;
-				if (bp != NULL) {
-					bp[3] = length;
-					bp[5] = 0;
-					bp += length;
-				}
-				extra_tell_used_size(&ctl, length);
-				break;
-			}
-		}
-	}
-
-	/* Write "TF" System Use Entry. */
-	if (rr_flag & RR_USE_TF) {
-		/*
-		 *   "TF" Format:
-		 *               len  ver
-		 *    +----+----+----+----+-----+-------------+
-		 *    | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
-		 *    +----+----+----+----+-----+-------------+
-		 *    0    1    2    3    4     5            XX
-		 *    TIME STAMPS : ISO 9660 Standard 9.1.5.
-		 *                  If TF_LONG_FORM FLAGS is set,
-		 *                  use ISO9660 Standard 8.4.26.1.
-		 */
-#define TF_CREATION	0x01	/* Creation time recorded		*/
-#define TF_MODIFY	0x02	/* Modification time recorded		*/
-#define TF_ACCESS	0x04	/* Last Access time recorded		*/
-#define TF_ATTRIBUTES	0x08	/* Last Attribute Change time recorded  */
-#define TF_BACKUP	0x10	/* Last Backup time recorded		*/
-#define TF_EXPIRATION	0x20	/* Expiration time recorded		*/
-#define TF_EFFECTIVE	0x40	/* Effective time recorded		*/
-#define TF_LONG_FORM	0x80	/* ISO 9660 17-byte time format used	*/
-		unsigned char tf_flags;
-
-		length = 5;
-		tf_flags = 0;
-#ifndef COMPAT_MKISOFS
-		if (archive_entry_birthtime_is_set(file->entry) &&
-		    archive_entry_birthtime(file->entry) <=
-		    archive_entry_mtime(file->entry)) {
-			length += 7;
-			tf_flags |= TF_CREATION;
-		}
-#endif
-		if (archive_entry_mtime_is_set(file->entry)) {
-			length += 7;
-			tf_flags |= TF_MODIFY;
-		}
-		if (archive_entry_atime_is_set(file->entry)) {
-			length += 7;
-			tf_flags |= TF_ACCESS;
-		}
-		if (archive_entry_ctime_is_set(file->entry)) {
-			length += 7;
-			tf_flags |= TF_ATTRIBUTES;
-		}
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			bp[1] = 'T';
-			bp[2] = 'F';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			bp[5] = tf_flags;
-			bp += 5;
-			/* Creation time */
-			if (tf_flags & TF_CREATION) {
-				set_time_915(bp+1,
-				    archive_entry_birthtime(file->entry));
-				bp += 7;
-			}
-			/* Modification time */
-			if (tf_flags & TF_MODIFY) {
-				set_time_915(bp+1,
-				    archive_entry_mtime(file->entry));
-				bp += 7;
-			}
-			/* Last Access time */
-			if (tf_flags & TF_ACCESS) {
-				set_time_915(bp+1,
-				    archive_entry_atime(file->entry));
-				bp += 7;
-			}
-			/* Last Attribute Change time */
-			if (tf_flags & TF_ATTRIBUTES) {
-				set_time_915(bp+1,
-				    archive_entry_ctime(file->entry));
-				bp += 7;
-			}
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "RE" System Use Entry. */
-	if (rr_flag & RR_USE_RE) {
-		/*
-		 *   "RE" Format:
-		 *               len  ver
-		 *    +----+----+----+----+
-		 *    | 'R'| 'E'| 04 | 01 |
-		 *    +----+----+----+----+
-		 *    0    1    2    3    4
-		 */
-		length = 4;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			bp[1] = 'R';
-			bp[2] = 'E';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "PL" System Use Entry. */
-	if (rr_flag & RR_USE_PL) {
-		/*
-		 *   "PL" Format:
-		 *               len  ver
-		 *    +----+----+----+----+------------+
-		 *    | 'P'| 'L'| 0C | 01 | *LOCATION  |
-		 *    +----+----+----+----+------------+
-		 *    0    1    2    3    4           12
-		 *    *LOCATION: location of parent directory
-		 */
-		length = 12;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			bp[1] = 'P';
-			bp[2] = 'L';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			set_num_733(bp + 5,
-			    rr_parent->dir_location);
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "CL" System Use Entry. */
-	if (rr_flag & RR_USE_CL) {
-		/*
-		 *   "CL" Format:
-		 *               len  ver
-		 *    +----+----+----+----+------------+
-		 *    | 'C'| 'L'| 0C | 01 | *LOCATION  |
-		 *    +----+----+----+----+------------+
-		 *    0    1    2    3    4           12
-		 *    *LOCATION: location of child directory
-		 */
-		length = 12;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			bp[1] = 'C';
-			bp[2] = 'L';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			set_num_733(bp + 5,
-			    isoent->rr_child->dir_location);
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "PN" System Use Entry. */
-	if (rr_flag & RR_USE_PN) {
-		/*
-		 *   "PN" Format:
-		 *               len  ver
-		 *    +----+----+----+----+------------+------------+
-		 *    | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low  |
-		 *    +----+----+----+----+------------+------------+
-		 *    0    1    2    3    4           12           20
-		 */
-		length = 20;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			uint64_t dev;
-
-			bp[1] = 'P';
-			bp[2] = 'N';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			dev = (uint64_t)archive_entry_rdev(file->entry);
-			set_num_733(bp + 5, (uint32_t)(dev >> 32));
-			set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "ZF" System Use Entry. */
-	if (file->zisofs.header_size) {
-		/*
-		 *   "ZF" Format:
-		 *               len  ver
-		 *    +----+----+----+----+----+----+-------------+
-		 *    | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
-		 *    +----+----+----+----+----+----+-------------+
-		 *    0    1    2    3    4    5    6             7
-		 *    +--------------------+-------------------+
-		 *    | Log2 of block Size | Uncompressed Size |
-		 *    +--------------------+-------------------+
-		 *    7                    8                   16
-		 */
-		length = 16;
-		if (extra_space(&ctl) < length)
-			bp = extra_next_record(&ctl, length);
-		if (bp != NULL) {
-			bp[1] = 'Z';
-			bp[2] = 'F';
-			bp[3] = length;
-			bp[4] = 1;	/* version	*/
-			bp[5] = 'p';
-			bp[6] = 'z';
-			bp[7] = file->zisofs.header_size;
-			bp[8] = file->zisofs.log2_bs;
-			set_num_733(bp + 9, file->zisofs.uncompressed_size);
-			bp += length;
-		}
-		extra_tell_used_size(&ctl, length);
-	}
-
-	/* Write "CE" System Use Entry. */
-	if (t == DIR_REC_SELF && isoent == isoent->parent) {
-		length = RR_CE_SIZE;
-		if (bp != NULL)
-			set_SUSP_CE(bp+1, iso9660->location_rrip_er,
-			    0, RRIP_ER_SIZE);
-		extra_tell_used_size(&ctl, length);
-	}
-
-	extra_close_record(&ctl, 0);
-
-	return (ctl.dr_len);
-}
-
-/*
- * Write data of a Directory Record or calculate writing bytes itself.
- * If parameter `p' is NULL, calculates the size of writing data, which
- * a Directory Record needs to write, then it saved and return
- * the calculated size.
- * Parameter `n' is a remaining size of buffer. when parameter `p' is
- * not NULL, check whether that `n' is not less than the saved size.
- * if that `n' is small, return zero.
- *
- * This format of the Directory Record is according to
- * ISO9660 Standard 9.1
- */
-static int
-set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
-    struct iso9660 *iso9660, enum dir_rec_type t,
-    enum vdd_type vdd_type)
-{
-	unsigned char *bp;
-	size_t dr_len;
-	size_t fi_len;
-
-	if (p != NULL) {
-		/*
-		 * Check whether a write buffer size is less than the
-		 * saved size which is needed to write this Directory
-		 * Record.
-		 */
-		switch (t) {
-		case DIR_REC_VD:
-			dr_len = isoent->dr_len.vd; break;
-		case DIR_REC_SELF:
-			dr_len = isoent->dr_len.self; break;
-		case DIR_REC_PARENT:
-			dr_len = isoent->dr_len.parent; break;
-		case DIR_REC_NORMAL:
-		default:
-			dr_len = isoent->dr_len.normal; break;
-		}
-		if (dr_len > n)
-			return (0);/* Needs more buffer size. */
-	}
-
-	if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
-		fi_len = isoent->id_len;
-	else
-		fi_len = 1;
-
-	if (p != NULL) {
-		struct isoent *xisoent;
-		struct isofile *file;
-		unsigned char flag;
-
-		if (t == DIR_REC_PARENT)
-			xisoent = isoent->parent;
-		else
-			xisoent = isoent;
-		file = isoent->file;
-		if (file->hardlink_target != NULL)
-			file = file->hardlink_target;
-		/* Make a file flag. */
-		if (xisoent->dir)
-			flag = FILE_FLAG_DIRECTORY;
-		else {
-			if (file->cur_content->next != NULL)
-				flag = FILE_FLAG_MULTI_EXTENT;
-			else
-				flag = 0;
-		}
-
-		bp = p -1;
-		/* Extended Attribute Record Length */
-		set_num_711(bp+2, 0);
-		/* Location of Extent */
-		if (xisoent->dir)
-			set_num_733(bp+3, xisoent->dir_location);
-		else
-			set_num_733(bp+3, file->cur_content->location);
-		/* Data Length */
-		if (xisoent->dir)
-			set_num_733(bp+11,
-			    xisoent->dir_block * LOGICAL_BLOCK_SIZE);
-		else
-			set_num_733(bp+11, (uint32_t)file->cur_content->size);
-		/* Recording Date and Time */
-		/* NOTE:
-		 *  If a file type is symbolic link, you are seeing this
-		 *  field value is different from a value mkisofs makes.
-		 *  libarchive uses lstat to get this one, but it
-		 *  seems mkisofs uses stat to get.
-		 */
-		set_time_915(bp+19,
-		    archive_entry_mtime(xisoent->file->entry));
-		/* File Flags */
-		bp[26] = flag;
-		/* File Unit Size */
-		set_num_711(bp+27, 0);
-		/* Interleave Gap Size */
-		set_num_711(bp+28, 0);
-		/* Volume Sequence Number */
-		set_num_723(bp+29, iso9660->volume_sequence_number);
-		/* Length of File Identifier */
-		set_num_711(bp+33, (unsigned char)fi_len);
-		/* File Identifier */
-		switch (t) {
-		case DIR_REC_VD:
-		case DIR_REC_SELF:
-			set_num_711(bp+34, 0);
-			break;
-		case DIR_REC_PARENT:
-			set_num_711(bp+34, 1);
-			break;
-		case DIR_REC_NORMAL:
-			if (isoent->identifier != NULL)
-				memcpy(bp+34, isoent->identifier, fi_len);
-			else
-				set_num_711(bp+34, 0);
-			break;
-		}
-	} else
-		bp = NULL;
-	dr_len = 33 + fi_len;
-	/* Padding Field */
-	if (dr_len & 0x01) {
-		dr_len ++;
-		if (p != NULL)
-			bp[dr_len] = 0;
-	}
-
-	/* Volume Descriptor does not record extension. */
-	if (t == DIR_REC_VD) {
-		if (p != NULL)
-			/* Length of Directory Record */
-			set_num_711(p, (unsigned char)dr_len);
-		else
-			isoent->dr_len.vd = (int)dr_len;
-		return ((int)dr_len);
-	}
-
-	/* Rockridge */
-	if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
-		dr_len = set_directory_record_rr(bp, (int)dr_len,
-		    isoent, iso9660, t);
-
-	if (p != NULL)
-		/* Length of Directory Record */
-		set_num_711(p, (unsigned char)dr_len);
-	else {
-		/*
-		 * Save the size which is needed to write this
-		 * Directory Record.
-		 */
-		switch (t) {
-		case DIR_REC_VD:
-			/* This case does not come, but compiler
-			 * complains that DIR_REC_VD not handled
-			 *  in switch ....  */
-			break;
-		case DIR_REC_SELF:
-			isoent->dr_len.self = (int)dr_len; break;
-		case DIR_REC_PARENT:
-			isoent->dr_len.parent = (int)dr_len; break;
-		case DIR_REC_NORMAL:
-			isoent->dr_len.normal = (int)dr_len; break;
-		}
-	}
-
-	return ((int)dr_len);
-}
-
-/*
- * Calculate the size of a directory record.
- */
-static inline int
-get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
-    enum dir_rec_type t, enum vdd_type vdd_type)
-{
-
-	return (set_directory_record(NULL, SIZE_MAX,
-	    isoent, iso9660, t, vdd_type));
-}
-
-/*
- * Manage to write ISO-image data with wbuff to reduce calling
- * __archive_write_output() for performance.
- */
-
-
-static inline unsigned char *
-wb_buffptr(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
-
-	return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
-		- iso9660->wbuff_remaining]));
-}
-
-static int
-wb_write_out(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
-	size_t wsize, nw;
-	int r;
-
-	wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
-	nw = wsize % LOGICAL_BLOCK_SIZE;
-	if (iso9660->wbuff_type == WB_TO_STREAM)
-		r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
-	else
-		r = write_to_temp(a, iso9660->wbuff, wsize - nw);
-	/* Increase the offset. */
-	iso9660->wbuff_offset += wsize - nw;
-	if (iso9660->wbuff_offset > iso9660->wbuff_written)
-		iso9660->wbuff_written = iso9660->wbuff_offset;
-	iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
-	if (nw) {
-		iso9660->wbuff_remaining -= nw;
-		memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
-	}
-	return (r);
-}
-
-static int
-wb_consume(struct archive_write *a, size_t size)
-{
-	struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
-
-	if (size > iso9660->wbuff_remaining ||
-	    iso9660->wbuff_remaining == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal Programming error: iso9660:wb_consume()"
-		    " size=%jd, wbuff_remaining=%jd",
-		    (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->wbuff_remaining -= size;
-	if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
-		return (wb_write_out(a));
-	return (ARCHIVE_OK);
-}
-
-#ifdef HAVE_ZLIB_H
-
-static int
-wb_set_offset(struct archive_write *a, int64_t off)
-{
-	struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
-	int64_t used, ext_bytes;
-
-	if (iso9660->wbuff_type != WB_TO_TEMP) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal Programming error: iso9660:wb_set_offset()");
-		return (ARCHIVE_FATAL);
-	}
-
-	used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
-	if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
-		iso9660->wbuff_tail = iso9660->wbuff_offset + used;
-	if (iso9660->wbuff_offset < iso9660->wbuff_written) {
-		if (used > 0 &&
-		    write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		iso9660->wbuff_offset = iso9660->wbuff_written;
-		lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
-		iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
-		used = 0;
-	}
-	if (off < iso9660->wbuff_offset) {
-		/*
-		 * Write out waiting data.
-		 */
-		if (used > 0) {
-			if (wb_write_out(a) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		}
-		lseek(iso9660->temp_fd, off, SEEK_SET);
-		iso9660->wbuff_offset = off;
-		iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
-	} else if (off <= iso9660->wbuff_tail) {
-		iso9660->wbuff_remaining = (size_t)
-		    (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
-	} else {
-		ext_bytes = off - iso9660->wbuff_tail;
-		iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
-		   - (iso9660->wbuff_tail - iso9660->wbuff_offset));
-		while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
-			if (write_null(a, (size_t)iso9660->wbuff_remaining)
-			    != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			ext_bytes -= iso9660->wbuff_remaining;
-		}
-		if (ext_bytes > 0) {
-			if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_ZLIB_H */
-
-static int
-write_null(struct archive_write *a, size_t size)
-{
-	size_t remaining;
-	unsigned char *p, *old;
-	int r;
-
-	remaining = wb_remaining(a);
-	p = wb_buffptr(a);
-	if (size <= remaining) {
-		memset(p, 0, size);
-		return (wb_consume(a, size));
-	}
-	memset(p, 0, remaining);
-	r = wb_consume(a, remaining);
-	if (r != ARCHIVE_OK)
-		return (r);
-	size -= remaining;
-	old = p;
-	p = wb_buffptr(a);
-	memset(p, 0, old - p);
-	remaining = wb_remaining(a);
-	while (size) {
-		size_t wsize = size;
-
-		if (wsize > remaining)
-			wsize = remaining;
-		r = wb_consume(a, wsize);
-		if (r != ARCHIVE_OK)
-			return (r);
-		size -= wsize;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Write Volume Descriptor Set Terminator
- */
-static int
-write_VD_terminator(struct archive_write *a)
-{
-	unsigned char *bp;
-
-	bp = wb_buffptr(a) -1;
-	set_VD_bp(bp, VDT_TERMINATOR, 1);
-	set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
-
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-static int
-set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
-    struct archive_write *a, struct vdd *vdd, struct archive_string *id,
-    const char *label, int leading_under, enum char_type char_type)
-{
-	char identifier[256];
-	struct isoent *isoent;
-	const char *ids;
-	size_t len;
-	int r;
-
-	if (id->length > 0 && leading_under && id->s[0] != '_') {
-		if (char_type == A_CHAR)
-			r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
-		else
-			r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
-	} else if (id->length > 0) {
-		ids = id->s;
-		if (leading_under)
-			ids++;
-		isoent = isoent_find_entry(vdd->rootent, ids);
-		if (isoent == NULL) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Not Found %s `%s'.",
-			    label, ids);
-			return (ARCHIVE_FATAL);
-		}
-		len = isoent->ext_off + isoent->ext_len;
-		if (vdd->vdd_type == VDD_JOLIET) {
-			if (len > sizeof(identifier)-2)
-				len = sizeof(identifier)-2;
-		} else {
-			if (len > sizeof(identifier)-1)
-				len = sizeof(identifier)-1;
-		}
-		memcpy(identifier, isoent->identifier, len);
-		identifier[len] = '\0';
-		if (vdd->vdd_type == VDD_JOLIET) {
-			identifier[len+1] = 0;
-			vdc = VDC_UCS2_DIRECT;
-		}
-		if (char_type == A_CHAR)
-			r = set_str_a_characters_bp(a, bp, from, to,
-			    identifier, vdc);
-		else
-			r = set_str_d_characters_bp(a, bp, from, to,
-			    identifier, vdc);
-	} else {
-		if (char_type == A_CHAR)
-			r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
-		else
-			r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
-	}
-	return (r);
-}
-
-/*
- * Write Primary/Supplementary Volume Descriptor
- */
-static int
-write_VD(struct archive_write *a, struct vdd *vdd)
-{
-	struct iso9660 *iso9660;
-	unsigned char *bp;
-	uint16_t volume_set_size = 1;
-	char identifier[256];
-	enum VD_type vdt;
-	enum vdc vdc;
-	unsigned char vd_ver, fst_ver;
-	int r;
-
-	iso9660 = a->format_data;
-	switch (vdd->vdd_type) {
-	case VDD_JOLIET:
-		vdt = VDT_SUPPLEMENTARY;
-		vd_ver = fst_ver = 1;
-		vdc = VDC_UCS2;
-		break;
-	case VDD_ENHANCED:
-		vdt = VDT_SUPPLEMENTARY;
-		vd_ver = fst_ver = 2;
-		vdc = VDC_LOWERCASE;
-		break;
-	case VDD_PRIMARY:
-	default:
-		vdt = VDT_PRIMARY;
-		vd_ver = fst_ver = 1;
-#ifdef COMPAT_MKISOFS
-		vdc = VDC_LOWERCASE;
-#else
-		vdc = VDC_STD;
-#endif
-		break;
-	}
-
-	bp = wb_buffptr(a) -1;
-	/* Volume Descriptor Type */
-	set_VD_bp(bp, vdt, vd_ver);
-	/* Unused Field */
-	set_unused_field_bp(bp, 8, 8);
-	/* System Identifier */
-	get_system_identitier(identifier, sizeof(identifier));
-	r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Volume Identifier */
-	r = set_str_d_characters_bp(a, bp, 41, 72,
-	    iso9660->volume_identifier.s, vdc);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Unused Field */
-	set_unused_field_bp(bp, 73, 80);
-	/* Volume Space Size */
-	set_num_733(bp+81, iso9660->volume_space_size);
-	if (vdd->vdd_type == VDD_JOLIET) {
-		/* Escape Sequences */
-		bp[89] = 0x25;/* UCS-2 Level 3 */
-		bp[90] = 0x2F;
-		bp[91] = 0x45;
-		memset(bp + 92, 0, 120 - 92 + 1);
-	} else {
-		/* Unused Field */
-		set_unused_field_bp(bp, 89, 120);
-	}
-	/* Volume Set Size */
-	set_num_723(bp+121, volume_set_size);
-	/* Volume Sequence Number */
-	set_num_723(bp+125, iso9660->volume_sequence_number);
-	/* Logical Block Size */
-	set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
-	/* Path Table Size */
-	set_num_733(bp+133, vdd->path_table_size);
-	/* Location of Occurrence of Type L Path Table */
-	set_num_731(bp+141, vdd->location_type_L_path_table);
-	/* Location of Optional Occurrence of Type L Path Table */
-	set_num_731(bp+145, 0);
-	/* Location of Occurrence of Type M Path Table */
-	set_num_732(bp+149, vdd->location_type_M_path_table);
-	/* Location of Optional Occurrence of Type M Path Table */
-	set_num_732(bp+153, 0);
-	/* Directory Record for Root Directory(BP 157 to 190) */
-	set_directory_record(bp+157, 190-157+1, vdd->rootent,
-	    iso9660, DIR_REC_VD, vdd->vdd_type);
-	/* Volume Set Identifier */
-	r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Publisher Identifier */
-	r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
-	    &(iso9660->publisher_identifier),
-	    "Publisher File", 1, A_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Data Preparer Identifier */
-	r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
-	    &(iso9660->data_preparer_identifier),
-	    "Data Preparer File", 1, A_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Application Identifier */
-	r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
-	    &(iso9660->application_identifier),
-	    "Application File", 1, A_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Copyright File Identifier */
-	r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
-	    &(iso9660->copyright_file_identifier),
-	    "Copyright File", 0, D_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Abstract File Identifier */
-	r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
-	    &(iso9660->abstract_file_identifier),
-	    "Abstract File", 0, D_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Bibliographic File Identifier */
-	r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
-	    &(iso9660->bibliographic_file_identifier),
-	    "Bibliongraphic File", 0, D_CHAR);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* Volume Creation Date and Time */
-	set_date_time(bp+814, iso9660->birth_time);
-	/* Volume Modification Date and Time */
-	set_date_time(bp+831, iso9660->birth_time);
-	/* Volume Expiration Date and Time(obsolete) */
-	set_date_time_null(bp+848);
-	/* Volume Effective Date and Time */
-	set_date_time(bp+865, iso9660->birth_time);
-	/* File Structure Version */
-	bp[882] = fst_ver;
-	/* Reserved */
-	bp[883] = 0;
-	/* Application Use */
-	memset(bp + 884, 0x20, 1395 - 884 + 1);
-	/* Reserved */
-	set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
-
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-/*
- * Write Boot Record Volume Descriptor
- */
-static int
-write_VD_boot_record(struct archive_write *a)
-{
-	struct iso9660 *iso9660;
-	unsigned char *bp;
-
-	iso9660 = a->format_data;
-	bp = wb_buffptr(a) -1;
-	/* Volume Descriptor Type */
-	set_VD_bp(bp, VDT_BOOT_RECORD, 1);
-	/* Boot System Identifier */
-	memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
-	set_unused_field_bp(bp, 8+23, 39);
-	/* Unused */
-	set_unused_field_bp(bp, 40, 71);
-	/* Absolute pointer to first sector of Boot Catalog */
-	set_num_731(bp+72,
-	    iso9660->el_torito.catalog->file->content.location);
-	/* Unused */
-	set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
-
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-enum keytype {
-	KEY_FLG,
-	KEY_STR,
-	KEY_INT,
-	KEY_HEX
-};
-static void
-set_option_info(struct archive_string *info, int *opt, const char *key,
-    enum keytype type,  ...)
-{
-	va_list ap;
-	char prefix;
-	const char *s;
-	int d;
-
-	prefix = (*opt==0)? ' ':',';
-	va_start(ap, type);
-	switch (type) {
-	case KEY_FLG:
-		d = va_arg(ap, int);
-		archive_string_sprintf(info, "%c%s%s",
-		    prefix, (d == 0)?"!":"", key);
-		break;
-	case KEY_STR:
-		s = va_arg(ap, const char *);
-		archive_string_sprintf(info, "%c%s=%s",
-		    prefix, key, s);
-		break;
-	case KEY_INT:
-		d = va_arg(ap, int);
-		archive_string_sprintf(info, "%c%s=%d",
-		    prefix, key, d);
-		break;
-	case KEY_HEX:
-		d = va_arg(ap, int);
-		archive_string_sprintf(info, "%c%s=%x",
-		    prefix, key, d);
-		break;
-	}
-	va_end(ap);
-
-	*opt = 1;
-}
-
-/*
- * Make Non-ISO File System Information
- */
-static int
-write_information_block(struct archive_write *a)
-{
-	struct iso9660 *iso9660;
-	char buf[128];
-	const char *v;
-	int opt, r;
-	struct archive_string info;
-	size_t info_size = LOGICAL_BLOCK_SIZE *
-			       NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
-
-	iso9660 = (struct iso9660 *)a->format_data;
-	if (info_size > wb_remaining(a)) {
-		r = wb_write_out(a);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-	archive_string_init(&info);
-	if (archive_string_ensure(&info, info_size) == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	memset(info.s, 0, info_size);
-	opt = 0;
-#if defined(HAVE_CTIME_S)
-	ctime_s(buf, sizeof(buf), &(iso9660->birth_time));
-#elif defined(HAVE_CTIME_R)
-	ctime_r(&(iso9660->birth_time), buf);
-#else
-	strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
-	buf[sizeof(buf)-1] = '\0';
-#endif
-	archive_string_sprintf(&info,
-	    "INFO %s%s", buf, archive_version_string());
-	if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
-		set_option_info(&info, &opt, "abstract-file",
-		    KEY_STR, iso9660->abstract_file_identifier.s);
-	if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
-		set_option_info(&info, &opt, "application-id",
-		    KEY_STR, iso9660->application_identifier.s);
-	if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
-		set_option_info(&info, &opt, "allow-vernum",
-		    KEY_FLG, iso9660->opt.allow_vernum);
-	if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
-		set_option_info(&info, &opt, "biblio-file",
-		    KEY_STR, iso9660->bibliographic_file_identifier.s);
-	if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
-		set_option_info(&info, &opt, "boot",
-		    KEY_STR, iso9660->el_torito.boot_filename.s);
-	if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
-		set_option_info(&info, &opt, "boot-catalog",
-		    KEY_STR, iso9660->el_torito.catalog_filename.s);
-	if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
-		set_option_info(&info, &opt, "boot-info-table",
-		    KEY_FLG, iso9660->opt.boot_info_table);
-	if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
-		set_option_info(&info, &opt, "boot-load-seg",
-		    KEY_HEX, iso9660->el_torito.boot_load_seg);
-	if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
-		set_option_info(&info, &opt, "boot-load-size",
-		    KEY_INT, iso9660->el_torito.boot_load_size);
-	if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
-		v = "no-emulation";
-		if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
-			v = "fd";
-		if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
-			v = "hard-disk";
-		set_option_info(&info, &opt, "boot-type",
-		    KEY_STR, v);
-	}
-#ifdef HAVE_ZLIB_H
-	if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
-		set_option_info(&info, &opt, "compression-level",
-		    KEY_INT, iso9660->zisofs.compression_level);
-#endif
-	if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
-		set_option_info(&info, &opt, "copyright-file",
-		    KEY_STR, iso9660->copyright_file_identifier.s);
-	if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
-		set_option_info(&info, &opt, "iso-level",
-		    KEY_INT, iso9660->opt.iso_level);
-	if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
-		if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
-			set_option_info(&info, &opt, "joliet",
-			    KEY_STR, "long");
-		else
-			set_option_info(&info, &opt, "joliet",
-			    KEY_FLG, iso9660->opt.joliet);
-	}
-	if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
-		set_option_info(&info, &opt, "limit-depth",
-		    KEY_FLG, iso9660->opt.limit_depth);
-	if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
-		set_option_info(&info, &opt, "limit-dirs",
-		    KEY_FLG, iso9660->opt.limit_dirs);
-	if (iso9660->opt.pad != OPT_PAD_DEFAULT)
-		set_option_info(&info, &opt, "pad",
-		    KEY_FLG, iso9660->opt.pad);
-	if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
-		set_option_info(&info, &opt, "publisher",
-		    KEY_STR, iso9660->publisher_identifier.s);
-	if (iso9660->opt.rr != OPT_RR_DEFAULT) {
-		if (iso9660->opt.rr == OPT_RR_DISABLED)
-			set_option_info(&info, &opt, "rockridge",
-			    KEY_FLG, iso9660->opt.rr);
-		else if (iso9660->opt.rr == OPT_RR_STRICT)
-			set_option_info(&info, &opt, "rockridge",
-			    KEY_STR, "strict");
-		else if (iso9660->opt.rr == OPT_RR_USEFUL)
-			set_option_info(&info, &opt, "rockridge",
-			    KEY_STR, "useful");
-	}
-	if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
-		set_option_info(&info, &opt, "volume-id",
-		    KEY_STR, iso9660->volume_identifier.s);
-	if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
-		set_option_info(&info, &opt, "zisofs",
-		    KEY_FLG, iso9660->opt.zisofs);
-
-	memcpy(wb_buffptr(a), info.s, info_size);
-	archive_string_free(&info);
-	return (wb_consume(a, info_size));
-}
-
-static int
-write_rr_ER(struct archive_write *a)
-{
-	unsigned char *p;
-
-	p = wb_buffptr(a);
-
-	memset(p, 0, LOGICAL_BLOCK_SIZE);
-	p[0] = 'E';
-	p[1] = 'R';
-	p[3] = 0x01;
-	p[2] = RRIP_ER_SIZE;
-	p[4] = RRIP_ER_ID_SIZE;
-	p[5] = RRIP_ER_DSC_SIZE;
-	p[6] = RRIP_ER_SRC_SIZE;
-	p[7] = 0x01;
-	memcpy(&p[8], rrip_identifier, p[4]);
-	memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
-	memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
-
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-static void
-calculate_path_table_size(struct vdd *vdd)
-{
-	int depth, size;
-	struct path_table *pt;
-
-	pt = vdd->pathtbl;
-	size = 0;
-	for (depth = 0; depth < vdd->max_depth; depth++) {
-		struct isoent **ptbl;
-		int i, cnt;
-
-		if ((cnt = pt[depth].cnt) == 0)
-			break;
-
-		ptbl = pt[depth].sorted;
-		for (i = 0; i < cnt; i++) {
-			int len;
-
-			if (ptbl[i]->identifier == NULL)
-				len = 1; /* root directory */
-			else
-				len = ptbl[i]->id_len;
-			if (len & 0x01)
-				len++; /* Padding Field */
-			size += 8 + len;
-		}
-	}
-	vdd->path_table_size = size;
-	vdd->path_table_block =
-	    ((size + PATH_TABLE_BLOCK_SIZE -1) /
-	    PATH_TABLE_BLOCK_SIZE) *
-	    (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
-}
-
-static int
-_write_path_table(struct archive_write *a, int type_m, int depth,
-    struct vdd *vdd)
-{
-	unsigned char *bp, *wb;
-	struct isoent **ptbl;
-	size_t wbremaining;
-	int i, r, wsize;
-
-	if (vdd->pathtbl[depth].cnt == 0)
-		return (0);
-
-	wsize = 0;
-	wb = wb_buffptr(a);
-	wbremaining = wb_remaining(a);
-	bp = wb - 1;
-	ptbl = vdd->pathtbl[depth].sorted;
-	for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
-		struct isoent *np;
-		size_t len;
-
-		np = ptbl[i];
-		if (np->identifier == NULL)
-			len = 1; /* root directory */
-		else
-			len = np->id_len;
-		if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
-			r = wb_consume(a, (bp+1) - wb);
-			if (r < 0)
-				return (r);
-			wb = wb_buffptr(a);
-			wbremaining = wb_remaining(a);
-			bp = wb -1;
-		}
-		/* Length of Directory Identifier */
-		set_num_711(bp+1, (unsigned char)len);
-		/* Extended Attribute Record Length */
-		set_num_711(bp+2, 0);
-		/* Location of Extent */
-		if (type_m)
-			set_num_732(bp+3, np->dir_location);
-		else
-			set_num_731(bp+3, np->dir_location);
-		/* Parent Directory Number */
-		if (type_m)
-			set_num_722(bp+7, np->parent->dir_number);
-		else
-			set_num_721(bp+7, np->parent->dir_number);
-		/* Directory Identifier */
-		if (np->identifier == NULL)
-			bp[9] = 0;
-		else
-			memcpy(&bp[9], np->identifier, len);
-		if (len & 0x01) {
-			/* Padding Field */
-			bp[9+len] = 0;
-			len++;
-		}
-		wsize += 8 + (int)len;
-		bp += 8 + len;
-	}
-	if ((bp + 1) > wb) {
-		r = wb_consume(a, (bp+1)-wb);
-		if (r < 0)
-			return (r);
-	}
-	return (wsize);
-}
-
-static int
-write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
-{
-	int depth, r;
-	size_t path_table_size;
-
-	r = ARCHIVE_OK;
-	path_table_size = 0;
-	for (depth = 0; depth < vdd->max_depth; depth++) {
-		r = _write_path_table(a, type_m, depth, vdd);
-		if (r < 0)
-			return (r);
-		path_table_size += r;
-	}
-
-	/* Write padding data. */
-	path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
-	if (path_table_size > 0)
-		r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
-	return (r);
-}
-
-static int
-calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
-    struct isoent *isoent, int depth)
-{
-	struct isoent **enttbl;
-	int bs, block, i;
-
-	block = 1;
-	bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
-	bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
-
-	if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
-	    !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
-		return (block);
-
-	enttbl = isoent->children_sorted;
-	for (i = 0; i < isoent->children.cnt; i++) {
-		struct isoent *np = enttbl[i];
-		struct isofile *file;
-
-		file = np->file;
-		if (file->hardlink_target != NULL)
-			file = file->hardlink_target;
-		file->cur_content = &(file->content);
-		do {
-			int dr_l;
-
-			dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
-			    vdd->vdd_type);
-			if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
-				block ++;
-				bs = dr_l;
-			} else
-				bs += dr_l;
-			file->cur_content = file->cur_content->next;
-		} while (file->cur_content != NULL);
-	}
-	return (block);
-}
-
-static int
-_write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
-    struct isoent *isoent, int depth)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isoent **enttbl;
-	unsigned char *p, *wb;
-	int i, r;
-	int dr_l;
-
-	p = wb = wb_buffptr(a);
-#define WD_REMAINING	(LOGICAL_BLOCK_SIZE - (p - wb))
-	p += set_directory_record(p, WD_REMAINING, isoent,
-	    iso9660, DIR_REC_SELF, vdd->vdd_type);
-	p += set_directory_record(p, WD_REMAINING, isoent,
-	    iso9660, DIR_REC_PARENT, vdd->vdd_type);
-
-	if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
-	    !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
-		memset(p, 0, WD_REMAINING);
-		return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-	}
-
-	enttbl = isoent->children_sorted;
-	for (i = 0; i < isoent->children.cnt; i++) {
-		struct isoent *np = enttbl[i];
-		struct isofile *file = np->file;
-
-		if (file->hardlink_target != NULL)
-			file = file->hardlink_target;
-		file->cur_content = &(file->content);
-		do {
-			dr_l = set_directory_record(p, WD_REMAINING,
-			    np, iso9660, DIR_REC_NORMAL,
-			    vdd->vdd_type);
-			if (dr_l == 0) {
-				memset(p, 0, WD_REMAINING);
-				r = wb_consume(a, LOGICAL_BLOCK_SIZE);
-				if (r < 0)
-					return (r);
-				p = wb = wb_buffptr(a);
-				dr_l = set_directory_record(p,
-				    WD_REMAINING, np, iso9660,
-				    DIR_REC_NORMAL, vdd->vdd_type);
-			}
-			p += dr_l;
-			file->cur_content = file->cur_content->next;
-		} while (file->cur_content != NULL);
-	}
-	memset(p, 0, WD_REMAINING);
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-static int
-write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
-{
-	struct isoent *np;
-	int depth, r;
-
-	depth = 0;
-	np = vdd->rootent;
-	do {
-		struct extr_rec *extr;
-
-		r = _write_directory_descriptors(a, vdd, np, depth);
-		if (r < 0)
-			return (r);
-		if (vdd->vdd_type != VDD_JOLIET) {
-			/*
-			 * This extract record is used by SUSP,RRIP.
-			 * Not for joliet.
-			 */
-			for (extr = np->extr_rec_list.first;
-			    extr != NULL;
-			    extr = extr->next) {
-				unsigned char *wb;
-
-				wb = wb_buffptr(a);
-				memcpy(wb, extr->buf, extr->offset);
-				memset(wb + extr->offset, 0,
-				    LOGICAL_BLOCK_SIZE - extr->offset);
-				r = wb_consume(a, LOGICAL_BLOCK_SIZE);
-				if (r < 0)
-					return (r);
-			}
-		}
-
-		if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
-			/* Enter to sub directories. */
-			np = np->subdirs.first;
-			depth++;
-			continue;
-		}
-		while (np != np->parent) {
-			if (np->drnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				depth--;
-			} else {
-				np = np->drnext;
-				break;
-			}
-		}
-	} while (np != np->parent);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Read file contents from the temporary file, and write it.
- */
-static int
-write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	int r;
-
-	lseek(iso9660->temp_fd, offset, SEEK_SET);
-
-	while (size) {
-		size_t rsize;
-		ssize_t rs;
-		unsigned char *wb;
-
-		wb = wb_buffptr(a);
-		rsize = wb_remaining(a);
-		if (rsize > (size_t)size)
-			rsize = (size_t)size;
-		rs = read(iso9660->temp_fd, wb, rsize);
-		if (rs <= 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't read temporary file(%jd)", (intmax_t)rs);
-			return (ARCHIVE_FATAL);
-		}
-		size -= rs;
-		r = wb_consume(a, rs);
-		if (r < 0)
-			return (r);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-write_file_descriptors(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file;
-	int64_t blocks, offset;
-	int r;
-
-	blocks = 0;
-	offset = 0;
-
-	/* Make the boot catalog contents, and write it. */
-	if (iso9660->el_torito.catalog != NULL) {
-		r = make_boot_catalog(a);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Write the boot file contents. */
-	if (iso9660->el_torito.boot != NULL) {
-		file = iso9660->el_torito.boot->file;
-		blocks = file->content.blocks;
-		offset = file->content.offset_of_temp;
-		if (offset != 0) {
-			r = write_file_contents(a, offset,
-			    blocks << LOGICAL_BLOCK_BITS);
-			if (r < 0)
-				return (r);
-			blocks = 0;
-			offset = 0;
-		}
-	}
-
-	/* Write out all file contents. */
-	for (file = iso9660->data_file_list.first;
-	    file != NULL; file = file->datanext) {
-
-		if (!file->write_content)
-			continue;
-
-		if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
-		     file->content.offset_of_temp) {
-			if (blocks > 0) {
-				r = write_file_contents(a, offset,
-				    blocks << LOGICAL_BLOCK_BITS);
-				if (r < 0)
-					return (r);
-			}
-			blocks = 0;
-			offset = file->content.offset_of_temp;
-		}
-
-		file->cur_content = &(file->content);
-		do {
-			blocks += file->cur_content->blocks;
-			/* Next fragment */
-			file->cur_content = file->cur_content->next;
-		} while (file->cur_content != NULL);
-	}
-
-	/* Flush out remaining blocks. */
-	if (blocks > 0) {
-		r = write_file_contents(a, offset,
-		    blocks << LOGICAL_BLOCK_BITS);
-		if (r < 0)
-			return (r);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static void
-isofile_init_entry_list(struct iso9660 *iso9660)
-{
-	iso9660->all_file_list.first = NULL;
-	iso9660->all_file_list.last = &(iso9660->all_file_list.first);
-}
-
-static void
-isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
-{
-	file->allnext = NULL;
-	*iso9660->all_file_list.last = file;
-	iso9660->all_file_list.last = &(file->allnext);
-}
-
-static void
-isofile_free_all_entries(struct iso9660 *iso9660)
-{
-	struct isofile *file, *file_next;
-
-	file = iso9660->all_file_list.first;
-	while (file != NULL) {
-		file_next = file->allnext;
-		isofile_free(file);
-		file = file_next;
-	}
-}
-
-static void
-isofile_init_entry_data_file_list(struct iso9660 *iso9660)
-{
-	iso9660->data_file_list.first = NULL;
-	iso9660->data_file_list.last = &(iso9660->data_file_list.first);
-}
-
-static void
-isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
-{
-	file->datanext = NULL;
-	*iso9660->data_file_list.last = file;
-	iso9660->data_file_list.last = &(file->datanext);
-}
-
-
-static struct isofile *
-isofile_new(struct archive_write *a, struct archive_entry *entry)
-{
-	struct isofile *file;
-
-	file = calloc(1, sizeof(*file));
-	if (file == NULL)
-		return (NULL);
-
-	if (entry != NULL)
-		file->entry = archive_entry_clone(entry);
-	else
-		file->entry = archive_entry_new2(&a->archive);
-	if (file->entry == NULL) {
-		free(file);
-		return (NULL);
-	}
-	archive_string_init(&(file->parentdir));
-	archive_string_init(&(file->basename));
-	archive_string_init(&(file->basename_utf16));
-	archive_string_init(&(file->symlink));
-	file->cur_content = &(file->content);
-
-	return (file);
-}
-
-static void
-isofile_free(struct isofile *file)
-{
-	struct content *con, *tmp;
-
-	con = file->content.next;
-	while (con != NULL) {
-		tmp = con;
-		con = con->next;
-		free(tmp);
-	}
-	archive_entry_free(file->entry);
-	archive_string_free(&(file->parentdir));
-	archive_string_free(&(file->basename));
-	archive_string_free(&(file->basename_utf16));
-	archive_string_free(&(file->symlink));
-	free(file);
-}
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-static int
-cleanup_backslash_1(char *p)
-{
-	int mb, dos;
-
-	mb = dos = 0;
-	while (*p) {
-		if (*(unsigned char *)p > 127)
-			mb = 1;
-		if (*p == '\\') {
-			/* If we have not met any multi-byte characters,
-			 * we can replace '\' with '/'. */
-			if (!mb)
-				*p = '/';
-			dos = 1;
-		}
-		p++;
-	}
-	if (!mb || !dos)
-		return (0);
-	return (-1);
-}
-
-static void
-cleanup_backslash_2(wchar_t *p)
-{
-
-	/* Convert a path-separator from '\' to  '/' */
-	while (*p != L'\0') {
-		if (*p == L'\\')
-			*p = L'/';
-		p++;
-	}
-}
-#endif
-
-/*
- * Generate a parent directory name and a base name from a pathname.
- */
-static int
-isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
-{
-	struct iso9660 *iso9660;
-	const char *pathname;
-	char *p, *dirname, *slash;
-	size_t len;
-	int ret = ARCHIVE_OK;
-
-	iso9660 = a->format_data;
-
-	archive_string_empty(&(file->parentdir));
-	archive_string_empty(&(file->basename));
-	archive_string_empty(&(file->basename_utf16));
-	archive_string_empty(&(file->symlink));
-
-	pathname =  archive_entry_pathname(file->entry);
-	if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
-		file->dircnt = 0;
-		return (ret);
-	}
-
-	/*
-	 * Make a UTF-16BE basename if Joliet extension enabled.
-	 */
-	if (iso9660->opt.joliet) {
-		const char *u16, *ulast;
-		size_t u16len, ulen_last;
-
-		if (iso9660->sconv_to_utf16be == NULL) {
-			iso9660->sconv_to_utf16be =
-			    archive_string_conversion_to_charset(
-				&(a->archive), "UTF-16BE", 1);
-			if (iso9660->sconv_to_utf16be == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FATAL);
-			iso9660->sconv_from_utf16be =
-			    archive_string_conversion_from_charset(
-				&(a->archive), "UTF-16BE", 1);
-			if (iso9660->sconv_from_utf16be == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FATAL);
-		}
-
-		/*
-		 * Convert a filename to UTF-16BE.
-		 */
-		if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
-		    iso9660->sconv_to_utf16be)) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for UTF-16BE");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "A filename cannot be converted to UTF-16BE;"
-			    "You should disable making Joliet extension");
-			ret = ARCHIVE_WARN;
-		}
-
-		/*
-		 * Make sure a path separator is not in the last;
-		 * Remove trailing '/'.
-		 */
-		while (u16len >= 2) {
-#if defined(_WIN32) || defined(__CYGWIN__)
-			if (u16[u16len-2] == 0 &&
-			    (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
-#else
-			if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
-#endif
-			{
-				u16len -= 2;
-			} else
-				break;
-		}
-
-		/*
-		 * Find a basename in UTF-16BE.
-		 */
-		ulast = u16;
-		u16len >>= 1;
-		ulen_last = u16len;
-		while (u16len > 0) {
-#if defined(_WIN32) || defined(__CYGWIN__)
-			if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
-#else
-			if (u16[0] == 0 && u16[1] == '/')
-#endif
-			{
-				ulast = u16 + 2;
-				ulen_last = u16len -1;
-			}
-			u16 += 2;
-			u16len --;
-		}
-		ulen_last <<= 1;
-		if (archive_string_ensure(&(file->basename_utf16),
-		    ulen_last) == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for UTF-16BE");
-			return (ARCHIVE_FATAL);
-		}
-
-		/*
-		 * Set UTF-16BE basename.
-		 */
-		memcpy(file->basename_utf16.s, ulast, ulen_last);
-		file->basename_utf16.length = ulen_last;
-	}
-
-	archive_strcpy(&(file->parentdir), pathname);
-#if defined(_WIN32) || defined(__CYGWIN__)
-	/*
-	 * Convert a path-separator from '\' to  '/'
-	 */
-	if (cleanup_backslash_1(file->parentdir.s) != 0) {
-		const wchar_t *wp = archive_entry_pathname_w(file->entry);
-		struct archive_wstring ws;
-
-		if (wp != NULL) {
-			int r;
-			archive_string_init(&ws);
-			archive_wstrcpy(&ws, wp);
-			cleanup_backslash_2(ws.s);
-			archive_string_empty(&(file->parentdir));
-			r = archive_string_append_from_wcs(&(file->parentdir),
-			    ws.s, ws.length);
-			archive_wstring_free(&ws);
-			if (r < 0 && errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory");
-				return (ARCHIVE_FATAL);
-			}
-		}
-	}
-#endif
-
-	len = file->parentdir.length;
-	p = dirname = file->parentdir.s;
-
-	/*
-	 * Remove leading '/', '../' and './' elements
-	 */
-	while (*p) {
-		if (p[0] == '/') {
-			p++;
-			len--;
-		} else if (p[0] != '.')
-			break;
-		else if (p[1] == '.' && p[2] == '/') {
-			p += 3;
-			len -= 3;
-		} else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
-			p += 2;
-			len -= 2;
-		} else if (p[1] == '\0') {
-			p++;
-			len--;
-		} else
-			break;
-	}
-	if (p != dirname) {
-		memmove(dirname, p, len+1);
-		p = dirname;
-	}
-	/*
-	 * Remove "/","/." and "/.." elements from tail.
-	 */
-	while (len > 0) {
-		size_t ll = len;
-
-		if (len > 0 && p[len-1] == '/') {
-			p[len-1] = '\0';
-			len--;
-		}
-		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
-			p[len-2] = '\0';
-			len -= 2;
-		}
-		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
-		    p[len-1] == '.') {
-			p[len-3] = '\0';
-			len -= 3;
-		}
-		if (ll == len)
-			break;
-	}
-	while (*p) {
-		if (p[0] == '/') {
-			if (p[1] == '/')
-				/* Convert '//' --> '/' */
-				memmove(p, p+1, strlen(p+1) + 1);
-			else if (p[1] == '.' && p[2] == '/')
-				/* Convert '/./' --> '/' */
-				memmove(p, p+2, strlen(p+2) + 1);
-			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
-				/* Convert 'dir/dir1/../dir2/'
-				 *     --> 'dir/dir2/'
-				 */
-				char *rp = p -1;
-				while (rp >= dirname) {
-					if (*rp == '/')
-						break;
-					--rp;
-				}
-				if (rp > dirname) {
-					strcpy(rp, p+3);
-					p = rp;
-				} else {
-					strcpy(dirname, p+4);
-					p = dirname;
-				}
-			} else
-				p++;
-		} else
-			p++;
-	}
-	p = dirname;
-	len = strlen(p);
-
-	if (archive_entry_filetype(file->entry) == AE_IFLNK) {
-		/* Convert symlink name too. */
-		pathname = archive_entry_symlink(file->entry);
-		archive_strcpy(&(file->symlink),  pathname);
-#if defined(_WIN32) || defined(__CYGWIN__)
-		/*
-		 * Convert a path-separator from '\' to  '/'
-		 */
-		if (archive_strlen(&(file->symlink)) > 0 &&
-		    cleanup_backslash_1(file->symlink.s) != 0) {
-			const wchar_t *wp =
-			    archive_entry_symlink_w(file->entry);
-			struct archive_wstring ws;
-
-			if (wp != NULL) {
-				int r;
-				archive_string_init(&ws);
-				archive_wstrcpy(&ws, wp);
-				cleanup_backslash_2(ws.s);
-				archive_string_empty(&(file->symlink));
-				r = archive_string_append_from_wcs(
-				    &(file->symlink),
-				    ws.s, ws.length);
-				archive_wstring_free(&ws);
-				if (r < 0 && errno == ENOMEM) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate memory");
-					return (ARCHIVE_FATAL);
-				}
-			}
-		}
-#endif
-	}
-	/*
-	 * - Count up directory elements.
-	 * - Find out the position which points the last position of
-	 *   path separator('/').
-	 */
-	slash = NULL;
-	file->dircnt = 0;
-	for (; *p != '\0'; p++)
-		if (*p == '/') {
-			slash = p;
-			file->dircnt++;
-		}
-	if (slash == NULL) {
-		/* The pathname doesn't have a parent directory. */
-		file->parentdir.length = len;
-		archive_string_copy(&(file->basename), &(file->parentdir));
-		archive_string_empty(&(file->parentdir));
-		*file->parentdir.s = '\0';
-		return (ret);
-	}
-
-	/* Make a basename from dirname and slash */
-	*slash  = '\0';
-	file->parentdir.length = slash - dirname;
-	archive_strcpy(&(file->basename),  slash + 1);
-	if (archive_entry_filetype(file->entry) == AE_IFDIR)
-		file->dircnt ++;
-	return (ret);
-}
-
-/*
- * Register a entry to get a hardlink target.
- */
-static int
-isofile_register_hardlink(struct archive_write *a, struct isofile *file)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct hardlink *hl;
-	const char *pathname;
-
-	archive_entry_set_nlink(file->entry, 1);
-	pathname = archive_entry_hardlink(file->entry);
-	if (pathname == NULL) {
-		/* This `file` is a hardlink target. */
-		hl = malloc(sizeof(*hl));
-		if (hl == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		hl->nlink = 1;
-		/* A hardlink target must be the first position. */
-		file->hlnext = NULL;
-		hl->file_list.first = file;
-		hl->file_list.last = &(file->hlnext);
-		__archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
-		    (struct archive_rb_node *)hl);
-	} else {
-		hl = (struct hardlink *)__archive_rb_tree_find_node(
-		    &(iso9660->hardlink_rbtree), pathname);
-		if (hl != NULL) {
-			/* Insert `file` entry into the tail. */
-			file->hlnext = NULL;
-			*hl->file_list.last = file;
-			hl->file_list.last = &(file->hlnext);
-			hl->nlink++;
-		}
-		archive_entry_unset_size(file->entry);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Hardlinked files have to have the same location of extent.
- * We have to find out hardlink target entries for the entries
- * which have a hardlink target name.
- */
-static void
-isofile_connect_hardlink_files(struct iso9660 *iso9660)
-{
-	struct archive_rb_node *n;
-	struct hardlink *hl;
-	struct isofile *target, *nf;
-
-	ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
-		hl = (struct hardlink *)n;
-
-		/* The first entry must be a hardlink target. */
-		target = hl->file_list.first;
-		archive_entry_set_nlink(target->entry, hl->nlink);
-		/* Set a hardlink target to reference entries. */
-		for (nf = target->hlnext;
-		    nf != NULL; nf = nf->hlnext) {
-			nf->hardlink_target = target;
-			archive_entry_set_nlink(nf->entry, hl->nlink);
-		}
-	}
-}
-
-static int
-isofile_hd_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct hardlink *h1 = (const struct hardlink *)n1;
-	const struct hardlink *h2 = (const struct hardlink *)n2;
-
-	return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
-		       archive_entry_pathname(h2->file_list.first->entry)));
-}
-
-static int
-isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct hardlink *h = (const struct hardlink *)n;
-
-	return (strcmp(archive_entry_pathname(h->file_list.first->entry),
-		       (const char *)key));
-}
-
-static void
-isofile_init_hardlinks(struct iso9660 *iso9660)
-{
-	static const struct archive_rb_tree_ops rb_ops = {
-		isofile_hd_cmp_node, isofile_hd_cmp_key,
-	};
-
-	__archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
-}
-
-static void
-isofile_free_hardlinks(struct iso9660 *iso9660)
-{
-	struct archive_rb_node *n, *tmp;
-
-	ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) {
-		__archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n);
-		free(n);
-	}
-}
-
-static struct isoent *
-isoent_new(struct isofile *file)
-{
-	struct isoent *isoent;
-	static const struct archive_rb_tree_ops rb_ops = {
-		isoent_cmp_node, isoent_cmp_key,
-	};
-
-	isoent = calloc(1, sizeof(*isoent));
-	if (isoent == NULL)
-		return (NULL);
-	isoent->file = file;
-	isoent->children.first = NULL;
-	isoent->children.last = &(isoent->children.first);
-	__archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
-	isoent->subdirs.first = NULL;
-	isoent->subdirs.last = &(isoent->subdirs.first);
-	isoent->extr_rec_list.first = NULL;
-	isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
-	isoent->extr_rec_list.current = NULL;
-	if (archive_entry_filetype(file->entry) == AE_IFDIR)
-		isoent->dir = 1;
-
-	return (isoent);
-}
-
-static inline struct isoent *
-isoent_clone(struct isoent *src)
-{
-	return (isoent_new(src->file));
-}
-
-static void
-_isoent_free(struct isoent *isoent)
-{
-	struct extr_rec *er, *er_next;
-
-	free(isoent->children_sorted);
-	free(isoent->identifier);
-	er = isoent->extr_rec_list.first;
-	while (er != NULL) {
-		er_next = er->next;
-		free(er);
-		er = er_next;
-	}
-	free(isoent);
-}
-
-static void
-isoent_free_all(struct isoent *isoent)
-{
-	struct isoent *np, *np_temp;
-
-	if (isoent == NULL)
-		return;
-	np = isoent;
-	for (;;) {
-		if (np->dir) {
-			if (np->children.first != NULL) {
-				/* Enter to sub directories. */
-				np = np->children.first;
-				continue;
-			}
-		}
-		for (;;) {
-			np_temp = np;
-			if (np->chnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				_isoent_free(np_temp);
-				if (np == np_temp)
-					return;
-			} else {
-				np = np->chnext;
-				_isoent_free(np_temp);
-				break;
-			}
-		}
-	}
-}
-
-static struct isoent *
-isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
-{
-	struct isofile *file;
-	struct isoent *isoent;
-
-	file = isofile_new(a, NULL);
-	if (file == NULL)
-		return (NULL);
-	archive_entry_set_pathname(file->entry, pathname);
-	archive_entry_unset_mtime(file->entry);
-	archive_entry_unset_atime(file->entry);
-	archive_entry_unset_ctime(file->entry);
-	archive_entry_set_uid(file->entry, getuid());
-	archive_entry_set_gid(file->entry, getgid());
-	archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
-	archive_entry_set_nlink(file->entry, 2);
-	if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
-		isofile_free(file);
-		return (NULL);
-	}
-	isofile_add_entry(iso9660, file);
-
-	isoent = isoent_new(file);
-	if (isoent == NULL)
-		return (NULL);
-	isoent->dir = 1;
-	isoent->virtual = 1;
-
-	return (isoent);
-}
-
-static int
-isoent_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct isoent *e1 = (const struct isoent *)n1;
-	const struct isoent *e2 = (const struct isoent *)n2;
-
-	return (strcmp(e1->file->basename.s, e2->file->basename.s));
-}
-
-static int
-isoent_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct isoent *e = (const struct isoent *)n;
-
-	return (strcmp(e->file->basename.s, (const char *)key));
-}
-
-static int
-isoent_add_child_head(struct isoent *parent, struct isoent *child)
-{
-
-	if (!__archive_rb_tree_insert_node(
-	    &(parent->rbtree), (struct archive_rb_node *)child))
-		return (0);
-	if ((child->chnext = parent->children.first) == NULL)
-		parent->children.last = &(child->chnext);
-	parent->children.first = child;
-	parent->children.cnt++;
-	child->parent = parent;
-
-	/* Add a child to a sub-directory chain */
-	if (child->dir) {
-		if ((child->drnext = parent->subdirs.first) == NULL)
-			parent->subdirs.last = &(child->drnext);
-		parent->subdirs.first = child;
-		parent->subdirs.cnt++;
-		child->parent = parent;
-	} else
-		child->drnext = NULL;
-	return (1);
-}
-
-static int
-isoent_add_child_tail(struct isoent *parent, struct isoent *child)
-{
-
-	if (!__archive_rb_tree_insert_node(
-	    &(parent->rbtree), (struct archive_rb_node *)child))
-		return (0);
-	child->chnext = NULL;
-	*parent->children.last = child;
-	parent->children.last = &(child->chnext);
-	parent->children.cnt++;
-	child->parent = parent;
-
-	/* Add a child to a sub-directory chain */
-	child->drnext = NULL;
-	if (child->dir) {
-		*parent->subdirs.last = child;
-		parent->subdirs.last = &(child->drnext);
-		parent->subdirs.cnt++;
-		child->parent = parent;
-	}
-	return (1);
-}
-
-static void
-isoent_remove_child(struct isoent *parent, struct isoent *child)
-{
-	struct isoent *ent;
-
-	/* Remove a child entry from children chain. */
-	ent = parent->children.first;
-	while (ent->chnext != child)
-		ent = ent->chnext;
-	if ((ent->chnext = ent->chnext->chnext) == NULL)
-		parent->children.last = &(ent->chnext);
-	parent->children.cnt--;
-
-	if (child->dir) {
-		/* Remove a child entry from sub-directory chain. */
-		ent = parent->subdirs.first;
-		while (ent->drnext != child)
-			ent = ent->drnext;
-		if ((ent->drnext = ent->drnext->drnext) == NULL)
-			parent->subdirs.last = &(ent->drnext);
-		parent->subdirs.cnt--;
-	}
-
-	__archive_rb_tree_remove_node(&(parent->rbtree),
-	    (struct archive_rb_node *)child);
-}
-
-static int
-isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
-    struct isoent *root)
-{
-	struct isoent *np, *xroot, *newent;
-
-	np = root;
-	xroot = NULL;
-	do {
-		newent = isoent_clone(np);
-		if (newent == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		if (xroot == NULL) {
-			*nroot = xroot = newent;
-			newent->parent = xroot;
-		} else
-			isoent_add_child_tail(xroot, newent);
-		if (np->dir && np->children.first != NULL) {
-			/* Enter to sub directories. */
-			np = np->children.first;
-			xroot = newent;
-			continue;
-		}
-		while (np != np->parent) {
-			if (np->chnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				xroot = xroot->parent;
-			} else {
-				np = np->chnext;
-				break;
-			}
-		}
-	} while (np != np->parent);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Setup directory locations.
- */
-static void
-isoent_setup_directory_location(struct iso9660 *iso9660, int location,
-    struct vdd *vdd)
-{
-	struct isoent *np;
-	int depth;
-
-	vdd->total_dir_block = 0;
-	depth = 0;
-	np = vdd->rootent;
-	do {
-		int block;
-
-		np->dir_block = calculate_directory_descriptors(
-		    iso9660, vdd, np, depth);
-		vdd->total_dir_block += np->dir_block;
-		np->dir_location = location;
-		location += np->dir_block;
-		block = extra_setup_location(np, location);
-		vdd->total_dir_block += block;
-		location += block;
-
-		if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
-			/* Enter to sub directories. */
-			np = np->subdirs.first;
-			depth++;
-			continue;
-		}
-		while (np != np->parent) {
-			if (np->drnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				depth--;
-			} else {
-				np = np->drnext;
-				break;
-			}
-		}
-	} while (np != np->parent);
-}
-
-static void
-_isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
-    int *symlocation)
-{
-	struct isoent **children;
-	int n;
-
-	if (isoent->children.cnt == 0)
-		return;
-
-	children = isoent->children_sorted;
-	for (n = 0; n < isoent->children.cnt; n++) {
-		struct isoent *np;
-		struct isofile *file;
-
-		np = children[n];
-		if (np->dir)
-			continue;
-		if (np == iso9660->el_torito.boot)
-			continue;
-		file = np->file;
-		if (file->boot || file->hardlink_target != NULL)
-			continue;
-		if (archive_entry_filetype(file->entry) == AE_IFLNK ||
-		    file->content.size == 0) {
-			/*
-			 * Do not point a valid location.
-			 * Make sure entry is not hardlink file.
-			 */
-			file->content.location = (*symlocation)--;
-			continue;
-		}
-
-		file->write_content = 1;
-	}
-}
-
-/*
- * Setup file locations.
- */
-static void
-isoent_setup_file_location(struct iso9660 *iso9660, int location)
-{
-	struct isoent *isoent;
-	struct isoent *np;
-	struct isofile *file;
-	size_t size;
-	int block;
-	int depth;
-	int joliet;
-	int symlocation;
-	int total_block;
-
-	iso9660->total_file_block = 0;
-	if ((isoent = iso9660->el_torito.catalog) != NULL) {
-		isoent->file->content.location = location;
-		block = (int)((archive_entry_size(isoent->file->entry) +
-		    LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
-		location += block;
-		iso9660->total_file_block += block;
-	}
-	if ((isoent = iso9660->el_torito.boot) != NULL) {
-		isoent->file->content.location = location;
-		size = fd_boot_image_size(iso9660->el_torito.media_type);
-		if (size == 0)
-			size = (size_t)archive_entry_size(isoent->file->entry);
-		block = ((int)size + LOGICAL_BLOCK_SIZE -1)
-		    >> LOGICAL_BLOCK_BITS;
-		location += block;
-		iso9660->total_file_block += block;
-		isoent->file->content.blocks = block;
-	}
-
-	depth = 0;
-	symlocation = -16;
-	if (!iso9660->opt.rr && iso9660->opt.joliet) {
-		joliet = 1;
-		np = iso9660->joliet.rootent;
-	} else {
-		joliet = 0;
-		np = iso9660->primary.rootent;
-	}
-	do {
-		_isoent_file_location(iso9660, np, &symlocation);
-
-		if (np->subdirs.first != NULL &&
-		    (joliet ||
-		    ((iso9660->opt.rr == OPT_RR_DISABLED &&
-		      depth + 2 < iso9660->primary.max_depth) ||
-		     (iso9660->opt.rr &&
-		      depth + 1 < iso9660->primary.max_depth)))) {
-			/* Enter to sub directories. */
-			np = np->subdirs.first;
-			depth++;
-			continue;
-		}
-		while (np != np->parent) {
-			if (np->drnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				depth--;
-			} else {
-				np = np->drnext;
-				break;
-			}
-		}
-	} while (np != np->parent);
-
-	total_block = 0;
-	for (file = iso9660->data_file_list.first;
-	    file != NULL; file = file->datanext) {
-
-		if (!file->write_content)
-			continue;
-
-		file->cur_content = &(file->content);
-		do {
-			file->cur_content->location = location;
-			location += file->cur_content->blocks;
-			total_block += file->cur_content->blocks;
-			/* Next fragment */
-			file->cur_content = file->cur_content->next;
-		} while (file->cur_content != NULL);
-	}
-	iso9660->total_file_block += total_block;
-}
-
-static int
-get_path_component(char *name, size_t n, const char *fn)
-{
-	char *p;
-	size_t l;
-
-	p = strchr(fn, '/');
-	if (p == NULL) {
-		if ((l = strlen(fn)) == 0)
-			return (0);
-	} else
-		l = p - fn;
-	if (l > n -1)
-		return (-1);
-	memcpy(name, fn, l);
-	name[l] = '\0';
-
-	return ((int)l);
-}
-
-/*
- * Add a new entry into the tree.
- */
-static int
-isoent_tree(struct archive_write *a, struct isoent **isoentpp)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	char name[_MAX_FNAME];/* Included null terminator size. */
-#elif defined(NAME_MAX) && NAME_MAX >= 255
-	char name[NAME_MAX+1];
-#else
-	char name[256];
-#endif
-	struct iso9660 *iso9660 = a->format_data;
-	struct isoent *dent, *isoent, *np;
-	struct isofile *f1, *f2;
-	const char *fn, *p;
-	int l;
-
-	isoent = *isoentpp;
-	dent = iso9660->primary.rootent;
-	if (isoent->file->parentdir.length > 0)
-		fn = p = isoent->file->parentdir.s;
-	else
-		fn = p = "";
-
-	/*
-	 * If the path of the parent directory of `isoent' entry is
-	 * the same as the path of `cur_dirent', add isoent to
-	 * `cur_dirent'.
-	 */
-	if (archive_strlen(&(iso9660->cur_dirstr))
-	      == archive_strlen(&(isoent->file->parentdir)) &&
-	    strcmp(iso9660->cur_dirstr.s, fn) == 0) {
-		if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
-			np = (struct isoent *)__archive_rb_tree_find_node(
-			    &(iso9660->cur_dirent->rbtree),
-			    isoent->file->basename.s);
-			goto same_entry;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	for (;;) {
-		l = get_path_component(name, sizeof(name), fn);
-		if (l == 0) {
-			np = NULL;
-			break;
-		}
-		if (l < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "A name buffer is too small");
-			_isoent_free(isoent);
-			return (ARCHIVE_FATAL);
-		}
-
-		np = isoent_find_child(dent, name);
-		if (np == NULL || fn[0] == '\0')
-			break;
-
-		/* Find next subdirectory. */
-		if (!np->dir) {
-			/* NOT Directory! */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "`%s' is not directory, we cannot insert `%s' ",
-			    archive_entry_pathname(np->file->entry),
-			    archive_entry_pathname(isoent->file->entry));
-			_isoent_free(isoent);
-			*isoentpp = NULL;
-			return (ARCHIVE_FAILED);
-		}
-		fn += l;
-		if (fn[0] == '/')
-			fn++;
-		dent = np;
-	}
-	if (np == NULL) {
-		/*
-		 * Create virtual parent directories.
-		 */
-		while (fn[0] != '\0') {
-			struct isoent *vp;
-			struct archive_string as;
-
-			archive_string_init(&as);
-			archive_strncat(&as, p, fn - p + l);
-			if (as.s[as.length-1] == '/') {
-				as.s[as.length-1] = '\0';
-				as.length--;
-			}
-			vp = isoent_create_virtual_dir(a, iso9660, as.s);
-			if (vp == NULL) {
-				archive_string_free(&as);
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory");
-				_isoent_free(isoent);
-				*isoentpp = NULL;
-				return (ARCHIVE_FATAL);
-			}
-			archive_string_free(&as);
-
-			if (vp->file->dircnt > iso9660->dircnt_max)
-				iso9660->dircnt_max = vp->file->dircnt;
-			isoent_add_child_tail(dent, vp);
-			np = vp;
-
-			fn += l;
-			if (fn[0] == '/')
-				fn++;
-			l = get_path_component(name, sizeof(name), fn);
-			if (l < 0) {
-				archive_string_free(&as);
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "A name buffer is too small");
-				_isoent_free(isoent);
-				*isoentpp = NULL;
-				return (ARCHIVE_FATAL);
-			}
-			dent = np;
-		}
-
-		/* Found out the parent directory where isoent can be
-		 * inserted. */
-		iso9660->cur_dirent = dent;
-		archive_string_empty(&(iso9660->cur_dirstr));
-		archive_string_ensure(&(iso9660->cur_dirstr),
-		    archive_strlen(&(dent->file->parentdir)) +
-		    archive_strlen(&(dent->file->basename)) + 2);
-		if (archive_strlen(&(dent->file->parentdir)) +
-		    archive_strlen(&(dent->file->basename)) == 0)
-			iso9660->cur_dirstr.s[0] = 0;
-		else {
-			if (archive_strlen(&(dent->file->parentdir)) > 0) {
-				archive_string_copy(&(iso9660->cur_dirstr),
-				    &(dent->file->parentdir));
-				archive_strappend_char(&(iso9660->cur_dirstr), '/');
-			}
-			archive_string_concat(&(iso9660->cur_dirstr),
-			    &(dent->file->basename));
-		}
-
-		if (!isoent_add_child_tail(dent, isoent)) {
-			np = (struct isoent *)__archive_rb_tree_find_node(
-			    &(dent->rbtree), isoent->file->basename.s);
-			goto same_entry;
-		}
-		return (ARCHIVE_OK);
-	}
-
-same_entry:
-	/*
-	 * We have already has the entry the filename of which is
-	 * the same.
-	 */
-	f1 = np->file;
-	f2 = isoent->file;
-
-	/* If the file type of entries is different,
-	 * we cannot handle it. */
-	if (archive_entry_filetype(f1->entry) !=
-	    archive_entry_filetype(f2->entry)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Found duplicate entries `%s' and its file type is "
-		    "different",
-		    archive_entry_pathname(f1->entry));
-		_isoent_free(isoent);
-		*isoentpp = NULL;
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Swap file entries. */
-	np->file = f2;
-	isoent->file = f1;
-	np->virtual = 0;
-
-	_isoent_free(isoent);
-	*isoentpp = np;
-	return (ARCHIVE_OK);
-}
-
-/*
- * Find a entry from `isoent'
- */
-static struct isoent *
-isoent_find_child(struct isoent *isoent, const char *child_name)
-{
-	struct isoent *np;
-
-	np = (struct isoent *)__archive_rb_tree_find_node(
-	    &(isoent->rbtree), child_name);
-	return (np);
-}
-
-/*
- * Find a entry full-path of which is specified by `fn' parameter,
- * in the tree.
- */
-static struct isoent *
-isoent_find_entry(struct isoent *rootent, const char *fn)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	char name[_MAX_FNAME];/* Included null terminator size. */
-#elif defined(NAME_MAX) && NAME_MAX >= 255
-	char name[NAME_MAX+1];
-#else
-	char name[256];
-#endif
-	struct isoent *isoent, *np;
-	int l;
-
-	isoent = rootent;
-	np = NULL;
-	for (;;) {
-		l = get_path_component(name, sizeof(name), fn);
-		if (l == 0)
-			break;
-		fn += l;
-		if (fn[0] == '/')
-			fn++;
-
-		np = isoent_find_child(isoent, name);
-		if (np == NULL)
-			break;
-		if (fn[0] == '\0')
-			break;/* We found out the entry */
-
-		/* Try sub directory. */
-		isoent = np;
-		np = NULL;
-		if (!isoent->dir)
-			break;/* Not directory */
-	}
-
-	return (np);
-}
-
-/*
- * Following idr_* functions are used for resolving duplicated filenames
- * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
- */
-
-static void
-idr_relaxed_filenames(char *map)
-{
-	int i;
-
-	for (i = 0x21; i <= 0x2F; i++)
-		map[i] = 1;
-	for (i = 0x3A; i <= 0x41; i++)
-		map[i] = 1;
-	for (i = 0x5B; i <= 0x5E; i++)
-		map[i] = 1;
-	map[0x60] = 1;
-	for (i = 0x7B; i <= 0x7E; i++)
-		map[i] = 1;
-}
-
-static void
-idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
-{
-
-	idr->idrent_pool = NULL;
-	idr->pool_size = 0;
-	if (vdd->vdd_type != VDD_JOLIET) {
-		if (iso9660->opt.iso_level <= 3) {
-			memcpy(idr->char_map, d_characters_map,
-			    sizeof(idr->char_map));
-		} else {
-			memcpy(idr->char_map, d1_characters_map,
-			    sizeof(idr->char_map));
-			idr_relaxed_filenames(idr->char_map);
-		}
-	}
-}
-
-static void
-idr_cleanup(struct idr *idr)
-{
-	free(idr->idrent_pool);
-}
-
-static int
-idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
-    int cnt)
-{
-
-	if (idr->pool_size < cnt) {
-		void *p;
-		const int bk = (1 << 7) - 1;
-		int psize;
-
-		psize = (cnt + bk) & ~bk;
-		p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		idr->idrent_pool = (struct idrent *)p;
-		idr->pool_size = psize;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
-    int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
-{
-	int r;
-
-	(void)ffmax; /* UNUSED */
-
-	r = idr_ensure_poolsize(a, idr, cnt);
-	if (r != ARCHIVE_OK)
-		return (r);
-	__archive_rb_tree_init(&(idr->rbtree), rbt_ops);
-	idr->wait_list.first = NULL;
-	idr->wait_list.last = &(idr->wait_list.first);
-	idr->pool_idx = 0;
-	idr->num_size = num_size;
-	idr->null_size = null_size;
-	return (ARCHIVE_OK);
-}
-
-static void
-idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
-{
-	struct idrent *idrent, *n;
-
-	idrent = &(idr->idrent_pool[idr->pool_idx++]);
-	idrent->wnext = idrent->avail = NULL;
-	idrent->isoent = isoent;
-	idrent->weight = weight;
-	idrent->noff = noff;
-	idrent->rename_num = 0;
-
-	if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
-		n = (struct idrent *)__archive_rb_tree_find_node(
-		    &(idr->rbtree), idrent->isoent);
-		if (n != NULL) {
-			/* this `idrent' needs to rename. */
-			idrent->avail = n;
-			*idr->wait_list.last = idrent;
-			idr->wait_list.last = &(idrent->wnext);
-		}
-	}
-}
-
-static void
-idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
-{
-	unsigned char *p;
-	int wnp_ext_off;
-
-	wnp_ext_off = wnp->isoent->ext_off;
-	if (wnp->noff + numsize != wnp_ext_off) {
-		p = (unsigned char *)wnp->isoent->identifier;
-		/* Extend the filename; foo.c --> foo___.c */
-		memmove(p + wnp->noff + numsize, p + wnp_ext_off,
-		    wnp->isoent->ext_len + nullsize);
-		wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
-		wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
-	}
-}
-
-static void
-idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
-{
-	struct idrent *n;
-	unsigned char *p;
-
-	for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
-		idr_extend_identifier(n, idr->num_size, idr->null_size);
-		p = (unsigned char *)n->isoent->identifier + n->noff;
-		do {
-			fsetnum(p, n->avail->rename_num++);
-		} while (!__archive_rb_tree_insert_node(
-		    &(idr->rbtree), &(n->rbnode)));
-	}
-}
-
-static void
-idr_set_num(unsigned char *p, int num)
-{
-	static const char xdig[] = {
-		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-		'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-		'U', 'V', 'W', 'X', 'Y', 'Z'
-	};
-
-	num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
-	p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
-	num %= sizeof(xdig) * sizeof(xdig);
-	p[1] = xdig[ (num / sizeof(xdig))];
-	num %= sizeof(xdig);
-	p[2] = xdig[num];
-}
-
-static void
-idr_set_num_beutf16(unsigned char *p, int num)
-{
-	static const uint16_t xdig[] = {
-		0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
-		0x0036, 0x0037, 0x0038, 0x0039,
-		0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
-		0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
-		0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
-		0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
-		0x0059, 0x005A
-	};
-#define XDIG_CNT	(sizeof(xdig)/sizeof(xdig[0]))
-
-	num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
-	archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
-	num %= XDIG_CNT * XDIG_CNT;
-	archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
-	num %= XDIG_CNT;
-	archive_be16enc(p+4, xdig[num]);
-}
-
-/*
- * Generate ISO9660 Identifier.
- */
-static int
-isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
-    struct idr *idr)
-{
-	struct iso9660 *iso9660;
-	struct isoent *np;
-	char *p;
-	int l, r;
-	const char *char_map;
-	char allow_ldots, allow_multidot, allow_period, allow_vernum;
-	int fnmax, ffmax, dnmax;
-	static const struct archive_rb_tree_ops rb_ops = {
-		isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
-	};
-
-	if (isoent->children.cnt == 0)
-		return (0);
-
-	iso9660 = a->format_data;
-	char_map = idr->char_map;
-	if (iso9660->opt.iso_level <= 3) {
-		allow_ldots = 0;
-		allow_multidot = 0;
-		allow_period = 1;
-		allow_vernum = iso9660->opt.allow_vernum;
-		if (iso9660->opt.iso_level == 1) {
-			fnmax = 8;
-			ffmax = 12;/* fnmax + '.' + 3 */
-			dnmax = 8;
-		} else {
-			fnmax = 30;
-			ffmax = 31;
-			dnmax = 31;
-		}
-	} else {
-		allow_ldots = allow_multidot = 1;
-		allow_period = allow_vernum = 0;
-		if (iso9660->opt.rr)
-			/*
-			 * MDR : The maximum size of Directory Record(254).
-			 * DRL : A Directory Record Length(33).
-			 * CE  : A size of SUSP CE System Use Entry(28).
-			 * MDR - DRL - CE = 254 - 33 - 28 = 193.
-			 */
-			fnmax = ffmax = dnmax = 193;
-		else
-			/*
-			 * XA  : CD-ROM XA System Use Extension
-			 *       Information(14).
-			 * MDR - DRL - XA = 254 - 33 -14 = 207.
-			 */
-			fnmax = ffmax = dnmax = 207;
-	}
-
-	r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
-	if (r < 0)
-		return (r);
-
-	for (np = isoent->children.first; np != NULL; np = np->chnext) {
-		char *dot, *xdot;
-		int ext_off, noff, weight;
-
-		l = (int)np->file->basename.length;
-		p = malloc(l+31+2+1);
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		memcpy(p, np->file->basename.s, l);
-		p[l] = '\0';
-		np->identifier = p;
-
-		dot = xdot = NULL;
-		if (!allow_ldots) {
-			/*
-			 * If there is a '.' character at the first byte,
-			 * it has to be replaced by '_' character.
-			 */
-			if (*p == '.')
-				*p++ = '_';
-		}
-		for (;*p; p++) {
-			if (*p & 0x80) {
-				*p = '_';
-				continue;
-			}
-			if (char_map[(unsigned char)*p]) {
-				/* if iso-level is '4', a character '.' is
-				 * allowed by char_map. */
-				if (*p == '.') {
-					xdot = dot;
-					dot = p;
-				}
-				continue;
-			}
-			if (*p >= 'a' && *p <= 'z') {
-				*p -= 'a' - 'A';
-				continue;
-			}
-			if (*p == '.') {
-				xdot = dot;
-				dot = p;
-				if (allow_multidot)
-					continue;
-			}
-			*p = '_';
-		}
-		p = np->identifier;
-		weight = -1;
-		if (dot == NULL) {
-			int nammax;
-
-			if (np->dir)
-				nammax = dnmax;
-			else
-				nammax = fnmax;
-
-			if (l > nammax) {
-				p[nammax] = '\0';
-				weight = nammax;
-				ext_off = nammax;
-			} else
-				ext_off = l;
-		} else {
-			*dot = '.';
-			ext_off = (int)(dot - p);
-
-			if (iso9660->opt.iso_level == 1) {
-				if (dot - p <= 8) {
-					if (strlen(dot) > 4) {
-						/* A length of a file extension
-						 * must be less than 4 */
-						dot[4] = '\0';
-						weight = 0;
-					}
-				} else {
-					p[8] = dot[0];
-					p[9] = dot[1];
-					p[10] = dot[2];
-					p[11] = dot[3];
-					p[12] = '\0';
-					weight = 8;
-					ext_off = 8;
-				}
-			} else if (np->dir) {
-				if (l > dnmax) {
-					p[dnmax] = '\0';
-					weight = dnmax;
-					if (ext_off > dnmax)
-						ext_off = dnmax;
-				}
-			} else if (l > ffmax) {
-				int extlen = (int)strlen(dot);
-				int xdoff;
-
-				if (xdot != NULL)
-					xdoff = (int)(xdot - p);
-				else
-					xdoff = 0;
-
-				if (extlen > 1 && xdoff < fnmax-1) {
-					int off;
-
-					if (extlen > ffmax)
-						extlen = ffmax;
-					off = ffmax - extlen;
-					if (off == 0) {
-						/* A dot('.')  character
-						 * doesn't place to the first
-						 * byte of identifier. */
-						off ++;
-						extlen --;
-					}
-					memmove(p+off, dot, extlen);
-					p[ffmax] = '\0';
-					ext_off = off;
-					weight = off;
-#ifdef COMPAT_MKISOFS
-				} else if (xdoff >= fnmax-1) {
-					/* Simulate a bug(?) of mkisofs. */
-					p[fnmax-1] = '\0';
-					ext_off = fnmax-1;
-					weight = fnmax-1;
-#endif
-				} else {
-					p[fnmax] = '\0';
-					ext_off = fnmax;
-					weight = fnmax;
-				}
-			}
-		}
-		/* Save an offset of a file name extension to sort files. */
-		np->ext_off = ext_off;
-		np->ext_len = (int)strlen(&p[ext_off]);
-		np->id_len = l = ext_off + np->ext_len;
-
-		/* Make an offset of the number which is used to be set
-		 * hexadecimal number to avoid duplicate identifier. */
-		if (iso9660->opt.iso_level == 1) {
-			if (ext_off >= 5)
-				noff = 5;
-			else
-				noff = ext_off;
-		} else {
-			if (l == ffmax)
-				noff = ext_off - 3;
-			else if (l == ffmax-1)
-				noff = ext_off - 2;
-			else if (l == ffmax-2)
-				noff = ext_off - 1;
-			else
-				noff = ext_off;
-		}
-		/* Register entry to the identifier resolver. */
-		idr_register(idr, np, weight, noff);
-	}
-
-	/* Resolve duplicate identifier. */
-	idr_resolve(idr, idr_set_num);
-
-	/* Add a period and a version number to identifiers. */
-	for (np = isoent->children.first; np != NULL; np = np->chnext) {
-		if (!np->dir && np->rr_child == NULL) {
-			p = np->identifier + np->ext_off + np->ext_len;
-			if (np->ext_len == 0 && allow_period) {
-				*p++ = '.';
-				np->ext_len = 1;
-			}
-			if (np->ext_len == 1 && !allow_period) {
-				*--p = '\0';
-				np->ext_len = 0;
-			}
-			np->id_len = np->ext_off + np->ext_len;
-			if (allow_vernum) {
-				*p++ = ';';
-				*p++ = '1';
-				np->id_len += 2;
-			}
-			*p = '\0';
-		} else
-			np->id_len = np->ext_off + np->ext_len;
-		np->mb_len = np->id_len;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Generate Joliet Identifier.
- */
-static int
-isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
-    struct idr *idr)
-{
-	struct iso9660 *iso9660;
-	struct isoent *np;
-	unsigned char *p;
-	size_t l;
-	int r;
-	size_t ffmax, parent_len;
-	static const struct archive_rb_tree_ops rb_ops = {
-		isoent_cmp_node_joliet, isoent_cmp_key_joliet
-	};
-
-	if (isoent->children.cnt == 0)
-		return (0);
-
-	iso9660 = a->format_data;
-	if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
-		ffmax = 206;
-	else
-		ffmax = 128;
-
-	r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops);
-	if (r < 0)
-		return (r);
-
-	parent_len = 1;
-	for (np = isoent; np->parent != np; np = np->parent)
-		parent_len += np->mb_len + 1;
-
-	for (np = isoent->children.first; np != NULL; np = np->chnext) {
-		unsigned char *dot;
-		int ext_off, noff, weight;
-		size_t lt;
-
-		if ((l = np->file->basename_utf16.length) > ffmax)
-			l = ffmax;
-
-		p = malloc((l+1)*2);
-		if (p == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		memcpy(p, np->file->basename_utf16.s, l);
-		p[l] = 0;
-		p[l+1] = 0;
-
-		np->identifier = (char *)p;
-		lt = l;
-		dot = p + l;
-		weight = 0;
-		while (lt > 0) {
-			if (!joliet_allowed_char(p[0], p[1]))
-				archive_be16enc(p, 0x005F); /* '_' */
-			else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
-				dot = p;
-			p += 2;
-			lt -= 2;
-		}
-		ext_off = (int)(dot - (unsigned char *)np->identifier);
-		np->ext_off = ext_off;
-		np->ext_len = (int)l - ext_off;
-		np->id_len = (int)l;
-
-		/*
-		 * Get a length of MBS of a full-pathname.
-		 */
-		if (np->file->basename_utf16.length > ffmax) {
-			if (archive_strncpy_l(&iso9660->mbs,
-			    (const char *)np->identifier, l,
-				iso9660->sconv_from_utf16be) != 0 &&
-			    errno == ENOMEM) {
-				archive_set_error(&a->archive, errno,
-				    "No memory");
-				return (ARCHIVE_FATAL);
-			}
-			np->mb_len = (int)iso9660->mbs.length;
-			if (np->mb_len != (int)np->file->basename.length)
-				weight = np->mb_len;
-		} else
-			np->mb_len = (int)np->file->basename.length;
-
-		/* If a length of full-pathname is longer than 240 bytes,
-		 * it violates Joliet extensions regulation. */
-		if (parent_len > 240
-		    || np->mb_len > 240
-		    || parent_len + np->mb_len > 240) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "The regulation of Joliet extensions;"
-			    " A length of a full-pathname of `%s' is "
-			    "longer than 240 bytes, (p=%d, b=%d)",
-			    archive_entry_pathname(np->file->entry),
-			    (int)parent_len, (int)np->mb_len);
-			return (ARCHIVE_FATAL);
-		}
-
-		/* Make an offset of the number which is used to be set
-		 * hexadecimal number to avoid duplicate identifier. */
-		if (l == ffmax)
-			noff = ext_off - 6;
-		else if (l == ffmax-2)
-			noff = ext_off - 4;
-		else if (l == ffmax-4)
-			noff = ext_off - 2;
-		else
-			noff = ext_off;
-		/* Register entry to the identifier resolver. */
-		idr_register(idr, np, weight, noff);
-	}
-
-	/* Resolve duplicate identifier with Joliet Volume. */
-	idr_resolve(idr, idr_set_num_beutf16);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * This comparing rule is according to ISO9660 Standard 9.3
- */
-static int
-isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
-{
-	const char *s1, *s2;
-	int cmp;
-	int l;
-
-	s1 = p1->identifier;
-	s2 = p2->identifier;
-
-	/* Compare File Name */
-	l = p1->ext_off;
-	if (l > p2->ext_off)
-		l = p2->ext_off;
-	cmp = memcmp(s1, s2, l);
-	if (cmp != 0)
-		return (cmp);
-	if (p1->ext_off < p2->ext_off) {
-		s2 += l;
-		l = p2->ext_off - p1->ext_off;
-		while (l--)
-			if (0x20 != *s2++)
-				return (0x20
-				    - *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_off > p2->ext_off) {
-		s1 += l;
-		l = p1->ext_off - p2->ext_off;
-		while (l--)
-			if (0x20 != *s1++)
-				return (*(const unsigned char *)(s1 - 1)
-				    - 0x20);
-	}
-	/* Compare File Name Extension */
-	if (p1->ext_len == 0 && p2->ext_len == 0)
-		return (0);
-	if (p1->ext_len == 1 && p2->ext_len == 1)
-		return (0);
-	if (p1->ext_len <= 1)
-		return (-1);
-	if (p2->ext_len <= 1)
-		return (1);
-	l = p1->ext_len;
-	if (l > p2->ext_len)
-		l = p2->ext_len;
-	s1 = p1->identifier + p1->ext_off;
-	s2 = p2->identifier + p2->ext_off;
-	if (l > 1) {
-		cmp = memcmp(s1, s2, l);
-		if (cmp != 0)
-			return (cmp);
-	}
-	if (p1->ext_len < p2->ext_len) {
-		s2 += l;
-		l = p2->ext_len - p1->ext_len;
-		while (l--)
-			if (0x20 != *s2++)
-				return (0x20
-				    - *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_len > p2->ext_len) {
-		s1 += l;
-		l = p1->ext_len - p2->ext_len;
-		while (l--)
-			if (0x20 != *s1++)
-				return (*(const unsigned char *)(s1 - 1)
-				    - 0x20);
-	}
-	/* Compare File Version Number */
-	/* No operation. The File Version Number is always one. */
-
-	return (cmp);
-}
-
-static int
-isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct idrent *e1 = (const struct idrent *)n1;
-	const struct idrent *e2 = (const struct idrent *)n2;
-
-	return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
-}
-
-static int
-isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
-{
-	const struct isoent *isoent = (const struct isoent *)key;
-	const struct idrent *idrent = (const struct idrent *)node;
-
-	return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
-}
-
-static int
-isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
-{
-	const unsigned char *s1, *s2;
-	int cmp;
-	int l;
-
-	s1 = (const unsigned char *)p1->identifier;
-	s2 = (const unsigned char *)p2->identifier;
-
-	/* Compare File Name */
-	l = p1->ext_off;
-	if (l > p2->ext_off)
-		l = p2->ext_off;
-	cmp = memcmp(s1, s2, l);
-	if (cmp != 0)
-		return (cmp);
-	if (p1->ext_off < p2->ext_off) {
-		s2 += l;
-		l = p2->ext_off - p1->ext_off;
-		while (l--)
-			if (0 != *s2++)
-				return (- *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_off > p2->ext_off) {
-		s1 += l;
-		l = p1->ext_off - p2->ext_off;
-		while (l--)
-			if (0 != *s1++)
-				return (*(const unsigned char *)(s1 - 1));
-	}
-	/* Compare File Name Extension */
-	if (p1->ext_len == 0 && p2->ext_len == 0)
-		return (0);
-	if (p1->ext_len == 2 && p2->ext_len == 2)
-		return (0);
-	if (p1->ext_len <= 2)
-		return (-1);
-	if (p2->ext_len <= 2)
-		return (1);
-	l = p1->ext_len;
-	if (l > p2->ext_len)
-		l = p2->ext_len;
-	s1 = (unsigned char *)(p1->identifier + p1->ext_off);
-	s2 = (unsigned char *)(p2->identifier + p2->ext_off);
-	if (l > 1) {
-		cmp = memcmp(s1, s2, l);
-		if (cmp != 0)
-			return (cmp);
-	}
-	if (p1->ext_len < p2->ext_len) {
-		s2 += l;
-		l = p2->ext_len - p1->ext_len;
-		while (l--)
-			if (0 != *s2++)
-				return (- *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_len > p2->ext_len) {
-		s1 += l;
-		l = p1->ext_len - p2->ext_len;
-		while (l--)
-			if (0 != *s1++)
-				return (*(const unsigned char *)(s1 - 1));
-	}
-	/* Compare File Version Number */
-	/* No operation. The File Version Number is always one. */
-
-	return (cmp);
-}
-
-static int
-isoent_cmp_node_joliet(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct idrent *e1 = (const struct idrent *)n1;
-	const struct idrent *e2 = (const struct idrent *)n2;
-
-	return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
-}
-
-static int
-isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
-{
-	const struct isoent *isoent = (const struct isoent *)key;
-	const struct idrent *idrent = (const struct idrent *)node;
-
-	return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
-}
-
-static int
-isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
-    struct idr *idr)
-{
-	struct archive_rb_node *rn;
-	struct isoent **children;
-
-	children = malloc(isoent->children.cnt * sizeof(struct isoent *));
-	if (children == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	isoent->children_sorted = children;
-
-	ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
-		struct idrent *idrent = (struct idrent *)rn;
-		*children ++ = idrent->isoent;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * - Generate ISO9660 and Joliet identifiers from basenames.
- * - Sort files by each directory.
- */
-static int
-isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isoent *np;
-	struct idr idr;
-	int depth;
-	int r;
-	int (*genid)(struct archive_write *, struct isoent *, struct idr *);
-
-	idr_init(iso9660, vdd, &idr);
-	np = vdd->rootent;
-	depth = 0;
-	if (vdd->vdd_type == VDD_JOLIET)
-		genid = isoent_gen_joliet_identifier;
-	else
-		genid = isoent_gen_iso9660_identifier;
-	do {
-		if (np->virtual &&
-		    !archive_entry_mtime_is_set(np->file->entry)) {
-			/* Set properly times to virtual directory */
-			archive_entry_set_mtime(np->file->entry,
-			    iso9660->birth_time, 0);
-			archive_entry_set_atime(np->file->entry,
-			    iso9660->birth_time, 0);
-			archive_entry_set_ctime(np->file->entry,
-			    iso9660->birth_time, 0);
-		}
-		if (np->children.first != NULL) {
-			if (vdd->vdd_type != VDD_JOLIET &&
-			    !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
-				if (np->children.cnt > 0)
-					iso9660->directories_too_deep = np;
-			} else {
-				/* Generate Identifier */
-				r = genid(a, np, &idr);
-				if (r < 0)
-					goto exit_traverse_tree;
-				r = isoent_make_sorted_files(a, np, &idr);
-				if (r < 0)
-					goto exit_traverse_tree;
-
-				if (np->subdirs.first != NULL &&
-				    depth + 1 < vdd->max_depth) {
-					/* Enter to sub directories. */
-					np = np->subdirs.first;
-					depth++;
-					continue;
-				}
-			}
-		}
-		while (np != np->parent) {
-			if (np->drnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				depth--;
-			} else {
-				np = np->drnext;
-				break;
-			}
-		}
-	} while (np != np->parent);
-
-	r = ARCHIVE_OK;
-exit_traverse_tree:
-	idr_cleanup(&idr);
-
-	return (r);
-}
-
-/*
- * Collect directory entries into path_table by a directory depth.
- */
-static int
-isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
-{
-	struct isoent *np;
-
-	if (rootent == NULL)
-		rootent = vdd->rootent;
-	np = rootent;
-	do {
-		/* Register current directory to pathtable. */
-		path_table_add_entry(&(vdd->pathtbl[depth]), np);
-
-		if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
-			/* Enter to sub directories. */
-			np = np->subdirs.first;
-			depth++;
-			continue;
-		}
-		while (np != rootent) {
-			if (np->drnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-				depth--;
-			} else {
-				np = np->drnext;
-				break;
-			}
-		}
-	} while (np != rootent);
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * The entry whose number of levels in a directory hierarchy is
- * large than eight relocate to rr_move directory.
- */
-static int
-isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
-    struct isoent *curent, struct isoent **newent)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isoent *rrmoved, *mvent, *np;
-
-	if ((rrmoved = *rr_moved) == NULL) {
-		struct isoent *rootent = iso9660->primary.rootent;
-		/* There isn't rr_move entry.
-		 * Create rr_move entry and insert it into the root entry.
-		 */
-		rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
-		if (rrmoved == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		/* Add "rr_moved" entry to the root entry. */
-		isoent_add_child_head(rootent, rrmoved);
-		archive_entry_set_nlink(rootent->file->entry,
-		    archive_entry_nlink(rootent->file->entry) + 1);
-		/* Register "rr_moved" entry to second level pathtable. */
-		path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
-		/* Save rr_moved. */
-		*rr_moved = rrmoved;
-	}
-	/*
-	 * Make a clone of curent which is going to be relocated
-	 * to rr_moved.
-	 */
-	mvent = isoent_clone(curent);
-	if (mvent == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	/* linking..  and use for creating "CL", "PL" and "RE" */
-	mvent->rr_parent = curent->parent;
-	curent->rr_child = mvent;
-	/*
-	 * Move subdirectories from the curent to mvent
-	 */
-	if (curent->children.first != NULL) {
-		*mvent->children.last = curent->children.first;
-		mvent->children.last = curent->children.last;
-	}
-	for (np = mvent->children.first; np != NULL; np = np->chnext)
-		np->parent = mvent;
-	mvent->children.cnt = curent->children.cnt;
-	curent->children.cnt = 0;
-	curent->children.first = NULL;
-	curent->children.last = &curent->children.first;
-
-	if (curent->subdirs.first != NULL) {
-		*mvent->subdirs.last = curent->subdirs.first;
-		mvent->subdirs.last = curent->subdirs.last;
-	}
-	mvent->subdirs.cnt = curent->subdirs.cnt;
-	curent->subdirs.cnt = 0;
-	curent->subdirs.first = NULL;
-	curent->subdirs.last = &curent->subdirs.first;
-
-	/*
-	 * The mvent becomes a child of the rr_moved entry.
-	 */
-	isoent_add_child_tail(rrmoved, mvent);
-	archive_entry_set_nlink(rrmoved->file->entry,
-	    archive_entry_nlink(rrmoved->file->entry) + 1);
-	/*
-	 * This entry which relocated to the rr_moved directory
-	 * has to set the flag as a file.
-	 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
-	 */
-	curent->dir = 0;
-
-	*newent = mvent;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-isoent_rr_move(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct path_table *pt;
-	struct isoent *rootent, *rr_moved;
-	struct isoent *np, *last;
-	int r;
-
-	pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
-	/* There aren't level 8 directories reaching a deeper level. */
-	if (pt->cnt == 0)
-		return (ARCHIVE_OK);
-
-	rootent = iso9660->primary.rootent;
-	/* If "rr_moved" directory is already existing,
-	 * we have to use it. */
-	rr_moved = isoent_find_child(rootent, "rr_moved");
-	if (rr_moved != NULL &&
-	    rr_moved != rootent->children.first) {
-		/*
-		 * It's necessary that rr_move is the first entry
-		 * of the root.
-		 */
-		/* Remove "rr_moved" entry from children chain. */
-		isoent_remove_child(rootent, rr_moved);
-
-		/* Add "rr_moved" entry into the head of children chain. */
-		isoent_add_child_head(rootent, rr_moved);
-	}
-
-	/*
-	 * Check level 8 path_table.
-	 * If find out sub directory entries, that entries move to rr_move.
-	 */
-	np = pt->first;
-	while (np != NULL) {
-		last = path_table_last_entry(pt);
-		for (; np != NULL; np = np->ptnext) {
-			struct isoent *mvent;
-			struct isoent *newent;
-
-			if (!np->dir)
-				continue;
-			for (mvent = np->subdirs.first;
-			    mvent != NULL; mvent = mvent->drnext) {
-				r = isoent_rr_move_dir(a, &rr_moved,
-				    mvent, &newent);
-				if (r < 0)
-					return (r);
-				isoent_collect_dirs(&(iso9660->primary),
-				    newent, 2);
-			}
-		}
-		/* If new entries are added to level 8 path_talbe,
-		 * its sub directory entries move to rr_move too.
-		 */
-		np = last->ptnext;
-	}
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * This comparing rule is according to ISO9660 Standard 6.9.1
- */
-static int
-__LA_LIBC_CC
-_compare_path_table(const void *v1, const void *v2)
-{
-	const struct isoent *p1, *p2;
-	const char *s1, *s2;
-	int cmp, l;
-
-	p1 = *((const struct isoent **)(uintptr_t)v1);
-	p2 = *((const struct isoent **)(uintptr_t)v2);
-
-	/* Compare parent directory number */
-	cmp = p1->parent->dir_number - p2->parent->dir_number;
-	if (cmp != 0)
-		return (cmp);
-
-	/* Compare identifier */
-	s1 = p1->identifier;
-	s2 = p2->identifier;
-	l = p1->ext_off;
-	if (l > p2->ext_off)
-		l = p2->ext_off;
-	cmp = strncmp(s1, s2, l);
-	if (cmp != 0)
-		return (cmp);
-	if (p1->ext_off < p2->ext_off) {
-		s2 += l;
-		l = p2->ext_off - p1->ext_off;
-		while (l--)
-			if (0x20 != *s2++)
-				return (0x20
-				    - *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_off > p2->ext_off) {
-		s1 += l;
-		l = p1->ext_off - p2->ext_off;
-		while (l--)
-			if (0x20 != *s1++)
-				return (*(const unsigned char *)(s1 - 1)
-				    - 0x20);
-	}
-	return (0);
-}
-
-static int
-__LA_LIBC_CC
-_compare_path_table_joliet(const void *v1, const void *v2)
-{
-	const struct isoent *p1, *p2;
-	const unsigned char *s1, *s2;
-	int cmp, l;
-
-	p1 = *((const struct isoent **)(uintptr_t)v1);
-	p2 = *((const struct isoent **)(uintptr_t)v2);
-
-	/* Compare parent directory number */
-	cmp = p1->parent->dir_number - p2->parent->dir_number;
-	if (cmp != 0)
-		return (cmp);
-
-	/* Compare identifier */
-	s1 = (const unsigned char *)p1->identifier;
-	s2 = (const unsigned char *)p2->identifier;
-	l = p1->ext_off;
-	if (l > p2->ext_off)
-		l = p2->ext_off;
-	cmp = memcmp(s1, s2, l);
-	if (cmp != 0)
-		return (cmp);
-	if (p1->ext_off < p2->ext_off) {
-		s2 += l;
-		l = p2->ext_off - p1->ext_off;
-		while (l--)
-			if (0 != *s2++)
-				return (- *(const unsigned char *)(s2 - 1));
-	} else if (p1->ext_off > p2->ext_off) {
-		s1 += l;
-		l = p1->ext_off - p2->ext_off;
-		while (l--)
-			if (0 != *s1++)
-				return (*(const unsigned char *)(s1 - 1));
-	}
-	return (0);
-}
-
-static inline void
-path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
-{
-	ent->ptnext = NULL;
-	*pathtbl->last = ent;
-	pathtbl->last = &(ent->ptnext);
-	pathtbl->cnt ++;
-}
-
-static inline struct isoent *
-path_table_last_entry(struct path_table *pathtbl)
-{
-	if (pathtbl->first == NULL)
-		return (NULL);
-	return (((struct isoent *)(void *)
-		((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
-}
-
-/*
- * Sort directory entries in path_table
- * and assign directory number to each entries.
- */
-static int
-isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
-    int depth, int *dir_number)
-{
-	struct isoent *np;
-	struct isoent **enttbl;
-	struct path_table *pt;
-	int i;
-
-	pt = &vdd->pathtbl[depth];
-	if (pt->cnt == 0) {
-		pt->sorted = NULL;
-		return (ARCHIVE_OK);
-	}
-	enttbl = malloc(pt->cnt * sizeof(struct isoent *));
-	if (enttbl == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	pt->sorted = enttbl;
-	for (np = pt->first; np != NULL; np = np->ptnext)
-		*enttbl ++ = np;
-	enttbl = pt->sorted;
-
-	switch (vdd->vdd_type) {
-	case VDD_PRIMARY:
-	case VDD_ENHANCED:
-#ifdef __COMPAR_FN_T
-		qsort(enttbl, pt->cnt, sizeof(struct isoent *),
-		    (__compar_fn_t)_compare_path_table);
-#else
-		qsort(enttbl, pt->cnt, sizeof(struct isoent *),
-		    _compare_path_table);
-#endif
-		break;
-	case VDD_JOLIET:
-#ifdef __COMPAR_FN_T
-		qsort(enttbl, pt->cnt, sizeof(struct isoent *),
-		    (__compar_fn_t)_compare_path_table_joliet);
-#else
-		qsort(enttbl, pt->cnt, sizeof(struct isoent *),
-		    _compare_path_table_joliet);
-#endif
-		break;
-	}
-	for (i = 0; i < pt->cnt; i++)
-		enttbl[i]->dir_number = (*dir_number)++;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
-    int max_depth)
-{
-	int i;
-
-	vdd->max_depth = max_depth;
-	vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
-	if (vdd->pathtbl == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	for (i = 0; i < vdd->max_depth; i++) {
-		vdd->pathtbl[i].first = NULL;
-		vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
-		vdd->pathtbl[i].sorted = NULL;
-		vdd->pathtbl[i].cnt = 0;
-	}
-	return (ARCHIVE_OK);
-}
-
-/*
- * Make Path Tables
- */
-static int
-isoent_make_path_table(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	int depth, r;
-	int dir_number;
-
-	/*
-	 * Init Path Table.
-	 */
-	if (iso9660->dircnt_max >= MAX_DEPTH &&
-	    (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
-		r = isoent_alloc_path_table(a, &(iso9660->primary),
-		    iso9660->dircnt_max + 1);
-	else
-		/* The number of levels in the hierarchy cannot exceed
-		 * eight. */
-		r = isoent_alloc_path_table(a, &(iso9660->primary),
-		    MAX_DEPTH);
-	if (r < 0)
-		return (r);
-	if (iso9660->opt.joliet) {
-		r = isoent_alloc_path_table(a, &(iso9660->joliet),
-		    iso9660->dircnt_max + 1);
-		if (r < 0)
-			return (r);
-	}
-
-	/* Step 0.
-	 * - Collect directories for primary and joliet.
-	 */
-	isoent_collect_dirs(&(iso9660->primary), NULL, 0);
-	if (iso9660->opt.joliet)
-		isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
-	/*
-	 * Rockridge; move deeper depth directories to rr_moved.
-	 */
-	if (iso9660->opt.rr) {
-		r = isoent_rr_move(a);
-		if (r < 0)
-			return (r);
-	}
-
- 	/* Update nlink. */
-	isofile_connect_hardlink_files(iso9660);
-
-	/* Step 1.
-	 * - Renew a value of the depth of that directories.
-	 * - Resolve hardlinks.
- 	 * - Convert pathnames to ISO9660 name or UCS2(joliet).
-	 * - Sort files by each directory.
-	 */
-	r = isoent_traverse_tree(a, &(iso9660->primary));
-	if (r < 0)
-		return (r);
-	if (iso9660->opt.joliet) {
-		r = isoent_traverse_tree(a, &(iso9660->joliet));
-		if (r < 0)
-			return (r);
-	}
-
-	/* Step 2.
-	 * - Sort directories.
-	 * - Assign all directory number.
-	 */
-	dir_number = 1;
-	for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
-		r = isoent_make_path_table_2(a, &(iso9660->primary),
-		    depth, &dir_number);
-		if (r < 0)
-			return (r);
-	}
-	if (iso9660->opt.joliet) {
-		dir_number = 1;
-		for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
-			r = isoent_make_path_table_2(a, &(iso9660->joliet),
-			    depth, &dir_number);
-			if (r < 0)
-				return (r);
-		}
-	}
-	if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
-		/*
-		 * Maximum number of directories is 65535(0xffff)
-		 * doe to size(16bit) of Parent Directory Number of
-		 * the Path Table.
-		 * See also ISO9660 Standard 9.4.
-		 */
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Too many directories(%d) over 65535.", dir_number);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* Get the size of the Path Table. */
-	calculate_path_table_size(&(iso9660->primary));
-	if (iso9660->opt.joliet)
-		calculate_path_table_size(&(iso9660->joliet));
-
-	return (ARCHIVE_OK);
-}
-
-static int
-isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
-{
-	struct iso9660 *iso9660 = a->format_data;
-
-	/* Find a isoent of the boot file. */
-	iso9660->el_torito.boot = isoent_find_entry(rootent,
-	    iso9660->el_torito.boot_filename.s);
-	if (iso9660->el_torito.boot == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Can't find the boot image file ``%s''",
-		    iso9660->el_torito.boot_filename.s);
-		return (ARCHIVE_FATAL);
-	}
-	iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
-	return (ARCHIVE_OK);
-}
-
-static int
-isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file;
-	struct isoent *isoent;
-	struct archive_entry *entry;
-
-	(void)rootent; /* UNUSED */
-	/*
-	 * Create the entry which is the "boot.catalog" file.
-	 */
-	file = isofile_new(a, NULL);
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	archive_entry_set_pathname(file->entry,
-	    iso9660->el_torito.catalog_filename.s);
-	archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
-	archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
-	archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
-	archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
-	archive_entry_set_uid(file->entry, getuid());
-	archive_entry_set_gid(file->entry, getgid());
-	archive_entry_set_mode(file->entry, AE_IFREG | 0444);
-	archive_entry_set_nlink(file->entry, 1);
-
-	if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
-		isofile_free(file);
-		return (ARCHIVE_FATAL);
-	}
-	file->boot = BOOT_CATALOG;
-	file->content.size = LOGICAL_BLOCK_SIZE;
-	isofile_add_entry(iso9660, file);
-
-	isoent = isoent_new(file);
-	if (isoent == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	isoent->virtual = 1;
-
-	/* Add the "boot.catalog" entry into tree */
-	if (isoent_tree(a, &isoent) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	iso9660->el_torito.catalog = isoent;
-	/*
-	 * Get a boot media type.
-	 */
-	switch (iso9660->opt.boot_type) {
-	default:
-	case OPT_BOOT_TYPE_AUTO:
-		/* Try detecting a media type of the boot image. */
-		entry = iso9660->el_torito.boot->file->entry;
-		if (archive_entry_size(entry) == FD_1_2M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_1_2M_DISKETTE;
-		else if (archive_entry_size(entry) == FD_1_44M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_1_44M_DISKETTE;
-		else if (archive_entry_size(entry) == FD_2_88M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_2_88M_DISKETTE;
-		else
-			/* We cannot decide whether the boot image is
-			 * hard-disk. */
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_NO_EMULATION;
-		break;
-	case OPT_BOOT_TYPE_NO_EMU:
-		iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
-		break;
-	case OPT_BOOT_TYPE_HARD_DISK:
-		iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
-		break;
-	case OPT_BOOT_TYPE_FD:
-		entry = iso9660->el_torito.boot->file->entry;
-		if (archive_entry_size(entry) <= FD_1_2M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_1_2M_DISKETTE;
-		else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_1_44M_DISKETTE;
-		else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
-			iso9660->el_torito.media_type =
-			    BOOT_MEDIA_2_88M_DISKETTE;
-		else {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Boot image file(``%s'') size is too big "
-			    "for fd type.",
-			    iso9660->el_torito.boot_filename.s);
-			return (ARCHIVE_FATAL);
-		}
-		break;
-	}
-
-	/*
-	 * Get a system type.
-	 * TODO: `El Torito' specification says "A copy of byte 5 from the
-	 *       Partition Table found in the boot image".
-	 */
-	iso9660->el_torito.system_type = 0;
-
-	/*
-	 * Get an ID.
-	 */
-	if (iso9660->opt.publisher)
-		archive_string_copy(&(iso9660->el_torito.id),
-		    &(iso9660->publisher_identifier));
-
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * If a media type is floppy, return its image size.
- * otherwise return 0.
- */
-static size_t
-fd_boot_image_size(int media_type)
-{
-	switch (media_type) {
-	case BOOT_MEDIA_1_2M_DISKETTE:
-		return (FD_1_2M_SIZE);
-	case BOOT_MEDIA_1_44M_DISKETTE:
-		return (FD_1_44M_SIZE);
-	case BOOT_MEDIA_2_88M_DISKETTE:
-		return (FD_2_88M_SIZE);
-	default:
-		return (0);
-	}
-}
-
-/*
- * Make a boot catalog image data.
- */
-static int
-make_boot_catalog(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	unsigned char *block;
-	unsigned char *p;
-	uint16_t sum, *wp;
-
-	block = wb_buffptr(a);
-	memset(block, 0, LOGICAL_BLOCK_SIZE);
-	p = block;
-	/*
-	 * Validation Entry
-	 */
-	/* Header ID */
-	p[0] = 1;
-	/* Platform ID */
-	p[1] = iso9660->el_torito.platform_id;
-	/* Reserved */
-	p[2] = p[3] = 0;
-	/* ID */
-	if (archive_strlen(&(iso9660->el_torito.id)) > 0)
-		strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
-	p[27] = 0;
-	/* Checksum */
-	p[28] = p[29] = 0;
-	/* Key */
-	p[30] = 0x55;
-	p[31] = 0xAA;
-
-	sum = 0;
-	wp = (uint16_t *)block;
-	while (wp < (uint16_t *)&block[32])
-		sum += archive_le16dec(wp++);
-	set_num_721(&block[28], (~sum) + 1);
-
-	/*
-	 * Initial/Default Entry
-	 */
-	p = &block[32];
-	/* Boot Indicator */
-	p[0] = 0x88;
-	/* Boot media type */
-	p[1] = iso9660->el_torito.media_type;
-	/* Load Segment */
-	if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
-		set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
-	else
-		set_num_721(&p[2], 0);
-	/* System Type */
-	p[4] = iso9660->el_torito.system_type;
-	/* Unused */
-	p[5] = 0;
-	/* Sector Count */
-	if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
-		set_num_721(&p[6], iso9660->el_torito.boot_load_size);
-	else
-		set_num_721(&p[6], 1);
-	/* Load RBA */
-	set_num_731(&p[8],
-	    iso9660->el_torito.boot->file->content.location);
-	/* Unused */
-	memset(&p[12], 0, 20);
-
-	return (wb_consume(a, LOGICAL_BLOCK_SIZE));
-}
-
-static int
-setup_boot_information(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isoent *np;
-	int64_t size;
-	uint32_t sum;
-	unsigned char buff[4096];
-
-	np = iso9660->el_torito.boot;
-	lseek(iso9660->temp_fd,
-	    np->file->content.offset_of_temp + 64, SEEK_SET);
-	size = archive_entry_size(np->file->entry) - 64;
-	if (size <= 0) {
-		archive_set_error(&a->archive, errno,
-		    "Boot file(%jd) is too small", (intmax_t)size + 64);
-		return (ARCHIVE_FATAL);
-	}
-	sum = 0;
-	while (size > 0) {
-		size_t rsize;
-		ssize_t i, rs;
-
-		if (size > (int64_t)sizeof(buff))
-			rsize = sizeof(buff);
-		else
-			rsize = (size_t)size;
-
-		rs = read(iso9660->temp_fd, buff, rsize);
-		if (rs <= 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't read temporary file(%jd)",
-			    (intmax_t)rs);
-			return (ARCHIVE_FATAL);
-		}
-		for (i = 0; i < rs; i += 4)
-			sum += archive_le32dec(buff + i);
-		size -= rs;
-	}
-	/* Set the location of Primary Volume Descriptor. */
-	set_num_731(buff, SYSTEM_AREA_BLOCK);
-	/* Set the location of the boot file. */
-	set_num_731(buff+4, np->file->content.location);
-	/* Set the size of the boot file. */
-	size = fd_boot_image_size(iso9660->el_torito.media_type);
-	if (size == 0)
-		size = archive_entry_size(np->file->entry);
-	set_num_731(buff+8, (uint32_t)size);
-	/* Set the sum of the boot file. */
-	set_num_731(buff+12, sum);
-	/* Clear reserved bytes. */
-	memset(buff+16, 0, 40);
-
-	/* Overwrite the boot file. */
-	lseek(iso9660->temp_fd,
-	    np->file->content.offset_of_temp + 8, SEEK_SET);
-	return (write_to_temp(a, buff, 56));
-}
-
-#ifdef HAVE_ZLIB_H
-
-static int
-zisofs_init_zstream(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	int r;
-
-	iso9660->zisofs.stream.next_in = NULL;
-	iso9660->zisofs.stream.avail_in = 0;
-	iso9660->zisofs.stream.total_in = 0;
-	iso9660->zisofs.stream.total_out = 0;
-	if (iso9660->zisofs.stream_valid)
-		r = deflateReset(&(iso9660->zisofs.stream));
-	else {
-		r = deflateInit(&(iso9660->zisofs.stream),
-		    iso9660->zisofs.compression_level);
-		iso9660->zisofs.stream_valid = 1;
-	}
-	switch (r) {
-	case Z_OK:
-		break;
-	default:
-	case Z_STREAM_ERROR:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing "
-		    "compression library: invalid setup parameter");
-		return (ARCHIVE_FATAL);
-	case Z_MEM_ERROR:
-		archive_set_error(&a->archive, ENOMEM,
-		    "Internal error initializing "
-		    "compression library");
-		return (ARCHIVE_FATAL);
-	case Z_VERSION_ERROR:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing "
-		    "compression library: invalid library version");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_ZLIB_H */
-
-static int
-zisofs_init(struct archive_write *a,  struct isofile *file)
-{
-	struct iso9660 *iso9660 = a->format_data;
-#ifdef HAVE_ZLIB_H
-	uint64_t tsize;
-	size_t _ceil, bpsize;
-	int r;
-#endif
-
-	iso9660->zisofs.detect_magic = 0;
-	iso9660->zisofs.making = 0;
-
-	if (!iso9660->opt.rr || !iso9660->opt.zisofs)
-		return (ARCHIVE_OK);
-
-	if (archive_entry_size(file->entry) >= 24 &&
-	    archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
-		/* Acceptable file size for zisofs. */
-		iso9660->zisofs.detect_magic = 1;
-		iso9660->zisofs.magic_cnt = 0;
-	}
-	if (!iso9660->zisofs.detect_magic)
-		return (ARCHIVE_OK);
-
-#ifdef HAVE_ZLIB_H
-	/* The number of Logical Blocks which uncompressed data
-	 * will use in iso-image file is the same as the number of
-	 * Logical Blocks which zisofs(compressed) data will use
-	 * in ISO-image file. It won't reduce iso-image file size. */
-	if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
-		return (ARCHIVE_OK);
-
-	/* Initialize compression library */
-	r = zisofs_init_zstream(a);
-	if (r != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
-	file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
-	file->zisofs.log2_bs = ZF_LOG2_BS;
-	file->zisofs.uncompressed_size =
-		(uint32_t)archive_entry_size(file->entry);
-
-	/* Calculate a size of Block Pointers of zisofs. */
-	_ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
-		>> file->zisofs.log2_bs;
-	iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
-	iso9660->zisofs.block_pointers_idx = 0;
-
-	/* Ensure a buffer size used for Block Pointers */
-	bpsize = iso9660->zisofs.block_pointers_cnt *
-	    sizeof(iso9660->zisofs.block_pointers[0]);
-	if (iso9660->zisofs.block_pointers_allocated < bpsize) {
-		free(iso9660->zisofs.block_pointers);
-		iso9660->zisofs.block_pointers = malloc(bpsize);
-		if (iso9660->zisofs.block_pointers == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate data");
-			return (ARCHIVE_FATAL);
-		}
-		iso9660->zisofs.block_pointers_allocated = bpsize;
-	}
-
-	/*
-	 * Skip zisofs header and Block Pointers, which we will write
-	 * after all compressed data of a file written to the temporary
-	 * file.
-	 */
-	tsize = ZF_HEADER_SIZE + bpsize;
-	if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/*
-	 * Initialize some variables to make zisofs.
-	 */
-	archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
-		(uint32_t)tsize);
-	iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
-	iso9660->zisofs.making = 1;
-	iso9660->zisofs.allzero = 1;
-	iso9660->zisofs.block_offset = tsize;
-	iso9660->zisofs.total_size = tsize;
-	iso9660->cur_file->cur_content->size = tsize;
-#endif
-
-	return (ARCHIVE_OK);
-}
-
-static void
-zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file = iso9660->cur_file;
-	const unsigned char *p, *endp;
-	const unsigned char *magic_buff;
-	uint32_t uncompressed_size;
-	unsigned char header_size;
-	unsigned char log2_bs;
-	size_t _ceil, doff;
-	uint32_t bst, bed;
-	int magic_max;
-	int64_t entry_size;
-
-	entry_size = archive_entry_size(file->entry);
-	if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
-		magic_max = (int)entry_size;
-	else
-		magic_max = sizeof(iso9660->zisofs.magic_buffer);
-
-	if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
-		/* It's unnecessary we copy buffer. */
-		magic_buff = buff;
-	else {
-		if (iso9660->zisofs.magic_cnt < magic_max) {
-			size_t l;
-
-			l = sizeof(iso9660->zisofs.magic_buffer)
-			    - iso9660->zisofs.magic_cnt;
-			if (l > s)
-				l = s;
-			memcpy(iso9660->zisofs.magic_buffer
-			    + iso9660->zisofs.magic_cnt, buff, l);
-			iso9660->zisofs.magic_cnt += (int)l;
-			if (iso9660->zisofs.magic_cnt < magic_max)
-				return;
-		}
-		magic_buff = iso9660->zisofs.magic_buffer;
-	}
-	iso9660->zisofs.detect_magic = 0;
-	p = magic_buff;
-
-	/* Check the magic code of zisofs. */
-	if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
-		/* This is not zisofs file which made by mkzftree. */
-		return;
-	p += sizeof(zisofs_magic);
-
-	/* Read a zisofs header. */
-	uncompressed_size = archive_le32dec(p);
-	header_size = p[4];
-	log2_bs = p[5];
-	if (uncompressed_size < 24 || header_size != 4 ||
-	    log2_bs > 30 || log2_bs < 7)
-		return;/* Invalid or not supported header. */
-
-	/* Calculate a size of Block Pointers of zisofs. */
-	_ceil = (uncompressed_size +
-	        (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
-	doff = (_ceil + 1) * 4 + 16;
-	if (entry_size < (int64_t)doff)
-		return;/* Invalid data. */
-
-	/* Check every Block Pointer has valid value. */
-	p = magic_buff + 16;
-	endp = magic_buff + magic_max;
-	while (_ceil && p + 8 <= endp) {
-		bst = archive_le32dec(p);
-		if (bst != doff)
-			return;/* Invalid data. */
-		p += 4;
-		bed = archive_le32dec(p);
-		if (bed < bst || bed > entry_size)
-			return;/* Invalid data. */
-		doff += bed - bst;
-		_ceil--;
-	}
-
-	file->zisofs.uncompressed_size = uncompressed_size;
-	file->zisofs.header_size = header_size;
-	file->zisofs.log2_bs = log2_bs;
-
-	/* Disable making a zisofs image. */
-	iso9660->zisofs.making = 0;
-}
-
-#ifdef HAVE_ZLIB_H
-
-/*
- * Compress data and write it to a temporary file.
- */
-static int
-zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file = iso9660->cur_file;
-	const unsigned char *b;
-	z_stream *zstrm;
-	size_t avail, csize;
-	int flush, r;
-
-	zstrm = &(iso9660->zisofs.stream);
-	zstrm->next_out = wb_buffptr(a);
-	zstrm->avail_out = (uInt)wb_remaining(a);
-	b = (const unsigned char *)buff;
-	do {
-		avail = ZF_BLOCK_SIZE - zstrm->total_in;
-		if (s < avail) {
-			avail = s;
-			flush = Z_NO_FLUSH;
-		} else
-			flush = Z_FINISH;
-		iso9660->zisofs.remaining -= avail;
-		if (iso9660->zisofs.remaining <= 0)
-			flush = Z_FINISH;
-
-		zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
-		zstrm->avail_in = (uInt)avail;
-
-		/*
-		 * Check if current data block are all zero.
-		 */
-		if (iso9660->zisofs.allzero) {
-			const unsigned char *nonzero = b;
-			const unsigned char *nonzeroend = b + avail;
-
-			while (nonzero < nonzeroend)
-				if (*nonzero++) {
-					iso9660->zisofs.allzero = 0;
-					break;
-				}
-		}
-		b += avail;
-		s -= avail;
-
-		/*
-		 * If current data block are all zero, we do not use
-		 * compressed data.
-		 */
-		if (flush == Z_FINISH && iso9660->zisofs.allzero &&
-		    avail + zstrm->total_in == ZF_BLOCK_SIZE) {
-			if (iso9660->zisofs.block_offset !=
-			    file->cur_content->size) {
-				int64_t diff;
-
-				r = wb_set_offset(a,
-				    file->cur_content->offset_of_temp +
-				        iso9660->zisofs.block_offset);
-				if (r != ARCHIVE_OK)
-					return (r);
-				diff = file->cur_content->size -
-				    iso9660->zisofs.block_offset;
-				file->cur_content->size -= diff;
-				iso9660->zisofs.total_size -= diff;
-			}
-			zstrm->avail_in = 0;
-		}
-
-		/*
-		 * Compress file data.
-		 */
-		while (zstrm->avail_in > 0) {
-			csize = zstrm->total_out;
-			r = deflate(zstrm, flush);
-			switch (r) {
-			case Z_OK:
-			case Z_STREAM_END:
-				csize = zstrm->total_out - csize;
-				if (wb_consume(a, csize) != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-				iso9660->zisofs.total_size += csize;
-				iso9660->cur_file->cur_content->size += csize;
-				zstrm->next_out = wb_buffptr(a);
-				zstrm->avail_out = (uInt)wb_remaining(a);
-				break;
-			default:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Compression failed:"
-				    " deflate() call returned status %d",
-				    r);
-				return (ARCHIVE_FATAL);
-			}
-		}
-
-		if (flush == Z_FINISH) {
-			/*
-			 * Save the information of one zisofs block.
-			 */
-			iso9660->zisofs.block_pointers_idx ++;
-			archive_le32enc(&(iso9660->zisofs.block_pointers[
-			    iso9660->zisofs.block_pointers_idx]),
-				(uint32_t)iso9660->zisofs.total_size);
-			r = zisofs_init_zstream(a);
-			if (r != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			iso9660->zisofs.allzero = 1;
-			iso9660->zisofs.block_offset = file->cur_content->size;
-		}
-	} while (s);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-zisofs_finish_entry(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file = iso9660->cur_file;
-	unsigned char buff[16];
-	size_t s;
-	int64_t tail;
-
-	/* Direct temp file stream to zisofs temp file stream. */
-	archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
-
-	/*
-	 * Save a file pointer which points the end of current zisofs data.
-	 */
-	tail = wb_offset(a);
-
-	/*
-	 * Make a header.
-	 *
-	 * +-----------------+----------------+-----------------+
-	 * | Header 16 bytes | Block Pointers | Compressed data |
-	 * +-----------------+----------------+-----------------+
-	 * 0                16               +X
-	 * Block Pointers :
-	 *   4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
-	 *
-	 * Write zisofs header.
-	 *    Magic number
-	 * +----+----+----+----+----+----+----+----+
-	 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
-	 * +----+----+----+----+----+----+----+----+
-	 * 0    1    2    3    4    5    6    7    8
-	 *
-	 * +------------------------+------------------+
-	 * | Uncompressed file size | header_size >> 2 |
-	 * +------------------------+------------------+
-	 * 8                       12                 13
-	 *
-	 * +-----------------+----------------+
-	 * | log2 block_size | Reserved(0000) |
-	 * +-----------------+----------------+
-	 * 13               14               16
-	 */
-	memcpy(buff, zisofs_magic, 8);
-	set_num_731(buff+8, file->zisofs.uncompressed_size);
-	buff[12] = file->zisofs.header_size;
-	buff[13] = file->zisofs.log2_bs;
-	buff[14] = buff[15] = 0;/* Reserved */
-
-	/* Move to the right position to write the header. */
-	wb_set_offset(a, file->content.offset_of_temp);
-
-	/* Write the header. */
-	if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/*
-	 * Write zisofs Block Pointers.
-	 */
-	s = iso9660->zisofs.block_pointers_cnt *
-	    sizeof(iso9660->zisofs.block_pointers[0]);
-	if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
-	    != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Set a file pointer back to the end of the temporary file. */
-	wb_set_offset(a, tail);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-zisofs_free(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	int ret = ARCHIVE_OK;
-
-	free(iso9660->zisofs.block_pointers);
-	if (iso9660->zisofs.stream_valid &&
-	    deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		ret = ARCHIVE_FATAL;
-	}
-	iso9660->zisofs.block_pointers = NULL;
-	iso9660->zisofs.stream_valid = 0;
-	return (ret);
-}
-
-struct zisofs_extract {
-	int		 pz_log2_bs; /* Log2 of block size */
-	uint64_t	 pz_uncompressed_size;
-	size_t		 uncompressed_buffer_size;
-
-	unsigned int	 initialized:1;
-	unsigned int	 header_passed:1;
-
-	uint32_t	 pz_offset;
-	unsigned char	*block_pointers;
-	size_t		 block_pointers_size;
-	size_t		 block_pointers_avail;
-	size_t		 block_off;
-	uint32_t	 block_avail;
-
-	z_stream	 stream;
-	int		 stream_valid;
-};
-
-static ssize_t
-zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
-    const unsigned char *p, size_t bytes)
-{
-	size_t avail = bytes;
-	size_t _ceil, xsize;
-
-	/* Allocate block pointers buffer. */
-	_ceil = (size_t)((zisofs->pz_uncompressed_size +
-		(((int64_t)1) << zisofs->pz_log2_bs) - 1)
-		>> zisofs->pz_log2_bs);
-	xsize = (_ceil + 1) * 4;
-	if (zisofs->block_pointers == NULL) {
-		size_t alloc = ((xsize >> 10) + 1) << 10;
-		zisofs->block_pointers = malloc(alloc);
-		if (zisofs->block_pointers == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "No memory for zisofs decompression");
-			return (ARCHIVE_FATAL);
-		}
-	}
-	zisofs->block_pointers_size = xsize;
-
-	/* Allocate uncompressed data buffer. */
-	zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
-
-	/*
-	 * Read the file header, and check the magic code of zisofs.
-	 */
-	if (!zisofs->header_passed) {
-		int err = 0;
-		if (avail < 16) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs file body");
-			return (ARCHIVE_FATAL);
-		}
-
-		if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
-			err = 1;
-		else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
-			err = 1;
-		else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
-			err = 1;
-		if (err) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs file body");
-			return (ARCHIVE_FATAL);
-		}
-		avail -= 16;
-		p += 16;
-		zisofs->header_passed = 1;
-	}
-
-	/*
-	 * Read block pointers.
-	 */
-	if (zisofs->header_passed &&
-	    zisofs->block_pointers_avail < zisofs->block_pointers_size) {
-		xsize = zisofs->block_pointers_size
-		    - zisofs->block_pointers_avail;
-		if (avail < xsize)
-			xsize = avail;
-		memcpy(zisofs->block_pointers
-		    + zisofs->block_pointers_avail, p, xsize);
-		zisofs->block_pointers_avail += xsize;
-		avail -= xsize;
-	    	if (zisofs->block_pointers_avail
-		    == zisofs->block_pointers_size) {
-			/* We've got all block pointers and initialize
-			 * related variables.	*/
-			zisofs->block_off = 0;
-			zisofs->block_avail = 0;
-			/* Complete a initialization */
-			zisofs->initialized = 1;
-		}
-	}
-	return ((ssize_t)avail);
-}
-
-static ssize_t
-zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
-    const unsigned char *p, size_t bytes)
-{
-	size_t avail;
-	int r;
-
-	if (!zisofs->initialized) {
-		ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
-		if (rs < 0)
-			return (rs);
-		if (!zisofs->initialized) {
-			/* We need more data. */
-			zisofs->pz_offset += (uint32_t)bytes;
-			return (bytes);
-		}
-		avail = rs;
-		p += bytes - avail;
-	} else
-		avail = bytes;
-
-	/*
-	 * Get block offsets from block pointers.
-	 */
-	if (zisofs->block_avail == 0) {
-		uint32_t bst, bed;
-
-		if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
-			/* There isn't a pair of offsets. */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers");
-			return (ARCHIVE_FATAL);
-		}
-		bst = archive_le32dec(
-		    zisofs->block_pointers + zisofs->block_off);
-		if (bst != zisofs->pz_offset + (bytes - avail)) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers(cannot seek)");
-			return (ARCHIVE_FATAL);
-		}
-		bed = archive_le32dec(
-		    zisofs->block_pointers + zisofs->block_off + 4);
-		if (bed < bst) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Illegal zisofs block pointers");
-			return (ARCHIVE_FATAL);
-		}
-		zisofs->block_avail = bed - bst;
-		zisofs->block_off += 4;
-
-		/* Initialize compression library for new block. */
-		if (zisofs->stream_valid)
-			r = inflateReset(&zisofs->stream);
-		else
-			r = inflateInit(&zisofs->stream);
-		if (r != Z_OK) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Can't initialize zisofs decompression.");
-			return (ARCHIVE_FATAL);
-		}
-		zisofs->stream_valid = 1;
-		zisofs->stream.total_in = 0;
-		zisofs->stream.total_out = 0;
-	}
-
-	/*
-	 * Make uncompressed data.
-	 */
-	if (zisofs->block_avail == 0) {
-		/*
-		 * It's basically 32K bytes NUL data.
-		 */
-		unsigned char *wb;
-		size_t size, wsize;
-
-		size = zisofs->uncompressed_buffer_size;
-		while (size) {
-			wb = wb_buffptr(a);
-			if (size > wb_remaining(a))
-				wsize = wb_remaining(a);
-			else
-				wsize = size;
-			memset(wb, 0, wsize);
-			r = wb_consume(a, wsize);
-			if (r < 0)
-				return (r);
-			size -= wsize;
-		}
-	} else {
-		zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
-		if (avail > zisofs->block_avail)
-			zisofs->stream.avail_in = zisofs->block_avail;
-		else
-			zisofs->stream.avail_in = (uInt)avail;
-		zisofs->stream.next_out = wb_buffptr(a);
-		zisofs->stream.avail_out = (uInt)wb_remaining(a);
-
-		r = inflate(&zisofs->stream, 0);
-		switch (r) {
-		case Z_OK: /* Decompressor made some progress.*/
-		case Z_STREAM_END: /* Found end of stream. */
-			break;
-		default:
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "zisofs decompression failed (%d)", r);
-			return (ARCHIVE_FATAL);
-		}
-		avail -= zisofs->stream.next_in - p;
-		zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
-		r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
-		if (r < 0)
-			return (r);
-	}
-	zisofs->pz_offset += (uint32_t)bytes;
-	return (bytes - avail);
-}
-
-static int
-zisofs_rewind_boot_file(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-	struct isofile *file;
-	unsigned char *rbuff;
-	ssize_t r;
-	size_t remaining, rbuff_size;
-	struct zisofs_extract zext;
-	int64_t read_offset, write_offset, new_offset;
-	int fd, ret = ARCHIVE_OK;
-
-	file = iso9660->el_torito.boot->file;
-	/*
-	 * There is nothing to do if this boot file does not have
-	 * zisofs header.
-	 */
-	if (file->zisofs.header_size == 0)
-		return (ARCHIVE_OK);
-
-	/*
-	 * Uncompress the zisofs'ed file contents.
-	 */
-	memset(&zext, 0, sizeof(zext));
-	zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
-	zext.pz_log2_bs = file->zisofs.log2_bs;
-
-	fd = iso9660->temp_fd;
-	new_offset = wb_offset(a);
-	read_offset = file->content.offset_of_temp;
-	remaining = (size_t)file->content.size;
-	if (remaining > 1024 * 32)
-		rbuff_size = 1024 * 32;
-	else
-		rbuff_size = remaining;
-
-	rbuff = malloc(rbuff_size);
-	if (rbuff == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	while (remaining) {
-		size_t rsize;
-		ssize_t rs;
-
-		/* Get the current file pointer. */
-		write_offset = lseek(fd, 0, SEEK_CUR);
-
-		/* Change the file pointer to read. */
-		lseek(fd, read_offset, SEEK_SET);
-
-		rsize = rbuff_size;
-		if (rsize > remaining)
-			rsize = remaining;
-		rs = read(iso9660->temp_fd, rbuff, rsize);
-		if (rs <= 0) {
-			archive_set_error(&a->archive, errno,
-			    "Can't read temporary file(%jd)", (intmax_t)rs);
-			ret = ARCHIVE_FATAL;
-			break;
-		}
-		remaining -= rs;
-		read_offset += rs;
-
-		/* Put the file pointer back to write. */
-		lseek(fd, write_offset, SEEK_SET);
-
-		r = zisofs_extract(a, &zext, rbuff, rs);
-		if (r < 0) {
-			ret = (int)r;
-			break;
-		}
-	}
-
-	if (ret == ARCHIVE_OK) {
-		/*
-		 * Change the boot file content from zisofs'ed data
-		 * to plain data.
-		 */
-		file->content.offset_of_temp = new_offset;
-		file->content.size = file->zisofs.uncompressed_size;
-		archive_entry_set_size(file->entry, file->content.size);
-		/* Set to be no zisofs. */
-		file->zisofs.header_size = 0;
-		file->zisofs.log2_bs = 0;
-		file->zisofs.uncompressed_size = 0;
-		r = wb_write_padding_to_temp(a, file->content.size);
-		if (r < 0)
-			ret = ARCHIVE_FATAL;
-	}
-
-	/*
-	 * Free the resource we used in this function only.
-	 */
-	free(rbuff);
-	free(zext.block_pointers);
-	if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
-        	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		ret = ARCHIVE_FATAL;
-	}
-
-	return (ret);
-}
-
-#else
-
-static int
-zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	(void)buff; /* UNUSED */
-	(void)s; /* UNUSED */
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programming error");
-	return (ARCHIVE_FATAL);
-}
-
-static int
-zisofs_rewind_boot_file(struct archive_write *a)
-{
-	struct iso9660 *iso9660 = a->format_data;
-
-	if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "We cannot extract the zisofs imaged boot file;"
-		    " this may not boot in being zisofs imaged");
-		return (ARCHIVE_FAILED);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-zisofs_finish_entry(struct archive_write *a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-static int
-zisofs_free(struct archive_write *a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-#endif /* HAVE_ZLIB_H */
-
diff --git a/c/archive_write_set_format_mtree.c b/c/archive_write_set_format_mtree.c
deleted file mode 100644
--- a/c/archive_write_set_format_mtree.c
+++ /dev/null
@@ -1,2217 +0,0 @@
-/*-
- * Copyright (c) 2008 Joerg Sonnenberger
- * Copyright (c) 2009-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "archive.h"
-#include "archive_digest_private.h"
-#include "archive_entry.h"
-#include "archive_entry_private.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-#define INDENTNAMELEN	15
-#define MAXLINELEN	80
-#define SET_KEYS	\
-	(F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
-
-struct attr_counter {
-	struct attr_counter *prev;
-	struct attr_counter *next;
-	struct mtree_entry *m_entry;
-	int count;
-};
-
-struct att_counter_set {
-	struct attr_counter *uid_list;
-	struct attr_counter *gid_list;
-	struct attr_counter *mode_list;
-	struct attr_counter *flags_list;
-};
-
-struct mtree_chain {
-	struct mtree_entry *first;
-	struct mtree_entry **last;
-};
-
-/*
- * The Data only for a directory file.
- */
-struct dir_info {
-	struct archive_rb_tree rbtree;
-	struct mtree_chain children;
-	struct mtree_entry *chnext;
-	int virtual;
-};
-
-/*
- * The Data only for a regular file.
- */
-struct reg_info {
-	int compute_sum;
-	uint32_t crc;
-	struct ae_digest digest;
-};
-
-struct mtree_entry {
-	struct archive_rb_node rbnode;
-	struct mtree_entry *next;
-	struct mtree_entry *parent;
-	struct dir_info *dir_info;
-	struct reg_info *reg_info;
-
-	struct archive_string parentdir;
-	struct archive_string basename;
-	struct archive_string pathname;
-	struct archive_string symlink;
-	struct archive_string uname;
-	struct archive_string gname;
-	struct archive_string fflags_text;
-	unsigned int nlink;
-	mode_t filetype;
-	mode_t mode;
-	int64_t size;
-	int64_t uid;
-	int64_t gid;
-	time_t mtime;
-	long mtime_nsec;
-	unsigned long fflags_set;
-	unsigned long fflags_clear;
-	dev_t rdevmajor;
-	dev_t rdevminor;
-	dev_t devmajor;
-	dev_t devminor;
-	int64_t ino;
-};
-
-struct mtree_writer {
-	struct mtree_entry *mtree_entry;
-	struct mtree_entry *root;
-	struct mtree_entry *cur_dirent;
-	struct archive_string cur_dirstr;
-	struct mtree_chain file_list;
-
-	struct archive_string ebuf;
-	struct archive_string buf;
-	int first;
-	uint64_t entry_bytes_remaining;
-
-	/*
-	 * Set global value.
-	 */
-	struct {
-		int		processing;
-		mode_t		type;
-		int		keys;
-		int64_t		uid;
-		int64_t		gid;
-		mode_t		mode;
-		unsigned long	fflags_set;
-		unsigned long	fflags_clear;
-	} set;
-	struct att_counter_set	acs;
-	int classic;
-	int depth;
-
-	/* check sum */
-	int compute_sum;
-	uint32_t crc;
-	uint64_t crc_len;
-#ifdef ARCHIVE_HAS_MD5
-	archive_md5_ctx md5ctx;
-#endif
-#ifdef ARCHIVE_HAS_RMD160
-	archive_rmd160_ctx rmd160ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	archive_sha1_ctx sha1ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA256
-	archive_sha256_ctx sha256ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA384
-	archive_sha384_ctx sha384ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA512
-	archive_sha512_ctx sha512ctx;
-#endif
-	/* Keyword options */
-	int keys;
-#define	F_CKSUM		0x00000001		/* checksum */
-#define	F_DEV		0x00000002		/* device type */
-#define	F_DONE		0x00000004		/* directory done */
-#define	F_FLAGS		0x00000008		/* file flags */
-#define	F_GID		0x00000010		/* gid */
-#define	F_GNAME		0x00000020		/* group name */
-#define	F_IGN		0x00000040		/* ignore */
-#define	F_MAGIC		0x00000080		/* name has magic chars */
-#define	F_MD5		0x00000100		/* MD5 digest */
-#define	F_MODE		0x00000200		/* mode */
-#define	F_NLINK		0x00000400		/* number of links */
-#define	F_NOCHANGE 	0x00000800		/* If owner/mode "wrong", do
-						 * not change */
-#define	F_OPT		0x00001000		/* existence optional */
-#define	F_RMD160 	0x00002000		/* RIPEMD160 digest */
-#define	F_SHA1		0x00004000		/* SHA-1 digest */
-#define	F_SIZE		0x00008000		/* size */
-#define	F_SLINK		0x00010000		/* symbolic link */
-#define	F_TAGS		0x00020000		/* tags */
-#define	F_TIME		0x00040000		/* modification time */
-#define	F_TYPE		0x00080000		/* file type */
-#define	F_UID		0x00100000		/* uid */
-#define	F_UNAME		0x00200000		/* user name */
-#define	F_VISIT		0x00400000		/* file visited */
-#define	F_SHA256	0x00800000		/* SHA-256 digest */
-#define	F_SHA384	0x01000000		/* SHA-384 digest */
-#define	F_SHA512	0x02000000		/* SHA-512 digest */
-#define	F_INO		0x04000000		/* inode number */
-#define	F_RESDEV	0x08000000		/* device ID on which the
-						 * entry resides */
-
-	/* Options */
-	int dironly;		/* If it is set, ignore all files except
-				 * directory files, like mtree(8) -d option. */
-	int indent;		/* If it is set, indent output data. */
-	int output_global_set;	/* If it is set, use /set keyword to set
-				 * global values. When generating mtree
-				 * classic format, it is set by default. */
-};
-
-#define DEFAULT_KEYS	(F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
-			 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
-			 | F_UNAME)
-#define attr_counter_set_reset	attr_counter_set_free
-
-static void attr_counter_free(struct attr_counter **);
-static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
-	struct attr_counter *, struct mtree_entry *);
-static struct attr_counter * attr_counter_new(struct mtree_entry *,
-	struct attr_counter *);
-static int attr_counter_set_collect(struct mtree_writer *,
-	struct mtree_entry *);
-static void attr_counter_set_free(struct mtree_writer *);
-static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
-static int mtree_entry_add_child_tail(struct mtree_entry *,
-	struct mtree_entry *);
-static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
-	struct mtree_entry **);
-static int mtree_entry_cmp_node(const struct archive_rb_node *,
-	const struct archive_rb_node *);
-static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
-static int mtree_entry_exchange_same_entry(struct archive_write *,
-    struct mtree_entry *, struct mtree_entry *);
-static void mtree_entry_free(struct mtree_entry *);
-static int mtree_entry_new(struct archive_write *, struct archive_entry *,
-	struct mtree_entry **);
-static void mtree_entry_register_free(struct mtree_writer *);
-static void mtree_entry_register_init(struct mtree_writer *);
-static int mtree_entry_setup_filenames(struct archive_write *,
-	struct mtree_entry *, struct archive_entry *);
-static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
-static void sum_init(struct mtree_writer *);
-static void sum_update(struct mtree_writer *, const void *, size_t);
-static void sum_final(struct mtree_writer *, struct reg_info *);
-static void sum_write(struct archive_string *, struct reg_info *);
-static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
-static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *);
-
-#define	COMPUTE_CRC(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
-static const uint32_t crctab[] = {
-	0x0,
-	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
-	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
-	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
-	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
-	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
-	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
-	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
-	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
-	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
-	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
-	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
-	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
-	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
-	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
-	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
-	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
-	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
-	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
-	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
-	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
-	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
-	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
-	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
-	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
-	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
-	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
-	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
-	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
-	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
-	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
-	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
-	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
-	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
-	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
-	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
-	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
-	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
-	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
-	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
-	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
-	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
-	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
-	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
-	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
-	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
-	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
-	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
-	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
-	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
-	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
-	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
-};
-
-static const unsigned char safe_char[256] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
-	/* !"$%&'()*+,-./  EXCLUSION:0x20( ) 0x23(#) */
-	0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
-	/* 0123456789:;<>?  EXCLUSION:0x3d(=) */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
-	/* @ABCDEFGHIJKLMNO */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
-	/* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\)  */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */
-	/* `abcdefghijklmno */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
-	/* pqrstuvwxyz{|}~ */
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-};
-
-static void
-mtree_quote(struct archive_string *s, const char *str)
-{
-	const char *start;
-	char buf[4];
-	unsigned char c;
-
-	for (start = str; *str != '\0'; ++str) {
-		if (safe_char[*(const unsigned char *)str])
-			continue;
-		if (start != str)
-			archive_strncat(s, start, str - start);
-		c = (unsigned char)*str;
-		buf[0] = '\\';
-		buf[1] = (c / 64) + '0';
-		buf[2] = (c / 8 % 8) + '0';
-		buf[3] = (c % 8) + '0';
-		archive_strncat(s, buf, 4);
-		start = str + 1;
-	}
-
-	if (start != str)
-		archive_strncat(s, start, str - start);
-}
-
-/*
- * Indent a line as the mtree utility does so it is readable for people.
- */
-static void
-mtree_indent(struct mtree_writer *mtree)
-{
-	int i, fn, nd, pd;
-	const char *r, *s, *x;
-
-	if (mtree->classic) {
-		if (mtree->indent) {
-			nd = 0;
-			pd = mtree->depth * 4;
-		} else {
-			nd = mtree->depth?4:0;
-			pd = 0;
-		}
-	} else
-		nd = pd = 0;
-	fn = 1;
-	s = r = mtree->ebuf.s;
-	x = NULL;
-	while (*r == ' ')
-		r++;
-	while ((r = strchr(r, ' ')) != NULL) {
-		if (fn) {
-			fn = 0;
-			for (i = 0; i < nd + pd; i++)
-				archive_strappend_char(&mtree->buf, ' ');
-			archive_strncat(&mtree->buf, s, r - s);
-			if (nd + (r -s) > INDENTNAMELEN) {
-				archive_strncat(&mtree->buf, " \\\n", 3);
-				for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
-					archive_strappend_char(&mtree->buf, ' ');
-			} else {
-				for (i = (int)(r -s + nd);
-				    i < (INDENTNAMELEN + 1); i++)
-					archive_strappend_char(&mtree->buf, ' ');
-			}
-			s = ++r;
-			x = NULL;
-			continue;
-		}
-		if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN)
-			x = r++;
-		else {
-			if (x == NULL)
-				x = r;
-			archive_strncat(&mtree->buf, s, x - s);
-			archive_strncat(&mtree->buf, " \\\n", 3);
-			for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
-				archive_strappend_char(&mtree->buf, ' ');
-			s = r = ++x;
-			x = NULL;
-		}
-	}
-	if (fn) {
-		for (i = 0; i < nd + pd; i++)
-			archive_strappend_char(&mtree->buf, ' ');
-		archive_strcat(&mtree->buf, s);
-		s += strlen(s);
-	}
-	if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
-		/* Last keyword is longer. */
-		archive_strncat(&mtree->buf, s, x - s);
-		archive_strncat(&mtree->buf, " \\\n", 3);
-		for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
-			archive_strappend_char(&mtree->buf, ' ');
-		s = ++x;
-	}
-	archive_strcat(&mtree->buf, s);
-	archive_string_empty(&mtree->ebuf);
-}
-
-/*
- * Write /set keyword.
- * Set the most used value of uid, gid, mode and fflags, which are
- * collected by the attr_counter_set_collect() function.
- */
-static void
-write_global(struct mtree_writer *mtree)
-{
-	struct archive_string setstr;
-	struct archive_string unsetstr;
-	struct att_counter_set *acs;
-	int keys, oldkeys, effkeys;
-
-	archive_string_init(&setstr);
-	archive_string_init(&unsetstr);
-	keys = mtree->keys & SET_KEYS;
-	oldkeys = mtree->set.keys;
-	effkeys = keys;
-	acs = &mtree->acs;
-	if (mtree->set.processing) {
-		/*
-		 * Check if the global data needs updating.
-		 */
-		effkeys &= ~F_TYPE;
-		if (acs->uid_list == NULL)
-			effkeys &= ~(F_UNAME | F_UID);
-		else if (oldkeys & (F_UNAME | F_UID)) {
-			if (acs->uid_list->count < 2 ||
-			    mtree->set.uid == acs->uid_list->m_entry->uid)
-				effkeys &= ~(F_UNAME | F_UID);
-		}
-		if (acs->gid_list == NULL)
-			effkeys &= ~(F_GNAME | F_GID);
-		else if (oldkeys & (F_GNAME | F_GID)) {
-			if (acs->gid_list->count < 2 ||
-			    mtree->set.gid == acs->gid_list->m_entry->gid)
-				effkeys &= ~(F_GNAME | F_GID);
-		}
-		if (acs->mode_list == NULL)
-			effkeys &= ~F_MODE;
-		else if (oldkeys & F_MODE) {
-			if (acs->mode_list->count < 2 ||
-			    mtree->set.mode == acs->mode_list->m_entry->mode)
-				effkeys &= ~F_MODE;
-		}
-		if (acs->flags_list == NULL)
-			effkeys &= ~F_FLAGS;
-		else if ((oldkeys & F_FLAGS) != 0) {
-			if (acs->flags_list->count < 2 ||
-			    (acs->flags_list->m_entry->fflags_set ==
-				mtree->set.fflags_set &&
-			     acs->flags_list->m_entry->fflags_clear ==
-				mtree->set.fflags_clear))
-				effkeys &= ~F_FLAGS;
-		}
-	} else {
-		if (acs->uid_list == NULL)
-			keys &= ~(F_UNAME | F_UID);
-		if (acs->gid_list == NULL)
-			keys &= ~(F_GNAME | F_GID);
-		if (acs->mode_list == NULL)
-			keys &= ~F_MODE;
-		if (acs->flags_list == NULL)
-			keys &= ~F_FLAGS;
-	}
-	if ((keys & effkeys & F_TYPE) != 0) {
-		if (mtree->dironly) {
-			archive_strcat(&setstr, " type=dir");
-			mtree->set.type = AE_IFDIR;
-		} else {
-			archive_strcat(&setstr, " type=file");
-			mtree->set.type = AE_IFREG;
-		}
-	}
-	if ((keys & effkeys & F_UNAME) != 0) {
-		if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) {
-			archive_strcat(&setstr, " uname=");
-			mtree_quote(&setstr, acs->uid_list->m_entry->uname.s);
-		} else {
-			keys &= ~F_UNAME;
-			if ((oldkeys & F_UNAME) != 0)
-				archive_strcat(&unsetstr, " uname");
-		}
-	}
-	if ((keys & effkeys & F_UID) != 0) {
-		mtree->set.uid = acs->uid_list->m_entry->uid;
-		archive_string_sprintf(&setstr, " uid=%jd",
-		    (intmax_t)mtree->set.uid);
-	}
-	if ((keys & effkeys & F_GNAME) != 0) {
-		if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) {
-			archive_strcat(&setstr, " gname=");
-			mtree_quote(&setstr, acs->gid_list->m_entry->gname.s);
-		} else {
-			keys &= ~F_GNAME;
-			if ((oldkeys & F_GNAME) != 0)
-				archive_strcat(&unsetstr, " gname");
-		}
-	}
-	if ((keys & effkeys & F_GID) != 0) {
-		mtree->set.gid = acs->gid_list->m_entry->gid;
-		archive_string_sprintf(&setstr, " gid=%jd",
-		    (intmax_t)mtree->set.gid);
-	}
-	if ((keys & effkeys & F_MODE) != 0) {
-		mtree->set.mode = acs->mode_list->m_entry->mode;
-		archive_string_sprintf(&setstr, " mode=%o",
-		    (unsigned int)mtree->set.mode);
-	}
-	if ((keys & effkeys & F_FLAGS) != 0) {
-		if (archive_strlen(
-		    &(acs->flags_list->m_entry->fflags_text)) > 0) {
-			archive_strcat(&setstr, " flags=");
-			mtree_quote(&setstr,
-			    acs->flags_list->m_entry->fflags_text.s);
-			mtree->set.fflags_set =
-			    acs->flags_list->m_entry->fflags_set;
-			mtree->set.fflags_clear =
-			    acs->flags_list->m_entry->fflags_clear;
-		} else {
-			keys &= ~F_FLAGS;
-			if ((oldkeys & F_FLAGS) != 0)
-				archive_strcat(&unsetstr, " flags");
-		}
-	}
-	if (unsetstr.length > 0)
-		archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
-	archive_string_free(&unsetstr);
-	if (setstr.length > 0)
-		archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
-	archive_string_free(&setstr);
-	mtree->set.keys = keys;
-	mtree->set.processing = 1;
-}
-
-static struct attr_counter *
-attr_counter_new(struct mtree_entry *me, struct attr_counter *prev)
-{
-	struct attr_counter *ac;
-
-	ac = malloc(sizeof(*ac));
-	if (ac != NULL) {
-		ac->prev = prev;
-		ac->next = NULL;
-		ac->count = 1;
-		ac->m_entry = me;
-	}
-	return (ac);
-}
-
-static void
-attr_counter_free(struct attr_counter **top)
-{
-	struct attr_counter *ac, *tac;
-
-	if (*top == NULL)
-		return;
-	ac = *top;
-        while (ac != NULL) {
-		tac = ac->next;
-		free(ac);
-		ac = tac;
-	}
-	*top = NULL;
-}
-
-static int
-attr_counter_inc(struct attr_counter **top, struct attr_counter *ac,
-    struct attr_counter *last, struct mtree_entry *me)
-{
-	struct attr_counter *pac;
-
-	if (ac != NULL) {
-		ac->count++;
-		if (*top == ac || ac->prev->count >= ac->count)
-			return (0);
-		for (pac = ac->prev; pac; pac = pac->prev) {
-			if (pac->count >= ac->count)
-				break;
-		}
-		ac->prev->next = ac->next;
-		if (ac->next != NULL)
-			ac->next->prev = ac->prev;
-		if (pac != NULL) {
-			ac->prev = pac;
-			ac->next = pac->next;
-			pac->next = ac;
-			if (ac->next != NULL)
-				ac->next->prev = ac;
-		} else {
-			ac->prev = NULL;
-			ac->next = *top;
-			*top = ac;
-			ac->next->prev = ac;
-		}
-	} else if (last != NULL) {
-		ac = attr_counter_new(me, last);
-		if (ac == NULL)
-			return (-1);
-		last->next = ac;
-	}
-	return (0);
-}
-
-/*
- * Tabulate uid, gid, mode and fflags of a entry in order to be used for /set.
- */
-static int
-attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
-{
-	struct attr_counter *ac, *last;
-	struct att_counter_set *acs = &mtree->acs;
-	int keys = mtree->keys;
-
-	if (keys & (F_UNAME | F_UID)) {
-		if (acs->uid_list == NULL) {
-			acs->uid_list = attr_counter_new(me, NULL);
-			if (acs->uid_list == NULL)
-				return (-1);
-		} else {
-			last = NULL;
-			for (ac = acs->uid_list; ac; ac = ac->next) {
-				if (ac->m_entry->uid == me->uid)
-					break;
-				last = ac;
-			}
-			if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0)
-				return (-1);
-		}
-	}
-	if (keys & (F_GNAME | F_GID)) {
-		if (acs->gid_list == NULL) {
-			acs->gid_list = attr_counter_new(me, NULL);
-			if (acs->gid_list == NULL)
-				return (-1);
-		} else {
-			last = NULL;
-			for (ac = acs->gid_list; ac; ac = ac->next) {
-				if (ac->m_entry->gid == me->gid)
-					break;
-				last = ac;
-			}
-			if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0)
-				return (-1);
-		}
-	}
-	if (keys & F_MODE) {
-		if (acs->mode_list == NULL) {
-			acs->mode_list = attr_counter_new(me, NULL);
-			if (acs->mode_list == NULL)
-				return (-1);
-		} else {
-			last = NULL;
-			for (ac = acs->mode_list; ac; ac = ac->next) {
-				if (ac->m_entry->mode == me->mode)
-					break;
-				last = ac;
-			}
-			if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0)
-				return (-1);
-		}
-	}
-	if (keys & F_FLAGS) {
-		if (acs->flags_list == NULL) {
-			acs->flags_list = attr_counter_new(me, NULL);
-			if (acs->flags_list == NULL)
-				return (-1);
-		} else {
-			last = NULL;
-			for (ac = acs->flags_list; ac; ac = ac->next) {
-				if (ac->m_entry->fflags_set == me->fflags_set &&
-				    ac->m_entry->fflags_clear ==
-							me->fflags_clear)
-					break;
-				last = ac;
-			}
-			if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0)
-				return (-1);
-		}
-	}
-
-	return (0);
-}
-
-static void
-attr_counter_set_free(struct mtree_writer *mtree)
-{
-	struct att_counter_set *acs = &mtree->acs;
-
-	attr_counter_free(&acs->uid_list);
-	attr_counter_free(&acs->gid_list);
-	attr_counter_free(&acs->mode_list);
-	attr_counter_free(&acs->flags_list);
-}
-
-static int
-get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me)
-{
-	int keys;
-
-	keys = mtree->keys;
-
-	/*
-	 * If a keyword has been set by /set, we do not need to
-	 * output it.
-	 */
-	if (mtree->set.keys == 0)
-		return (keys);/* /set is not used. */
-
-	if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
-	     mtree->set.gid == me->gid)
-		keys &= ~(F_GNAME | F_GID);
-	if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
-	     mtree->set.uid == me->uid)
-		keys &= ~(F_UNAME | F_UID);
-	if (mtree->set.keys & F_FLAGS) {
-		if (mtree->set.fflags_set == me->fflags_set &&
-		    mtree->set.fflags_clear == me->fflags_clear)
-			keys &= ~F_FLAGS;
-	}
-	if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
-		keys &= ~F_MODE;
-
-	switch (me->filetype) {
-	case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
-	case AE_IFBLK: case AE_IFIFO:
-		break;
-	case AE_IFDIR:
-		if ((mtree->set.keys & F_TYPE) != 0 &&
-		    mtree->set.type == AE_IFDIR)
-			keys &= ~F_TYPE;
-		break;
-	case AE_IFREG:
-	default:	/* Handle unknown file types as regular files. */
-		if ((mtree->set.keys & F_TYPE) != 0 &&
-		    mtree->set.type == AE_IFREG)
-			keys &= ~F_TYPE;
-		break;
-	}
-
-	return (keys);
-}
-
-static int
-mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
-    struct mtree_entry **m_entry)
-{
-	struct mtree_entry *me;
-	const char *s;
-	int r;
-	static const struct archive_rb_tree_ops rb_ops = {
-		mtree_entry_cmp_node, mtree_entry_cmp_key
-	};
-
-	me = calloc(1, sizeof(*me));
-	if (me == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory for a mtree entry");
-		*m_entry = NULL;
-		return (ARCHIVE_FATAL);
-	}
-
-	r = mtree_entry_setup_filenames(a, me, entry);
-	if (r < ARCHIVE_WARN) {
-		mtree_entry_free(me);
-		*m_entry = NULL;
-		return (r);
-	}
-
-	if ((s = archive_entry_symlink(entry)) != NULL)
-		archive_strcpy(&me->symlink, s);
-	me->nlink = archive_entry_nlink(entry);
-	me->filetype = archive_entry_filetype(entry);
-	me->mode = archive_entry_mode(entry) & 07777;
-	me->uid = archive_entry_uid(entry);
-	me->gid = archive_entry_gid(entry);
-	if ((s = archive_entry_uname(entry)) != NULL)
-		archive_strcpy(&me->uname, s);
-	if ((s = archive_entry_gname(entry)) != NULL)
-		archive_strcpy(&me->gname, s);
-	if ((s = archive_entry_fflags_text(entry)) != NULL)
-		archive_strcpy(&me->fflags_text, s);
-	archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
-	me->mtime = archive_entry_mtime(entry);
-	me->mtime_nsec = archive_entry_mtime_nsec(entry);
-	me->rdevmajor = archive_entry_rdevmajor(entry);
-	me->rdevminor = archive_entry_rdevminor(entry);
-	me->devmajor = archive_entry_devmajor(entry);
-	me->devminor = archive_entry_devminor(entry);
-	me->ino = archive_entry_ino(entry);
-	me->size = archive_entry_size(entry);
-	if (me->filetype == AE_IFDIR) {
-		me->dir_info = calloc(1, sizeof(*me->dir_info));
-		if (me->dir_info == NULL) {
-			mtree_entry_free(me);
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for a mtree entry");
-			*m_entry = NULL;
-			return (ARCHIVE_FATAL);
-		}
-		__archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops);
-		me->dir_info->children.first = NULL;
-		me->dir_info->children.last = &(me->dir_info->children.first);
-		me->dir_info->chnext = NULL;
-	} else if (me->filetype == AE_IFREG) {
-		me->reg_info = calloc(1, sizeof(*me->reg_info));
-		if (me->reg_info == NULL) {
-			mtree_entry_free(me);
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for a mtree entry");
-			*m_entry = NULL;
-			return (ARCHIVE_FATAL);
-		}
-		me->reg_info->compute_sum = 0;
-	}
-
-	*m_entry = me;
-	return (ARCHIVE_OK);
-}
-
-static void
-mtree_entry_free(struct mtree_entry *me)
-{
-	archive_string_free(&me->parentdir);
-	archive_string_free(&me->basename);
-	archive_string_free(&me->pathname);
-	archive_string_free(&me->symlink);
-	archive_string_free(&me->uname);
-	archive_string_free(&me->gname);
-	archive_string_free(&me->fflags_text);
-	free(me->dir_info);
-	free(me->reg_info);
-	free(me);
-}
-
-static int
-archive_write_mtree_header(struct archive_write *a,
-    struct archive_entry *entry)
-{
-	struct mtree_writer *mtree= a->format_data;
-	struct mtree_entry *mtree_entry;
-	int r, r2;
-
-	if (mtree->first) {
-		mtree->first = 0;
-		archive_strcat(&mtree->buf, "#mtree\n");
-		if ((mtree->keys & SET_KEYS) == 0)
-			mtree->output_global_set = 0;/* Disabled. */
-	}
-
-	mtree->entry_bytes_remaining = archive_entry_size(entry);
-
-	/* While directory only mode, we do not handle non directory files. */
-	if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
-		return (ARCHIVE_OK);
-
-	r2 = mtree_entry_new(a, entry, &mtree_entry);
-	if (r2 < ARCHIVE_WARN)
-		return (r2);
-	r = mtree_entry_tree_add(a, &mtree_entry);
-	if (r < ARCHIVE_WARN) {
-		mtree_entry_free(mtree_entry);
-		return (r);
-	}
-	mtree->mtree_entry = mtree_entry;
-
-	/* If the current file is a regular file, we have to
-	 * compute the sum of its content.
-	 * Initialize a bunch of checksum context. */
-	if (mtree_entry->reg_info)
-		sum_init(mtree);
-
-	return (r2);
-}
-
-static int
-write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
-{
-	struct mtree_writer *mtree = a->format_data;
-	struct archive_string *str;
-	int keys, ret;
-
-	if (me->dir_info) {
-		if (mtree->classic) {
-			/*
-			 * Output a comment line to describe the full
-			 * pathname of the entry as mtree utility does
-			 * while generating classic format.
-			 */
-			if (!mtree->dironly)
-				archive_strappend_char(&mtree->buf, '\n');
-			if (me->parentdir.s)
-				archive_string_sprintf(&mtree->buf,
-				    "# %s/%s\n",
-				    me->parentdir.s, me->basename.s);
-			else
-				archive_string_sprintf(&mtree->buf,
-				    "# %s\n",
-				    me->basename.s);
-		}
-		if (mtree->output_global_set)
-			write_global(mtree);
-	}
-	archive_string_empty(&mtree->ebuf);
-	str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
-
-	if (!mtree->classic && me->parentdir.s) {
-		/*
-		 * If generating format is not classic one(v1), output
-		 * a full pathname.
-		 */
-		mtree_quote(str, me->parentdir.s);
-		archive_strappend_char(str, '/');
-	}
-	mtree_quote(str, me->basename.s);
-
-	keys = get_global_set_keys(mtree, me);
-	if ((keys & F_NLINK) != 0 &&
-	    me->nlink != 1 && me->filetype != AE_IFDIR)
-		archive_string_sprintf(str, " nlink=%u", me->nlink);
-
-	if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
-		archive_strcat(str, " gname=");
-		mtree_quote(str, me->gname.s);
-	}
-	if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
-		archive_strcat(str, " uname=");
-		mtree_quote(str, me->uname.s);
-	}
-	if ((keys & F_FLAGS) != 0) {
-		if (archive_strlen(&me->fflags_text) > 0) {
-			archive_strcat(str, " flags=");
-			mtree_quote(str, me->fflags_text.s);
-		} else if (mtree->set.processing &&
-		    (mtree->set.keys & F_FLAGS) != 0)
-			/* Overwrite the global parameter. */
-			archive_strcat(str, " flags=none");
-	}
-	if ((keys & F_TIME) != 0)
-		archive_string_sprintf(str, " time=%jd.%jd",
-		    (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
-	if ((keys & F_MODE) != 0)
-		archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
-	if ((keys & F_GID) != 0)
-		archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
-	if ((keys & F_UID) != 0)
-		archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
-
-	if ((keys & F_INO) != 0)
-		archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
-	if ((keys & F_RESDEV) != 0) {
-		archive_string_sprintf(str,
-		    " resdevice=native,%ju,%ju",
-		    (uintmax_t)me->devmajor,
-		    (uintmax_t)me->devminor);
-	}
-
-	switch (me->filetype) {
-	case AE_IFLNK:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=link");
-		if ((keys & F_SLINK) != 0) {
-			archive_strcat(str, " link=");
-			mtree_quote(str, me->symlink.s);
-		}
-		break;
-	case AE_IFSOCK:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=socket");
-		break;
-	case AE_IFCHR:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=char");
-		if ((keys & F_DEV) != 0) {
-			archive_string_sprintf(str,
-			    " device=native,%ju,%ju",
-			    (uintmax_t)me->rdevmajor,
-			    (uintmax_t)me->rdevminor);
-		}
-		break;
-	case AE_IFBLK:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=block");
-		if ((keys & F_DEV) != 0) {
-			archive_string_sprintf(str,
-			    " device=native,%ju,%ju",
-			    (uintmax_t)me->rdevmajor,
-			    (uintmax_t)me->rdevminor);
-		}
-		break;
-	case AE_IFDIR:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=dir");
-		break;
-	case AE_IFIFO:
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=fifo");
-		break;
-	case AE_IFREG:
-	default:	/* Handle unknown file types as regular files. */
-		if ((keys & F_TYPE) != 0)
-			archive_strcat(str, " type=file");
-		if ((keys & F_SIZE) != 0)
-			archive_string_sprintf(str, " size=%jd",
-			    (intmax_t)me->size);
-		break;
-	}
-
-	/* Write a bunch of sum. */
-	if (me->reg_info)
-		sum_write(str, me->reg_info);
-
-	archive_strappend_char(str, '\n');
-	if (mtree->indent || mtree->classic)
-		mtree_indent(mtree);
-
-	if (mtree->buf.length > 32768) {
-		ret = __archive_write_output(
-			a, mtree->buf.s, mtree->buf.length);
-		archive_string_empty(&mtree->buf);
-	} else
-		ret = ARCHIVE_OK;
-	return (ret);
-}
-
-static int
-write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
-{
-	struct mtree_writer *mtree = a->format_data;
-	int ret;
-
-	if (n->parentdir.s) {
-		if (mtree->indent) {
-			int i, pd = mtree->depth * 4;
-			for (i = 0; i < pd; i++)
-				archive_strappend_char(&mtree->buf, ' ');
-		}
-		archive_string_sprintf(&mtree->buf, "# %s/%s\n",
-			n->parentdir.s, n->basename.s);
-	}
-
-	if (mtree->indent) {
-		archive_string_empty(&mtree->ebuf);
-		archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
-		mtree_indent(mtree);
-	} else
-		archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
-
-	if (mtree->buf.length > 32768) {
-		ret = __archive_write_output(
-			a, mtree->buf.s, mtree->buf.length);
-		archive_string_empty(&mtree->buf);
-	} else
-		ret = ARCHIVE_OK;
-	return (ret);
-}
-
-/*
- * Write mtree entries saved at attr_counter_set_collect() function.
- */
-static int
-write_mtree_entry_tree(struct archive_write *a)
-{
-	struct mtree_writer *mtree = a->format_data;
-	struct mtree_entry *np = mtree->root;
-	struct archive_rb_node *n;
-	int ret;
-
-	do {
-		if (mtree->output_global_set) {
-			/*
-			 * Collect attribute information to know which value
-			 * is frequently used among the children.
-			 */
-			attr_counter_set_reset(mtree);
-			ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
-				struct mtree_entry *e = (struct mtree_entry *)n;
-				if (attr_counter_set_collect(mtree, e) < 0) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate memory");
-					return (ARCHIVE_FATAL);
-				}
-			}
-		}
-		if (!np->dir_info->virtual || mtree->classic) {
-			ret = write_mtree_entry(a, np);
-			if (ret != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		} else {
-			/* Whenever output_global_set is enabled
-			 * output global value(/set keywords)
-			 * even if the directory entry is not allowed
-			 * to be written because the global values
-			 * can be used for the children. */
-			if (mtree->output_global_set)
-				write_global(mtree);
-		}
-		/*
-		 * Output the attribute of all files except directory files.
-		 */
-		mtree->depth++;
-		ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
-			struct mtree_entry *e = (struct mtree_entry *)n;
-
-			if (e->dir_info)
-				mtree_entry_add_child_tail(np, e);
-			else {
-				ret = write_mtree_entry(a, e);
-				if (ret != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-			}
-		}
-		mtree->depth--;
-
-		if (np->dir_info->children.first != NULL) {
-			/*
-			 * Descend the tree.
-			 */
-			np = np->dir_info->children.first;
-			if (mtree->indent)
-				mtree->depth++;
-			continue;
-		} else if (mtree->classic) {
-			/*
-			 * While printing mtree classic, if there are not
-			 * any directory files(except "." and "..") in the
-			 * directory, output two dots ".." as returning
-			 * the parent directory.
-			 */
-			ret = write_dot_dot_entry(a, np);
-			if (ret != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-		}
-
-		while (np != np->parent) {
-			if (np->dir_info->chnext == NULL) {
-				/*
-				 * Ascend the tree; go back to the parent.
-				 */
-				if (mtree->indent)
-					mtree->depth--;
-				if (mtree->classic) {
-					ret = write_dot_dot_entry(a,
-						np->parent);
-					if (ret != ARCHIVE_OK)
-						return (ARCHIVE_FATAL);
-				}
-				np = np->parent;
-			} else {
-				/*
-				 * Switch to next mtree entry in the directory.
-				 */
-				np = np->dir_info->chnext;
-				break;
-			}
-		}
-	} while (np != np->parent); 
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_mtree_finish_entry(struct archive_write *a)
-{
-	struct mtree_writer *mtree = a->format_data;
-	struct mtree_entry *me;
-
-	if ((me = mtree->mtree_entry) == NULL)
-		return (ARCHIVE_OK);
-	mtree->mtree_entry = NULL;
-
-	if (me->reg_info)
-		sum_final(mtree, me->reg_info);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_mtree_close(struct archive_write *a)
-{
-	struct mtree_writer *mtree= a->format_data;
-	int ret;
-
-	if (mtree->root != NULL) {
-		ret = write_mtree_entry_tree(a);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	archive_write_set_bytes_in_last_block(&a->archive, 1);
-
-	return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
-}
-
-static ssize_t
-archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
-{
-	struct mtree_writer *mtree= a->format_data;
-
-	if (n > mtree->entry_bytes_remaining)
-		n = (size_t)mtree->entry_bytes_remaining;
-	mtree->entry_bytes_remaining -= n;
-
-	/* We don't need to compute a regular file sum */
-	if (mtree->mtree_entry == NULL)
-		return (n);
-
-	if (mtree->mtree_entry->filetype == AE_IFREG)
-		sum_update(mtree, buff, n);
-
-	return (n);
-}
-
-static int
-archive_write_mtree_free(struct archive_write *a)
-{
-	struct mtree_writer *mtree= a->format_data;
-
-	if (mtree == NULL)
-		return (ARCHIVE_OK);
-
-	/* Make sure we do not leave any entries. */
-	mtree_entry_register_free(mtree);
-	archive_string_free(&mtree->cur_dirstr);
-	archive_string_free(&mtree->ebuf);
-	archive_string_free(&mtree->buf);
-	attr_counter_set_free(mtree);
-	free(mtree);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_mtree_options(struct archive_write *a, const char *key,
-    const char *value)
-{
-	struct mtree_writer *mtree= a->format_data;
-	int keybit = 0;
-
-	switch (key[0]) {
-	case 'a':
-		if (strcmp(key, "all") == 0)
-			keybit = ~0;
-		break;
-	case 'c':
-		if (strcmp(key, "cksum") == 0)
-			keybit = F_CKSUM;
-		break;
-	case 'd':
-		if (strcmp(key, "device") == 0)
-			keybit = F_DEV;
-		else if (strcmp(key, "dironly") == 0) {
-			mtree->dironly = (value != NULL)? 1: 0;
-			return (ARCHIVE_OK);
-		}
-		break;
-	case 'f':
-		if (strcmp(key, "flags") == 0)
-			keybit = F_FLAGS;
-		break;
-	case 'g':
-		if (strcmp(key, "gid") == 0)
-			keybit = F_GID;
-		else if (strcmp(key, "gname") == 0)
-			keybit = F_GNAME;
-		break;
-	case 'i':
-		if (strcmp(key, "indent") == 0) {
-			mtree->indent = (value != NULL)? 1: 0;
-			return (ARCHIVE_OK);
-		} else if (strcmp(key, "inode") == 0) {
-			keybit = F_INO;
-		}
-		break;
-	case 'l':
-		if (strcmp(key, "link") == 0)
-			keybit = F_SLINK;
-		break;
-	case 'm':
-		if (strcmp(key, "md5") == 0 ||
-		    strcmp(key, "md5digest") == 0)
-			keybit = F_MD5;
-		if (strcmp(key, "mode") == 0)
-			keybit = F_MODE;
-		break;
-	case 'n':
-		if (strcmp(key, "nlink") == 0)
-			keybit = F_NLINK;
-		break;
-	case 'r':
-		if (strcmp(key, "resdevice") == 0) {
-			keybit = F_RESDEV;
-		} else if (strcmp(key, "ripemd160digest") == 0 ||
-		    strcmp(key, "rmd160") == 0 ||
-		    strcmp(key, "rmd160digest") == 0)
-			keybit = F_RMD160;
-		break;
-	case 's':
-		if (strcmp(key, "sha1") == 0 ||
-		    strcmp(key, "sha1digest") == 0)
-			keybit = F_SHA1;
-		if (strcmp(key, "sha256") == 0 ||
-		    strcmp(key, "sha256digest") == 0)
-			keybit = F_SHA256;
-		if (strcmp(key, "sha384") == 0 ||
-		    strcmp(key, "sha384digest") == 0)
-			keybit = F_SHA384;
-		if (strcmp(key, "sha512") == 0 ||
-		    strcmp(key, "sha512digest") == 0)
-			keybit = F_SHA512;
-		if (strcmp(key, "size") == 0)
-			keybit = F_SIZE;
-		break;
-	case 't':
-		if (strcmp(key, "time") == 0)
-			keybit = F_TIME;
-		else if (strcmp(key, "type") == 0)
-			keybit = F_TYPE;
-		break;
-	case 'u':
-		if (strcmp(key, "uid") == 0)
-			keybit = F_UID;
-		else if (strcmp(key, "uname") == 0)
-			keybit = F_UNAME;
-		else if (strcmp(key, "use-set") == 0) {
-			mtree->output_global_set = (value != NULL)? 1: 0;
-			return (ARCHIVE_OK);
-		}
-		break;
-	}
-	if (keybit != 0) {
-		if (value != NULL)
-			mtree->keys |= keybit;
-		else
-			mtree->keys &= ~keybit;
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct mtree_writer *mtree;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
-
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate mtree data");
-		return (ARCHIVE_FATAL);
-	}
-
-	mtree->mtree_entry = NULL;
-	mtree->first = 1;
-	memset(&(mtree->set), 0, sizeof(mtree->set));
-	mtree->keys = DEFAULT_KEYS;
-	mtree->dironly = 0;
-	mtree->indent = 0;
-	archive_string_init(&mtree->ebuf);
-	archive_string_init(&mtree->buf);
-	mtree_entry_register_init(mtree);
-	a->format_data = mtree;
-	a->format_free = archive_write_mtree_free;
-	a->format_name = "mtree";
-	a->format_options = archive_write_mtree_options;
-	a->format_write_header = archive_write_mtree_header;
-	a->format_close = archive_write_mtree_close;
-	a->format_write_data = archive_write_mtree_data;
-	a->format_finish_entry = archive_write_mtree_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
-	a->archive.archive_format_name = "mtree";
-
-	return (ARCHIVE_OK);
-}
-
-int
-archive_write_set_format_mtree(struct archive *_a)
-{
-	return archive_write_set_format_mtree_default(_a,
-		"archive_write_set_format_mtree");
-}
-
-int
-archive_write_set_format_mtree_classic(struct archive *_a)
-{
-	int r;
-
-	r = archive_write_set_format_mtree_default(_a,
-		"archive_write_set_format_mtree_classic");
-	if (r == ARCHIVE_OK) {
-		struct archive_write *a = (struct archive_write *)_a;
-		struct mtree_writer *mtree;
-
-		mtree = (struct mtree_writer *)a->format_data;
-
-		/* Set to output a mtree archive in classic format. */
-		mtree->classic = 1;
-		/* Basically, mtree classic format uses '/set' global
-		 * value. */
-		mtree->output_global_set = 1;
-	}
-	return (r);
-}
-
-static void
-sum_init(struct mtree_writer *mtree)
-{
-
-	mtree->compute_sum = 0;
-
-	if (mtree->keys & F_CKSUM) {
-		mtree->compute_sum |= F_CKSUM;
-		mtree->crc = 0;
-		mtree->crc_len = 0;
-	}
-#ifdef ARCHIVE_HAS_MD5
-	if (mtree->keys & F_MD5) {
-		if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_MD5;
-		else
-			mtree->keys &= ~F_MD5;/* Not supported. */
-	}
-#endif
-#ifdef ARCHIVE_HAS_RMD160
-	if (mtree->keys & F_RMD160) {
-		if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_RMD160;
-		else
-			mtree->keys &= ~F_RMD160;/* Not supported. */
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	if (mtree->keys & F_SHA1) {
-		if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_SHA1;
-		else
-			mtree->keys &= ~F_SHA1;/* Not supported. */
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA256
-	if (mtree->keys & F_SHA256) {
-		if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_SHA256;
-		else
-			mtree->keys &= ~F_SHA256;/* Not supported. */
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA384
-	if (mtree->keys & F_SHA384) {
-		if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_SHA384;
-		else
-			mtree->keys &= ~F_SHA384;/* Not supported. */
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA512
-	if (mtree->keys & F_SHA512) {
-		if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
-			mtree->compute_sum |= F_SHA512;
-		else
-			mtree->keys &= ~F_SHA512;/* Not supported. */
-	}
-#endif
-}
-
-static void
-sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
-{
-	if (mtree->compute_sum & F_CKSUM) {
-		/*
-		 * Compute a POSIX 1003.2 checksum
-		 */
-		const unsigned char *p;
-		size_t nn;
-
-		for (nn = n, p = buff; nn--; ++p)
-			COMPUTE_CRC(mtree->crc, *p);
-		mtree->crc_len += n;
-	}
-#ifdef ARCHIVE_HAS_MD5
-	if (mtree->compute_sum & F_MD5)
-		archive_md5_update(&mtree->md5ctx, buff, n);
-#endif
-#ifdef ARCHIVE_HAS_RMD160
-	if (mtree->compute_sum & F_RMD160)
-		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	if (mtree->compute_sum & F_SHA1)
-		archive_sha1_update(&mtree->sha1ctx, buff, n);
-#endif
-#ifdef ARCHIVE_HAS_SHA256
-	if (mtree->compute_sum & F_SHA256)
-		archive_sha256_update(&mtree->sha256ctx, buff, n);
-#endif
-#ifdef ARCHIVE_HAS_SHA384
-	if (mtree->compute_sum & F_SHA384)
-		archive_sha384_update(&mtree->sha384ctx, buff, n);
-#endif
-#ifdef ARCHIVE_HAS_SHA512
-	if (mtree->compute_sum & F_SHA512)
-		archive_sha512_update(&mtree->sha512ctx, buff, n);
-#endif
-}
-
-static void
-sum_final(struct mtree_writer *mtree, struct reg_info *reg)
-{
-
-	if (mtree->compute_sum & F_CKSUM) {
-		uint64_t len;
-		/* Include the length of the file. */
-		for (len = mtree->crc_len; len != 0; len >>= 8)
-			COMPUTE_CRC(mtree->crc, len & 0xff);
-		reg->crc = ~mtree->crc;
-	}
-#ifdef ARCHIVE_HAS_MD5
-	if (mtree->compute_sum & F_MD5)
-		archive_md5_final(&mtree->md5ctx, reg->digest.md5);
-#endif
-#ifdef ARCHIVE_HAS_RMD160
-	if (mtree->compute_sum & F_RMD160)
-		archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	if (mtree->compute_sum & F_SHA1)
-		archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
-#endif
-#ifdef ARCHIVE_HAS_SHA256
-	if (mtree->compute_sum & F_SHA256)
-		archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
-#endif
-#ifdef ARCHIVE_HAS_SHA384
-	if (mtree->compute_sum & F_SHA384)
-		archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
-#endif
-#ifdef ARCHIVE_HAS_SHA512
-	if (mtree->compute_sum & F_SHA512)
-		archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
-#endif
-	/* Save what types of sum are computed. */
-	reg->compute_sum = mtree->compute_sum;
-}
-
-#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
-    defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
-    defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
-static void
-strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
-{
-	static const char hex[] = "0123456789abcdef";
-	int i;
-
-	for (i = 0; i < n; i++) {
-		archive_strappend_char(s, hex[bin[i] >> 4]);
-		archive_strappend_char(s, hex[bin[i] & 0x0f]);
-	}
-}
-#endif
-
-static void
-sum_write(struct archive_string *str, struct reg_info *reg)
-{
-
-	if (reg->compute_sum & F_CKSUM) {
-		archive_string_sprintf(str, " cksum=%ju",
-		    (uintmax_t)reg->crc);
-	}
-
-#define append_digest(_s, _r, _t) \
-	strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t))
-
-#ifdef ARCHIVE_HAS_MD5
-	if (reg->compute_sum & F_MD5) {
-		archive_strcat(str, " md5digest=");
-		append_digest(str, reg, md5);
-	}
-#endif
-#ifdef ARCHIVE_HAS_RMD160
-	if (reg->compute_sum & F_RMD160) {
-		archive_strcat(str, " rmd160digest=");
-		append_digest(str, reg, rmd160);
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	if (reg->compute_sum & F_SHA1) {
-		archive_strcat(str, " sha1digest=");
-		append_digest(str, reg, sha1);
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA256
-	if (reg->compute_sum & F_SHA256) {
-		archive_strcat(str, " sha256digest=");
-		append_digest(str, reg, sha256);
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA384
-	if (reg->compute_sum & F_SHA384) {
-		archive_strcat(str, " sha384digest=");
-		append_digest(str, reg, sha384);
-	}
-#endif
-#ifdef ARCHIVE_HAS_SHA512
-	if (reg->compute_sum & F_SHA512) {
-		archive_strcat(str, " sha512digest=");
-		append_digest(str, reg, sha512);
-	}
-#endif
-#undef append_digest
-}
-
-static int
-mtree_entry_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
-	const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
-
-	return (strcmp(e2->basename.s, e1->basename.s));
-}
-
-static int
-mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct mtree_entry *e = (const struct mtree_entry *)n;
-
-	return (strcmp((const char *)key, e->basename.s));
-}
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-static int
-cleanup_backslash_1(char *p)
-{
-	int mb, dos;
-
-	mb = dos = 0;
-	while (*p) {
-		if (*(unsigned char *)p > 127)
-			mb = 1;
-		if (*p == '\\') {
-			/* If we have not met any multi-byte characters,
-			 * we can replace '\' with '/'. */
-			if (!mb)
-				*p = '/';
-			dos = 1;
-		}
-		p++;
-	}
-	if (!mb || !dos)
-		return (0);
-	return (-1);
-}
-
-static void
-cleanup_backslash_2(wchar_t *p)
-{
-
-	/* Convert a path-separator from '\' to  '/' */
-	while (*p != L'\0') {
-		if (*p == L'\\')
-			*p = L'/';
-		p++;
-	}
-}
-#endif
-
-/*
- * Generate a parent directory name and a base name from a pathname.
- */
-static int
-mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
-    struct archive_entry *entry)
-{
-	const char *pathname;
-	char *p, *dirname, *slash;
-	size_t len;
-	int ret = ARCHIVE_OK;
-
-	archive_strcpy(&file->pathname, archive_entry_pathname(entry));
-#if defined(_WIN32) || defined(__CYGWIN__)
-	/*
-	 * Convert a path-separator from '\' to  '/'
-	 */
-	if (cleanup_backslash_1(file->pathname.s) != 0) {
-		const wchar_t *wp = archive_entry_pathname_w(entry);
-		struct archive_wstring ws;
-
-		if (wp != NULL) {
-			int r;
-			archive_string_init(&ws);
-			archive_wstrcpy(&ws, wp);
-			cleanup_backslash_2(ws.s);
-			archive_string_empty(&(file->pathname));
-			r = archive_string_append_from_wcs(&(file->pathname),
-			    ws.s, ws.length);
-			archive_wstring_free(&ws);
-			if (r < 0 && errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory");
-				return (ARCHIVE_FATAL);
-			}
-		}
-	}
-#else
-	(void)a; /* UNUSED */
-#endif
-	pathname =  file->pathname.s;
-	if (strcmp(pathname, ".") == 0) {
-		archive_strcpy(&file->basename, ".");
-		return (ARCHIVE_OK);
-	}
-
-	archive_strcpy(&(file->parentdir), pathname);
-
-	len = file->parentdir.length;
-	p = dirname = file->parentdir.s;
-
-	/*
-	 * Remove leading '/' and '../' elements
-	 */
-	while (*p) {
-		if (p[0] == '/') {
-			p++;
-			len--;
-		} else if (p[0] != '.')
-			break;
-		else if (p[1] == '.' && p[2] == '/') {
-			p += 3;
-			len -= 3;
-		} else
-			break;
-	}
-	if (p != dirname) {
-		memmove(dirname, p, len+1);
-		p = dirname;
-	}
-	/*
-	 * Remove "/","/." and "/.." elements from tail.
-	 */
-	while (len > 0) {
-		size_t ll = len;
-
-		if (len > 0 && p[len-1] == '/') {
-			p[len-1] = '\0';
-			len--;
-		}
-		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
-			p[len-2] = '\0';
-			len -= 2;
-		}
-		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
-		    p[len-1] == '.') {
-			p[len-3] = '\0';
-			len -= 3;
-		}
-		if (ll == len)
-			break;
-	}
-	while (*p) {
-		if (p[0] == '/') {
-			if (p[1] == '/')
-				/* Convert '//' --> '/' */
-				memmove(p, p+1, strlen(p+1) + 1);
-			else if (p[1] == '.' && p[2] == '/')
-				/* Convert '/./' --> '/' */
-				memmove(p, p+2, strlen(p+2) + 1);
-			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
-				/* Convert 'dir/dir1/../dir2/'
-				 *     --> 'dir/dir2/'
-				 */
-				char *rp = p -1;
-				while (rp >= dirname) {
-					if (*rp == '/')
-						break;
-					--rp;
-				}
-				if (rp > dirname) {
-					strcpy(rp, p+3);
-					p = rp;
-				} else {
-					strcpy(dirname, p+4);
-					p = dirname;
-				}
-			} else
-				p++;
-		} else
-			p++;
-	}
-	p = dirname;
-	len = strlen(p);
-
-	/*
-	 * Add "./" prefix.
-	 * NOTE: If the pathname does not have a path separator, we have
-	 * to add "./" to the head of the pathname because mtree reader
-	 * will suppose that it is v1(a.k.a classic) mtree format and
-	 * change the directory unexpectedly and so it will make a wrong
-	 * path.
-	 */
-	if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
-		struct archive_string as;
-		archive_string_init(&as);
-		archive_strcpy(&as, "./");
-		archive_strncat(&as, p, len);
-		archive_string_empty(&file->parentdir);
-		archive_string_concat(&file->parentdir, &as);
-		archive_string_free(&as);
-		p = file->parentdir.s;
-		len = archive_strlen(&file->parentdir);
-	}
-
-	/*
-	 * Find out the position which points the last position of
-	 * path separator('/').
-	 */
-	slash = NULL;
-	for (; *p != '\0'; p++) {
-		if (*p == '/')
-			slash = p;
-	}
-	if (slash == NULL) {
-		/* The pathname doesn't have a parent directory. */
-		file->parentdir.length = len;
-		archive_string_copy(&(file->basename), &(file->parentdir));
-		archive_string_empty(&(file->parentdir));
-		*file->parentdir.s = '\0';
-		return (ret);
-	}
-
-	/* Make a basename from file->parentdir.s and slash */
-	*slash  = '\0';
-	file->parentdir.length = slash - file->parentdir.s;
-	archive_strcpy(&(file->basename),  slash + 1);
-	return (ret);
-}
-
-static int
-mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
-    struct mtree_entry **m_entry)
-{
-	struct archive_entry *entry;
-	struct mtree_entry *file;
-	int r;
-
-	entry = archive_entry_new();
-	if (entry == NULL) {
-		*m_entry = NULL;
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	archive_entry_copy_pathname(entry, pathname);
-	archive_entry_set_mode(entry, AE_IFDIR | 0755);
-	archive_entry_set_mtime(entry, time(NULL), 0);
-
-	r = mtree_entry_new(a, entry, &file);
-	archive_entry_free(entry);
-	if (r < ARCHIVE_WARN) {
-		*m_entry = NULL;
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	file->dir_info->virtual = 1;
-
-	*m_entry = file;
-	return (ARCHIVE_OK);
-}
-
-static void
-mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
-{
-        file->next = NULL;
-        *mtree->file_list.last = file;
-        mtree->file_list.last = &(file->next);
-}
-
-static void
-mtree_entry_register_init(struct mtree_writer *mtree)
-{
-	mtree->file_list.first = NULL;
-	mtree->file_list.last = &(mtree->file_list.first);
-}
-
-static void
-mtree_entry_register_free(struct mtree_writer *mtree)
-{
-	struct mtree_entry *file, *file_next;
-
-	file = mtree->file_list.first;
-	while (file != NULL) {
-		file_next = file->next;
-		mtree_entry_free(file);
-		file = file_next;
-	}
-}
-
-static int
-mtree_entry_add_child_tail(struct mtree_entry *parent,
-    struct mtree_entry *child)
-{
-	child->dir_info->chnext = NULL;
-	*parent->dir_info->children.last = child;
-	parent->dir_info->children.last = &(child->dir_info->chnext);
-	return (1);
-}
-
-/*
- * Find a entry from a parent entry with the name.
- */
-static struct mtree_entry *
-mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
-{
-	struct mtree_entry *np;
-
-	if (parent == NULL)
-		return (NULL);
-	np = (struct mtree_entry *)__archive_rb_tree_find_node(
-	    &(parent->dir_info->rbtree), child_name);
-	return (np);
-}
-
-static int
-get_path_component(char *name, size_t n, const char *fn)
-{
-	char *p;
-	size_t l;
-
-	p = strchr(fn, '/');
-	if (p == NULL) {
-		if ((l = strlen(fn)) == 0)
-			return (0);
-	} else
-		l = p - fn;
-	if (l > n -1)
-		return (-1);
-	memcpy(name, fn, l);
-	name[l] = '\0';
-
-	return ((int)l);
-}
-
-/*
- * Add a new entry into the tree.
- */
-static int
-mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	char name[_MAX_FNAME];/* Included null terminator size. */
-#elif defined(NAME_MAX) && NAME_MAX >= 255
-	char name[NAME_MAX+1];
-#else
-	char name[256];
-#endif
-	struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
-	struct mtree_entry *dent, *file, *np;
-	const char *fn, *p;
-	int l, r;
-
-	file = *filep;
-	if (file->parentdir.length == 0 && file->basename.length == 1 &&
-	    file->basename.s[0] == '.') {
-		file->parent = file;
-		if (mtree->root != NULL) {
-			np = mtree->root;
-			goto same_entry;
-		}
-		mtree->root = file;
-		mtree_entry_register_add(mtree, file);
-		return (ARCHIVE_OK);
-	}
-
-	if (file->parentdir.length == 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal programming error "
-		    "in generating canonical name for %s",
-		    file->pathname.s);
-		return (ARCHIVE_FAILED);
-	}
-
-	fn = p = file->parentdir.s;
-
-	/*
-	 * If the path of the parent directory of `file' entry is
-	 * the same as the path of `cur_dirent', add `file' entry to
-	 * `cur_dirent'.
-	 */
-	if (archive_strlen(&(mtree->cur_dirstr))
-	      == archive_strlen(&(file->parentdir)) &&
-	    strcmp(mtree->cur_dirstr.s, fn) == 0) {
-		if (!__archive_rb_tree_insert_node(
-		    &(mtree->cur_dirent->dir_info->rbtree),
-		    (struct archive_rb_node *)file)) {
-			/* There is the same name in the tree. */
-			np = (struct mtree_entry *)__archive_rb_tree_find_node(
-			    &(mtree->cur_dirent->dir_info->rbtree),
-			    file->basename.s);
-			goto same_entry;
-		}
-		file->parent = mtree->cur_dirent;
-		mtree_entry_register_add(mtree, file);
-		return (ARCHIVE_OK);
-	}
-
-	dent = mtree->root;
-	for (;;) {
-		l = get_path_component(name, sizeof(name), fn);
-		if (l == 0) {
-			np = NULL;
-			break;
-		}
-		if (l < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "A name buffer is too small");
-			return (ARCHIVE_FATAL);
-		}
-		if (l == 1 && name[0] == '.' && dent != NULL &&
-		    dent == mtree->root) {
-			fn += l;
-			if (fn[0] == '/')
-				fn++;
-			continue;
-		}
-
-		np = mtree_entry_find_child(dent, name);
-		if (np == NULL || fn[0] == '\0')
-			break;
-
-		/* Find next sub directory. */
-		if (!np->dir_info) {
-			/* NOT Directory! */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "`%s' is not directory, we cannot insert `%s' ",
-			    np->pathname.s, file->pathname.s);
-			return (ARCHIVE_FAILED);
-		}
-		fn += l;
-		if (fn[0] == '/')
-			fn++;
-		dent = np;
-	}
-	if (np == NULL) {
-		/*
-		 * Create virtual parent directories.
-		 */
-		while (fn[0] != '\0') {
-			struct mtree_entry *vp;
-			struct archive_string as;
-
-			archive_string_init(&as);
-			archive_strncat(&as, p, fn - p + l);
-			if (as.s[as.length-1] == '/') {
-				as.s[as.length-1] = '\0';
-				as.length--;
-			}
-			r = mtree_entry_create_virtual_dir(a, as.s, &vp);
-			archive_string_free(&as);
-			if (r < ARCHIVE_WARN)
-				return (r);
-
-			if (strcmp(vp->pathname.s, ".") == 0) {
-				vp->parent = vp;
-				mtree->root = vp;
-			} else {
-				__archive_rb_tree_insert_node(
-				    &(dent->dir_info->rbtree),
-				    (struct archive_rb_node *)vp);
-				vp->parent = dent;
-			}
-			mtree_entry_register_add(mtree, vp);
-			np = vp;
-
-			fn += l;
-			if (fn[0] == '/')
-				fn++;
-			l = get_path_component(name, sizeof(name), fn);
-			if (l < 0) {
-				archive_string_free(&as);
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "A name buffer is too small");
-				return (ARCHIVE_FATAL);
-			}
-			dent = np;
-		}
-
-		/* Found out the parent directory where `file' can be
-		 * inserted. */
-		mtree->cur_dirent = dent;
-		archive_string_empty(&(mtree->cur_dirstr));
-		archive_string_ensure(&(mtree->cur_dirstr),
-		    archive_strlen(&(dent->parentdir)) +
-		    archive_strlen(&(dent->basename)) + 2);
-		if (archive_strlen(&(dent->parentdir)) +
-		    archive_strlen(&(dent->basename)) == 0)
-			mtree->cur_dirstr.s[0] = 0;
-		else {
-			if (archive_strlen(&(dent->parentdir)) > 0) {
-				archive_string_copy(&(mtree->cur_dirstr),
-				    &(dent->parentdir));
-				archive_strappend_char(
-				    &(mtree->cur_dirstr), '/');
-			}
-			archive_string_concat(&(mtree->cur_dirstr),
-			    &(dent->basename));
-		}
-
-		if (!__archive_rb_tree_insert_node(
-		    &(dent->dir_info->rbtree),
-		    (struct archive_rb_node *)file)) {
-			np = (struct mtree_entry *)__archive_rb_tree_find_node(
-			    &(dent->dir_info->rbtree), file->basename.s);
-			goto same_entry;
-		}
-		file->parent = dent;
-		mtree_entry_register_add(mtree, file);
-		return (ARCHIVE_OK);
-	}
-
-same_entry:
-	/*
-	 * We have already has the entry the filename of which is
-	 * the same.
-	 */
-	r = mtree_entry_exchange_same_entry(a, np, file);
-	if (r < ARCHIVE_WARN)
-		return (r);
-	if (np->dir_info)
-		np->dir_info->virtual = 0;
-	*filep = np;
-	mtree_entry_free(file);
-	return (ARCHIVE_WARN);
-}
-
-static int
-mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
-    struct mtree_entry *file)
-{
-
-	if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Found duplicate entries `%s' and its file type is "
-		    "different",
-		    np->pathname.s);
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Update the existent mtree entry's attributes by the new one's. */
-	archive_string_empty(&np->symlink);
-	archive_string_concat(&np->symlink, &file->symlink);
-	archive_string_empty(&np->uname);
-	archive_string_concat(&np->uname, &file->uname);
-	archive_string_empty(&np->gname);
-	archive_string_concat(&np->gname, &file->gname);
-	archive_string_empty(&np->fflags_text);
-	archive_string_concat(&np->fflags_text, &file->fflags_text);
-	np->nlink = file->nlink;
-	np->filetype = file->filetype;
-	np->mode = file->mode;
-	np->size = file->size;
-	np->uid = file->uid;
-	np->gid = file->gid;
-	np->fflags_set = file->fflags_set;
-	np->fflags_clear = file->fflags_clear;
-	np->mtime = file->mtime;
-	np->mtime_nsec = file->mtime_nsec;
-	np->rdevmajor = file->rdevmajor;
-	np->rdevminor = file->rdevminor;
-	np->devmajor = file->devmajor;
-	np->devminor = file->devminor;
-	np->ino = file->ino;
-
-	return (ARCHIVE_WARN);
-}
diff --git a/c/archive_write_set_format_pax.c b/c/archive_write_set_format_pax.c
deleted file mode 100644
--- a/c/archive_write_set_format_pax.c
+++ /dev/null
@@ -1,2063 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * Copyright (c) 2016 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_pax.c 201162 2009-12-29 05:47:46Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct sparse_block {
-	struct sparse_block	*next;
-	int		is_hole;
-	uint64_t	offset;
-	uint64_t	remaining;
-};
-
-struct pax {
-	uint64_t	entry_bytes_remaining;
-	uint64_t	entry_padding;
-	struct archive_string	l_url_encoded_name;
-	struct archive_string	pax_header;
-	struct archive_string	sparse_map;
-	size_t			sparse_map_padding;
-	struct sparse_block	*sparse_list;
-	struct sparse_block	*sparse_tail;
-	struct archive_string_conv *sconv_utf8;
-	int			 opt_binary;
-
-	unsigned flags;
-#define WRITE_SCHILY_XATTR       (1 << 0)
-#define WRITE_LIBARCHIVE_XATTR   (1 << 1)
-};
-
-static void		 add_pax_attr(struct archive_string *, const char *key,
-			     const char *value);
-static void		 add_pax_attr_binary(struct archive_string *,
-			     const char *key,
-			     const char *value, size_t value_len);
-static void		 add_pax_attr_int(struct archive_string *,
-			     const char *key, int64_t value);
-static void		 add_pax_attr_time(struct archive_string *,
-			     const char *key, int64_t sec,
-			     unsigned long nanos);
-static int		 add_pax_acl(struct archive_write *,
-			    struct archive_entry *, struct pax *, int);
-static ssize_t		 archive_write_pax_data(struct archive_write *,
-			     const void *, size_t);
-static int		 archive_write_pax_close(struct archive_write *);
-static int		 archive_write_pax_free(struct archive_write *);
-static int		 archive_write_pax_finish_entry(struct archive_write *);
-static int		 archive_write_pax_header(struct archive_write *,
-			     struct archive_entry *);
-static int		 archive_write_pax_options(struct archive_write *,
-			     const char *, const char *);
-static char		*base64_encode(const char *src, size_t len);
-static char		*build_gnu_sparse_name(char *dest, const char *src);
-static char		*build_pax_attribute_name(char *dest, const char *src);
-static char		*build_ustar_entry_name(char *dest, const char *src,
-			     size_t src_length, const char *insert);
-static char		*format_int(char *dest, int64_t);
-static int		 has_non_ASCII(const char *);
-static void		 sparse_list_clear(struct pax *);
-static int		 sparse_list_add(struct pax *, int64_t, int64_t);
-static char		*url_encode(const char *in);
-static time_t		 get_ustar_max_mtime(void);
-
-/*
- * Set output format to 'restricted pax' format.
- *
- * This is the same as normal 'pax', but tries to suppress
- * the pax header whenever possible.  This is the default for
- * bsdtar, for instance.
- */
-int
-archive_write_set_format_pax_restricted(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int r;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_pax_restricted");
-
-	r = archive_write_set_format_pax(&a->archive);
-	a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
-	a->archive.archive_format_name = "restricted POSIX pax interchange";
-	return (r);
-}
-
-/*
- * Set output format to 'pax' format.
- */
-int
-archive_write_set_format_pax(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct pax *pax;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_pax");
-
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	pax = (struct pax *)calloc(1, sizeof(*pax));
-	if (pax == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate pax data");
-		return (ARCHIVE_FATAL);
-	}
-	pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
-
-	a->format_data = pax;
-	a->format_name = "pax";
-	a->format_options = archive_write_pax_options;
-	a->format_write_header = archive_write_pax_header;
-	a->format_write_data = archive_write_pax_data;
-	a->format_close = archive_write_pax_close;
-	a->format_free = archive_write_pax_free;
-	a->format_finish_entry = archive_write_pax_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
-	a->archive.archive_format_name = "POSIX pax interchange";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_pax_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct pax *pax = (struct pax *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		/*
-		 * The character-set we can use are defined in
-		 * IEEE Std 1003.1-2001
-		 */
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "pax: hdrcharset option needs a character-set name");
-		else if (strcmp(val, "BINARY") == 0 ||
-		    strcmp(val, "binary") == 0) {
-			/*
-			 * Specify binary mode. We will not convert
-			 * filenames, uname and gname to any charsets.
-			 */
-			pax->opt_binary = 1;
-			ret = ARCHIVE_OK;
-		} else if (strcmp(val, "UTF-8") == 0) {
-			/*
-			 * Specify UTF-8 character-set to be used for
-			 * filenames. This is almost the test that
-			 * running platform supports the string conversion.
-			 * Especially libarchive_test needs this trick for
-			 * its test.
-			 */
-			pax->sconv_utf8 = archive_string_conversion_to_charset(
-			    &(a->archive), "UTF-8", 0);
-			if (pax->sconv_utf8 == NULL)
-				ret = ARCHIVE_FATAL;
-			else
-				ret = ARCHIVE_OK;
-		} else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "pax: invalid charset name");
-		return (ret);
-	} else if (strcmp(key, "xattrheader") == 0) {
-		if (val == NULL || val[0] == 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "pax: xattrheader requires a value");
-		} else if (strcmp(val, "ALL") == 0 ||
-		    strcmp(val, "all") == 0) {
-			pax->flags |= WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
-			ret = ARCHIVE_OK;
-		} else if (strcmp(val, "SCHILY") == 0 ||
-		    strcmp(val, "schily") == 0) {
-			pax->flags |= WRITE_SCHILY_XATTR;
-			pax->flags &= ~WRITE_LIBARCHIVE_XATTR;
-			ret = ARCHIVE_OK;
-		} else if (strcmp(val, "LIBARCHIVE") == 0 ||
-		    strcmp(val, "libarchive") == 0) {
-			pax->flags |= WRITE_LIBARCHIVE_XATTR;
-			pax->flags &= ~WRITE_SCHILY_XATTR;
-			ret = ARCHIVE_OK;
-		} else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "pax: invalid xattr header name");
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-/*
- * Note: This code assumes that 'nanos' has the same sign as 'sec',
- * which implies that sec=-1, nanos=200000000 represents -1.2 seconds
- * and not -0.8 seconds.  This is a pretty pedantic point, as we're
- * unlikely to encounter many real files created before Jan 1, 1970,
- * much less ones with timestamps recorded to sub-second resolution.
- */
-static void
-add_pax_attr_time(struct archive_string *as, const char *key,
-    int64_t sec, unsigned long nanos)
-{
-	int digit, i;
-	char *t;
-	/*
-	 * Note that each byte contributes fewer than 3 base-10
-	 * digits, so this will always be big enough.
-	 */
-	char tmp[1 + 3*sizeof(sec) + 1 + 3*sizeof(nanos)];
-
-	tmp[sizeof(tmp) - 1] = 0;
-	t = tmp + sizeof(tmp) - 1;
-
-	/* Skip trailing zeros in the fractional part. */
-	for (digit = 0, i = 10; i > 0 && digit == 0; i--) {
-		digit = nanos % 10;
-		nanos /= 10;
-	}
-
-	/* Only format the fraction if it's non-zero. */
-	if (i > 0) {
-		while (i > 0) {
-			*--t = "0123456789"[digit];
-			digit = nanos % 10;
-			nanos /= 10;
-			i--;
-		}
-		*--t = '.';
-	}
-	t = format_int(t, sec);
-
-	add_pax_attr(as, key, t);
-}
-
-static char *
-format_int(char *t, int64_t i)
-{
-	uint64_t ui;
-
-	if (i < 0) 
-		ui = (i == INT64_MIN) ? (uint64_t)(INT64_MAX) + 1 : (uint64_t)(-i);
-	else
-		ui = i;
-
-	do {
-		*--t = "0123456789"[ui % 10];
-	} while (ui /= 10);
-	if (i < 0)
-		*--t = '-';
-	return (t);
-}
-
-static void
-add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
-{
-	char tmp[1 + 3 * sizeof(value)];
-
-	tmp[sizeof(tmp) - 1] = 0;
-	add_pax_attr(as, key, format_int(tmp + sizeof(tmp) - 1, value));
-}
-
-/*
- * Add a key/value attribute to the pax header.  This function handles
- * the length field and various other syntactic requirements.
- */
-static void
-add_pax_attr(struct archive_string *as, const char *key, const char *value)
-{
-	add_pax_attr_binary(as, key, value, strlen(value));
-}
-
-/*
- * Add a key/value attribute to the pax header.  This function handles
- * binary values.
- */
-static void
-add_pax_attr_binary(struct archive_string *as, const char *key,
-		    const char *value, size_t value_len)
-{
-	int digits, i, len, next_ten;
-	char tmp[1 + 3 * sizeof(int)];	/* < 3 base-10 digits per byte */
-
-	/*-
-	 * PAX attributes have the following layout:
-	 *     <len> <space> <key> <=> <value> <nl>
-	 */
-	len = 1 + (int)strlen(key) + 1 + (int)value_len + 1;
-
-	/*
-	 * The <len> field includes the length of the <len> field, so
-	 * computing the correct length is tricky.  I start by
-	 * counting the number of base-10 digits in 'len' and
-	 * computing the next higher power of 10.
-	 */
-	next_ten = 1;
-	digits = 0;
-	i = len;
-	while (i > 0) {
-		i = i / 10;
-		digits++;
-		next_ten = next_ten * 10;
-	}
-	/*
-	 * For example, if string without the length field is 99
-	 * chars, then adding the 2 digit length "99" will force the
-	 * total length past 100, requiring an extra digit.  The next
-	 * statement adjusts for this effect.
-	 */
-	if (len + digits >= next_ten)
-		digits++;
-
-	/* Now, we have the right length so we can build the line. */
-	tmp[sizeof(tmp) - 1] = 0;	/* Null-terminate the work area. */
-	archive_strcat(as, format_int(tmp + sizeof(tmp) - 1, len + digits));
-	archive_strappend_char(as, ' ');
-	archive_strcat(as, key);
-	archive_strappend_char(as, '=');
-	archive_array_append(as, value, value_len);
-	archive_strappend_char(as, '\n');
-}
-
-static void
-archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name,
-    const void *value, size_t value_len)
-{
-	struct archive_string s;
-	char *encoded_value;
-
-	if (pax->flags & WRITE_LIBARCHIVE_XATTR) {
-		encoded_value = base64_encode((const char *)value, value_len);
-
-		if (encoded_name != NULL && encoded_value != NULL) {
-			archive_string_init(&s);
-			archive_strcpy(&s, "LIBARCHIVE.xattr.");
-			archive_strcat(&s, encoded_name);
-			add_pax_attr(&(pax->pax_header), s.s, encoded_value);
-			archive_string_free(&s);
-		}
-		free(encoded_value);
-	}
-	if (pax->flags & WRITE_SCHILY_XATTR) {
-		archive_string_init(&s);
-		archive_strcpy(&s, "SCHILY.xattr.");
-		archive_strcat(&s, encoded_name);
-		add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len);
-		archive_string_free(&s);
-	}
-}
-
-static int
-archive_write_pax_header_xattrs(struct archive_write *a,
-    struct pax *pax, struct archive_entry *entry)
-{
-	int i = archive_entry_xattr_reset(entry);
-
-	while (i--) {
-		const char *name;
-		const void *value;
-		char *url_encoded_name = NULL, *encoded_name = NULL;
-		size_t size;
-		int r;
-
-		archive_entry_xattr_next(entry, &name, &value, &size);
-		url_encoded_name = url_encode(name);
-		if (url_encoded_name != NULL) {
-			/* Convert narrow-character to UTF-8. */
-			r = archive_strcpy_l(&(pax->l_url_encoded_name),
-			    url_encoded_name, pax->sconv_utf8);
-			free(url_encoded_name); /* Done with this. */
-			if (r == 0)
-				encoded_name = pax->l_url_encoded_name.s;
-			else if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				return (ARCHIVE_FATAL);
-			}
-		}
-
-		archive_write_pax_header_xattr(pax, encoded_name,
-		    value, size);
-
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-get_entry_hardlink(struct archive_write *a, struct archive_entry *entry,
-    const char **name, size_t *length, struct archive_string_conv *sc)
-{
-	int r;
-	
-	r = archive_entry_hardlink_l(entry, name, length, sc);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-get_entry_pathname(struct archive_write *a, struct archive_entry *entry,
-    const char **name, size_t *length, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_entry_pathname_l(entry, name, length, sc);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-get_entry_uname(struct archive_write *a, struct archive_entry *entry,
-    const char **name, size_t *length, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_entry_uname_l(entry, name, length, sc);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Uname");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-get_entry_gname(struct archive_write *a, struct archive_entry *entry,
-    const char **name, size_t *length, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_entry_gname_l(entry, name, length, sc);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Gname");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
-    const char **name, size_t *length, struct archive_string_conv *sc)
-{
-	int r;
-
-	r = archive_entry_symlink_l(entry, name, length, sc);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			return (ARCHIVE_FATAL);
-		}
-		return (ARCHIVE_WARN);
-	}
-	return (ARCHIVE_OK);
-}
-
-/* Add ACL to pax header */
-static int
-add_pax_acl(struct archive_write *a,
-    struct archive_entry *entry, struct pax *pax, int flags)
-{
-	char *p;
-	const char *attr;
-	int acl_types;
-
-	acl_types = archive_entry_acl_types(entry);
-
-	if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
-		attr = "SCHILY.acl.ace";
-	else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
-		attr = "SCHILY.acl.access";
-	else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-		attr = "SCHILY.acl.default";
-	else
-		return (ARCHIVE_FATAL);
-
-	p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
-	if (p == NULL) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM, "%s %s",
-			    "Can't allocate memory for ", attr);
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
-		    "Can't translate ", attr, " to UTF-8");
-		return(ARCHIVE_WARN);
-	}
-
-	if (*p != '\0') {
-		add_pax_attr(&(pax->pax_header),
-		    attr, p);
-	}
-	free(p);
-	return(ARCHIVE_OK);
-}
-
-/*
- * TODO: Consider adding 'comment' and 'charset' fields to
- * archive_entry so that clients can specify them.  Also, consider
- * adding generic key/value tags so clients can add arbitrary
- * key/value data.
- *
- * TODO: Break up this 700-line function!!!!  Yowza!
- */
-static int
-archive_write_pax_header(struct archive_write *a,
-    struct archive_entry *entry_original)
-{
-	struct archive_entry *entry_main;
-	const char *p;
-	const char *suffix;
-	int need_extension, r, ret;
-	int acl_types;
-	int sparse_count;
-	uint64_t sparse_total, real_size;
-	struct pax *pax;
-	const char *hardlink;
-	const char *path = NULL, *linkpath = NULL;
-	const char *uname = NULL, *gname = NULL;
-	const void *mac_metadata;
-	size_t mac_metadata_size;
-	struct archive_string_conv *sconv;
-	size_t hardlink_length, path_length, linkpath_length;
-	size_t uname_length, gname_length;
-
-	char paxbuff[512];
-	char ustarbuff[512];
-	char ustar_entry_name[256];
-	char pax_entry_name[256];
-	char gnu_sparse_name[256];
-	struct archive_string entry_name;
-
-	ret = ARCHIVE_OK;
-	need_extension = 0;
-	pax = (struct pax *)a->format_data;
-
-	const time_t ustar_max_mtime = get_ustar_max_mtime();
-
-	/* Sanity check. */
-	if (archive_entry_pathname(entry_original) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			  "Can't record entry in tar file without pathname");
-		return (ARCHIVE_FAILED);
-	}
-
-	/*
-	 * Choose a header encoding.
-	 */
-	if (pax->opt_binary)
-		sconv = NULL;/* Binary mode. */
-	else {
-		/* Header encoding is UTF-8. */
-		if (pax->sconv_utf8 == NULL) {
-			/* Initialize the string conversion object
-			 * we must need */
-			pax->sconv_utf8 = archive_string_conversion_to_charset(
-			    &(a->archive), "UTF-8", 1);
-			if (pax->sconv_utf8 == NULL)
-				/* Couldn't allocate memory */
-				return (ARCHIVE_FAILED);
-		}
-		sconv = pax->sconv_utf8;
-	}
-
-	r = get_entry_hardlink(a, entry_original, &hardlink,
-	    &hardlink_length, sconv);
-	if (r == ARCHIVE_FATAL)
-		return (r);
-	else if (r != ARCHIVE_OK) {
-		r = get_entry_hardlink(a, entry_original, &hardlink,
-		    &hardlink_length, NULL);
-		if (r == ARCHIVE_FATAL)
-			return (r);
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s", hardlink,
-		    archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-		sconv = NULL;/* The header charset switches to binary mode. */
-	}
-
-	/* Make sure this is a type of entry that we can handle here */
-	if (hardlink == NULL) {
-		switch (archive_entry_filetype(entry_original)) {
-		case AE_IFBLK:
-		case AE_IFCHR:
-		case AE_IFIFO:
-		case AE_IFLNK:
-		case AE_IFREG:
-			break;
-		case AE_IFDIR:
-		{
-			/*
-			 * Ensure a trailing '/'.  Modify the original
-			 * entry so the client sees the change.
-			 */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-			const wchar_t *wp;
-
-			wp = archive_entry_pathname_w(entry_original);
-			if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
-				struct archive_wstring ws;
-
-				archive_string_init(&ws);
-				path_length = wcslen(wp);
-				if (archive_wstring_ensure(&ws,
-				    path_length + 2) == NULL) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate pax data");
-					archive_wstring_free(&ws);
-					return(ARCHIVE_FATAL);
-				}
-				/* Should we keep '\' ? */
-				if (wp[path_length -1] == L'\\')
-					path_length--;
-				archive_wstrncpy(&ws, wp, path_length);
-				archive_wstrappend_wchar(&ws, L'/');
-				archive_entry_copy_pathname_w(
-				    entry_original, ws.s);
-				archive_wstring_free(&ws);
-				p = NULL;
-			} else
-#endif
-				p = archive_entry_pathname(entry_original);
-			/*
-			 * On Windows, this is a backup operation just in
-			 * case getting WCS failed. On POSIX, this is a
-			 * normal operation.
-			 */
-			if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
-				struct archive_string as;
-
-				archive_string_init(&as);
-				path_length = strlen(p);
-				if (archive_string_ensure(&as,
-				    path_length + 2) == NULL) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate pax data");
-					archive_string_free(&as);
-					return(ARCHIVE_FATAL);
-				}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-				/* NOTE: This might break the pathname
-				 * if the current code page is CP932 and
-				 * the pathname includes a character '\'
-				 * as a part of its multibyte pathname. */
-				if (p[strlen(p) -1] == '\\')
-					path_length--;
-				else
-#endif
-				archive_strncpy(&as, p, path_length);
-				archive_strappend_char(&as, '/');
-				archive_entry_copy_pathname(
-				    entry_original, as.s);
-				archive_string_free(&as);
-			}
-			break;
-		}
-		default: /* AE_IFSOCK and unknown */
-			__archive_write_entry_filetype_unsupported(
-			    &a->archive, entry_original, "pax");
-			return (ARCHIVE_FAILED);
-		}
-	}
-
-	/*
-	 * If Mac OS metadata blob is here, recurse to write that
-	 * as a separate entry.  This is really a pretty poor design:
-	 * In particular, it doubles the overhead for long filenames.
-	 * TODO: Help Apple folks design something better and figure
-	 * out how to transition from this legacy format.
-	 *
-	 * Note that this code is present on every platform; clients
-	 * on non-Mac are unlikely to ever provide this data, but
-	 * applications that copy entries from one archive to another
-	 * should not lose data just because the local filesystem
-	 * can't store it.
-	 */
-	mac_metadata =
-	    archive_entry_mac_metadata(entry_original, &mac_metadata_size);
-	if (mac_metadata != NULL) {
-		const char *oname;
-		char *name, *bname;
-		size_t name_length;
-		struct archive_entry *extra = archive_entry_new2(&a->archive);
-
-		oname = archive_entry_pathname(entry_original);
-		name_length = strlen(oname);
-		name = malloc(name_length + 3);
-		if (name == NULL || extra == NULL) {
-			/* XXX error message */
-			archive_entry_free(extra);
-			free(name);
-			return (ARCHIVE_FAILED);
-		}
-		strcpy(name, oname);
-		/* Find last '/'; strip trailing '/' characters */
-		bname = strrchr(name, '/');
-		while (bname != NULL && bname[1] == '\0') {
-			*bname = '\0';
-			bname = strrchr(name, '/');
-		}
-		if (bname == NULL) {
-			memmove(name + 2, name, name_length + 1);
-			memmove(name, "._", 2);
-		} else {
-			bname += 1;
-			memmove(bname + 2, bname, strlen(bname) + 1);
-			memmove(bname, "._", 2);
-		}
-		archive_entry_copy_pathname(extra, name);
-		free(name);
-
-		archive_entry_set_size(extra, mac_metadata_size);
-		archive_entry_set_filetype(extra, AE_IFREG);
-		archive_entry_set_perm(extra,
-		    archive_entry_perm(entry_original));
-		archive_entry_set_mtime(extra,
-		    archive_entry_mtime(entry_original),
-		    archive_entry_mtime_nsec(entry_original));
-		archive_entry_set_gid(extra,
-		    archive_entry_gid(entry_original));
-		archive_entry_set_gname(extra,
-		    archive_entry_gname(entry_original));
-		archive_entry_set_uid(extra,
-		    archive_entry_uid(entry_original));
-		archive_entry_set_uname(extra,
-		    archive_entry_uname(entry_original));
-
-		/* Recurse to write the special copyfile entry. */
-		r = archive_write_pax_header(a, extra);
-		archive_entry_free(extra);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if (r < ret)
-			ret = r;
-		r = (int)archive_write_pax_data(a, mac_metadata,
-		    mac_metadata_size);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if (r < ret)
-			ret = r;
-		r = archive_write_pax_finish_entry(a);
-		if (r < ARCHIVE_WARN)
-			return (r);
-		if (r < ret)
-			ret = r;
-	}
-
-	/* Copy entry so we can modify it as needed. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
-	if (entry_main == entry_original)
-		entry_main = archive_entry_clone(entry_original);
-#else
-	entry_main = archive_entry_clone(entry_original);
-#endif
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate pax data");
-		return(ARCHIVE_FATAL);
-	}
-	archive_string_empty(&(pax->pax_header)); /* Blank our work area. */
-	archive_string_empty(&(pax->sparse_map));
-	sparse_total = 0;
-	sparse_list_clear(pax);
-
-	if (hardlink == NULL &&
-	    archive_entry_filetype(entry_main) == AE_IFREG)
-		sparse_count = archive_entry_sparse_reset(entry_main);
-	else
-		sparse_count = 0;
-	if (sparse_count) {
-		int64_t offset, length, last_offset = 0;
-		/* Get the last entry of sparse block. */
-		while (archive_entry_sparse_next(
-		    entry_main, &offset, &length) == ARCHIVE_OK)
-			last_offset = offset + length;
-
-		/* If the last sparse block does not reach the end of file,
-		 * We have to add a empty sparse block as the last entry to
-		 * manage storing file data. */
-		if (last_offset < archive_entry_size(entry_main))
-			archive_entry_sparse_add_entry(entry_main,
-			    archive_entry_size(entry_main), 0);
-		sparse_count = archive_entry_sparse_reset(entry_main);
-	}
-
-	/*
-	 * First, check the name fields and see if any of them
-	 * require binary coding.  If any of them does, then all of
-	 * them do.
-	 */
-	r = get_entry_pathname(a, entry_main, &path, &path_length, sconv);
-	if (r == ARCHIVE_FATAL) {
-		archive_entry_free(entry_main);
-		return (r);
-	} else if (r != ARCHIVE_OK) {
-		r = get_entry_pathname(a, entry_main, &path,
-		    &path_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s", path,
-		    archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-		sconv = NULL;/* The header charset switches to binary mode. */
-	}
-	r = get_entry_uname(a, entry_main, &uname, &uname_length, sconv);
-	if (r == ARCHIVE_FATAL) {
-		archive_entry_free(entry_main);
-		return (r);
-	} else if (r != ARCHIVE_OK) {
-		r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate uname '%s' to %s", uname,
-		    archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-		sconv = NULL;/* The header charset switches to binary mode. */
-	}
-	r = get_entry_gname(a, entry_main, &gname, &gname_length, sconv);
-	if (r == ARCHIVE_FATAL) {
-		archive_entry_free(entry_main);
-		return (r);
-	} else if (r != ARCHIVE_OK) {
-		r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate gname '%s' to %s", gname,
-		    archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-		sconv = NULL;/* The header charset switches to binary mode. */
-	}
-	linkpath = hardlink;
-	linkpath_length = hardlink_length;
-	if (linkpath == NULL) {
-		r = get_entry_symlink(a, entry_main, &linkpath,
-		    &linkpath_length, sconv);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		} else if (r != ARCHIVE_OK) {
-			r = get_entry_symlink(a, entry_main, &linkpath,
-			    &linkpath_length, NULL);
-			if (r == ARCHIVE_FATAL) {
-				archive_entry_free(entry_main);
-				return (r);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate linkname '%s' to %s", linkpath,
-			    archive_string_conversion_charset_name(sconv));
-			ret = ARCHIVE_WARN;
-			sconv = NULL;
-		}
-	}
-
-	/* If any string conversions failed, get all attributes
-	 * in binary-mode. */
-	if (sconv == NULL && !pax->opt_binary) {
-		if (hardlink != NULL) {
-			r = get_entry_hardlink(a, entry_main, &hardlink,
-			    &hardlink_length, NULL);
-			if (r == ARCHIVE_FATAL) {
-				archive_entry_free(entry_main);
-				return (r);
-			}
-			linkpath = hardlink;
-			linkpath_length = hardlink_length;
-		}
-		r = get_entry_pathname(a, entry_main, &path,
-		    &path_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-		r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-		r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL);
-		if (r == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			return (r);
-		}
-	}
-
-	/* Store the header encoding first, to be nice to readers. */
-	if (sconv == NULL)
-		add_pax_attr(&(pax->pax_header), "hdrcharset", "BINARY");
-
-
-	/*
-	 * If name is too long, or has non-ASCII characters, add
-	 * 'path' to pax extended attrs.  (Note that an unconvertible
-	 * name must have non-ASCII characters.)
-	 */
-	if (has_non_ASCII(path)) {
-		/* We have non-ASCII characters. */
-		add_pax_attr(&(pax->pax_header), "path", path);
-		archive_entry_set_pathname(entry_main,
-		    build_ustar_entry_name(ustar_entry_name,
-			path, path_length, NULL));
-		need_extension = 1;
-	} else {
-		/* We have an all-ASCII path; we'd like to just store
-		 * it in the ustar header if it will fit.  Yes, this
-		 * duplicates some of the logic in
-		 * archive_write_set_format_ustar.c
-		 */
-		if (path_length <= 100) {
-			/* Fits in the old 100-char tar name field. */
-		} else {
-			/* Find largest suffix that will fit. */
-			/* Note: strlen() > 100, so strlen() - 100 - 1 >= 0 */
-			suffix = strchr(path + path_length - 100 - 1, '/');
-			/* Don't attempt an empty prefix. */
-			if (suffix == path)
-				suffix = strchr(suffix + 1, '/');
-			/* We can put it in the ustar header if it's
-			 * all ASCII and it's either <= 100 characters
-			 * or can be split at a '/' into a prefix <=
-			 * 155 chars and a suffix <= 100 chars.  (Note
-			 * the strchr() above will return NULL exactly
-			 * when the path can't be split.)
-			 */
-			if (suffix == NULL       /* Suffix > 100 chars. */
-			    || suffix[1] == '\0'    /* empty suffix */
-			    || suffix - path > 155)  /* Prefix > 155 chars */
-			{
-				add_pax_attr(&(pax->pax_header), "path", path);
-				archive_entry_set_pathname(entry_main,
-				    build_ustar_entry_name(ustar_entry_name,
-					path, path_length, NULL));
-				need_extension = 1;
-			}
-		}
-	}
-
-	if (linkpath != NULL) {
-		/* If link name is too long or has non-ASCII characters, add
-		 * 'linkpath' to pax extended attrs. */
-		if (linkpath_length > 100 || has_non_ASCII(linkpath)) {
-			add_pax_attr(&(pax->pax_header), "linkpath", linkpath);
-			if (linkpath_length > 100) {
-				if (hardlink != NULL)
-					archive_entry_set_hardlink(entry_main,
-					    "././@LongHardLink");
-				else
-					archive_entry_set_symlink(entry_main,
-					    "././@LongSymLink");
-			}
-			need_extension = 1;
-		}
-	}
-	/* Save a pathname since it will be renamed if `entry_main` has
-	 * sparse blocks. */
-	archive_string_init(&entry_name);
-	archive_strcpy(&entry_name, archive_entry_pathname(entry_main));
-
-	/* If file size is too large, we need pax extended attrs. */
-	if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) {
-		need_extension = 1;
-	}
-
-	/* If numeric GID is too large, add 'gid' to pax extended attrs. */
-	if ((unsigned int)archive_entry_gid(entry_main) >= (1 << 18)) {
-		add_pax_attr_int(&(pax->pax_header), "gid",
-		    archive_entry_gid(entry_main));
-		need_extension = 1;
-	}
-
-	/* If group name is too large or has non-ASCII characters, add
-	 * 'gname' to pax extended attrs. */
-	if (gname != NULL) {
-		if (gname_length > 31 || has_non_ASCII(gname)) {
-			add_pax_attr(&(pax->pax_header), "gname", gname);
-			need_extension = 1;
-		}
-	}
-
-	/* If numeric UID is too large, add 'uid' to pax extended attrs. */
-	if ((unsigned int)archive_entry_uid(entry_main) >= (1 << 18)) {
-		add_pax_attr_int(&(pax->pax_header), "uid",
-		    archive_entry_uid(entry_main));
-		need_extension = 1;
-	}
-
-	/* Add 'uname' to pax extended attrs if necessary. */
-	if (uname != NULL) {
-		if (uname_length > 31 || has_non_ASCII(uname)) {
-			add_pax_attr(&(pax->pax_header), "uname", uname);
-			need_extension = 1;
-		}
-	}
-
-	/*
-	 * POSIX/SUSv3 doesn't provide a standard key for large device
-	 * numbers.  I use the same keys here that Joerg Schilling
-	 * used for 'star.'  (Which, somewhat confusingly, are called
-	 * "devXXX" even though they code "rdev" values.)  No doubt,
-	 * other implementations use other keys.  Note that there's no
-	 * reason we can't write the same information into a number of
-	 * different keys.
-	 *
-	 * Of course, this is only needed for block or char device entries.
-	 */
-	if (archive_entry_filetype(entry_main) == AE_IFBLK
-	    || archive_entry_filetype(entry_main) == AE_IFCHR) {
-		/*
-		 * If rdevmajor is too large, add 'SCHILY.devmajor' to
-		 * extended attributes.
-		 */
-		int rdevmajor, rdevminor;
-		rdevmajor = archive_entry_rdevmajor(entry_main);
-		rdevminor = archive_entry_rdevminor(entry_main);
-		if (rdevmajor >= (1 << 18)) {
-			add_pax_attr_int(&(pax->pax_header), "SCHILY.devmajor",
-			    rdevmajor);
-			/*
-			 * Non-strict formatting below means we don't
-			 * have to truncate here.  Not truncating improves
-			 * the chance that some more modern tar archivers
-			 * (such as GNU tar 1.13) can restore the full
-			 * value even if they don't understand the pax
-			 * extended attributes.  See my rant below about
-			 * file size fields for additional details.
-			 */
-			/* archive_entry_set_rdevmajor(entry_main,
-			   rdevmajor & ((1 << 18) - 1)); */
-			need_extension = 1;
-		}
-
-		/*
-		 * If devminor is too large, add 'SCHILY.devminor' to
-		 * extended attributes.
-		 */
-		if (rdevminor >= (1 << 18)) {
-			add_pax_attr_int(&(pax->pax_header), "SCHILY.devminor",
-			    rdevminor);
-			/* Truncation is not necessary here, either. */
-			/* archive_entry_set_rdevminor(entry_main,
-			   rdevminor & ((1 << 18) - 1)); */
-			need_extension = 1;
-		}
-	}
-
-	/*
-	 * Yes, this check is duplicated just below; this helps to
-	 * avoid writing an mtime attribute just to handle a
-	 * high-resolution timestamp in "restricted pax" mode.
-	 */
-	if (!need_extension &&
-	    ((archive_entry_mtime(entry_main) < 0)
-		|| (archive_entry_mtime(entry_main) >= ustar_max_mtime)))
-		need_extension = 1;
-
-	/* I use a star-compatible file flag attribute. */
-	p = archive_entry_fflags_text(entry_main);
-	if (!need_extension && p != NULL  &&  *p != '\0')
-		need_extension = 1;
-
-	/* If there are extended attributes, we need an extension */
-	if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
-		need_extension = 1;
-
-	/* If there are sparse info, we need an extension */
-	if (!need_extension && sparse_count > 0)
-		need_extension = 1;
-
-	acl_types = archive_entry_acl_types(entry_original);
-
-	/* If there are any ACL entries, we need an extension */
-	if (!need_extension && acl_types != 0)
-		need_extension = 1;
-
-	/* If the symlink type is defined, we need an extension */
-	if (!need_extension && archive_entry_symlink_type(entry_main) > 0)
-		need_extension = 1;
-
-	/*
-	 * Libarchive used to include these in extended headers for
-	 * restricted pax format, but that confused people who
-	 * expected ustar-like time semantics.  So now we only include
-	 * them in full pax format.
-	 */
-	if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED) {
-		if (archive_entry_ctime(entry_main) != 0  ||
-		    archive_entry_ctime_nsec(entry_main) != 0)
-			add_pax_attr_time(&(pax->pax_header), "ctime",
-			    archive_entry_ctime(entry_main),
-			    archive_entry_ctime_nsec(entry_main));
-
-		if (archive_entry_atime(entry_main) != 0 ||
-		    archive_entry_atime_nsec(entry_main) != 0)
-			add_pax_attr_time(&(pax->pax_header), "atime",
-			    archive_entry_atime(entry_main),
-			    archive_entry_atime_nsec(entry_main));
-
-		/* Store birth/creationtime only if it's earlier than mtime */
-		if (archive_entry_birthtime_is_set(entry_main) &&
-		    archive_entry_birthtime(entry_main)
-		    < archive_entry_mtime(entry_main))
-			add_pax_attr_time(&(pax->pax_header),
-			    "LIBARCHIVE.creationtime",
-			    archive_entry_birthtime(entry_main),
-			    archive_entry_birthtime_nsec(entry_main));
-	}
-
-	/*
-	 * The following items are handled differently in "pax
-	 * restricted" format.  In particular, in "pax restricted"
-	 * format they won't be added unless need_extension is
-	 * already set (we're already generating an extended header, so
-	 * may as well include these).
-	 */
-	if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
-	    need_extension) {
-		if (archive_entry_mtime(entry_main) < 0  ||
-		    archive_entry_mtime(entry_main) >= ustar_max_mtime  ||
-		    archive_entry_mtime_nsec(entry_main) != 0)
-			add_pax_attr_time(&(pax->pax_header), "mtime",
-			    archive_entry_mtime(entry_main),
-			    archive_entry_mtime_nsec(entry_main));
-
-		/* I use a star-compatible file flag attribute. */
-		p = archive_entry_fflags_text(entry_main);
-		if (p != NULL  &&  *p != '\0')
-			add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
-
-		/* I use star-compatible ACL attributes. */
-		if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			ret = add_pax_acl(a, entry_original, pax,
-			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
-			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
-			    ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
-			if (ret == ARCHIVE_FATAL) {
-				archive_entry_free(entry_main);
-				archive_string_free(&entry_name);
-				return (ARCHIVE_FATAL);
-			}
-		}
-		if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
-			ret = add_pax_acl(a, entry_original, pax,
-			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
-			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
-			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
-			if (ret == ARCHIVE_FATAL) {
-				archive_entry_free(entry_main);
-				archive_string_free(&entry_name);
-				return (ARCHIVE_FATAL);
-			}
-		}
-		if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
-			ret = add_pax_acl(a, entry_original, pax,
-			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
-			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
-			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
-			if (ret == ARCHIVE_FATAL) {
-				archive_entry_free(entry_main);
-				archive_string_free(&entry_name);
-				return (ARCHIVE_FATAL);
-			}
-		}
-
-		/* We use GNU-tar-compatible sparse attributes. */
-		if (sparse_count > 0) {
-			int64_t soffset, slength;
-
-			add_pax_attr_int(&(pax->pax_header),
-			    "GNU.sparse.major", 1);
-			add_pax_attr_int(&(pax->pax_header),
-			    "GNU.sparse.minor", 0);
-			/*
-			 * Make sure to store the original path, since
-			 * truncation to ustar limit happened already.
-			 */
-			add_pax_attr(&(pax->pax_header),
-			    "GNU.sparse.name", path);
-			add_pax_attr_int(&(pax->pax_header),
-			    "GNU.sparse.realsize",
-			    archive_entry_size(entry_main));
-
-			/* Rename the file name which will be used for
-			 * ustar header to a special name, which GNU
-			 * PAX Format 1.0 requires */
-			archive_entry_set_pathname(entry_main,
-			    build_gnu_sparse_name(gnu_sparse_name,
-			        entry_name.s));
-
-			/*
-			 * - Make a sparse map, which will precede a file data.
-			 * - Get the total size of available data of sparse.
-			 */
-			archive_string_sprintf(&(pax->sparse_map), "%d\n",
-			    sparse_count);
-			while (archive_entry_sparse_next(entry_main,
-			    &soffset, &slength) == ARCHIVE_OK) {
-				archive_string_sprintf(&(pax->sparse_map),
-				    "%jd\n%jd\n",
-				    (intmax_t)soffset,
-				    (intmax_t)slength);
-				sparse_total += slength;
-				if (sparse_list_add(pax, soffset, slength)
-				    != ARCHIVE_OK) {
-					archive_set_error(&a->archive,
-					    ENOMEM,
-					    "Can't allocate memory");
-					archive_entry_free(entry_main);
-					archive_string_free(&entry_name);
-					return (ARCHIVE_FATAL);
-				}
-			}
-		}
-
-		/* Store extended attributes */
-		if (archive_write_pax_header_xattrs(a, pax, entry_original)
-		    == ARCHIVE_FATAL) {
-			archive_entry_free(entry_main);
-			archive_string_free(&entry_name);
-			return (ARCHIVE_FATAL);
-		}
-
-		/* Store extended symlink information */
-		if (archive_entry_symlink_type(entry_main) ==
-		    AE_SYMLINK_TYPE_FILE) {
-			add_pax_attr(&(pax->pax_header),
-			    "LIBARCHIVE.symlinktype", "file");
-		} else if (archive_entry_symlink_type(entry_main) ==
-		    AE_SYMLINK_TYPE_DIRECTORY) {
-			add_pax_attr(&(pax->pax_header),
-			    "LIBARCHIVE.symlinktype", "dir");
-		}
-	}
-
-	/* Only regular files have data. */
-	if (archive_entry_filetype(entry_main) != AE_IFREG)
-		archive_entry_set_size(entry_main, 0);
-
-	/*
-	 * Pax-restricted does not store data for hardlinks, in order
-	 * to improve compatibility with ustar.
-	 */
-	if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
-	    hardlink != NULL)
-		archive_entry_set_size(entry_main, 0);
-
-	/*
-	 * XXX Full pax interchange format does permit a hardlink
-	 * entry to have data associated with it.  I'm not supporting
-	 * that here because the client expects me to tell them whether
-	 * or not this format expects data for hardlinks.  If I
-	 * don't check here, then every pax archive will end up with
-	 * duplicated data for hardlinks.  Someday, there may be
-	 * need to select this behavior, in which case the following
-	 * will need to be revisited. XXX
-	 */
-	if (hardlink != NULL)
-		archive_entry_set_size(entry_main, 0);
-
-	/* Save a real file size. */
-	real_size = archive_entry_size(entry_main);
-	/*
-	 * Overwrite a file size by the total size of sparse blocks and
-	 * the size of sparse map info. That file size is the length of
-	 * the data, which we will exactly store into an archive file.
-	 */
-	if (archive_strlen(&(pax->sparse_map))) {
-		size_t mapsize = archive_strlen(&(pax->sparse_map));
-		pax->sparse_map_padding = 0x1ff & (-(ssize_t)mapsize);
-		archive_entry_set_size(entry_main,
-		    mapsize + pax->sparse_map_padding + sparse_total);
-	}
-
-	/* If file size is too large, add 'size' to pax extended attrs. */
-	if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) {
-		add_pax_attr_int(&(pax->pax_header), "size",
-		    archive_entry_size(entry_main));
-	}
-
-	/* Format 'ustar' header for main entry.
-	 *
-	 * The trouble with file size: If the reader can't understand
-	 * the file size, they may not be able to locate the next
-	 * entry and the rest of the archive is toast.  Pax-compliant
-	 * readers are supposed to ignore the file size in the main
-	 * header, so the question becomes how to maximize portability
-	 * for readers that don't support pax attribute extensions.
-	 * For maximum compatibility, I permit numeric extensions in
-	 * the main header so that the file size stored will always be
-	 * correct, even if it's in a format that only some
-	 * implementations understand.  The technique used here is:
-	 *
-	 *  a) If possible, follow the standard exactly.  This handles
-	 *  files up to 8 gigabytes minus 1.
-	 *
-	 *  b) If that fails, try octal but omit the field terminator.
-	 *  That handles files up to 64 gigabytes minus 1.
-	 *
-	 *  c) Otherwise, use base-256 extensions.  That handles files
-	 *  up to 2^63 in this implementation, with the potential to
-	 *  go up to 2^94.  That should hold us for a while. ;-)
-	 *
-	 * The non-strict formatter uses similar logic for other
-	 * numeric fields, though they're less critical.
-	 */
-	if (__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0,
-	    NULL) == ARCHIVE_FATAL) {
-		archive_entry_free(entry_main);
-		archive_string_free(&entry_name);
-		return (ARCHIVE_FATAL);
-	}
-
-	/* If we built any extended attributes, write that entry first. */
-	if (archive_strlen(&(pax->pax_header)) > 0) {
-		struct archive_entry *pax_attr_entry;
-		time_t s;
-		int64_t uid, gid;
-		int mode;
-
-		pax_attr_entry = archive_entry_new2(&a->archive);
-		p = entry_name.s;
-		archive_entry_set_pathname(pax_attr_entry,
-		    build_pax_attribute_name(pax_entry_name, p));
-		archive_entry_set_size(pax_attr_entry,
-		    archive_strlen(&(pax->pax_header)));
-		/* Copy uid/gid (but clip to ustar limits). */
-		uid = archive_entry_uid(entry_main);
-		if (uid >= 1 << 18)
-			uid = (1 << 18) - 1;
-		archive_entry_set_uid(pax_attr_entry, uid);
-		gid = archive_entry_gid(entry_main);
-		if (gid >= 1 << 18)
-			gid = (1 << 18) - 1;
-		archive_entry_set_gid(pax_attr_entry, gid);
-		/* Copy mode over (but not setuid/setgid bits) */
-		mode = archive_entry_mode(entry_main);
-#ifdef S_ISUID
-		mode &= ~S_ISUID;
-#endif
-#ifdef S_ISGID
-		mode &= ~S_ISGID;
-#endif
-#ifdef S_ISVTX
-		mode &= ~S_ISVTX;
-#endif
-		archive_entry_set_mode(pax_attr_entry, mode);
-
-		/* Copy uname/gname. */
-		archive_entry_set_uname(pax_attr_entry,
-		    archive_entry_uname(entry_main));
-		archive_entry_set_gname(pax_attr_entry,
-		    archive_entry_gname(entry_main));
-
-		/* Copy mtime, but clip to ustar limits. */
-		s = archive_entry_mtime(entry_main);
-		if (s < 0) { s = 0; }
-		if (s > ustar_max_mtime) { s = ustar_max_mtime; }
-		archive_entry_set_mtime(pax_attr_entry, s, 0);
-
-		/* Standard ustar doesn't support atime. */
-		archive_entry_set_atime(pax_attr_entry, 0, 0);
-
-		/* Standard ustar doesn't support ctime. */
-		archive_entry_set_ctime(pax_attr_entry, 0, 0);
-
-		r = __archive_write_format_header_ustar(a, paxbuff,
-		    pax_attr_entry, 'x', 1, NULL);
-
-		archive_entry_free(pax_attr_entry);
-
-		/* Note that the 'x' header shouldn't ever fail to format */
-		if (r < ARCHIVE_WARN) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "archive_write_pax_header: "
-			    "'x' header failed?!  This can't happen.\n");
-			archive_entry_free(entry_main);
-			archive_string_free(&entry_name);
-			return (ARCHIVE_FATAL);
-		} else if (r < ret)
-			ret = r;
-		r = __archive_write_output(a, paxbuff, 512);
-		if (r != ARCHIVE_OK) {
-			sparse_list_clear(pax);
-			pax->entry_bytes_remaining = 0;
-			pax->entry_padding = 0;
-			archive_entry_free(entry_main);
-			archive_string_free(&entry_name);
-			return (ARCHIVE_FATAL);
-		}
-
-		pax->entry_bytes_remaining = archive_strlen(&(pax->pax_header));
-		pax->entry_padding =
-		    0x1ff & (-(int64_t)pax->entry_bytes_remaining);
-
-		r = __archive_write_output(a, pax->pax_header.s,
-		    archive_strlen(&(pax->pax_header)));
-		if (r != ARCHIVE_OK) {
-			/* If a write fails, we're pretty much toast. */
-			archive_entry_free(entry_main);
-			archive_string_free(&entry_name);
-			return (ARCHIVE_FATAL);
-		}
-		/* Pad out the end of the entry. */
-		r = __archive_write_nulls(a, (size_t)pax->entry_padding);
-		if (r != ARCHIVE_OK) {
-			/* If a write fails, we're pretty much toast. */
-			archive_entry_free(entry_main);
-			archive_string_free(&entry_name);
-			return (ARCHIVE_FATAL);
-		}
-		pax->entry_bytes_remaining = pax->entry_padding = 0;
-	}
-
-	/* Write the header for main entry. */
-	r = __archive_write_output(a, ustarbuff, 512);
-	if (r != ARCHIVE_OK) {
-		archive_entry_free(entry_main);
-		archive_string_free(&entry_name);
-		return (r);
-	}
-
-	/*
-	 * Inform the client of the on-disk size we're using, so
-	 * they can avoid unnecessarily writing a body for something
-	 * that we're just going to ignore.
-	 */
-	archive_entry_set_size(entry_original, real_size);
-	if (pax->sparse_list == NULL && real_size > 0) {
-		/* This is not a sparse file but we handle its data as
-		 * a sparse block. */
-		sparse_list_add(pax, 0, real_size);
-		sparse_total = real_size;
-	}
-	pax->entry_padding = 0x1ff & (-(int64_t)sparse_total);
-	archive_entry_free(entry_main);
-	archive_string_free(&entry_name);
-
-	return (ret);
-}
-
-/*
- * We need a valid name for the regular 'ustar' entry.  This routine
- * tries to hack something more-or-less reasonable.
- *
- * The approach here tries to preserve leading dir names.  We do so by
- * working with four sections:
- *   1) "prefix" directory names,
- *   2) "suffix" directory names,
- *   3) inserted dir name (optional),
- *   4) filename.
- *
- * These sections must satisfy the following requirements:
- *   * Parts 1 & 2 together form an initial portion of the dir name.
- *   * Part 3 is specified by the caller.  (It should not contain a leading
- *     or trailing '/'.)
- *   * Part 4 forms an initial portion of the base filename.
- *   * The filename must be <= 99 chars to fit the ustar 'name' field.
- *   * Parts 2, 3, 4 together must be <= 99 chars to fit the ustar 'name' fld.
- *   * Part 1 must be <= 155 chars to fit the ustar 'prefix' field.
- *   * If the original name ends in a '/', the new name must also end in a '/'
- *   * Trailing '/.' sequences may be stripped.
- *
- * Note: Recall that the ustar format does not store the '/' separating
- * parts 1 & 2, but does store the '/' separating parts 2 & 3.
- */
-static char *
-build_ustar_entry_name(char *dest, const char *src, size_t src_length,
-    const char *insert)
-{
-	const char *prefix, *prefix_end;
-	const char *suffix, *suffix_end;
-	const char *filename, *filename_end;
-	char *p;
-	int need_slash = 0; /* Was there a trailing slash? */
-	size_t suffix_length = 99;
-	size_t insert_length;
-
-	/* Length of additional dir element to be added. */
-	if (insert == NULL)
-		insert_length = 0;
-	else
-		/* +2 here allows for '/' before and after the insert. */
-		insert_length = strlen(insert) + 2;
-
-	/* Step 0: Quick bailout in a common case. */
-	if (src_length < 100 && insert == NULL) {
-		strncpy(dest, src, src_length);
-		dest[src_length] = '\0';
-		return (dest);
-	}
-
-	/* Step 1: Locate filename and enforce the length restriction. */
-	filename_end = src + src_length;
-	/* Remove trailing '/' chars and '/.' pairs. */
-	for (;;) {
-		if (filename_end > src && filename_end[-1] == '/') {
-			filename_end --;
-			need_slash = 1; /* Remember to restore trailing '/'. */
-			continue;
-		}
-		if (filename_end > src + 1 && filename_end[-1] == '.'
-		    && filename_end[-2] == '/') {
-			filename_end -= 2;
-			need_slash = 1; /* "foo/." will become "foo/" */
-			continue;
-		}
-		break;
-	}
-	if (need_slash)
-		suffix_length--;
-	/* Find start of filename. */
-	filename = filename_end - 1;
-	while ((filename > src) && (*filename != '/'))
-		filename --;
-	if ((*filename == '/') && (filename < filename_end - 1))
-		filename ++;
-	/* Adjust filename_end so that filename + insert fits in 99 chars. */
-	suffix_length -= insert_length;
-	if (filename_end > filename + suffix_length)
-		filename_end = filename + suffix_length;
-	/* Calculate max size for "suffix" section (#3 above). */
-	suffix_length -= filename_end - filename;
-
-	/* Step 2: Locate the "prefix" section of the dirname, including
-	 * trailing '/'. */
-	prefix = src;
-	prefix_end = prefix + 155;
-	if (prefix_end > filename)
-		prefix_end = filename;
-	while (prefix_end > prefix && *prefix_end != '/')
-		prefix_end--;
-	if ((prefix_end < filename) && (*prefix_end == '/'))
-		prefix_end++;
-
-	/* Step 3: Locate the "suffix" section of the dirname,
-	 * including trailing '/'. */
-	suffix = prefix_end;
-	suffix_end = suffix + suffix_length; /* Enforce limit. */
-	if (suffix_end > filename)
-		suffix_end = filename;
-	if (suffix_end < suffix)
-		suffix_end = suffix;
-	while (suffix_end > suffix && *suffix_end != '/')
-		suffix_end--;
-	if ((suffix_end < filename) && (*suffix_end == '/'))
-		suffix_end++;
-
-	/* Step 4: Build the new name. */
-	/* The OpenBSD strlcpy function is safer, but less portable. */
-	/* Rather than maintain two versions, just use the strncpy version. */
-	p = dest;
-	if (prefix_end > prefix) {
-		strncpy(p, prefix, prefix_end - prefix);
-		p += prefix_end - prefix;
-	}
-	if (suffix_end > suffix) {
-		strncpy(p, suffix, suffix_end - suffix);
-		p += suffix_end - suffix;
-	}
-	if (insert != NULL) {
-		/* Note: assume insert does not have leading or trailing '/' */
-		strcpy(p, insert);
-		p += strlen(insert);
-		*p++ = '/';
-	}
-	strncpy(p, filename, filename_end - filename);
-	p += filename_end - filename;
-	if (need_slash)
-		*p++ = '/';
-	*p = '\0';
-
-	return (dest);
-}
-
-/*
- * The ustar header for the pax extended attributes must have a
- * reasonable name:  SUSv3 requires 'dirname'/PaxHeader.'pid'/'filename'
- * where 'pid' is the PID of the archiving process.  Unfortunately,
- * that makes testing a pain since the output varies for each run,
- * so I'm sticking with the simpler 'dirname'/PaxHeader/'filename'
- * for now.  (Someday, I'll make this settable.  Then I can use the
- * SUS recommendation as default and test harnesses can override it
- * to get predictable results.)
- *
- * Joerg Schilling has argued that this is unnecessary because, in
- * practice, if the pax extended attributes get extracted as regular
- * files, no one is going to bother reading those attributes to
- * manually restore them.  Based on this, 'star' uses
- * /tmp/PaxHeader/'basename' as the ustar header name.  This is a
- * tempting argument, in part because it's simpler than the SUSv3
- * recommendation, but I'm not entirely convinced.  I'm also
- * uncomfortable with the fact that "/tmp" is a Unix-ism.
- *
- * The following routine leverages build_ustar_entry_name() above and
- * so is simpler than you might think.  It just needs to provide the
- * additional path element and handle a few pathological cases).
- */
-static char *
-build_pax_attribute_name(char *dest, const char *src)
-{
-	char buff[64];
-	const char *p;
-
-	/* Handle the null filename case. */
-	if (src == NULL || *src == '\0') {
-		strcpy(dest, "PaxHeader/blank");
-		return (dest);
-	}
-
-	/* Prune final '/' and other unwanted final elements. */
-	p = src + strlen(src);
-	for (;;) {
-		/* Ends in "/", remove the '/' */
-		if (p > src && p[-1] == '/') {
-			--p;
-			continue;
-		}
-		/* Ends in "/.", remove the '.' */
-		if (p > src + 1 && p[-1] == '.'
-		    && p[-2] == '/') {
-			--p;
-			continue;
-		}
-		break;
-	}
-
-	/* Pathological case: After above, there was nothing left.
-	 * This includes "/." "/./." "/.//./." etc. */
-	if (p == src) {
-		strcpy(dest, "/PaxHeader/rootdir");
-		return (dest);
-	}
-
-	/* Convert unadorned "." into a suitable filename. */
-	if (*src == '.' && p == src + 1) {
-		strcpy(dest, "PaxHeader/currentdir");
-		return (dest);
-	}
-
-	/*
-	 * TODO: Push this string into the 'pax' structure to avoid
-	 * recomputing it every time.  That will also open the door
-	 * to having clients override it.
-	 */
-#if HAVE_GETPID && 0  /* Disable this for now; see above comment. */
-	snprintf(buff, sizeof(buff), "PaxHeader.%d", getpid());
-#else
-	/* If the platform can't fetch the pid, don't include it. */
-	strcpy(buff, "PaxHeader");
-#endif
-	/* General case: build a ustar-compatible name adding
-	 * "/PaxHeader/". */
-	build_ustar_entry_name(dest, src, p - src, buff);
-
-	return (dest);
-}
-
-/*
- * GNU PAX Format 1.0 requires the special name, which pattern is:
- * <dir>/GNUSparseFile.<pid>/<original file name>
- *
- * Since reproducible archives are more important, use 0 as pid.
- *
- * This function is used for only Sparse file, a file type of which
- * is regular file.
- */
-static char *
-build_gnu_sparse_name(char *dest, const char *src)
-{
-	const char *p;
-
-	/* Handle the null filename case. */
-	if (src == NULL || *src == '\0') {
-		strcpy(dest, "GNUSparseFile/blank");
-		return (dest);
-	}
-
-	/* Prune final '/' and other unwanted final elements. */
-	p = src + strlen(src);
-	for (;;) {
-		/* Ends in "/", remove the '/' */
-		if (p > src && p[-1] == '/') {
-			--p;
-			continue;
-		}
-		/* Ends in "/.", remove the '.' */
-		if (p > src + 1 && p[-1] == '.'
-		    && p[-2] == '/') {
-			--p;
-			continue;
-		}
-		break;
-	}
-
-	/* General case: build a ustar-compatible name adding
-	 * "/GNUSparseFile/". */
-	build_ustar_entry_name(dest, src, p - src, "GNUSparseFile.0");
-
-	return (dest);
-}
-
-/* Write two null blocks for the end of archive */
-static int
-archive_write_pax_close(struct archive_write *a)
-{
-	return (__archive_write_nulls(a, 512 * 2));
-}
-
-static int
-archive_write_pax_free(struct archive_write *a)
-{
-	struct pax *pax;
-
-	pax = (struct pax *)a->format_data;
-	if (pax == NULL)
-		return (ARCHIVE_OK);
-
-	archive_string_free(&pax->pax_header);
-	archive_string_free(&pax->sparse_map);
-	archive_string_free(&pax->l_url_encoded_name);
-	sparse_list_clear(pax);
-	free(pax);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_pax_finish_entry(struct archive_write *a)
-{
-	struct pax *pax;
-	uint64_t remaining;
-	int ret;
-
-	pax = (struct pax *)a->format_data;
-	remaining = pax->entry_bytes_remaining;
-	if (remaining == 0) {
-		while (pax->sparse_list) {
-			struct sparse_block *sb;
-			if (!pax->sparse_list->is_hole)
-				remaining += pax->sparse_list->remaining;
-			sb = pax->sparse_list->next;
-			free(pax->sparse_list);
-			pax->sparse_list = sb;
-		}
-	}
-	ret = __archive_write_nulls(a, (size_t)(remaining + pax->entry_padding));
-	pax->entry_bytes_remaining = pax->entry_padding = 0;
-	return (ret);
-}
-
-static ssize_t
-archive_write_pax_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct pax *pax;
-	size_t ws;
-	size_t total;
-	int ret;
-
-	pax = (struct pax *)a->format_data;
-
-	/*
-	 * According to GNU PAX format 1.0, write a sparse map
-	 * before the body.
-	 */
-	if (archive_strlen(&(pax->sparse_map))) {
-		ret = __archive_write_output(a, pax->sparse_map.s,
-		    archive_strlen(&(pax->sparse_map)));
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		ret = __archive_write_nulls(a, pax->sparse_map_padding);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		archive_string_empty(&(pax->sparse_map));
-	}
-
-	total = 0;
-	while (total < s) {
-		const unsigned char *p;
-
-		while (pax->sparse_list != NULL &&
-		    pax->sparse_list->remaining == 0) {
-			struct sparse_block *sb = pax->sparse_list->next;
-			free(pax->sparse_list);
-			pax->sparse_list = sb;
-		}
-
-		if (pax->sparse_list == NULL)
-			return (total);
-
-		p = ((const unsigned char *)buff) + total;
-		ws = s - total;
-		if (ws > pax->sparse_list->remaining)
-			ws = (size_t)pax->sparse_list->remaining;
-
-		if (pax->sparse_list->is_hole) {
-			/* Current block is hole thus we do not write
-			 * the body. */
-			pax->sparse_list->remaining -= ws;
-			total += ws;
-			continue;
-		}
-
-		ret = __archive_write_output(a, p, ws);
-		pax->sparse_list->remaining -= ws;
-		total += ws;
-		if (ret != ARCHIVE_OK)
-			return (ret);
-	}
-	return (total);
-}
-
-static int
-has_non_ASCII(const char *_p)
-{
-	const unsigned char *p = (const unsigned char *)_p;
-
-	if (p == NULL)
-		return (1);
-	while (*p != '\0' && *p < 128)
-		p++;
-	return (*p != '\0');
-}
-
-/*
- * Used by extended attribute support; encodes the name
- * so that there will be no '=' characters in the result.
- */
-static char *
-url_encode(const char *in)
-{
-	const char *s;
-	char *d;
-	int out_len = 0;
-	char *out;
-
-	for (s = in; *s != '\0'; s++) {
-		if (*s < 33 || *s > 126 || *s == '%' || *s == '=')
-			out_len += 3;
-		else
-			out_len++;
-	}
-
-	out = (char *)malloc(out_len + 1);
-	if (out == NULL)
-		return (NULL);
-
-	for (s = in, d = out; *s != '\0'; s++) {
-		/* encode any non-printable ASCII character or '%' or '=' */
-		if (*s < 33 || *s > 126 || *s == '%' || *s == '=') {
-			/* URL encoding is '%' followed by two hex digits */
-			*d++ = '%';
-			*d++ = "0123456789ABCDEF"[0x0f & (*s >> 4)];
-			*d++ = "0123456789ABCDEF"[0x0f & *s];
-		} else {
-			*d++ = *s;
-		}
-	}
-	*d = '\0';
-	return (out);
-}
-
-/*
- * Encode a sequence of bytes into a C string using base-64 encoding.
- *
- * Returns a null-terminated C string allocated with malloc(); caller
- * is responsible for freeing the result.
- */
-static char *
-base64_encode(const char *s, size_t len)
-{
-	static const char digits[64] =
-	    { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
-	      'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d',
-	      'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s',
-	      't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
-	      '8','9','+','/' };
-	int v;
-	char *d, *out;
-
-	/* 3 bytes becomes 4 chars, but round up and allow for trailing NUL */
-	out = (char *)malloc((len * 4 + 2) / 3 + 1);
-	if (out == NULL)
-		return (NULL);
-	d = out;
-
-	/* Convert each group of 3 bytes into 4 characters. */
-	while (len >= 3) {
-		v = (((int)s[0] << 16) & 0xff0000)
-		    | (((int)s[1] << 8) & 0xff00)
-		    | (((int)s[2]) & 0x00ff);
-		s += 3;
-		len -= 3;
-		*d++ = digits[(v >> 18) & 0x3f];
-		*d++ = digits[(v >> 12) & 0x3f];
-		*d++ = digits[(v >> 6) & 0x3f];
-		*d++ = digits[(v) & 0x3f];
-	}
-	/* Handle final group of 1 byte (2 chars) or 2 bytes (3 chars). */
-	switch (len) {
-	case 0: break;
-	case 1:
-		v = (((int)s[0] << 16) & 0xff0000);
-		*d++ = digits[(v >> 18) & 0x3f];
-		*d++ = digits[(v >> 12) & 0x3f];
-		break;
-	case 2:
-		v = (((int)s[0] << 16) & 0xff0000)
-		    | (((int)s[1] << 8) & 0xff00);
-		*d++ = digits[(v >> 18) & 0x3f];
-		*d++ = digits[(v >> 12) & 0x3f];
-		*d++ = digits[(v >> 6) & 0x3f];
-		break;
-	}
-	/* Add trailing NUL character so output is a valid C string. */
-	*d = '\0';
-	return (out);
-}
-
-static void
-sparse_list_clear(struct pax *pax)
-{
-	while (pax->sparse_list != NULL) {
-		struct sparse_block *sb = pax->sparse_list;
-		pax->sparse_list = sb->next;
-		free(sb);
-	}
-	pax->sparse_tail = NULL;
-}
-
-static int
-_sparse_list_add_block(struct pax *pax, int64_t offset, int64_t length,
-    int is_hole)
-{
-	struct sparse_block *sb;
-
-	sb = (struct sparse_block *)malloc(sizeof(*sb));
-	if (sb == NULL)
-		return (ARCHIVE_FATAL);
-	sb->next = NULL;
-	sb->is_hole = is_hole;
-	sb->offset = offset;
-	sb->remaining = length;
-	if (pax->sparse_list == NULL || pax->sparse_tail == NULL)
-		pax->sparse_list = pax->sparse_tail = sb;
-	else {
-		pax->sparse_tail->next = sb;
-		pax->sparse_tail = sb;
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-sparse_list_add(struct pax *pax, int64_t offset, int64_t length)
-{
-	int64_t last_offset;
-	int r;
-
-	if (pax->sparse_tail == NULL)
-		last_offset = 0;
-	else {
-		last_offset = pax->sparse_tail->offset +
-		    pax->sparse_tail->remaining;
-	}
-	if (last_offset < offset) {
-		/* Add a hole block. */
-		r = _sparse_list_add_block(pax, last_offset,
-		    offset - last_offset, 1);
-		if (r != ARCHIVE_OK)
-			return (r);
-	}
-	/* Add data block. */
-	return (_sparse_list_add_block(pax, offset, length, 0));
-}
-
-static time_t
-get_ustar_max_mtime(void)
-{
-	/*
-	 * Technically, the mtime field in the ustar header can
-	 * support 33 bits. We are using all of them to keep
-	 * tar/test/test_option_C_mtree.c simple and passing after 2038.
-	 * For platforms that use signed 32-bit time values we
-	 * use the 32-bit maximum.
-	 */
-	if (sizeof(time_t) > sizeof(int32_t))
-		return (time_t)0x1ffffffff;
-	else
-		return (time_t)0x7fffffff;
-}
diff --git a/c/archive_write_set_format_private.h b/c/archive_write_set_format_private.h
deleted file mode 100644
--- a/c/archive_write_set_format_private.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * Copyright (c) 2020 Martin Matuska
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED
-#define ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#ifndef __LIBARCHIVE_TEST
-#error This header is only to be used internally to libarchive.
-#endif
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-
-void __archive_write_entry_filetype_unsupported(struct archive *a,
-    struct archive_entry *entry, const char *format);
-#endif
diff --git a/c/archive_write_set_format_raw.c b/c/archive_write_set_format_raw.c
deleted file mode 100644
--- a/c/archive_write_set_format_raw.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-
- * Copyright (c) 2013 Marek Kubica
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "archive_entry.h"
-#include "archive_write_private.h"
-
-static ssize_t	archive_write_raw_data(struct archive_write *,
-		    const void *buff, size_t s);
-static int	archive_write_raw_free(struct archive_write *);
-static int	archive_write_raw_header(struct archive_write *,
-		    struct archive_entry *);
-
-struct raw {
-        int entries_written;
-};
-
-/*
- * Set output format to 'raw' format.
- */
-int
-archive_write_set_format_raw(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct raw *raw;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_raw");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	raw = (struct raw *)calloc(1, sizeof(*raw));
-	if (raw == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate raw data");
-		return (ARCHIVE_FATAL);
-	}
-	raw->entries_written = 0;
-	a->format_data = raw;
-	a->format_name = "raw";
-        /* no options exist for this format */
-	a->format_options = NULL;
-	a->format_write_header = archive_write_raw_header;
-	a->format_write_data = archive_write_raw_data;
-	a->format_finish_entry = NULL;
-        /* nothing needs to be done on closing */
-	a->format_close = NULL;
-	a->format_free = archive_write_raw_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_RAW;
-	a->archive.archive_format_name = "RAW";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_raw_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct raw *raw = (struct raw *)a->format_data;
-
-	if (archive_entry_filetype(entry) != AE_IFREG) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Raw format only supports filetype AE_IFREG");
-		return (ARCHIVE_FATAL);
-	}
-
-
-	if (raw->entries_written > 0) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Raw format only supports one entry per archive");
-		return (ARCHIVE_FATAL);
-	}
-	raw->entries_written++;
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-archive_write_raw_data(struct archive_write *a, const void *buff, size_t s)
-{
-	int ret;
-
-	ret = __archive_write_output(a, buff, s);
-	if (ret >= 0)
-		return (s);
-	else
-		return (ret);
-}
-
-static int
-archive_write_raw_free(struct archive_write *a)
-{
-	struct raw *raw;
-
-	raw = (struct raw *)a->format_data;
-	free(raw);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_set_format_shar.c b/c/archive_write_set_format_shar.c
deleted file mode 100644
--- a/c/archive_write_set_format_shar.c
+++ /dev/null
@@ -1,641 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2008 Joerg Sonnenberger
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_shar.c 189438 2009-03-06 05:58:56Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct shar {
-	int			 dump;
-	int			 end_of_line;
-	struct archive_entry	*entry;
-	int			 has_data;
-	char			*last_dir;
-
-	/* Line buffer for uuencoded dump format */
-	char			 outbuff[45];
-	size_t			 outpos;
-
-	int			 wrote_header;
-	struct archive_string	 work;
-	struct archive_string	 quoted_name;
-};
-
-static int	archive_write_shar_close(struct archive_write *);
-static int	archive_write_shar_free(struct archive_write *);
-static int	archive_write_shar_header(struct archive_write *,
-		    struct archive_entry *);
-static ssize_t	archive_write_shar_data_sed(struct archive_write *,
-		    const void * buff, size_t);
-static ssize_t	archive_write_shar_data_uuencode(struct archive_write *,
-		    const void * buff, size_t);
-static int	archive_write_shar_finish_entry(struct archive_write *);
-
-/*
- * Copy the given string to the buffer, quoting all shell meta characters
- * found.
- */
-static void
-shar_quote(struct archive_string *buf, const char *str, int in_shell)
-{
-	static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
-	size_t len;
-
-	while (*str != '\0') {
-		if ((len = strcspn(str, meta)) != 0) {
-			archive_strncat(buf, str, len);
-			str += len;
-		} else if (*str == '\n') {
-			if (in_shell)
-				archive_strcat(buf, "\"\n\"");
-			else
-				archive_strcat(buf, "\\n");
-			++str;
-		} else {
-			archive_strappend_char(buf, '\\');
-			archive_strappend_char(buf, *str);
-			++str;
-		}
-	}
-}
-
-/*
- * Set output format to 'shar' format.
- */
-int
-archive_write_set_format_shar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct shar *shar;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_shar");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	shar = (struct shar *)calloc(1, sizeof(*shar));
-	if (shar == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
-		return (ARCHIVE_FATAL);
-	}
-	archive_string_init(&shar->work);
-	archive_string_init(&shar->quoted_name);
-	a->format_data = shar;
-	a->format_name = "shar";
-	a->format_write_header = archive_write_shar_header;
-	a->format_close = archive_write_shar_close;
-	a->format_free = archive_write_shar_free;
-	a->format_write_data = archive_write_shar_data_sed;
-	a->format_finish_entry = archive_write_shar_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_SHAR_BASE;
-	a->archive.archive_format_name = "shar";
-	return (ARCHIVE_OK);
-}
-
-/*
- * An alternate 'shar' that uses uudecode instead of 'sed' to encode
- * file contents and can therefore be used to archive binary files.
- * In addition, this variant also attempts to restore ownership, file modes,
- * and other extended file information.
- */
-int
-archive_write_set_format_shar_dump(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct shar *shar;
-
-	archive_write_set_format_shar(&a->archive);
-	shar = (struct shar *)a->format_data;
-	shar->dump = 1;
-	a->format_write_data = archive_write_shar_data_uuencode;
-	a->archive.archive_format = ARCHIVE_FORMAT_SHAR_DUMP;
-	a->archive.archive_format_name = "shar dump";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
-{
-	const char *linkname;
-	const char *name;
-	char *p, *pp;
-	struct shar *shar;
-
-	shar = (struct shar *)a->format_data;
-	if (!shar->wrote_header) {
-		archive_strcat(&shar->work, "#!/bin/sh\n");
-		archive_strcat(&shar->work, "# This is a shell archive\n");
-		shar->wrote_header = 1;
-	}
-
-	/* Save the entry for the closing. */
-	archive_entry_free(shar->entry);
-	shar->entry = archive_entry_clone(entry);
-	name = archive_entry_pathname(entry);
-
-	/* Handle some preparatory issues. */
-	switch(archive_entry_filetype(entry)) {
-	case AE_IFREG:
-		/* Only regular files have non-zero size. */
-		break;
-	case AE_IFDIR:
-		archive_entry_set_size(entry, 0);
-		/* Don't bother trying to recreate '.' */
-		if (strcmp(name, ".") == 0  ||  strcmp(name, "./") == 0)
-			return (ARCHIVE_OK);
-		break;
-	case AE_IFIFO:
-	case AE_IFCHR:
-	case AE_IFBLK:
-		/* All other file types have zero size in the archive. */
-		archive_entry_set_size(entry, 0);
-		break;
-	default:
-		archive_entry_set_size(entry, 0);
-		if (archive_entry_hardlink(entry) == NULL &&
-		    archive_entry_symlink(entry) == NULL) {
-			__archive_write_entry_filetype_unsupported(
-			    &a->archive, entry, "shar");
-			return (ARCHIVE_WARN);
-		}
-	}
-
-	archive_string_empty(&shar->quoted_name);
-	shar_quote(&shar->quoted_name, name, 1);
-
-	/* Stock preparation for all file types. */
-	archive_string_sprintf(&shar->work, "echo x %s\n", shar->quoted_name.s);
-
-	if (archive_entry_filetype(entry) != AE_IFDIR) {
-		/* Try to create the dir. */
-		p = strdup(name);
-		pp = strrchr(p, '/');
-		/* If there is a / character, try to create the dir. */
-		if (pp != NULL) {
-			*pp = '\0';
-
-			/* Try to avoid a lot of redundant mkdir commands. */
-			if (strcmp(p, ".") == 0) {
-				/* Don't try to "mkdir ." */
-				free(p);
-			} else if (shar->last_dir == NULL) {
-				archive_strcat(&shar->work, "mkdir -p ");
-				shar_quote(&shar->work, p, 1);
-				archive_strcat(&shar->work,
-				    " > /dev/null 2>&1\n");
-				shar->last_dir = p;
-			} else if (strcmp(p, shar->last_dir) == 0) {
-				/* We've already created this exact dir. */
-				free(p);
-			} else if (strlen(p) < strlen(shar->last_dir) &&
-			    strncmp(p, shar->last_dir, strlen(p)) == 0) {
-				/* We've already created a subdir. */
-				free(p);
-			} else {
-				archive_strcat(&shar->work, "mkdir -p ");
-				shar_quote(&shar->work, p, 1);
-				archive_strcat(&shar->work,
-				    " > /dev/null 2>&1\n");
-				shar->last_dir = p;
-			}
-		} else {
-			free(p);
-		}
-	}
-
-	/* Handle file-type specific issues. */
-	shar->has_data = 0;
-	if ((linkname = archive_entry_hardlink(entry)) != NULL) {
-		archive_strcat(&shar->work, "ln -f ");
-		shar_quote(&shar->work, linkname, 1);
-		archive_string_sprintf(&shar->work, " %s\n",
-		    shar->quoted_name.s);
-	} else if ((linkname = archive_entry_symlink(entry)) != NULL) {
-		archive_strcat(&shar->work, "ln -fs ");
-		shar_quote(&shar->work, linkname, 1);
-		archive_string_sprintf(&shar->work, " %s\n",
-		    shar->quoted_name.s);
-	} else {
-		switch(archive_entry_filetype(entry)) {
-		case AE_IFREG:
-			if (archive_entry_size(entry) == 0) {
-				/* More portable than "touch." */
-				archive_string_sprintf(&shar->work,
-				    "test -e \"%s\" || :> \"%s\"\n",
-				    shar->quoted_name.s, shar->quoted_name.s);
-			} else {
-				if (shar->dump) {
-					unsigned int mode = archive_entry_mode(entry) & 0777;
-					archive_string_sprintf(&shar->work,
-					    "uudecode -p > %s << 'SHAR_END'\n",
-					    shar->quoted_name.s);
-					archive_string_sprintf(&shar->work,
-					    "begin %o ", mode);
-					shar_quote(&shar->work, name, 0);
-					archive_strcat(&shar->work, "\n");
-				} else {
-					archive_string_sprintf(&shar->work,
-					    "sed 's/^X//' > %s << 'SHAR_END'\n",
-					    shar->quoted_name.s);
-				}
-				shar->has_data = 1;
-				shar->end_of_line = 1;
-				shar->outpos = 0;
-			}
-			break;
-		case AE_IFDIR:
-			archive_string_sprintf(&shar->work,
-			    "mkdir -p %s > /dev/null 2>&1\n",
-			    shar->quoted_name.s);
-			/* Record that we just created this directory. */
-			free(shar->last_dir);
-
-			shar->last_dir = strdup(name);
-			/* Trim a trailing '/'. */
-			pp = strrchr(shar->last_dir, '/');
-			if (pp != NULL && pp[1] == '\0')
-				*pp = '\0';
-			/*
-			 * TODO: Put dir name/mode on a list to be fixed
-			 * up at end of archive.
-			 */
-			break;
-		case AE_IFIFO:
-			archive_string_sprintf(&shar->work,
-			    "mkfifo %s\n", shar->quoted_name.s);
-			break;
-		case AE_IFCHR:
-			archive_string_sprintf(&shar->work,
-			    "mknod %s c %ju %ju\n", shar->quoted_name.s,
-			    (uintmax_t)archive_entry_rdevmajor(entry),
-			    (uintmax_t)archive_entry_rdevminor(entry));
-			break;
-		case AE_IFBLK:
-			archive_string_sprintf(&shar->work,
-			    "mknod %s b %ju %ju\n", shar->quoted_name.s,
-			    (uintmax_t)archive_entry_rdevmajor(entry),
-			    (uintmax_t)archive_entry_rdevminor(entry));
-			break;
-		default:
-			return (ARCHIVE_WARN);
-		}
-	}
-
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n)
-{
-	static const size_t ensured = 65533;
-	struct shar *shar;
-	const char *src;
-	char *buf, *buf_end;
-	int ret;
-	size_t written = n;
-
-	shar = (struct shar *)a->format_data;
-	if (!shar->has_data || n == 0)
-		return (0);
-
-	src = (const char *)buff;
-
-	/*
-	 * ensure is the number of bytes in buffer before expanding the
-	 * current character.  Each operation writes the current character
-	 * and optionally the start-of-new-line marker.  This can happen
-	 * twice before entering the loop, so make sure three additional
-	 * bytes can be written.
-	 */
-	if (archive_string_ensure(&shar->work, ensured + 3) == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (shar->work.length > ensured) {
-		ret = __archive_write_output(a, shar->work.s,
-		    shar->work.length);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		archive_string_empty(&shar->work);
-	}
-	buf = shar->work.s + shar->work.length;
-	buf_end = shar->work.s + ensured;
-
-	if (shar->end_of_line) {
-		*buf++ = 'X';
-		shar->end_of_line = 0;
-	}
-
-	while (n-- != 0) {
-		if ((*buf++ = *src++) == '\n') {
-			if (n == 0)
-				shar->end_of_line = 1;
-			else
-				*buf++ = 'X';
-		}
-
-		if (buf >= buf_end) {
-			shar->work.length = buf - shar->work.s;
-			ret = __archive_write_output(a, shar->work.s,
-			    shar->work.length);
-			if (ret != ARCHIVE_OK)
-				return (ARCHIVE_FATAL);
-			archive_string_empty(&shar->work);
-			buf = shar->work.s;
-		}
-	}
-
-	shar->work.length = buf - shar->work.s;
-
-	return (written);
-}
-
-#define	UUENC(c)	(((c)!=0) ? ((c) & 077) + ' ': '`')
-
-static void
-uuencode_group(const char _in[3], char out[4])
-{
-	const unsigned char *in = (const unsigned char *)_in;
-	int t;
-
-	t = (in[0] << 16) | (in[1] << 8) | in[2];
-	out[0] = UUENC( 0x3f & (t >> 18) );
-	out[1] = UUENC( 0x3f & (t >> 12) );
-	out[2] = UUENC( 0x3f & (t >> 6) );
-	out[3] = UUENC( 0x3f & t );
-}
-
-static int
-_uuencode_line(struct archive_write *a, struct shar *shar, const char *inbuf, size_t len)
-{
-	char *buf;
-	size_t alloc_len;
-
-	/* len <= 45 -> expanded to 60 + len byte + new line */
-	alloc_len = shar->work.length + 62;
-	if (archive_string_ensure(&shar->work, alloc_len) == NULL) {
-		archive_set_error(&a->archive, ENOMEM, "Out of memory");
-		return (ARCHIVE_FATAL);
-	}
-
-	buf = shar->work.s + shar->work.length;
-	*buf++ = UUENC(len);
-	while (len >= 3) {
-		uuencode_group(inbuf, buf);
-		len -= 3;
-		inbuf += 3;
-		buf += 4;
-	}
-	if (len != 0) {
-		char tmp_buf[3];
-		tmp_buf[0] = inbuf[0];
-		if (len == 1)
-			tmp_buf[1] = '\0';
-		else
-			tmp_buf[1] = inbuf[1];
-		tmp_buf[2] = '\0';
-		uuencode_group(tmp_buf, buf);
-		buf += 4;
-	}
-	*buf++ = '\n';
-	if ((buf - shar->work.s) > (ptrdiff_t)(shar->work.length + 62)) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC, "Buffer overflow");
-		return (ARCHIVE_FATAL);
-	}
-	shar->work.length = buf - shar->work.s;
-	return (ARCHIVE_OK);
-}
-
-#define uuencode_line(__a, __shar, __inbuf, __len) \
-	do { \
-		int r = _uuencode_line(__a, __shar, __inbuf, __len); \
-		if (r != ARCHIVE_OK) \
-			return (ARCHIVE_FATAL); \
-	} while (0)
-
-static ssize_t
-archive_write_shar_data_uuencode(struct archive_write *a, const void *buff,
-    size_t length)
-{
-	struct shar *shar;
-	const char *src;
-	size_t n;
-	int ret;
-
-	shar = (struct shar *)a->format_data;
-	if (!shar->has_data)
-		return (ARCHIVE_OK);
-	src = (const char *)buff;
-
-	if (shar->outpos != 0) {
-		n = 45 - shar->outpos;
-		if (n > length)
-			n = length;
-		memcpy(shar->outbuff + shar->outpos, src, n);
-		if (shar->outpos + n < 45) {
-			shar->outpos += n;
-			return length;
-		}
-		uuencode_line(a, shar, shar->outbuff, 45);
-		src += n;
-		n = length - n;
-	} else {
-		n = length;
-	}
-
-	while (n >= 45) {
-		uuencode_line(a, shar, src, 45);
-		src += 45;
-		n -= 45;
-
-		if (shar->work.length < 65536)
-			continue;
-		ret = __archive_write_output(a, shar->work.s,
-		    shar->work.length);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		archive_string_empty(&shar->work);
-	}
-	if (n != 0) {
-		memcpy(shar->outbuff, src, n);
-		shar->outpos = n;
-	}
-	return (length);
-}
-
-static int
-archive_write_shar_finish_entry(struct archive_write *a)
-{
-	const char *g, *p, *u;
-	struct shar *shar;
-	int ret;
-
-	shar = (struct shar *)a->format_data;
-	if (shar->entry == NULL)
-		return (0);
-
-	if (shar->dump) {
-		/* Finish uuencoded data. */
-		if (shar->has_data) {
-			if (shar->outpos > 0)
-				uuencode_line(a, shar, shar->outbuff,
-				    shar->outpos);
-			archive_strcat(&shar->work, "`\nend\n");
-			archive_strcat(&shar->work, "SHAR_END\n");
-		}
-		/* Restore file mode, owner, flags. */
-		/*
-		 * TODO: Don't immediately restore mode for
-		 * directories; defer that to end of script.
-		 */
-		archive_string_sprintf(&shar->work, "chmod %o ",
-		    (unsigned int)(archive_entry_mode(shar->entry) & 07777));
-		shar_quote(&shar->work, archive_entry_pathname(shar->entry), 1);
-		archive_strcat(&shar->work, "\n");
-
-		u = archive_entry_uname(shar->entry);
-		g = archive_entry_gname(shar->entry);
-		if (u != NULL || g != NULL) {
-			archive_strcat(&shar->work, "chown ");
-			if (u != NULL)
-				shar_quote(&shar->work, u, 1);
-			if (g != NULL) {
-				archive_strcat(&shar->work, ":");
-				shar_quote(&shar->work, g, 1);
-			}
-			archive_strcat(&shar->work, " ");
-			shar_quote(&shar->work,
-			    archive_entry_pathname(shar->entry), 1);
-			archive_strcat(&shar->work, "\n");
-		}
-
-		if ((p = archive_entry_fflags_text(shar->entry)) != NULL) {
-			archive_string_sprintf(&shar->work, "chflags %s ", p);
-			shar_quote(&shar->work,
-			    archive_entry_pathname(shar->entry), 1);
-			archive_strcat(&shar->work, "\n");
-		}
-
-		/* TODO: restore ACLs */
-
-	} else {
-		if (shar->has_data) {
-			/* Finish sed-encoded data:  ensure last line ends. */
-			if (!shar->end_of_line)
-				archive_strappend_char(&shar->work, '\n');
-			archive_strcat(&shar->work, "SHAR_END\n");
-		}
-	}
-
-	archive_entry_free(shar->entry);
-	shar->entry = NULL;
-
-	if (shar->work.length < 65536)
-		return (ARCHIVE_OK);
-
-	ret = __archive_write_output(a, shar->work.s, shar->work.length);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	archive_string_empty(&shar->work);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_shar_close(struct archive_write *a)
-{
-	struct shar *shar;
-	int ret;
-
-	/*
-	 * TODO: Accumulate list of directory names/modes and
-	 * fix them all up at end-of-archive.
-	 */
-
-	shar = (struct shar *)a->format_data;
-
-	/*
-	 * Only write the end-of-archive markers if the archive was
-	 * actually started.  This avoids problems if someone sets
-	 * shar format, then sets another format (which would invoke
-	 * shar_finish to free the format-specific data).
-	 */
-	if (shar->wrote_header == 0)
-		return (ARCHIVE_OK);
-
-	archive_strcat(&shar->work, "exit\n");
-
-	ret = __archive_write_output(a, shar->work.s, shar->work.length);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-
-	/* Shar output is never padded. */
-	archive_write_set_bytes_in_last_block(&a->archive, 1);
-	/*
-	 * TODO: shar should also suppress padding of
-	 * uncompressed data within gzip/bzip2 streams.
-	 */
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_shar_free(struct archive_write *a)
-{
-	struct shar *shar;
-
-	shar = (struct shar *)a->format_data;
-	if (shar == NULL)
-		return (ARCHIVE_OK);
-
-	archive_entry_free(shar->entry);
-	free(shar->last_dir);
-	archive_string_free(&(shar->work));
-	archive_string_free(&(shar->quoted_name));
-	free(shar);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
diff --git a/c/archive_write_set_format_ustar.c b/c/archive_write_set_format_ustar.c
deleted file mode 100644
--- a/c/archive_write_set_format_ustar.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ustar.c 191579 2009-04-27 18:35:03Z kientzle $");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct ustar {
-	uint64_t	entry_bytes_remaining;
-	uint64_t	entry_padding;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int	init_default_conversion;
-};
-
-/*
- * Define structure of POSIX 'ustar' tar header.
- */
-#define	USTAR_name_offset 0
-#define	USTAR_name_size 100
-#define	USTAR_mode_offset 100
-#define	USTAR_mode_size 6
-#define	USTAR_mode_max_size 8
-#define	USTAR_uid_offset 108
-#define	USTAR_uid_size 6
-#define	USTAR_uid_max_size 8
-#define	USTAR_gid_offset 116
-#define	USTAR_gid_size 6
-#define	USTAR_gid_max_size 8
-#define	USTAR_size_offset 124
-#define	USTAR_size_size 11
-#define	USTAR_size_max_size 12
-#define	USTAR_mtime_offset 136
-#define	USTAR_mtime_size 11
-#define	USTAR_mtime_max_size 11
-#define	USTAR_checksum_offset 148
-#define	USTAR_checksum_size 8
-#define	USTAR_typeflag_offset 156
-#define	USTAR_typeflag_size 1
-#define	USTAR_linkname_offset 157
-#define	USTAR_linkname_size 100
-#define	USTAR_magic_offset 257
-#define	USTAR_magic_size 6
-#define	USTAR_version_offset 263
-#define	USTAR_version_size 2
-#define	USTAR_uname_offset 265
-#define	USTAR_uname_size 32
-#define	USTAR_gname_offset 297
-#define	USTAR_gname_size 32
-#define	USTAR_rdevmajor_offset 329
-#define	USTAR_rdevmajor_size 6
-#define	USTAR_rdevmajor_max_size 8
-#define	USTAR_rdevminor_offset 337
-#define	USTAR_rdevminor_size 6
-#define	USTAR_rdevminor_max_size 8
-#define	USTAR_prefix_offset 345
-#define	USTAR_prefix_size 155
-#define	USTAR_padding_offset 500
-#define	USTAR_padding_size 12
-
-/*
- * A filled-in copy of the header for initialization.
- */
-static const char template_header[] = {
-	/* name: 100 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,
-	/* Mode, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* uid, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* gid, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* size, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* mtime, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* Initial checksum value: 8 spaces */
-	' ',' ',' ',' ',' ',' ',' ',' ',
-	/* Typeflag: 1 byte */
-	'0',			/* '0' = regular file */
-	/* Linkname: 100 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,
-	/* Magic: 6 bytes, Version: 2 bytes */
-	'u','s','t','a','r','\0', '0','0',
-	/* Uname: 32 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,
-	/* Gname: 32 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,
-	/* rdevmajor + space/null padding: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* rdevminor + space/null padding: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* Prefix: 155 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,
-	/* Padding: 12 bytes */
-	0,0,0,0,0,0,0,0, 0,0,0,0
-};
-
-static ssize_t	archive_write_ustar_data(struct archive_write *a, const void *buff,
-		    size_t s);
-static int	archive_write_ustar_free(struct archive_write *);
-static int	archive_write_ustar_close(struct archive_write *);
-static int	archive_write_ustar_finish_entry(struct archive_write *);
-static int	archive_write_ustar_header(struct archive_write *,
-		    struct archive_entry *entry);
-static int	archive_write_ustar_options(struct archive_write *,
-		    const char *, const char *);
-static int	format_256(int64_t, char *, int);
-static int	format_number(int64_t, char *, int size, int max, int strict);
-static int	format_octal(int64_t, char *, int);
-
-/*
- * Set output format to 'ustar' format.
- */
-int
-archive_write_set_format_ustar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct ustar *ustar;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_ustar");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	/* Basic internal sanity test. */
-	if (sizeof(template_header) != 512) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal: template_header wrong size: %zu should be 512",
-		    sizeof(template_header));
-		return (ARCHIVE_FATAL);
-	}
-
-	ustar = (struct ustar *)calloc(1, sizeof(*ustar));
-	if (ustar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = ustar;
-	a->format_name = "ustar";
-	a->format_options = archive_write_ustar_options;
-	a->format_write_header = archive_write_ustar_header;
-	a->format_write_data = archive_write_ustar_data;
-	a->format_close = archive_write_ustar_close;
-	a->format_free = archive_write_ustar_free;
-	a->format_finish_entry = archive_write_ustar_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
-	a->archive.archive_format_name = "POSIX ustar";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_ustar_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct ustar *ustar = (struct ustar *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			ustar->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (ustar->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
-{
-	char buff[512];
-	int ret, ret2;
-	struct ustar *ustar;
-	struct archive_entry *entry_main;
-	struct archive_string_conv *sconv;
-
-	ustar = (struct ustar *)a->format_data;
-
-	/* Setup default string conversion. */
-	if (ustar->opt_sconv == NULL) {
-		if (!ustar->init_default_conversion) {
-			ustar->sconv_default =
-			    archive_string_default_conversion_for_write(&(a->archive));
-			ustar->init_default_conversion = 1;
-		}
-		sconv = ustar->sconv_default;
-	} else
-		sconv = ustar->opt_sconv;
-
-	/* Sanity check. */
-	if (archive_entry_pathname(entry) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Can't record entry in tar file without pathname");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Only regular files (not hardlinks) have data. */
-	if (archive_entry_hardlink(entry) != NULL ||
-	    archive_entry_symlink(entry) != NULL ||
-	    !(archive_entry_filetype(entry) == AE_IFREG))
-		archive_entry_set_size(entry, 0);
-
-	if (AE_IFDIR == archive_entry_filetype(entry)) {
-		const char *p;
-		size_t path_length;
-		/*
-		 * Ensure a trailing '/'.  Modify the entry so
-		 * the client sees the change.
-		 */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		const wchar_t *wp;
-
-		wp = archive_entry_pathname_w(entry);
-		if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
-			struct archive_wstring ws;
-
-			archive_string_init(&ws);
-			path_length = wcslen(wp);
-			if (archive_wstring_ensure(&ws,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate ustar data");
-				archive_wstring_free(&ws);
-				return(ARCHIVE_FATAL);
-			}
-			/* Should we keep '\' ? */
-			if (wp[path_length -1] == L'\\')
-				path_length--;
-			archive_wstrncpy(&ws, wp, path_length);
-			archive_wstrappend_wchar(&ws, L'/');
-			archive_entry_copy_pathname_w(entry, ws.s);
-			archive_wstring_free(&ws);
-			p = NULL;
-		} else
-#endif
-			p = archive_entry_pathname(entry);
-		/*
-		 * On Windows, this is a backup operation just in
-		 * case getting WCS failed. On POSIX, this is a
-		 * normal operation.
-		 */
-		if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
-			struct archive_string as;
-
-			archive_string_init(&as);
-			path_length = strlen(p);
-			if (archive_string_ensure(&as,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate ustar data");
-				archive_string_free(&as);
-				return(ARCHIVE_FATAL);
-			}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-			/* NOTE: This might break the pathname
-			 * if the current code page is CP932 and
-			 * the pathname includes a character '\'
-			 * as a part of its multibyte pathname. */
-			if (p[strlen(p) -1] == '\\')
-				path_length--;
-			else
-#endif
-			archive_strncpy(&as, p, path_length);
-			archive_strappend_char(&as, '/');
-			archive_entry_copy_pathname(entry, as.s);
-			archive_string_free(&as);
-		}
-	}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate ustar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-	ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
-	if (ret < ARCHIVE_WARN) {
-		archive_entry_free(entry_main);
-		return (ret);
-	}
-	ret2 = __archive_write_output(a, buff, 512);
-	if (ret2 < ARCHIVE_WARN) {
-		archive_entry_free(entry_main);
-		return (ret2);
-	}
-	if (ret2 < ret)
-		ret = ret2;
-
-	ustar->entry_bytes_remaining = archive_entry_size(entry);
-	ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
-	archive_entry_free(entry_main);
-	return (ret);
-}
-
-/*
- * Format a basic 512-byte "ustar" header.
- *
- * Returns -1 if format failed (due to field overflow).
- * Note that this always formats as much of the header as possible.
- * If "strict" is set to zero, it will extend numeric fields as
- * necessary (overwriting terminators or using base-256 extensions).
- *
- * This is exported so that other 'tar' formats can use it.
- */
-int
-__archive_write_format_header_ustar(struct archive_write *a, char h[512],
-    struct archive_entry *entry, int tartype, int strict,
-    struct archive_string_conv *sconv)
-{
-	unsigned int checksum;
-	int i, r, ret;
-	size_t copy_length;
-	const char *p, *pp;
-	int mytartype;
-
-	ret = 0;
-	mytartype = -1;
-	/*
-	 * The "template header" already includes the "ustar"
-	 * signature, various end-of-field markers and other required
-	 * elements.
-	 */
-	memcpy(h, &template_header, 512);
-
-	/*
-	 * Because the block is already null-filled, and strings
-	 * are allowed to exactly fill their destination (without null),
-	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
-	 */
-	r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    pp, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (copy_length <= USTAR_name_size)
-		memcpy(h + USTAR_name_offset, pp, copy_length);
-	else {
-		/* Store in two pieces, splitting at a '/'. */
-		p = strchr(pp + copy_length - USTAR_name_size - 1, '/');
-		/*
-		 * Look for the next '/' if we chose the first character
-		 * as the separator.  (ustar format doesn't permit
-		 * an empty prefix.)
-		 */
-		if (p == pp)
-			p = strchr(p + 1, '/');
-		/* Fail if the name won't fit. */
-		if (!p) {
-			/* No separator. */
-			archive_set_error(&a->archive, ENAMETOOLONG,
-			    "Pathname too long");
-			ret = ARCHIVE_FAILED;
-		} else if (p[1] == '\0') {
-			/*
-			 * The only feasible separator is a final '/';
-			 * this would result in a non-empty prefix and
-			 * an empty name, which POSIX doesn't
-			 * explicitly forbid, but it just feels wrong.
-			 */
-			archive_set_error(&a->archive, ENAMETOOLONG,
-			    "Pathname too long");
-			ret = ARCHIVE_FAILED;
-		} else if (p  > pp + USTAR_prefix_size) {
-			/* Prefix is too long. */
-			archive_set_error(&a->archive, ENAMETOOLONG,
-			    "Pathname too long");
-			ret = ARCHIVE_FAILED;
-		} else {
-			/* Copy prefix and remainder to appropriate places */
-			memcpy(h + USTAR_prefix_offset, pp, p - pp);
-			memcpy(h + USTAR_name_offset, p + 1,
-			    pp + copy_length - p - 1);
-		}
-	}
-
-	r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    p, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (copy_length > 0)
-		mytartype = '1';
-	else {
-		r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate linkname '%s' to %s",
-			    p, archive_string_conversion_charset_name(sconv));
-			ret = ARCHIVE_WARN;
-		}
-	}
-	if (copy_length > 0) {
-		if (copy_length > USTAR_linkname_size) {
-			archive_set_error(&a->archive, ENAMETOOLONG,
-			    "Link contents too long");
-			ret = ARCHIVE_FAILED;
-			copy_length = USTAR_linkname_size;
-		}
-		memcpy(h + USTAR_linkname_offset, p, copy_length);
-	}
-
-	r = archive_entry_uname_l(entry, &p, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Uname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate uname '%s' to %s",
-		    p, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (copy_length > 0) {
-		if (copy_length > USTAR_uname_size) {
-			if (tartype != 'x') {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC, "Username too long");
-				ret = ARCHIVE_FAILED;
-			}
-			copy_length = USTAR_uname_size;
-		}
-		memcpy(h + USTAR_uname_offset, p, copy_length);
-	}
-
-	r = archive_entry_gname_l(entry, &p, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Gname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate gname '%s' to %s",
-		    p, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (copy_length > 0) {
-		if (strlen(p) > USTAR_gname_size) {
-			if (tartype != 'x') {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC, "Group name too long");
-				ret = ARCHIVE_FAILED;
-			}
-			copy_length = USTAR_gname_size;
-		}
-		memcpy(h + USTAR_gname_offset, p, copy_length);
-	}
-
-	if (format_number(archive_entry_mode(entry) & 07777,
-	    h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric mode too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_uid(entry),
-	    h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric user ID too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_gid(entry),
-	    h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric group ID too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_size(entry),
-	    h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File size out of range");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_mtime(entry),
-	    h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File modification time too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (archive_entry_filetype(entry) == AE_IFBLK
-	    || archive_entry_filetype(entry) == AE_IFCHR) {
-		if (format_number(archive_entry_rdevmajor(entry),
-		    h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size,
-		    USTAR_rdevmajor_max_size, strict)) {
-			archive_set_error(&a->archive, ERANGE,
-			    "Major device number too large");
-			ret = ARCHIVE_FAILED;
-		}
-
-		if (format_number(archive_entry_rdevminor(entry),
-		    h + USTAR_rdevminor_offset, USTAR_rdevminor_size,
-		    USTAR_rdevminor_max_size, strict)) {
-			archive_set_error(&a->archive, ERANGE,
-			    "Minor device number too large");
-			ret = ARCHIVE_FAILED;
-		}
-	}
-
-	if (tartype >= 0) {
-		h[USTAR_typeflag_offset] = tartype;
-	} else if (mytartype >= 0) {
-		h[USTAR_typeflag_offset] = mytartype;
-	} else {
-		switch (archive_entry_filetype(entry)) {
-		case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
-		case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
-		case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
-		case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
-		case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
-		case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
-		default: /* AE_IFSOCK and unknown */
-			__archive_write_entry_filetype_unsupported(
-			    &a->archive, entry, "ustar");
-			ret = ARCHIVE_FAILED;
-		}
-	}
-
-	checksum = 0;
-	for (i = 0; i < 512; i++)
-		checksum += 255 & (unsigned int)h[i];
-	h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
-	/* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
-	format_octal(checksum, h + USTAR_checksum_offset, 6);
-	return (ret);
-}
-
-/*
- * Format a number into a field, with some intelligence.
- */
-static int
-format_number(int64_t v, char *p, int s, int maxsize, int strict)
-{
-	int64_t limit;
-
-	limit = ((int64_t)1 << (s*3));
-
-	/* "Strict" only permits octal values with proper termination. */
-	if (strict)
-		return (format_octal(v, p, s));
-
-	/*
-	 * In non-strict mode, we allow the number to overwrite one or
-	 * more bytes of the field termination.  Even old tar
-	 * implementations should be able to handle this with no
-	 * problem.
-	 */
-	if (v >= 0) {
-		while (s <= maxsize) {
-			if (v < limit)
-				return (format_octal(v, p, s));
-			s++;
-			limit <<= 3;
-		}
-	}
-
-	/* Base-256 can handle any number, positive or negative. */
-	return (format_256(v, p, maxsize));
-}
-
-/*
- * Format a number into the specified field using base-256.
- */
-static int
-format_256(int64_t v, char *p, int s)
-{
-	p += s;
-	while (s-- > 0) {
-		*--p = (char)(v & 0xff);
-		v >>= 8;
-	}
-	*p |= 0x80; /* Set the base-256 marker bit. */
-	return (0);
-}
-
-/*
- * Format a number into the specified field.
- */
-static int
-format_octal(int64_t v, char *p, int s)
-{
-	int len;
-
-	len = s;
-
-	/* Octal values can't be negative, so use 0. */
-	if (v < 0) {
-		while (len-- > 0)
-			*p++ = '0';
-		return (-1);
-	}
-
-	p += s;		/* Start at the end and work backwards. */
-	while (s-- > 0) {
-		*--p = (char)('0' + (v & 7));
-		v >>= 3;
-	}
-
-	if (v == 0)
-		return (0);
-
-	/* If it overflowed, fill field with max value. */
-	while (len-- > 0)
-		*p++ = '7';
-
-	return (-1);
-}
-
-static int
-archive_write_ustar_close(struct archive_write *a)
-{
-	return (__archive_write_nulls(a, 512*2));
-}
-
-static int
-archive_write_ustar_free(struct archive_write *a)
-{
-	struct ustar *ustar;
-
-	ustar = (struct ustar *)a->format_data;
-	free(ustar);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_ustar_finish_entry(struct archive_write *a)
-{
-	struct ustar *ustar;
-	int ret;
-
-	ustar = (struct ustar *)a->format_data;
-	ret = __archive_write_nulls(a,
-	    (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding));
-	ustar->entry_bytes_remaining = ustar->entry_padding = 0;
-	return (ret);
-}
-
-static ssize_t
-archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct ustar *ustar;
-	int ret;
-
-	ustar = (struct ustar *)a->format_data;
-	if (s > ustar->entry_bytes_remaining)
-		s = (size_t)ustar->entry_bytes_remaining;
-	ret = __archive_write_output(a, buff, s);
-	ustar->entry_bytes_remaining -= s;
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	return (s);
-}
diff --git a/c/archive_write_set_format_v7tar.c b/c/archive_write_set_format_v7tar.c
deleted file mode 100644
--- a/c/archive_write_set_format_v7tar.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct v7tar {
-	uint64_t	entry_bytes_remaining;
-	uint64_t	entry_padding;
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	int	init_default_conversion;
-};
-
-/*
- * Define structure of POSIX 'v7tar' tar header.
- */
-#define	V7TAR_name_offset 0
-#define	V7TAR_name_size 100
-#define	V7TAR_mode_offset 100
-#define	V7TAR_mode_size 6
-#define	V7TAR_mode_max_size 8
-#define	V7TAR_uid_offset 108
-#define	V7TAR_uid_size 6
-#define	V7TAR_uid_max_size 8
-#define	V7TAR_gid_offset 116
-#define	V7TAR_gid_size 6
-#define	V7TAR_gid_max_size 8
-#define	V7TAR_size_offset 124
-#define	V7TAR_size_size 11
-#define	V7TAR_size_max_size 12
-#define	V7TAR_mtime_offset 136
-#define	V7TAR_mtime_size 11
-#define	V7TAR_mtime_max_size 12
-#define	V7TAR_checksum_offset 148
-#define	V7TAR_checksum_size 8
-#define	V7TAR_typeflag_offset 156
-#define	V7TAR_typeflag_size 1
-#define	V7TAR_linkname_offset 157
-#define	V7TAR_linkname_size 100
-#define	V7TAR_padding_offset 257
-#define	V7TAR_padding_size 255
-
-/*
- * A filled-in copy of the header for initialization.
- */
-static const char template_header[] = {
-	/* name: 100 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,
-	/* Mode, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* uid, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* gid, space-null termination: 8 bytes */
-	'0','0','0','0','0','0', ' ','\0',
-	/* size, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* mtime, space termination: 12 bytes */
-	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* Initial checksum value: 8 spaces */
-	' ',' ',' ',' ',' ',' ',' ',' ',
-	/* Typeflag: 1 byte */
-	0,
-	/* Linkname: 100 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,
-	/* Padding: 255 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
-};
-
-static ssize_t	archive_write_v7tar_data(struct archive_write *a, const void *buff,
-		    size_t s);
-static int	archive_write_v7tar_free(struct archive_write *);
-static int	archive_write_v7tar_close(struct archive_write *);
-static int	archive_write_v7tar_finish_entry(struct archive_write *);
-static int	archive_write_v7tar_header(struct archive_write *,
-		    struct archive_entry *entry);
-static int	archive_write_v7tar_options(struct archive_write *,
-		    const char *, const char *);
-static int	format_256(int64_t, char *, int);
-static int	format_number(int64_t, char *, int size, int max, int strict);
-static int	format_octal(int64_t, char *, int);
-static int	format_header_v7tar(struct archive_write *, char h[512],
-		    struct archive_entry *, int, struct archive_string_conv *);
-
-/*
- * Set output format to 'v7tar' format.
- */
-int
-archive_write_set_format_v7tar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct v7tar *v7tar;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_v7tar");
-
-	/* If someone else was already registered, unregister them. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	/* Basic internal sanity test. */
-	if (sizeof(template_header) != 512) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Internal: template_header wrong size: %zu should be 512",
-		    sizeof(template_header));
-		return (ARCHIVE_FATAL);
-	}
-
-	v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar));
-	if (v7tar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate v7tar data");
-		return (ARCHIVE_FATAL);
-	}
-	a->format_data = v7tar;
-	a->format_name = "tar (non-POSIX)";
-	a->format_options = archive_write_v7tar_options;
-	a->format_write_header = archive_write_v7tar_header;
-	a->format_write_data = archive_write_v7tar_data;
-	a->format_close = archive_write_v7tar_close;
-	a->format_free = archive_write_v7tar_free;
-	a->format_finish_entry = archive_write_v7tar_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_TAR;
-	a->archive.archive_format_name = "tar (non-POSIX)";
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_v7tar_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct v7tar *v7tar = (struct v7tar *)a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "hdrcharset")  == 0) {
-		if (val == NULL || val[0] == 0)
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		else {
-			v7tar->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (v7tar->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
-{
-	char buff[512];
-	int ret, ret2;
-	struct v7tar *v7tar;
-	struct archive_entry *entry_main;
-	struct archive_string_conv *sconv;
-
-	v7tar = (struct v7tar *)a->format_data;
-
-	/* Setup default string conversion. */
-	if (v7tar->opt_sconv == NULL) {
-		if (!v7tar->init_default_conversion) {
-			v7tar->sconv_default =
-			    archive_string_default_conversion_for_write(
-				&(a->archive));
-			v7tar->init_default_conversion = 1;
-		}
-		sconv = v7tar->sconv_default;
-	} else
-		sconv = v7tar->opt_sconv;
-
-	/* Sanity check. */
-	if (archive_entry_pathname(entry) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Can't record entry in tar file without pathname");
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Only regular files (not hardlinks) have data. */
-	if (archive_entry_hardlink(entry) != NULL ||
-	    archive_entry_symlink(entry) != NULL ||
-	    !(archive_entry_filetype(entry) == AE_IFREG))
-		archive_entry_set_size(entry, 0);
-
-	if (AE_IFDIR == archive_entry_filetype(entry)) {
-		const char *p;
-		size_t path_length;
-		/*
-		 * Ensure a trailing '/'.  Modify the entry so
-		 * the client sees the change.
-		 */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-		const wchar_t *wp;
-
-		wp = archive_entry_pathname_w(entry);
-		if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
-			struct archive_wstring ws;
-
-			archive_string_init(&ws);
-			path_length = wcslen(wp);
-			if (archive_wstring_ensure(&ws,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate v7tar data");
-				archive_wstring_free(&ws);
-				return(ARCHIVE_FATAL);
-			}
-			/* Should we keep '\' ? */
-			if (wp[path_length -1] == L'\\')
-				path_length--;
-			archive_wstrncpy(&ws, wp, path_length);
-			archive_wstrappend_wchar(&ws, L'/');
-			archive_entry_copy_pathname_w(entry, ws.s);
-			archive_wstring_free(&ws);
-			p = NULL;
-		} else
-#endif
-			p = archive_entry_pathname(entry);
-		/*
-		 * On Windows, this is a backup operation just in
-		 * case getting WCS failed. On POSIX, this is a
-		 * normal operation.
-		 */
-		if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
-			struct archive_string as;
-
-			archive_string_init(&as);
-			path_length = strlen(p);
-			if (archive_string_ensure(&as,
-			    path_length + 2) == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate v7tar data");
-				archive_string_free(&as);
-				return(ARCHIVE_FATAL);
-			}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-			/* NOTE: This might break the pathname
-			 * if the current code page is CP932 and
-			 * the pathname includes a character '\'
-			 * as a part of its multibyte pathname. */
-			if (p[strlen(p) -1] == '\\')
-				path_length--;
-			else
-#endif
-			archive_strncpy(&as, p, path_length);
-			archive_strappend_char(&as, '/');
-			archive_entry_copy_pathname(entry, as.s);
-			archive_string_free(&as);
-		}
-	}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	entry_main = __la_win_entry_in_posix_pathseparator(entry);
-	if (entry_main == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate v7tar data");
-		return(ARCHIVE_FATAL);
-	}
-	if (entry != entry_main)
-		entry = entry_main;
-	else
-		entry_main = NULL;
-#else
-	entry_main = NULL;
-#endif
-	ret = format_header_v7tar(a, buff, entry, 1, sconv);
-	if (ret < ARCHIVE_WARN) {
-		archive_entry_free(entry_main);
-		return (ret);
-	}
-	ret2 = __archive_write_output(a, buff, 512);
-	if (ret2 < ARCHIVE_WARN) {
-		archive_entry_free(entry_main);
-		return (ret2);
-	}
-	if (ret2 < ret)
-		ret = ret2;
-
-	v7tar->entry_bytes_remaining = archive_entry_size(entry);
-	v7tar->entry_padding = 0x1ff & (-(int64_t)v7tar->entry_bytes_remaining);
-	archive_entry_free(entry_main);
-	return (ret);
-}
-
-/*
- * Format a basic 512-byte "v7tar" header.
- *
- * Returns -1 if format failed (due to field overflow).
- * Note that this always formats as much of the header as possible.
- * If "strict" is set to zero, it will extend numeric fields as
- * necessary (overwriting terminators or using base-256 extensions).
- *
- */
-static int
-format_header_v7tar(struct archive_write *a, char h[512],
-    struct archive_entry *entry, int strict,
-    struct archive_string_conv *sconv)
-{
-	unsigned int checksum;
-	int i, r, ret;
-	size_t copy_length;
-	const char *p, *pp;
-	int mytartype;
-
-	ret = 0;
-	mytartype = -1;
-	/*
-	 * The "template header" already includes the "v7tar"
-	 * signature, various end-of-field markers and other required
-	 * elements.
-	 */
-	memcpy(h, &template_header, 512);
-
-	/*
-	 * Because the block is already null-filled, and strings
-	 * are allowed to exactly fill their destination (without null),
-	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
-	 */
-	r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to %s",
-		    pp, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (strict && copy_length < V7TAR_name_size)
-		memcpy(h + V7TAR_name_offset, pp, copy_length);
-	else if (!strict && copy_length <= V7TAR_name_size)
-		memcpy(h + V7TAR_name_offset, pp, copy_length);
-	else {
-		/* Prefix is too long. */
-		archive_set_error(&a->archive, ENAMETOOLONG,
-		    "Pathname too long");
-		ret = ARCHIVE_FAILED;
-	}
-
-	r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Linkname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate linkname '%s' to %s",
-		    p, archive_string_conversion_charset_name(sconv));
-		ret = ARCHIVE_WARN;
-	}
-	if (copy_length > 0)
-		mytartype = '1';
-	else {
-		r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate linkname '%s' to %s",
-			    p, archive_string_conversion_charset_name(sconv));
-			ret = ARCHIVE_WARN;
-		}
-	}
-	if (copy_length > 0) {
-		if (copy_length >= V7TAR_linkname_size) {
-			archive_set_error(&a->archive, ENAMETOOLONG,
-			    "Link contents too long");
-			ret = ARCHIVE_FAILED;
-			copy_length = V7TAR_linkname_size;
-		}
-		memcpy(h + V7TAR_linkname_offset, p, copy_length);
-	}
-
-	if (format_number(archive_entry_mode(entry) & 07777,
-	    h + V7TAR_mode_offset, V7TAR_mode_size,
-	    V7TAR_mode_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric mode too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_uid(entry),
-	    h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric user ID too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_gid(entry),
-	    h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "Numeric group ID too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_size(entry),
-	    h + V7TAR_size_offset, V7TAR_size_size,
-	    V7TAR_size_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File size out of range");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (format_number(archive_entry_mtime(entry),
-	    h + V7TAR_mtime_offset, V7TAR_mtime_size,
-	    V7TAR_mtime_max_size, strict)) {
-		archive_set_error(&a->archive, ERANGE,
-		    "File modification time too large");
-		ret = ARCHIVE_FAILED;
-	}
-
-	if (mytartype >= 0) {
-		h[V7TAR_typeflag_offset] = mytartype;
-	} else {
-		switch (archive_entry_filetype(entry)) {
-		case AE_IFREG: case AE_IFDIR:
-			break;
-		case AE_IFLNK:
-			h[V7TAR_typeflag_offset] = '2';
-			break;
-		default:
-			/* AE_IFBLK, AE_IFCHR, AE_IFIFO, AE_IFSOCK
-			 * and unknown */
-			__archive_write_entry_filetype_unsupported(
-			    &a->archive, entry, "v7tar");
-			ret = ARCHIVE_FAILED;
-		}
-	}
-
-	checksum = 0;
-	for (i = 0; i < 512; i++)
-		checksum += 255 & (unsigned int)h[i];
-	format_octal(checksum, h + V7TAR_checksum_offset, 6);
-	/* Can't be pre-set in the template. */
-	h[V7TAR_checksum_offset + 6] = '\0';
-	return (ret);
-}
-
-/*
- * Format a number into a field, with some intelligence.
- */
-static int
-format_number(int64_t v, char *p, int s, int maxsize, int strict)
-{
-	int64_t limit;
-
-	limit = ((int64_t)1 << (s*3));
-
-	/* "Strict" only permits octal values with proper termination. */
-	if (strict)
-		return (format_octal(v, p, s));
-
-	/*
-	 * In non-strict mode, we allow the number to overwrite one or
-	 * more bytes of the field termination.  Even old tar
-	 * implementations should be able to handle this with no
-	 * problem.
-	 */
-	if (v >= 0) {
-		while (s <= maxsize) {
-			if (v < limit)
-				return (format_octal(v, p, s));
-			s++;
-			limit <<= 3;
-		}
-	}
-
-	/* Base-256 can handle any number, positive or negative. */
-	return (format_256(v, p, maxsize));
-}
-
-/*
- * Format a number into the specified field using base-256.
- */
-static int
-format_256(int64_t v, char *p, int s)
-{
-	p += s;
-	while (s-- > 0) {
-		*--p = (char)(v & 0xff);
-		v >>= 8;
-	}
-	*p |= 0x80; /* Set the base-256 marker bit. */
-	return (0);
-}
-
-/*
- * Format a number into the specified field.
- */
-static int
-format_octal(int64_t v, char *p, int s)
-{
-	int len;
-
-	len = s;
-
-	/* Octal values can't be negative, so use 0. */
-	if (v < 0) {
-		while (len-- > 0)
-			*p++ = '0';
-		return (-1);
-	}
-
-	p += s;		/* Start at the end and work backwards. */
-	while (s-- > 0) {
-		*--p = (char)('0' + (v & 7));
-		v >>= 3;
-	}
-
-	if (v == 0)
-		return (0);
-
-	/* If it overflowed, fill field with max value. */
-	while (len-- > 0)
-		*p++ = '7';
-
-	return (-1);
-}
-
-static int
-archive_write_v7tar_close(struct archive_write *a)
-{
-	return (__archive_write_nulls(a, 512*2));
-}
-
-static int
-archive_write_v7tar_free(struct archive_write *a)
-{
-	struct v7tar *v7tar;
-
-	v7tar = (struct v7tar *)a->format_data;
-	free(v7tar);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_v7tar_finish_entry(struct archive_write *a)
-{
-	struct v7tar *v7tar;
-	int ret;
-
-	v7tar = (struct v7tar *)a->format_data;
-	ret = __archive_write_nulls(a,
-	    (size_t)(v7tar->entry_bytes_remaining + v7tar->entry_padding));
-	v7tar->entry_bytes_remaining = v7tar->entry_padding = 0;
-	return (ret);
-}
-
-static ssize_t
-archive_write_v7tar_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct v7tar *v7tar;
-	int ret;
-
-	v7tar = (struct v7tar *)a->format_data;
-	if (s > v7tar->entry_bytes_remaining)
-		s = (size_t)v7tar->entry_bytes_remaining;
-	ret = __archive_write_output(a, buff, s);
-	v7tar->entry_bytes_remaining -= s;
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	return (s);
-}
diff --git a/c/archive_write_set_format_warc.c b/c/archive_write_set_format_warc.c
deleted file mode 100644
--- a/c/archive_write_set_format_warc.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*-
- * Copyright (c) 2014 Sebastian Freundt
- * Author: Sebastian Freundt  <devel@fresse.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_random_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-struct warc_s {
-	unsigned int omit_warcinfo:1;
-
-	time_t now;
-	mode_t typ;
-	unsigned int rng;
-	/* populated size */
-	uint64_t populz;
-};
-
-static const char warcinfo[] =
-    "software: libarchive/" ARCHIVE_VERSION_ONLY_STRING "\r\n"
-    "format: WARC file version 1.0\r\n";
-
-typedef enum {
-	WT_NONE,
-	/* warcinfo */
-	WT_INFO,
-	/* metadata */
-	WT_META,
-	/* resource */
-	WT_RSRC,
-	/* request, unsupported */
-	WT_REQ,
-	/* response, unsupported */
-	WT_RSP,
-	/* revisit, unsupported */
-	WT_RVIS,
-	/* conversion, unsupported */
-	WT_CONV,
-	/* continuation, unsupported at the moment */
-	WT_CONT,
-	/* invalid type */
-	LAST_WT
-} warc_type_t;
-
-typedef struct {
-	warc_type_t type;
-	const char *tgturi;
-	const char *recid;
-	time_t rtime;
-	time_t mtime;
-	const char *cnttyp;
-	uint64_t cntlen;
-} warc_essential_hdr_t;
-
-typedef struct {
-	unsigned int u[4U];
-} warc_uuid_t;
-
-static int _warc_options(struct archive_write*, const char *key, const char *v);
-static int _warc_header(struct archive_write *a, struct archive_entry *entry);
-static ssize_t _warc_data(struct archive_write *a, const void *buf, size_t sz);
-static int _warc_finish_entry(struct archive_write *a);
-static int _warc_close(struct archive_write *a);
-static int _warc_free(struct archive_write *a);
-
-/* private routines */
-static ssize_t _popul_ehdr(struct archive_string *t, size_t z, warc_essential_hdr_t);
-static int _gen_uuid(warc_uuid_t *tgt);
-
-
-/*
- * Set output format to ISO 28500 (aka WARC) format.
- */
-int
-archive_write_set_format_warc(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct warc_s *w;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_warc");
-
-	/* If another format was already registered, unregister it. */
-	if (a->format_free != NULL) {
-		(a->format_free)(a);
-	}
-
-	w = malloc(sizeof(*w));
-	if (w == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate warc data");
-		return (ARCHIVE_FATAL);
-	}
-	/* by default we're emitting a file wide header */
-	w->omit_warcinfo = 0U;
-	/* obtain current time for date fields */
-	w->now = time(NULL);
-	/* reset file type info */
-	w->typ = 0;
-	/* also initialise our rng */
-	w->rng = (unsigned int)w->now;
-
-	a->format_data = w;
-	a->format_name = "WARC/1.0";
-	a->format_options = _warc_options;
-	a->format_write_header = _warc_header;
-	a->format_write_data = _warc_data;
-	a->format_close = _warc_close;
-	a->format_free = _warc_free;
-	a->format_finish_entry = _warc_finish_entry;
-	a->archive.archive_format = ARCHIVE_FORMAT_WARC;
-	a->archive.archive_format_name = "WARC/1.0";
-	return (ARCHIVE_OK);
-}
-
-
-/* archive methods */
-static int
-_warc_options(struct archive_write *a, const char *key, const char *val)
-{
-	struct warc_s *w = a->format_data;
-
-	if (strcmp(key, "omit-warcinfo") == 0) {
-		if (val == NULL || strcmp(val, "true") == 0) {
-			/* great */
-			w->omit_warcinfo = 1U;
-			return (ARCHIVE_OK);
-		}
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-_warc_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct warc_s *w = a->format_data;
-	struct archive_string hdr;
-#define MAX_HDR_SIZE 512
-
-	/* check whether warcinfo record needs outputting */
-	if (!w->omit_warcinfo) {
-		ssize_t r;
-		warc_essential_hdr_t wi = {
-			WT_INFO,
-			/*uri*/NULL,
-			/*urn*/NULL,
-			/*rtm*/0,
-			/*mtm*/0,
-			/*cty*/"application/warc-fields",
-			/*len*/sizeof(warcinfo) - 1U,
-		};
-		wi.rtime = w->now;
-		wi.mtime = w->now;
-
-		archive_string_init(&hdr);
-		r = _popul_ehdr(&hdr, MAX_HDR_SIZE, wi);
-		if (r >= 0) {
-			/* jackpot! */
-			/* now also use HDR buffer for the actual warcinfo */
-			archive_strncat(&hdr, warcinfo, sizeof(warcinfo) -1);
-
-			/* append end-of-record indicator */
-			archive_strncat(&hdr, "\r\n\r\n", 4);
-
-			/* write to output stream */
-			__archive_write_output(a, hdr.s, archive_strlen(&hdr));
-		}
-		/* indicate we're done with file header writing */
-		w->omit_warcinfo = 1U;
-		archive_string_free(&hdr);
-	}
-
-	if (archive_entry_pathname(entry) == NULL) {
-		archive_set_error(&a->archive, EINVAL,
-		    "Invalid filename");
-		return (ARCHIVE_WARN);
-	}
-
-	w->typ = archive_entry_filetype(entry);
-	w->populz = 0U;
-	if (w->typ == AE_IFREG) {
-		warc_essential_hdr_t rh = {
-			WT_RSRC,
-			/*uri*/NULL,
-			/*urn*/NULL,
-			/*rtm*/0,
-			/*mtm*/0,
-			/*cty*/NULL,
-			/*len*/0,
-		};
-		ssize_t r;
-		rh.tgturi = archive_entry_pathname(entry);
-		rh.rtime = w->now;
-		rh.mtime = archive_entry_mtime(entry);
-		rh.cntlen = (size_t)archive_entry_size(entry);
-
-		archive_string_init(&hdr);
-		r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh);
-		if (r < 0) {
-			/* don't bother */
-			archive_set_error(
-				&a->archive,
-				ARCHIVE_ERRNO_FILE_FORMAT,
-				"cannot archive file");
-			return (ARCHIVE_WARN);
-		}
-		/* otherwise append to output stream */
-		__archive_write_output(a, hdr.s, r);
-		/* and let subsequent calls to _data() know about the size */
-		w->populz = rh.cntlen;
-		archive_string_free(&hdr);
-		return (ARCHIVE_OK);
-	}
-	/* just resort to erroring as per Tim's advice */
-	__archive_write_entry_filetype_unsupported(
-	    &a->archive, entry, "WARC");
-	return (ARCHIVE_FAILED);
-}
-
-static ssize_t
-_warc_data(struct archive_write *a, const void *buf, size_t len)
-{
-	struct warc_s *w = a->format_data;
-
-	if (w->typ == AE_IFREG) {
-		int rc;
-
-		/* never write more bytes than announced */
-		if (len > w->populz) {
-			len = (size_t)w->populz;
-		}
-
-		/* now then, out we put the whole shebang */
-		rc = __archive_write_output(a, buf, len);
-		if (rc != ARCHIVE_OK) {
-			return rc;
-		}
-	}
-	return len;
-}
-
-static int
-_warc_finish_entry(struct archive_write *a)
-{
-	static const char _eor[] = "\r\n\r\n";
-	struct warc_s *w = a->format_data;
-
-	if (w->typ == AE_IFREG) {
-		int rc = __archive_write_output(a, _eor, sizeof(_eor) - 1U);
-
-		if (rc != ARCHIVE_OK) {
-			return rc;
-		}
-	}
-	/* reset type info */
-	w->typ = 0;
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_close(struct archive_write *a)
-{
-	(void)a; /* UNUSED */
-	return (ARCHIVE_OK);
-}
-
-static int
-_warc_free(struct archive_write *a)
-{
-	struct warc_s *w = a->format_data;
-
-	free(w);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-
-/* private routines */
-static void
-xstrftime(struct archive_string *as, const char *fmt, time_t t)
-{
-/** like strftime(3) but for time_t objects */
-	struct tm *rt;
-#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
-	struct tm timeHere;
-#endif
-	char strtime[100];
-	size_t len;
-
-#if defined(HAVE_GMTIME_S)
-	rt = gmtime_s(&timeHere, &t) ? NULL : &timeHere;
-#elif defined(HAVE_GMTIME_R)
-	rt = gmtime_r(&t, &timeHere);
-#else
-	rt = gmtime(&t);
-#endif
-	if (!rt)
-		return;
-	/* leave the hard yacker to our role model strftime() */
-	len = strftime(strtime, sizeof(strtime)-1, fmt, rt);
-	archive_strncat(as, strtime, len);
-}
-
-static ssize_t
-_popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr)
-{
-	static const char _ver[] = "WARC/1.0\r\n";
-	static const char * const _typ[LAST_WT] = {
-		NULL, "warcinfo", "metadata", "resource", NULL
-	};
-	char std_uuid[48U];
-
-	if (hdr.type == WT_NONE || hdr.type > WT_RSRC) {
-		/* brilliant, how exactly did we get here? */
-		return -1;
-	}
-
-	archive_strcpy(tgt, _ver);
-
-	archive_string_sprintf(tgt, "WARC-Type: %s\r\n", _typ[hdr.type]);
-
-	if (hdr.tgturi != NULL) {
-		/* check if there's a xyz:// */
-		static const char _uri[] = "";
-		static const char _fil[] = "file://";
-		const char *u;
-		char *chk = strchr(hdr.tgturi, ':');
-
-		if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') {
-			/* yep, it's definitely a URI */
-			u = _uri;
-		} else {
-			/* hm, best to prepend file:// then */
-			u = _fil;
-		}
-		archive_string_sprintf(tgt,
-			"WARC-Target-URI: %s%s\r\n", u, hdr.tgturi);
-	}
-
-	/* record time is usually when the http is sent off,
-	 * just treat the archive writing as such for a moment */
-	xstrftime(tgt, "WARC-Date: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.rtime);
-
-	/* while we're at it, record the mtime */
-	xstrftime(tgt, "Last-Modified: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.mtime);
-
-	if (hdr.recid == NULL) {
-		/* generate one, grrrr */
-		warc_uuid_t u;
-
-		_gen_uuid(&u);
-		/* Unfortunately, archive_string_sprintf does not
-		 * handle the minimum number following '%'.
-		 * So we have to use snprintf function here instead
-		 * of archive_string_snprintf function. */
-#if defined(_WIN32) && !defined(__CYGWIN__) && !( defined(_MSC_VER) && _MSC_VER >= 1900)
-#define snprintf _snprintf
-#endif
-		snprintf(
-			std_uuid, sizeof(std_uuid),
-			"<urn:uuid:%08x-%04x-%04x-%04x-%04x%08x>",
-			u.u[0U],
-			u.u[1U] >> 16U, u.u[1U] & 0xffffU,
-			u.u[2U] >> 16U, u.u[2U] & 0xffffU,
-			u.u[3U]);
-		hdr.recid = std_uuid;
-	}
-
-	/* record-id is mandatory, fingers crossed we won't fail */
-	archive_string_sprintf(tgt, "WARC-Record-ID: %s\r\n", hdr.recid);
-
-	if (hdr.cnttyp != NULL) {
-		archive_string_sprintf(tgt, "Content-Type: %s\r\n", hdr.cnttyp);
-	}
-
-	/* next one is mandatory */
-	archive_string_sprintf(tgt, "Content-Length: %ju\r\n", (uintmax_t)hdr.cntlen);
-	/**/
-	archive_strncat(tgt, "\r\n", 2);
-
-	return (archive_strlen(tgt) >= tsz)? -1: (ssize_t)archive_strlen(tgt);
-}
-
-static int
-_gen_uuid(warc_uuid_t *tgt)
-{
-	archive_random(tgt->u, sizeof(tgt->u));
-	/* obey uuid version 4 rules */
-	tgt->u[1U] &= 0xffff0fffU;
-	tgt->u[1U] |= 0x4000U;
-	tgt->u[2U] &= 0x3fffffffU;
-	tgt->u[2U] |= 0x80000000U;
-	return 0;
-}
-
-/* archive_write_set_format_warc.c ends here */
diff --git a/c/archive_write_set_format_xar.c b/c/archive_write_set_format_xar.c
deleted file mode 100644
--- a/c/archive_write_set_format_xar.c
+++ /dev/null
@@ -1,3255 +0,0 @@
-/*-
- * Copyright (c) 2010-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#include <stdlib.h>
-#if HAVE_LIBXML_XMLWRITER_H
-#include <libxml/xmlwriter.h>
-#endif
-#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
-#endif
-#if HAVE_LZMA_H
-#include <lzma.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_digest_private.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_rb.h"
-#include "archive_string.h"
-#include "archive_write_private.h"
-
-/*
- * Differences to xar utility.
- * - Subdocument is not supported yet.
- * - ACL is not supported yet.
- * - When writing an XML element <link type="<file-type>">, <file-type>
- *   which is a file type a symbolic link is referencing is always marked
- *   as "broken". Xar utility uses stat(2) to get the file type, but, in
- *   libarchive format writer, we should not use it; if it is needed, we
- *   should get about it at archive_read_disk.c.
- * - It is possible to appear both <flags> and <ext2> elements.
- *   Xar utility generates <flags> on BSD platform and <ext2> on Linux
- *   platform.
- *
- */
-
-#if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\
-	LIBXML_VERSION >= 20703) ||\
-	!defined(HAVE_ZLIB_H) || \
-	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
-/*
- * xar needs several external libraries.
- *   o libxml2
- *   o openssl or MD5/SHA1 hash function
- *   o zlib
- *   o bzlib2 (option)
- *   o liblzma (option)
- */
-int
-archive_write_set_format_xar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-
-	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-	    "Xar not supported on this platform");
-	return (ARCHIVE_WARN);
-}
-
-#else	/* Support xar format */
-
-/*#define DEBUG_PRINT_TOC		1 */
-
-#define BAD_CAST_CONST (const xmlChar *)
-
-#define HEADER_MAGIC	0x78617221
-#define HEADER_SIZE	28
-#define HEADER_VERSION	1
-
-enum sumalg {
-	CKSUM_NONE = 0,
-	CKSUM_SHA1 = 1,
-	CKSUM_MD5 = 2
-};
-
-#define MD5_SIZE	16
-#define SHA1_SIZE	20
-#define MAX_SUM_SIZE	20
-#define MD5_NAME	"md5"
-#define SHA1_NAME	"sha1"
-
-enum enctype {
-	NONE,
-	GZIP,
-	BZIP2,
-	LZMA,
-	XZ,
-};
-
-struct chksumwork {
-	enum sumalg		 alg;
-#ifdef ARCHIVE_HAS_MD5
-	archive_md5_ctx		 md5ctx;
-#endif
-#ifdef ARCHIVE_HAS_SHA1
-	archive_sha1_ctx	 sha1ctx;
-#endif
-};
-
-enum la_zaction {
-	ARCHIVE_Z_FINISH,
-	ARCHIVE_Z_RUN
-};
-
-/*
- * Universal zstream.
- */
-struct la_zstream {
-	const unsigned char	*next_in;
-	size_t			 avail_in;
-	uint64_t		 total_in;
-
-	unsigned char		*next_out;
-	size_t			 avail_out;
-	uint64_t		 total_out;
-
-	int			 valid;
-	void			*real_stream;
-	int			 (*code) (struct archive *a,
-				    struct la_zstream *lastrm,
-				    enum la_zaction action);
-	int			 (*end)(struct archive *a,
-				    struct la_zstream *lastrm);
-};
-
-struct chksumval {
-	enum sumalg		 alg;
-	size_t			 len;
-	unsigned char		 val[MAX_SUM_SIZE];
-};
-
-struct heap_data {
-	int			 id;
-	struct heap_data	*next;
-	uint64_t		 temp_offset;
-	uint64_t		 length;	/* archived size.	*/
-	uint64_t		 size;		/* extracted size.	*/
-	enum enctype		 compression;
-	struct chksumval	 a_sum;		/* archived checksum.	*/
-	struct chksumval	 e_sum;		/* extracted checksum.	*/
-};
-
-struct file {
-	struct archive_rb_node	 rbnode;
-
-	int			 id;
-	struct archive_entry	*entry;
-
-	struct archive_rb_tree	 rbtree;
-	struct file		*next;
-	struct file		*chnext;
-	struct file		*hlnext;
-	/* For hardlinked files.
-	 * Use only when archive_entry_nlink() > 1 */
-	struct file		*hardlink_target;
-	struct file		*parent;	/* parent directory entry */
-	/*
-	 * To manage sub directory files.
-	 * We use 'chnext' (a member of struct file) to chain.
-	 */
-	struct {
-		struct file	*first;
-		struct file	**last;
-	}			 children;
-
-	/* For making a directory tree. */
-        struct archive_string    parentdir;
-        struct archive_string    basename;
-        struct archive_string    symlink;
-
-	int			 ea_idx;
-	struct {
-		struct heap_data *first;
-		struct heap_data **last;
-	}			 xattr;
-	struct heap_data	 data;
-        struct archive_string    script;
-
-	unsigned int		 virtual:1;
-	unsigned int		 dir:1;
-};
-
-struct hardlink {
-	struct archive_rb_node	 rbnode;
-	int			 nlink;
-	struct {
-		struct file	*first;
-		struct file	**last;
-	}			 file_list;
-};
-
-struct xar {
-	int			 temp_fd;
-	uint64_t		 temp_offset;
-
-	int			 file_idx;
-	struct file		*root;
-	struct file		*cur_dirent;
-	struct archive_string	 cur_dirstr;
-	struct file		*cur_file;
-	uint64_t		 bytes_remaining;
-	struct archive_string	 tstr;
-	struct archive_string	 vstr;
-
-	enum sumalg		 opt_toc_sumalg;
-	enum sumalg		 opt_sumalg;
-	enum enctype		 opt_compression;
-	int			 opt_compression_level;
-	uint32_t		 opt_threads;
-
-	struct chksumwork	 a_sumwrk;	/* archived checksum.	*/
-	struct chksumwork	 e_sumwrk;	/* extracted checksum.	*/
-	struct la_zstream	 stream;
-	struct archive_string_conv *sconv;
-	/*
-	 * Compressed data buffer.
-	 */
-	unsigned char		 wbuff[1024 * 64];
-	size_t			 wbuff_remaining;
-
-	struct heap_data	 toc;
-	/*
-	 * The list of all file entries is used to manage struct file
-	 * objects.
-	 * We use 'next' (a member of struct file) to chain.
-	 */
-	struct {
-		struct file	*first;
-		struct file	**last;
-	}			 file_list;
-	/*
-	 * The list of hard-linked file entries.
-	 * We use 'hlnext' (a member of struct file) to chain.
-	 */
-	struct archive_rb_tree	 hardlink_rbtree;
-};
-
-static int	xar_options(struct archive_write *,
-		    const char *, const char *);
-static int	xar_write_header(struct archive_write *,
-		    struct archive_entry *);
-static ssize_t	xar_write_data(struct archive_write *,
-		    const void *, size_t);
-static int	xar_finish_entry(struct archive_write *);
-static int	xar_close(struct archive_write *);
-static int	xar_free(struct archive_write *);
-
-static struct file *file_new(struct archive_write *a, struct archive_entry *);
-static void	file_free(struct file *);
-static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
-		    const char *);
-static int	file_add_child_tail(struct file *, struct file *);
-static struct file *file_find_child(struct file *, const char *);
-static int	file_gen_utility_names(struct archive_write *,
-		    struct file *);
-static int	get_path_component(char *, int, const char *);
-static int	file_tree(struct archive_write *, struct file **);
-static void	file_register(struct xar *, struct file *);
-static void	file_init_register(struct xar *);
-static void	file_free_register(struct xar *);
-static int	file_register_hardlink(struct archive_write *,
-		    struct file *);
-static void	file_connect_hardlink_files(struct xar *);
-static void	file_init_hardlinks(struct xar *);
-static void	file_free_hardlinks(struct xar *);
-
-static void	checksum_init(struct chksumwork *, enum sumalg);
-static void	checksum_update(struct chksumwork *, const void *, size_t);
-static void	checksum_final(struct chksumwork *, struct chksumval *);
-static int	compression_init_encoder_gzip(struct archive *,
-		    struct la_zstream *, int, int);
-static int	compression_code_gzip(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_gzip(struct archive *, struct la_zstream *);
-static int	compression_init_encoder_bzip2(struct archive *,
-		    struct la_zstream *, int);
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-static int	compression_code_bzip2(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_bzip2(struct archive *, struct la_zstream *);
-#endif
-static int	compression_init_encoder_lzma(struct archive *,
-		    struct la_zstream *, int);
-static int	compression_init_encoder_xz(struct archive *,
-		    struct la_zstream *, int, int);
-#if defined(HAVE_LZMA_H)
-static int	compression_code_lzma(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end_lzma(struct archive *, struct la_zstream *);
-#endif
-static int	xar_compression_init_encoder(struct archive_write *);
-static int	compression_code(struct archive *,
-		    struct la_zstream *, enum la_zaction);
-static int	compression_end(struct archive *,
-		    struct la_zstream *);
-static int	save_xattrs(struct archive_write *, struct file *);
-static int	getalgsize(enum sumalg);
-static const char *getalgname(enum sumalg);
-
-int
-archive_write_set_format_xar(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct xar *xar;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
-
-	/* If another format was already registered, unregister it. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	xar = calloc(1, sizeof(*xar));
-	if (xar == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate xar data");
-		return (ARCHIVE_FATAL);
-	}
-	xar->temp_fd = -1;
-	file_init_register(xar);
-	file_init_hardlinks(xar);
-	archive_string_init(&(xar->tstr));
-	archive_string_init(&(xar->vstr));
-
-	/*
-	 * Create the root directory.
-	 */
-	xar->root = file_create_virtual_dir(a, xar, "");
-	if (xar->root == NULL) {
-		free(xar);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate xar data");
-		return (ARCHIVE_FATAL);
-	}
-	xar->root->parent = xar->root;
-	file_register(xar, xar->root);
-	xar->cur_dirent = xar->root;
-	archive_string_init(&(xar->cur_dirstr));
-	archive_string_ensure(&(xar->cur_dirstr), 1);
-	xar->cur_dirstr.s[0] = 0;
-
-	/*
-	 * Initialize option.
-	 */
-	/* Set default checksum type. */
-	xar->opt_toc_sumalg = CKSUM_SHA1;
-	xar->opt_sumalg = CKSUM_SHA1;
-	/* Set default compression type, level, and number of threads. */
-	xar->opt_compression = GZIP;
-	xar->opt_compression_level = 6;
-	xar->opt_threads = 1;
-
-	a->format_data = xar;
-
-	a->format_name = "xar";
-	a->format_options = xar_options;
-	a->format_write_header = xar_write_header;
-	a->format_write_data = xar_write_data;
-	a->format_finish_entry = xar_finish_entry;
-	a->format_close = xar_close;
-	a->format_free = xar_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_XAR;
-	a->archive.archive_format_name = "xar";
-
-	return (ARCHIVE_OK);
-}
-
-static int
-xar_options(struct archive_write *a, const char *key, const char *value)
-{
-	struct xar *xar;
-
-	xar = (struct xar *)a->format_data;
-
-	if (strcmp(key, "checksum") == 0) {
-		if (value == NULL)
-			xar->opt_sumalg = CKSUM_NONE;
-		else if (strcmp(value, "none") == 0)
-			xar->opt_sumalg = CKSUM_NONE;
-		else if (strcmp(value, "sha1") == 0)
-			xar->opt_sumalg = CKSUM_SHA1;
-		else if (strcmp(value, "md5") == 0)
-			xar->opt_sumalg = CKSUM_MD5;
-		else {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Unknown checksum name: `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "compression") == 0) {
-		const char *name = NULL;
-
-		if (value == NULL)
-			xar->opt_compression = NONE;
-		else if (strcmp(value, "none") == 0)
-			xar->opt_compression = NONE;
-		else if (strcmp(value, "gzip") == 0)
-			xar->opt_compression = GZIP;
-		else if (strcmp(value, "bzip2") == 0)
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-			xar->opt_compression = BZIP2;
-#else
-			name = "bzip2";
-#endif
-		else if (strcmp(value, "lzma") == 0)
-#if HAVE_LZMA_H
-			xar->opt_compression = LZMA;
-#else
-			name = "lzma";
-#endif
-		else if (strcmp(value, "xz") == 0)
-#if HAVE_LZMA_H
-			xar->opt_compression = XZ;
-#else
-			name = "xz";
-#endif
-		else {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Unknown compression name: `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		if (name != NULL) {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "`%s' compression not supported "
-			    "on this platform",
-			    name);
-			return (ARCHIVE_FAILED);
-		}
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL ||
-		    !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0') {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Illegal value `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		xar->opt_compression_level = value[0] - '0';
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "toc-checksum") == 0) {
-		if (value == NULL)
-			xar->opt_toc_sumalg = CKSUM_NONE;
-		else if (strcmp(value, "none") == 0)
-			xar->opt_toc_sumalg = CKSUM_NONE;
-		else if (strcmp(value, "sha1") == 0)
-			xar->opt_toc_sumalg = CKSUM_SHA1;
-		else if (strcmp(value, "md5") == 0)
-			xar->opt_toc_sumalg = CKSUM_MD5;
-		else {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Unknown checksum name: `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		return (ARCHIVE_OK);
-	}
-	if (strcmp(key, "threads") == 0) {
-		char *endptr;
-
-		if (value == NULL)
-			return (ARCHIVE_FAILED);
-		errno = 0;
-		xar->opt_threads = (int)strtoul(value, &endptr, 10);
-		if (errno != 0 || *endptr != '\0') {
-			xar->opt_threads = 1;
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Illegal value `%s'",
-			    value);
-			return (ARCHIVE_FAILED);
-		}
-		if (xar->opt_threads == 0) {
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-			xar->opt_threads = lzma_cputhreads();
-#else
-			xar->opt_threads = 1;
-#endif
-		}
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-static int
-xar_write_header(struct archive_write *a, struct archive_entry *entry)
-{
-	struct xar *xar;
-	struct file *file;
-	struct archive_entry *file_entry;
-	int r, r2;
-
-	xar = (struct xar *)a->format_data;
-	xar->cur_file = NULL;
-	xar->bytes_remaining = 0;
-
-	if (xar->sconv == NULL) {
-		xar->sconv = archive_string_conversion_to_charset(
-		    &a->archive, "UTF-8", 1);
-		if (xar->sconv == NULL)
-			return (ARCHIVE_FATAL);
-	}
-
-	file = file_new(a, entry);
-	if (file == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate data");
-		return (ARCHIVE_FATAL);
-	}
-	r2 = file_gen_utility_names(a, file);
-	if (r2 < ARCHIVE_WARN)
-		return (r2);
-
-	/*
-	 * Ignore a path which looks like the top of directory name
-	 * since we have already made the root directory of an Xar archive.
-	 */
-	if (archive_strlen(&(file->parentdir)) == 0 &&
-	    archive_strlen(&(file->basename)) == 0) {
-		file_free(file);
-		return (r2);
-	}
-
-	/* Add entry into tree */
-	file_entry = file->entry;
-	r = file_tree(a, &file);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/* There is the same file in tree and
-	 * the current file is older than the file in tree.
-	 * So we don't need the current file data anymore. */
-	if (file->entry != file_entry)
-		return (r2);
-	if (file->id == 0)
-		file_register(xar, file);
-
-	/* A virtual file, which is a directory, does not have
-	 * any contents and we won't store it into a archive
-	 * file other than its name. */
-	if (file->virtual)
-		return (r2);
-
-	/*
-	 * Prepare to save the contents of the file.
-	 */
-	if (xar->temp_fd == -1) {
-		int algsize;
-		xar->temp_offset = 0;
-		xar->temp_fd = __archive_mktemp(NULL);
-		if (xar->temp_fd < 0) {
-			archive_set_error(&a->archive, errno,
-			    "Couldn't create temporary file");
-			return (ARCHIVE_FATAL);
-		}
-		algsize = getalgsize(xar->opt_toc_sumalg);
-		if (algsize > 0) {
-			if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
-				archive_set_error(&(a->archive), errno,
-				    "lseek failed");
-				return (ARCHIVE_FATAL);
-			}
-			xar->temp_offset = algsize;
-		}
-	}
-
-	if (archive_entry_hardlink(file->entry) == NULL) {
-		r = save_xattrs(a, file);
-		if (r != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Non regular files contents are unneeded to be saved to
-	 * a temporary file. */
-	if (archive_entry_filetype(file->entry) != AE_IFREG)
-		return (r2);
-
-	/*
-	 * Set the current file to cur_file to read its contents.
-	 */
-	xar->cur_file = file;
-
-	if (archive_entry_nlink(file->entry) > 1) {
-		r = file_register_hardlink(a, file);
-		if (r != ARCHIVE_OK)
-			return (r);
-		if (archive_entry_hardlink(file->entry) != NULL) {
-			archive_entry_unset_size(file->entry);
-			return (r2);
-		}
-	}
-
-	/* Save a offset of current file in temporary file. */
-	file->data.temp_offset = xar->temp_offset;
-	file->data.size = archive_entry_size(file->entry);
-	file->data.compression = xar->opt_compression;
-	xar->bytes_remaining = archive_entry_size(file->entry);
-	checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
-	checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
-	r = xar_compression_init_encoder(a);
-
-	if (r != ARCHIVE_OK)
-		return (r);
-	else
-		return (r2);
-}
-
-static int
-write_to_temp(struct archive_write *a, const void *buff, size_t s)
-{
-	struct xar *xar;
-	const unsigned char *p;
-	ssize_t ws;
-
-	xar = (struct xar *)a->format_data;
-	p = (const unsigned char *)buff;
-	while (s) {
-		ws = write(xar->temp_fd, p, s);
-		if (ws < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "fwrite function failed");
-			return (ARCHIVE_FATAL);
-		}
-		s -= ws;
-		p += ws;
-		xar->temp_offset += ws;
-	}
-	return (ARCHIVE_OK);
-}
-
-static ssize_t
-xar_write_data(struct archive_write *a, const void *buff, size_t s)
-{
-	struct xar *xar;
-	enum la_zaction run;
-	size_t size = 0;
-	size_t rsize;
-	int r;
-
-	xar = (struct xar *)a->format_data;
-
-	if (s > xar->bytes_remaining)
-		s = (size_t)xar->bytes_remaining;
-	if (s == 0 || xar->cur_file == NULL)
-		return (0);
-	if (xar->cur_file->data.compression == NONE) {
-		checksum_update(&(xar->e_sumwrk), buff, s);
-		checksum_update(&(xar->a_sumwrk), buff, s);
-		size = rsize = s;
-	} else {
-		xar->stream.next_in = (const unsigned char *)buff;
-		xar->stream.avail_in = s;
-		if (xar->bytes_remaining > s)
-			run = ARCHIVE_Z_RUN;
-		else
-			run = ARCHIVE_Z_FINISH;
-		/* Compress file data. */
-		for (;;) {
-			r = compression_code(&(a->archive), &(xar->stream),
-			    run);
-			if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
-				return (ARCHIVE_FATAL);
-			if (xar->stream.avail_out == 0 ||
-			    run == ARCHIVE_Z_FINISH) {
-				size = sizeof(xar->wbuff) -
-				    xar->stream.avail_out;
-				checksum_update(&(xar->a_sumwrk), xar->wbuff,
-				    size);
-				xar->cur_file->data.length += size;
-				if (write_to_temp(a, xar->wbuff,
-				    size) != ARCHIVE_OK)
-					return (ARCHIVE_FATAL);
-				if (r == ARCHIVE_OK) {
-					/* Output buffer was full */
-					xar->stream.next_out = xar->wbuff;
-					xar->stream.avail_out =
-					    sizeof(xar->wbuff);
-				} else {
-					/* ARCHIVE_EOF - We are done */
-					break;
-				}
-			} else {
-				/* Compressor wants more input */
-				break;
-			}
-		}
-		rsize = s - xar->stream.avail_in;
-		checksum_update(&(xar->e_sumwrk), buff, rsize);
-	}
-#if !defined(_WIN32) || defined(__CYGWIN__)
-	if (xar->bytes_remaining ==
-	    (uint64_t)archive_entry_size(xar->cur_file->entry)) {
-		/*
-		 * Get the path of a shell script if so.
-		 */
-		const unsigned char *b = (const unsigned char *)buff;
-
-		archive_string_empty(&(xar->cur_file->script));
-		if (rsize > 2 && b[0] == '#' && b[1] == '!') {
-			size_t i, end, off;
-
-			off = 2;
-			if (b[off] == ' ')
-				off++;
-#ifdef PATH_MAX
-			if ((rsize - off) > PATH_MAX)
-				end = off + PATH_MAX;
-			else
-#endif
-				end = rsize;
-			/* Find the end of a script path. */
-			for (i = off; i < end && b[i] != '\0' &&
-			    b[i] != '\n' && b[i] != '\r' &&
-			    b[i] != ' ' && b[i] != '\t'; i++)
-				;
-			archive_strncpy(&(xar->cur_file->script), b + off,
-			    i - off);
-		}
-	}
-#endif
-
-	if (xar->cur_file->data.compression == NONE) {
-		if (write_to_temp(a, buff, size) != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		xar->cur_file->data.length += size;
-	}
-	xar->bytes_remaining -= rsize;
-
-	return (rsize);
-}
-
-static int
-xar_finish_entry(struct archive_write *a)
-{
-	struct xar *xar;
-	struct file *file;
-	size_t s;
-	ssize_t w;
-
-	xar = (struct xar *)a->format_data;
-	if (xar->cur_file == NULL)
-		return (ARCHIVE_OK);
-
-	while (xar->bytes_remaining > 0) {
-		s = (size_t)xar->bytes_remaining;
-		if (s > a->null_length)
-			s = a->null_length;
-		w = xar_write_data(a, a->nulls, s);
-		if (w > 0)
-			xar->bytes_remaining -= w;
-		else
-			return (w);
-	}
-	file = xar->cur_file;
-	checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
-	checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
-	xar->cur_file = NULL;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, const char *value,
-	const char *attrkey, const char *attrvalue)
-{
-	int r;
-
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
-		return (ARCHIVE_FATAL);
-	}
-	if (attrkey != NULL && attrvalue != NULL) {
-		r = xmlTextWriterWriteAttribute(writer,
-		    BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-	r = xmlTextWriterEndElement(writer);
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, const char *value)
-{
-	int r;
-
-	if (value == NULL)
-		return (ARCHIVE_OK);
-
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
-		return (ARCHIVE_FATAL);
-	}
-	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-	r = xmlTextWriterEndElement(writer);
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, const char *fmt, ...)
-{
-	struct xar *xar;
-	va_list ap;
-
-	xar = (struct xar *)a->format_data;
-	va_start(ap, fmt);
-	archive_string_empty(&xar->vstr);
-	archive_string_vsprintf(&xar->vstr, fmt, ap);
-	va_end(ap);
-	return (xmlwrite_string(a, writer, key, xar->vstr.s));
-}
-
-static int
-xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, time_t t, int z)
-{
-	char timestr[100];
-	struct tm tm;
-
-#if defined(HAVE_GMTIME_S)
-	gmtime_s(&tm, &t);
-#elif defined(HAVE_GMTIME_R)
-	gmtime_r(&t, &tm);
-#else
-	memcpy(&tm, gmtime(&t), sizeof(tm));
-#endif
-	memset(&timestr, 0, sizeof(timestr));
-	/* Do not use %F and %T for portability. */
-	strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
-	if (z)
-		strcat(timestr, "Z");
-	return (xmlwrite_string(a, writer, key, timestr));
-}
-
-static int
-xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, mode_t mode)
-{
-	char ms[5];
-
-	ms[0] = '0';
-	ms[1] = '0' + ((mode >> 6) & 07);
-	ms[2] = '0' + ((mode >> 3) & 07);
-	ms[3] = '0' + (mode & 07);
-	ms[4] = '\0';
-
-	return (xmlwrite_string(a, writer, key, ms));
-}
-
-static int
-xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
-	const char *key, struct chksumval *sum)
-{
-	const char *algname;
-	int algsize;
-	char buff[MAX_SUM_SIZE*2 + 1];
-	char *p;
-	unsigned char *s;
-	int i, r;
-
-	if (sum->len > 0) {
-		algname = getalgname(sum->alg);
-		algsize = getalgsize(sum->alg);
-		if (algname != NULL) {
-			const char *hex = "0123456789abcdef";
-			p = buff;
-			s = sum->val;
-			for (i = 0; i < algsize; i++) {
-				*p++ = hex[(*s >> 4)];
-				*p++ = hex[(*s & 0x0f)];
-				s++;
-			}
-			*p = '\0';
-			r = xmlwrite_string_attr(a, writer,
-			    key, buff,
-			    "style", algname);
-			if (r < 0)
-				return (ARCHIVE_FATAL);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
-	struct heap_data *heap)
-{
-	const char *encname;
-	int r;
-
-	r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	switch (heap->compression) {
-	case GZIP:
-		encname = "application/x-gzip"; break;
-	case BZIP2:
-		encname = "application/x-bzip2"; break;
-	case LZMA:
-		encname = "application/x-lzma"; break;
-	case XZ:
-		encname = "application/x-xz"; break;
-	default:
-		encname = "application/octet-stream"; break;
-	}
-	r = xmlwrite_string_attr(a, writer, "encoding", NULL,
-	    "style", encname);
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	return (ARCHIVE_OK);
-}
-
-/*
- * xar utility records fflags as following xml elements:
- *   <flags>
- *     <UserNoDump/>
- *     .....
- *   </flags>
- * or
- *   <ext2>
- *     <NoDump/>
- *     .....
- *   </ext2>
- * If xar is running on BSD platform, records <flags>..</flags>;
- * if xar is running on linux platform, records <ext2>..</ext2>;
- * otherwise does not record.
- *
- * Our implements records both <flags> and <ext2> if it's necessary.
- */
-static int
-make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
-    const char *element, const char *fflags_text)
-{
-	static const struct flagentry {
-		const char	*name;
-		const char	*xarname;
-	}
-	flagbsd[] = {
-		{ "sappnd",	"SystemAppend"},
-		{ "sappend",	"SystemAppend"},
-		{ "arch",	"SystemArchived"},
-		{ "archived",	"SystemArchived"},
-		{ "schg",	"SystemImmutable"},
-		{ "schange",	"SystemImmutable"},
-		{ "simmutable",	"SystemImmutable"},
-		{ "nosunlnk",	"SystemNoUnlink"},
-		{ "nosunlink",	"SystemNoUnlink"},
-		{ "snapshot",	"SystemSnapshot"},
-		{ "uappnd",	"UserAppend"},
-		{ "uappend",	"UserAppend"},
-		{ "uchg",	"UserImmutable"},
-		{ "uchange",	"UserImmutable"},
-		{ "uimmutable",	"UserImmutable"},
-		{ "nodump",	"UserNoDump"},
-		{ "noopaque",	"UserOpaque"},
-		{ "nouunlnk",	"UserNoUnlink"},
-		{ "nouunlink",	"UserNoUnlink"},
-		{ NULL, NULL}
-	},
-	flagext2[] = {
-		{ "sappnd",	"AppendOnly"},
-		{ "sappend",	"AppendOnly"},
-		{ "schg",	"Immutable"},
-		{ "schange",	"Immutable"},
-		{ "simmutable",	"Immutable"},
-		{ "nodump",	"NoDump"},
-		{ "nouunlnk",	"Undelete"},
-		{ "nouunlink",	"Undelete"},
-		{ "btree",	"BTree"},
-		{ "comperr",	"CompError"},
-		{ "compress",	"Compress"},
-		{ "noatime",	"NoAtime"},
-		{ "compdirty",	"CompDirty"},
-		{ "comprblk",	"CompBlock"},
-		{ "dirsync",	"DirSync"},
-		{ "hashidx",	"HashIndexed"},
-		{ "imagic",	"iMagic"},
-		{ "journal",	"Journaled"},
-		{ "securedeletion",	"SecureDeletion"},
-		{ "sync",	"Synchronous"},
-		{ "notail",	"NoTail"},
-		{ "topdir",	"TopDir"},
-		{ "reserved",	"Reserved"},
-		{ NULL, NULL}
-	};
-	const struct flagentry *fe, *flagentry;
-#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
-	const struct flagentry *avail[FLAGENTRY_MAXSIZE];
-	const char *p;
-	int i, n, r;
-
-	if (strcmp(element, "ext2") == 0)
-		flagentry = flagext2;
-	else
-		flagentry = flagbsd;
-	n = 0;
-	p = fflags_text;
-	do {
-		const char *cp;
-
-		cp = strchr(p, ',');
-		if (cp == NULL)
-			cp = p + strlen(p);
-
-		for (fe = flagentry; fe->name != NULL; fe++) {
-			if (fe->name[cp - p] != '\0'
-			    || p[0] != fe->name[0])
-				continue;
-			if (strncmp(p, fe->name, cp - p) == 0) {
-				avail[n++] = fe;
-				break;
-			}
-		}
-		if (*cp == ',')
-			p = cp + 1;
-		else
-			p = NULL;
-	} while (p != NULL);
-
-	if (n > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		for (i = 0; i < n; i++) {
-			r = xmlwrite_string(a, writer,
-			    avail[i]->xarname, NULL);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
-    struct file *file)
-{
-	struct xar *xar;
-	const char *filetype, *filelink, *fflags;
-	struct archive_string linkto;
-	struct heap_data *heap;
-	unsigned char *tmp;
-	const char *p;
-	size_t len;
-	int r, r2, l, ll;
-
-	xar = (struct xar *)a->format_data;
-	r2 = ARCHIVE_OK;
-
-	/*
-	 * Make a file name entry, "<name>".
-	 */
-	l = ll = archive_strlen(&(file->basename));
-	tmp = malloc(l);
-	if (tmp == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
-	free(tmp);
-	if (r < 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlTextWriterWriteAttribute(writer,
-		    BAD_CAST("enctype"), BAD_CAST("base64"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlTextWriterWriteBase64(writer, file->basename.s,
-		    0, archive_strlen(&(file->basename)));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteBase64() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	} else {
-		r = xmlwrite_string(a, writer, "name", file->basename.s);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a file type entry, "<type>".
-	 */
-	filelink = NULL;
-	archive_string_init(&linkto);
-	switch (archive_entry_filetype(file->entry)) {
-	case AE_IFDIR:
-		filetype = "directory"; break;
-	case AE_IFLNK:
-		filetype = "symlink"; break;
-	case AE_IFCHR:
-		filetype = "character special"; break;
-	case AE_IFBLK:
-		filetype = "block special"; break;
-	case AE_IFSOCK:
-		filetype = "socket"; break;
-	case AE_IFIFO:
-		filetype = "fifo"; break;
-	case AE_IFREG:
-	default:
-		if (file->hardlink_target != NULL) {
-			filetype = "hardlink";
-			filelink = "link";
-			if (file->hardlink_target == file)
-				archive_strcpy(&linkto, "original");
-			else
-				archive_string_sprintf(&linkto, "%d",
-				    file->hardlink_target->id);
-		} else
-			filetype = "file";
-		break;
-	}
-	r = xmlwrite_string_attr(a, writer, "type", filetype,
-	    filelink, linkto.s);
-	archive_string_free(&linkto);
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-
-	/*
-	 * On a virtual directory, we record "name" and "type" only.
-	 */
-	if (file->virtual)
-		return (ARCHIVE_OK);
-
-	switch (archive_entry_filetype(file->entry)) {
-	case AE_IFLNK:
-		/*
-		 * xar utility has checked a file type, which
-		 * a symbolic-link file has referenced.
-		 * For example:
-		 *   <link type="directory">../ref/</link>
-		 *   The symlink target file is "../ref/" and its
-		 *   file type is a directory.
-		 *
-		 *   <link type="file">../f</link>
-		 *   The symlink target file is "../f" and its
-		 *   file type is a regular file.
-		 *
-		 * But our implementation cannot do it, and then we
-		 * always record that a attribute "type" is "broken",
-		 * for example:
-		 *   <link type="broken">foo/bar</link>
-		 *   It means "foo/bar" is not reachable.
-		 */
-		r = xmlwrite_string_attr(a, writer, "link",
-		    file->symlink.s,
-		    "type", "broken");
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-		break;
-	case AE_IFCHR:
-	case AE_IFBLK:
-		r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlwrite_fstring(a, writer, "major",
-		    "%d", archive_entry_rdevmajor(file->entry));
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-		r = xmlwrite_fstring(a, writer, "minor",
-		    "%d", archive_entry_rdevminor(file->entry));
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		break;
-	default:
-		break;
-	}
-
-	/*
-	 * Make a inode entry, "<inode>".
-	 */
-	r = xmlwrite_fstring(a, writer, "inode",
-	    "%jd", archive_entry_ino64(file->entry));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	if (archive_entry_dev(file->entry) != 0) {
-		r = xmlwrite_fstring(a, writer, "deviceno",
-		    "%d", archive_entry_dev(file->entry));
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a file mode entry, "<mode>".
-	 */
-	r = xmlwrite_mode(a, writer, "mode",
-	    archive_entry_mode(file->entry));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-
-	/*
-	 * Make a user entry, "<uid>" and "<user>.
-	 */
-	r = xmlwrite_fstring(a, writer, "uid",
-	    "%d", archive_entry_uid(file->entry));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Uname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate uname '%s' to UTF-8",
-		    archive_entry_uname(file->entry));
-		r2 = ARCHIVE_WARN;
-	}
-	if (len > 0) {
-		r = xmlwrite_string(a, writer, "user", p);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a group entry, "<gid>" and "<group>.
-	 */
-	r = xmlwrite_fstring(a, writer, "gid",
-	    "%d", archive_entry_gid(file->entry));
-	if (r < 0)
-		return (ARCHIVE_FATAL);
-	r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
-	if (r != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Gname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate gname '%s' to UTF-8",
-		    archive_entry_gname(file->entry));
-		r2 = ARCHIVE_WARN;
-	}
-	if (len > 0) {
-		r = xmlwrite_string(a, writer, "group", p);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a ctime entry, "<ctime>".
-	 */
-	if (archive_entry_ctime_is_set(file->entry)) {
-		r = xmlwrite_time(a, writer, "ctime",
-		    archive_entry_ctime(file->entry), 1);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a mtime entry, "<mtime>".
-	 */
-	if (archive_entry_mtime_is_set(file->entry)) {
-		r = xmlwrite_time(a, writer, "mtime",
-		    archive_entry_mtime(file->entry), 1);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make a atime entry, "<atime>".
-	 */
-	if (archive_entry_atime_is_set(file->entry)) {
-		r = xmlwrite_time(a, writer, "atime",
-		    archive_entry_atime(file->entry), 1);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-	}
-
-	/*
-	 * Make fflags entries, "<flags>" and "<ext2>".
-	 */
-	fflags = archive_entry_fflags_text(file->entry);
-	if (fflags != NULL) {
-		r = make_fflags_entry(a, writer, "flags", fflags);
-		if (r < 0)
-			return (r);
-		r = make_fflags_entry(a, writer, "ext2", fflags);
-		if (r < 0)
-			return (r);
-	}
-
-	/*
-	 * Make extended attribute entries, "<ea>".
-	 */
-	archive_entry_xattr_reset(file->entry);
-	for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
-		const char *name;
-		const void *value;
-		size_t size;
-
-		archive_entry_xattr_next(file->entry,
-		    &name, &value, &size);
-		r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlTextWriterWriteFormatAttribute(writer,
-		    BAD_CAST("id"), "%d", heap->id);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-		r = xmlwrite_heap(a, writer, heap);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-		r = xmlwrite_string(a, writer, "name", name);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	/*
-	 * Make a file data entry, "<data>".
-	 */
-	if (file->data.length > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-
-		r = xmlwrite_heap(a, writer, &(file->data));
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	if (archive_strlen(&file->script) > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-
-		r = xmlwrite_string(a, writer,
-		    "interpreter", file->script.s);
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-
-		r = xmlwrite_string(a, writer, "type", "script");
-		if (r < 0)
-			return (ARCHIVE_FATAL);
-
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	return (r2);
-}
-
-/*
- * Make the TOC
- */
-static int
-make_toc(struct archive_write *a)
-{
-	struct xar *xar;
-	struct file *np;
-	xmlBufferPtr bp;
-	xmlTextWriterPtr writer;
-	int algsize;
-	int r, ret;
-
-	xar = (struct xar *)a->format_data;
-
-	ret = ARCHIVE_FATAL;
-
-	/*
-	 * Initialize xml writer.
-	 */
-	writer = NULL;
-	bp = xmlBufferCreate();
-	if (bp == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "xmlBufferCreate() "
-		    "couldn't create xml buffer");
-		goto exit_toc;
-	}
-	writer = xmlNewTextWriterMemory(bp, 0);
-	if (writer == NULL) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlNewTextWriterMemory() "
-		    "couldn't create xml writer");
-		goto exit_toc;
-	}
-	r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
-		goto exit_toc;
-	}
-	r = xmlTextWriterSetIndent(writer, 4);
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterSetIndent() failed: %d", r);
-		goto exit_toc;
-	}
-
-	/*
-	 * Start recording TOC
-	 */
-	r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
-		goto exit_toc;
-	}
-	r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
-		goto exit_toc;
-	}
-
-	/*
-	 * Record the creation time of the archive file.
-	 */
-	r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
-	if (r < 0)
-		goto exit_toc;
-
-	/*
-	 * Record the checksum value of TOC
-	 */
-	algsize = getalgsize(xar->opt_toc_sumalg);
-	if (algsize) {
-		/*
-		 * Record TOC checksum
-		 */
-		r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
-			goto exit_toc;
-		}
-		r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
-		    BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
-			goto exit_toc;
-		}
-
-		/*
-		 * Record the offset of the value of checksum of TOC
-		 */
-		r = xmlwrite_string(a, writer, "offset", "0");
-		if (r < 0)
-			goto exit_toc;
-
-		/*
-		 * Record the size of the value of checksum of TOC
-		 */
-		r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
-		if (r < 0)
-			goto exit_toc;
-
-		r = xmlTextWriterEndElement(writer);
-		if (r < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
-			goto exit_toc;
-		}
-	}
-
-	np = xar->root;
-	do {
-		if (np != np->parent) {
-			r = make_file_entry(a, writer, np);
-			if (r != ARCHIVE_OK)
-				goto exit_toc;
-		}
-
-		if (np->dir && np->children.first != NULL) {
-			/* Enter to sub directories. */
-			np = np->children.first;
-			r = xmlTextWriterStartElement(writer,
-			    BAD_CAST("file"));
-			if (r < 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterStartElement() "
-				    "failed: %d", r);
-				goto exit_toc;
-			}
-			r = xmlTextWriterWriteFormatAttribute(
-			    writer, BAD_CAST("id"), "%d", np->id);
-			if (r < 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterWriteAttribute() "
-				    "failed: %d", r);
-				goto exit_toc;
-			}
-			continue;
-		}
-		while (np != np->parent) {
-			r = xmlTextWriterEndElement(writer);
-			if (r < 0) {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterEndElement() "
-				    "failed: %d", r);
-				goto exit_toc;
-			}
-			if (np->chnext == NULL) {
-				/* Return to the parent directory. */
-				np = np->parent;
-			} else {
-				np = np->chnext;
-				r = xmlTextWriterStartElement(writer,
-				    BAD_CAST("file"));
-				if (r < 0) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterStartElement() "
-					    "failed: %d", r);
-					goto exit_toc;
-				}
-				r = xmlTextWriterWriteFormatAttribute(
-				    writer, BAD_CAST("id"), "%d", np->id);
-				if (r < 0) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterWriteAttribute() "
-					    "failed: %d", r);
-					goto exit_toc;
-				}
-				break;
-			}
-		}
-	} while (np != np->parent);
-
-	r = xmlTextWriterEndDocument(writer);
-	if (r < 0) {
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndDocument() failed: %d", r);
-		goto exit_toc;
-	}
-#if DEBUG_PRINT_TOC
-	fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
-	    strlen((const char *)bp->content), bp->content);
-#endif
-
-	/*
-	 * Compress the TOC and calculate the sum of the TOC.
-	 */
-	xar->toc.temp_offset = xar->temp_offset;
-	xar->toc.size = bp->use;
-	checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
-
-	r = compression_init_encoder_gzip(&(a->archive),
-	    &(xar->stream), 6, 1);
-	if (r != ARCHIVE_OK)
-		goto exit_toc;
-	xar->stream.next_in = bp->content;
-	xar->stream.avail_in = bp->use;
-	xar->stream.total_in = 0;
-	xar->stream.next_out = xar->wbuff;
-	xar->stream.avail_out = sizeof(xar->wbuff);
-	xar->stream.total_out = 0;
-	for (;;) {
-		size_t size;
-
-		r = compression_code(&(a->archive),
-		    &(xar->stream), ARCHIVE_Z_FINISH);
-		if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
-			goto exit_toc;
-		size = sizeof(xar->wbuff) - xar->stream.avail_out;
-		checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
-		if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
-			goto exit_toc;
-		if (r == ARCHIVE_EOF)
-			break;
-		xar->stream.next_out = xar->wbuff;
-		xar->stream.avail_out = sizeof(xar->wbuff);
-	}
-	r = compression_end(&(a->archive), &(xar->stream));
-	if (r != ARCHIVE_OK)
-		goto exit_toc;
-	xar->toc.length = xar->stream.total_out;
-	xar->toc.compression = GZIP;
-	checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
-
-	ret = ARCHIVE_OK;
-exit_toc:
-	if (writer)
-		xmlFreeTextWriter(writer);
-	if (bp)
-		xmlBufferFree(bp);
-
-	return (ret);
-}
-
-static int
-flush_wbuff(struct archive_write *a)
-{
-	struct xar *xar;
-	int r;
-	size_t s;
-
-	xar = (struct xar *)a->format_data;
-	s = sizeof(xar->wbuff) - xar->wbuff_remaining;
-	r = __archive_write_output(a, xar->wbuff, s);
-	if (r != ARCHIVE_OK)
-		return (r);
-	xar->wbuff_remaining = sizeof(xar->wbuff);
-	return (r);
-}
-
-static int
-copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
-{
-	struct xar *xar;
-	int r;
-
-	xar = (struct xar *)a->format_data;
-	if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
-		archive_set_error(&(a->archive), errno, "lseek failed");
-		return (ARCHIVE_FATAL);
-	}
-	while (length) {
-		size_t rsize;
-		ssize_t rs;
-		unsigned char *wb;
-
-		if (length > xar->wbuff_remaining)
-			rsize = xar->wbuff_remaining;
-		else
-			rsize = (size_t)length;
-		wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
-		rs = read(xar->temp_fd, wb, rsize);
-		if (rs < 0) {
-			archive_set_error(&(a->archive), errno,
-			    "Can't read temporary file(%jd)",
-			    (intmax_t)rs);
-			return (ARCHIVE_FATAL);
-		}
-		if (rs == 0) {
-			archive_set_error(&(a->archive), 0,
-			    "Truncated xar archive");
-			return (ARCHIVE_FATAL);
-		}
-		xar->wbuff_remaining -= rs;
-		length -= rs;
-		if (xar->wbuff_remaining == 0) {
-			r = flush_wbuff(a);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-xar_close(struct archive_write *a)
-{
-	struct xar *xar;
-	unsigned char *wb;
-	uint64_t length;
-	int r;
-
-	xar = (struct xar *)a->format_data;
-
-	/* Empty! */
-	if (xar->root->children.first == NULL)
-		return (ARCHIVE_OK);
-
-	/* Save the length of all file extended attributes and contents. */
-	length = xar->temp_offset;
-
-	/* Connect hardlinked files */
-	file_connect_hardlink_files(xar);
-
-	/* Make the TOC */
-	r = make_toc(a);
-	if (r != ARCHIVE_OK)
-		return (r);
-	/*
-	 * Make the xar header on wbuff(write buffer).
-	 */
-	wb = xar->wbuff;
-	xar->wbuff_remaining = sizeof(xar->wbuff);
-	archive_be32enc(&wb[0], HEADER_MAGIC);
-	archive_be16enc(&wb[4], HEADER_SIZE);
-	archive_be16enc(&wb[6], HEADER_VERSION);
-	archive_be64enc(&wb[8], xar->toc.length);
-	archive_be64enc(&wb[16], xar->toc.size);
-	archive_be32enc(&wb[24], xar->toc.a_sum.alg);
-	xar->wbuff_remaining -= HEADER_SIZE;
-
-	/*
-	 * Write the TOC
-	 */
-	r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
-	if (r != ARCHIVE_OK)
-		return (r);
-
-	/* Write the checksum value of the TOC. */
-	if (xar->toc.a_sum.len) {
-		if (xar->wbuff_remaining < xar->toc.a_sum.len) {
-			r = flush_wbuff(a);
-			if (r != ARCHIVE_OK)
-				return (r);
-		}
-		wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
-		memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
-		xar->wbuff_remaining -= xar->toc.a_sum.len;
-	}
-
-	/*
-	 * Write all file extended attributes and contents.
-	 */
-	r = copy_out(a, xar->toc.a_sum.len, length);
-	if (r != ARCHIVE_OK)
-		return (r);
-	r = flush_wbuff(a);
-	return (r);
-}
-
-static int
-xar_free(struct archive_write *a)
-{
-	struct xar *xar;
-
-	xar = (struct xar *)a->format_data;
-
-	/* Close the temporary file. */
-	if (xar->temp_fd >= 0)
-		close(xar->temp_fd);
-
-	archive_string_free(&(xar->cur_dirstr));
-	archive_string_free(&(xar->tstr));
-	archive_string_free(&(xar->vstr));
-	file_free_hardlinks(xar);
-	file_free_register(xar);
-	compression_end(&(a->archive), &(xar->stream));
-	free(xar);
-
-	return (ARCHIVE_OK);
-}
-
-static int
-file_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct file *f1 = (const struct file *)n1;
-	const struct file *f2 = (const struct file *)n2;
-
-	return (strcmp(f1->basename.s, f2->basename.s));
-}
-
-static int
-file_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct file *f = (const struct file *)n;
-
-	return (strcmp(f->basename.s, (const char *)key));
-}
-
-static struct file *
-file_new(struct archive_write *a, struct archive_entry *entry)
-{
-	struct file *file;
-	static const struct archive_rb_tree_ops rb_ops = {
-		file_cmp_node, file_cmp_key
-	};
-
-	file = calloc(1, sizeof(*file));
-	if (file == NULL)
-		return (NULL);
-
-	if (entry != NULL)
-		file->entry = archive_entry_clone(entry);
-	else
-		file->entry = archive_entry_new2(&a->archive);
-	if (file->entry == NULL) {
-		free(file);
-		return (NULL);
-	}
-	__archive_rb_tree_init(&(file->rbtree), &rb_ops);
-	file->children.first = NULL;
-	file->children.last = &(file->children.first);
-	file->xattr.first = NULL;
-	file->xattr.last = &(file->xattr.first);
-	archive_string_init(&(file->parentdir));
-	archive_string_init(&(file->basename));
-	archive_string_init(&(file->symlink));
-	archive_string_init(&(file->script));
-	if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
-		file->dir = 1;
-
-	return (file);
-}
-
-static void
-file_free(struct file *file)
-{
-	struct heap_data *heap, *next_heap;
-
-	heap = file->xattr.first;
-	while (heap != NULL) {
-		next_heap = heap->next;
-		free(heap);
-		heap = next_heap;
-	}
-	archive_string_free(&(file->parentdir));
-	archive_string_free(&(file->basename));
-	archive_string_free(&(file->symlink));
-	archive_string_free(&(file->script));
-	archive_entry_free(file->entry);
-	free(file);
-}
-
-static struct file *
-file_create_virtual_dir(struct archive_write *a, struct xar *xar,
-    const char *pathname)
-{
-	struct file *file;
-
-	(void)xar; /* UNUSED */
-
-	file = file_new(a, NULL);
-	if (file == NULL)
-		return (NULL);
-	archive_entry_set_pathname(file->entry, pathname);
-	archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
-
-	file->dir = 1;
-	file->virtual = 1;
-
-	return (file);
-}
-
-static int
-file_add_child_tail(struct file *parent, struct file *child)
-{
-	if (!__archive_rb_tree_insert_node(
-	    &(parent->rbtree), (struct archive_rb_node *)child))
-		return (0);
-	child->chnext = NULL;
-	*parent->children.last = child;
-	parent->children.last = &(child->chnext);
-	child->parent = parent;
-	return (1);
-}
-
-/*
- * Find a entry from `parent'
- */
-static struct file *
-file_find_child(struct file *parent, const char *child_name)
-{
-	struct file *np;
-
-	np = (struct file *)__archive_rb_tree_find_node(
-	    &(parent->rbtree), child_name);
-	return (np);
-}
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-static void
-cleanup_backslash(char *utf8, size_t len)
-{
-
-	/* Convert a path-separator from '\' to  '/' */
-	while (*utf8 != '\0' && len) {
-		if (*utf8 == '\\')
-			*utf8 = '/';
-		++utf8;
-		--len;
-	}
-}
-#else
-#define cleanup_backslash(p, len)	/* nop */
-#endif
-
-/*
- * Generate a parent directory name and a base name from a pathname.
- */
-static int
-file_gen_utility_names(struct archive_write *a, struct file *file)
-{
-	struct xar *xar;
-	const char *pp;
-	char *p, *dirname, *slash;
-	size_t len;
-	int r = ARCHIVE_OK;
-
-	xar = (struct xar *)a->format_data;
-	archive_string_empty(&(file->parentdir));
-	archive_string_empty(&(file->basename));
-	archive_string_empty(&(file->symlink));
-
-	if (file->parent == file)/* virtual root */
-		return (ARCHIVE_OK);
-
-	if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
-	    != 0) {
-		if (errno == ENOMEM) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for Pathname");
-			return (ARCHIVE_FATAL);
-		}
-		archive_set_error(&a->archive,
-		    ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Can't translate pathname '%s' to UTF-8",
-		    archive_entry_pathname(file->entry));
-		r = ARCHIVE_WARN;
-	}
-	archive_strncpy(&(file->parentdir), pp, len);
-	len = file->parentdir.length;
-	p = dirname = file->parentdir.s;
-	/*
-	 * Convert a path-separator from '\' to  '/'
-	 */
-	cleanup_backslash(p, len);
-
-	/*
-	 * Remove leading '/', '../' and './' elements
-	 */
-	while (*p) {
-		if (p[0] == '/') {
-			p++;
-			len--;
-		} else if (p[0] != '.')
-			break;
-		else if (p[1] == '.' && p[2] == '/') {
-			p += 3;
-			len -= 3;
-		} else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
-			p += 2;
-			len -= 2;
-		} else if (p[1] == '\0') {
-			p++;
-			len--;
-		} else
-			break;
-	}
-	if (p != dirname) {
-		memmove(dirname, p, len+1);
-		p = dirname;
-	}
-	/*
-	 * Remove "/","/." and "/.." elements from tail.
-	 */
-	while (len > 0) {
-		size_t ll = len;
-
-		if (p[len-1] == '/') {
-			p[len-1] = '\0';
-			len--;
-		}
-		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
-			p[len-2] = '\0';
-			len -= 2;
-		}
-		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
-		    p[len-1] == '.') {
-			p[len-3] = '\0';
-			len -= 3;
-		}
-		if (ll == len)
-			break;
-	}
-	while (*p) {
-		if (p[0] == '/') {
-			if (p[1] == '/')
-				/* Convert '//' --> '/' */
-				memmove(p, p+1, strlen(p+1) + 1);
-			else if (p[1] == '.' && p[2] == '/')
-				/* Convert '/./' --> '/' */
-				memmove(p, p+2, strlen(p+2) + 1);
-			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
-				/* Convert 'dir/dir1/../dir2/'
-				 *     --> 'dir/dir2/'
-				 */
-				char *rp = p -1;
-				while (rp >= dirname) {
-					if (*rp == '/')
-						break;
-					--rp;
-				}
-				if (rp > dirname) {
-					strcpy(rp, p+3);
-					p = rp;
-				} else {
-					strcpy(dirname, p+4);
-					p = dirname;
-				}
-			} else
-				p++;
-		} else
-			p++;
-	}
-	p = dirname;
-	len = strlen(p);
-
-	if (archive_entry_filetype(file->entry) == AE_IFLNK) {
-		size_t len2;
-		/* Convert symlink name too. */
-		if (archive_entry_symlink_l(file->entry, &pp, &len2,
-		    xar->sconv) != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Linkname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate symlink '%s' to UTF-8",
-			    archive_entry_symlink(file->entry));
-			r = ARCHIVE_WARN;
-		}
-		archive_strncpy(&(file->symlink), pp, len2);
-		cleanup_backslash(file->symlink.s, file->symlink.length);
-	}
-	/*
-	 * - Count up directory elements.
-	 * - Find out the position which points the last position of
-	 *   path separator('/').
-	 */
-	slash = NULL;
-	for (; *p != '\0'; p++)
-		if (*p == '/')
-			slash = p;
-	if (slash == NULL) {
-		/* The pathname doesn't have a parent directory. */
-		file->parentdir.length = len;
-		archive_string_copy(&(file->basename), &(file->parentdir));
-		archive_string_empty(&(file->parentdir));
-		*file->parentdir.s = '\0';
-		return (r);
-	}
-
-	/* Make a basename from dirname and slash */
-	*slash  = '\0';
-	file->parentdir.length = slash - dirname;
-	archive_strcpy(&(file->basename),  slash + 1);
-	return (r);
-}
-
-static int
-get_path_component(char *name, int n, const char *fn)
-{
-	char *p;
-	int l;
-
-	p = strchr(fn, '/');
-	if (p == NULL) {
-		if ((l = strlen(fn)) == 0)
-			return (0);
-	} else
-		l = p - fn;
-	if (l > n -1)
-		return (-1);
-	memcpy(name, fn, l);
-	name[l] = '\0';
-
-	return (l);
-}
-
-/*
- * Add a new entry into the tree.
- */
-static int
-file_tree(struct archive_write *a, struct file **filepp)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	char name[_MAX_FNAME];/* Included null terminator size. */
-#elif defined(NAME_MAX) && NAME_MAX >= 255
-	char name[NAME_MAX+1];
-#else
-	char name[256];
-#endif
-	struct xar *xar = (struct xar *)a->format_data;
-	struct file *dent, *file, *np;
-	struct archive_entry *ent;
-	const char *fn, *p;
-	int l;
-
-	file = *filepp;
-	dent = xar->root;
-	if (file->parentdir.length > 0)
-		fn = p = file->parentdir.s;
-	else
-		fn = p = "";
-
-	/*
-	 * If the path of the parent directory of `file' entry is
-	 * the same as the path of `cur_dirent', add isoent to
-	 * `cur_dirent'.
-	 */
-	if (archive_strlen(&(xar->cur_dirstr))
-	      == archive_strlen(&(file->parentdir)) &&
-	    strcmp(xar->cur_dirstr.s, fn) == 0) {
-		if (!file_add_child_tail(xar->cur_dirent, file)) {
-			np = (struct file *)__archive_rb_tree_find_node(
-			    &(xar->cur_dirent->rbtree),
-			    file->basename.s);
-			goto same_entry;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	for (;;) {
-		l = get_path_component(name, sizeof(name), fn);
-		if (l == 0) {
-			np = NULL;
-			break;
-		}
-		if (l < 0) {
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "A name buffer is too small");
-			file_free(file);
-			*filepp = NULL;
-			return (ARCHIVE_FATAL);
-		}
-
-		np = file_find_child(dent, name);
-		if (np == NULL || fn[0] == '\0')
-			break;
-
-		/* Find next subdirectory. */
-		if (!np->dir) {
-			/* NOT Directory! */
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "`%s' is not directory, we cannot insert `%s' ",
-			    archive_entry_pathname(np->entry),
-			    archive_entry_pathname(file->entry));
-			file_free(file);
-			*filepp = NULL;
-			return (ARCHIVE_FAILED);
-		}
-		fn += l;
-		if (fn[0] == '/')
-			fn++;
-		dent = np;
-	}
-	if (np == NULL) {
-		/*
-		 * Create virtual parent directories.
-		 */
-		while (fn[0] != '\0') {
-			struct file *vp;
-			struct archive_string as;
-
-			archive_string_init(&as);
-			archive_strncat(&as, p, fn - p + l);
-			if (as.s[as.length-1] == '/') {
-				as.s[as.length-1] = '\0';
-				as.length--;
-			}
-			vp = file_create_virtual_dir(a, xar, as.s);
-			if (vp == NULL) {
-				archive_string_free(&as);
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory");
-				file_free(file);
-				*filepp = NULL;
-				return (ARCHIVE_FATAL);
-			}
-			archive_string_free(&as);
-			if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
-				return (ARCHIVE_FATAL);
-			file_add_child_tail(dent, vp);
-			file_register(xar, vp);
-			np = vp;
-
-			fn += l;
-			if (fn[0] == '/')
-				fn++;
-			l = get_path_component(name, sizeof(name), fn);
-			if (l < 0) {
-				archive_string_free(&as);
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "A name buffer is too small");
-				file_free(file);
-				*filepp = NULL;
-				return (ARCHIVE_FATAL);
-			}
-			dent = np;
-		}
-
-		/* Found out the parent directory where isoent can be
-		 * inserted. */
-		xar->cur_dirent = dent;
-		archive_string_empty(&(xar->cur_dirstr));
-		archive_string_ensure(&(xar->cur_dirstr),
-		    archive_strlen(&(dent->parentdir)) +
-		    archive_strlen(&(dent->basename)) + 2);
-		if (archive_strlen(&(dent->parentdir)) +
-		    archive_strlen(&(dent->basename)) == 0)
-			xar->cur_dirstr.s[0] = 0;
-		else {
-			if (archive_strlen(&(dent->parentdir)) > 0) {
-				archive_string_copy(&(xar->cur_dirstr),
-				    &(dent->parentdir));
-				archive_strappend_char(&(xar->cur_dirstr), '/');
-			}
-			archive_string_concat(&(xar->cur_dirstr),
-			    &(dent->basename));
-		}
-
-		if (!file_add_child_tail(dent, file)) {
-			np = (struct file *)__archive_rb_tree_find_node(
-			    &(dent->rbtree), file->basename.s);
-			goto same_entry;
-		}
-		return (ARCHIVE_OK);
-	}
-
-same_entry:
-	/*
-	 * We have already has the entry the filename of which is
-	 * the same.
-	 */
-	if (archive_entry_filetype(np->entry) !=
-	    archive_entry_filetype(file->entry)) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Found duplicate entries `%s' and its file type is "
-		    "different",
-		    archive_entry_pathname(np->entry));
-		file_free(file);
-		*filepp = NULL;
-		return (ARCHIVE_FAILED);
-	}
-
-	/* Swap files. */
-	ent = np->entry;
-	np->entry = file->entry;
-	file->entry = ent;
-	np->virtual = 0;
-
-	file_free(file);
-	*filepp = np;
-	return (ARCHIVE_OK);
-}
-
-static void
-file_register(struct xar *xar, struct file *file)
-{
-	file->id = xar->file_idx++;
-        file->next = NULL;
-        *xar->file_list.last = file;
-        xar->file_list.last = &(file->next);
-}
-
-static void
-file_init_register(struct xar *xar)
-{
-	xar->file_list.first = NULL;
-	xar->file_list.last = &(xar->file_list.first);
-}
-
-static void
-file_free_register(struct xar *xar)
-{
-	struct file *file, *file_next;
-
-	file = xar->file_list.first;
-	while (file != NULL) {
-		file_next = file->next;
-		file_free(file);
-		file = file_next;
-	}
-}
-
-/*
- * Register entry to get a hardlink target.
- */
-static int
-file_register_hardlink(struct archive_write *a, struct file *file)
-{
-	struct xar *xar = (struct xar *)a->format_data;
-	struct hardlink *hl;
-	const char *pathname;
-
-	archive_entry_set_nlink(file->entry, 1);
-	pathname = archive_entry_hardlink(file->entry);
-	if (pathname == NULL) {
-		/* This `file` is a hardlink target. */
-		hl = malloc(sizeof(*hl));
-		if (hl == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory");
-			return (ARCHIVE_FATAL);
-		}
-		hl->nlink = 1;
-		/* A hardlink target must be the first position. */
-		file->hlnext = NULL;
-		hl->file_list.first = file;
-		hl->file_list.last = &(file->hlnext);
-		__archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
-		    (struct archive_rb_node *)hl);
-	} else {
-		hl = (struct hardlink *)__archive_rb_tree_find_node(
-		    &(xar->hardlink_rbtree), pathname);
-		if (hl != NULL) {
-			/* Insert `file` entry into the tail. */
-			file->hlnext = NULL;
-			*hl->file_list.last = file;
-			hl->file_list.last = &(file->hlnext);
-			hl->nlink++;
-		}
-		archive_entry_unset_size(file->entry);
-	}
-
-	return (ARCHIVE_OK);
-}
-
-/*
- * Hardlinked files have to have the same location of extent.
- * We have to find out hardlink target entries for entries which
- * have a hardlink target name.
- */
-static void
-file_connect_hardlink_files(struct xar *xar)
-{
-	struct archive_rb_node *n;
-	struct hardlink *hl;
-	struct file *target, *nf;
-
-	ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
-		hl = (struct hardlink *)n;
-
-		/* The first entry must be a hardlink target. */
-		target = hl->file_list.first;
-		archive_entry_set_nlink(target->entry, hl->nlink);
-		if (hl->nlink > 1)
-			/* It means this file is a hardlink
-			 * target itself. */
-			target->hardlink_target = target;
-		for (nf = target->hlnext;
-		    nf != NULL; nf = nf->hlnext) {
-			nf->hardlink_target = target;
-			archive_entry_set_nlink(nf->entry, hl->nlink);
-		}
-	}
-}
-
-static int
-file_hd_cmp_node(const struct archive_rb_node *n1,
-    const struct archive_rb_node *n2)
-{
-	const struct hardlink *h1 = (const struct hardlink *)n1;
-	const struct hardlink *h2 = (const struct hardlink *)n2;
-
-	return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
-		       archive_entry_pathname(h2->file_list.first->entry)));
-}
-
-static int
-file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
-{
-	const struct hardlink *h = (const struct hardlink *)n;
-
-	return (strcmp(archive_entry_pathname(h->file_list.first->entry),
-		       (const char *)key));
-}
-
-
-static void
-file_init_hardlinks(struct xar *xar)
-{
-	static const struct archive_rb_tree_ops rb_ops = {
-		file_hd_cmp_node, file_hd_cmp_key,
-	};
-
-	__archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
-}
-
-static void
-file_free_hardlinks(struct xar *xar)
-{
-	struct archive_rb_node *n, *tmp;
-
-	ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(xar->hardlink_rbtree), tmp) {
-		__archive_rb_tree_remove_node(&(xar->hardlink_rbtree), n);
-		free(n);
-	}
-}
-
-static void
-checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
-{
-	sumwrk->alg = sum_alg;
-	switch (sum_alg) {
-	case CKSUM_NONE:
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_init(&(sumwrk->sha1ctx));
-		break;
-	case CKSUM_MD5:
-		archive_md5_init(&(sumwrk->md5ctx));
-		break;
-	}
-}
-
-static void
-checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
-{
-
-	switch (sumwrk->alg) {
-	case CKSUM_NONE:
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
-		break;
-	case CKSUM_MD5:
-		archive_md5_update(&(sumwrk->md5ctx), buff, size);
-		break;
-	}
-}
-
-static void
-checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
-{
-
-	switch (sumwrk->alg) {
-	case CKSUM_NONE:
-		sumval->len = 0;
-		break;
-	case CKSUM_SHA1:
-		archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
-		sumval->len = SHA1_SIZE;
-		break;
-	case CKSUM_MD5:
-		archive_md5_final(&(sumwrk->md5ctx), sumval->val);
-		sumval->len = MD5_SIZE;
-		break;
-	}
-	sumval->alg = sumwrk->alg;
-}
-
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
-static int
-compression_unsupported_encoder(struct archive *a,
-    struct la_zstream *lastrm, const char *name)
-{
-
-	archive_set_error(a, ARCHIVE_ERRNO_MISC,
-	    "%s compression not supported on this platform", name);
-	lastrm->valid = 0;
-	lastrm->real_stream = NULL;
-	return (ARCHIVE_FAILED);
-}
-#endif
-
-static int
-compression_init_encoder_gzip(struct archive *a,
-    struct la_zstream *lastrm, int level, int withheader)
-{
-	z_stream *strm;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for gzip stream");
-		return (ARCHIVE_FATAL);
-	}
-	/* zlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in = (uLong)lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out = (uLong)lastrm->total_out;
-	if (deflateInit2(strm, level, Z_DEFLATED,
-	    (withheader)?15:-15,
-	    8, Z_DEFAULT_STRATEGY) != Z_OK) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lastrm->real_stream = strm;
-	lastrm->valid = 1;
-	lastrm->code = compression_code_gzip;
-	lastrm->end = compression_end_gzip;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_gzip(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	z_stream *strm;
-	int r;
-
-	strm = (z_stream *)lastrm->real_stream;
-	/* zlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in = (uLong)lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out = (uLong)lastrm->total_out;
-	r = deflate(strm,
-	    (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
-	lastrm->next_in = strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in = strm->total_in;
-	lastrm->next_out = strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out = strm->total_out;
-	switch (r) {
-	case Z_OK:
-		return (ARCHIVE_OK);
-	case Z_STREAM_END:
-		return (ARCHIVE_EOF);
-	default:
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "GZip compression failed:"
-		    " deflate() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
-{
-	z_stream *strm;
-	int r;
-
-	strm = (z_stream *)lastrm->real_stream;
-	r = deflateEnd(strm);
-	free(strm);
-	lastrm->real_stream = NULL;
-	lastrm->valid = 0;
-	if (r != Z_OK) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
-static int
-compression_init_encoder_bzip2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-	bz_stream *strm;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for bzip2 stream");
-		return (ARCHIVE_FATAL);
-	}
-	/* bzlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
-	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
-	strm->next_out = (char *)lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
-	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
-	if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lastrm->real_stream = strm;
-	lastrm->valid = 1;
-	lastrm->code = compression_code_bzip2;
-	lastrm->end = compression_end_bzip2;
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_code_bzip2(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	bz_stream *strm;
-	int r;
-
-	strm = (bz_stream *)lastrm->real_stream;
-	/* bzlib.h is not const-correct, so we need this one bit
-	 * of ugly hackery to convert a const * pointer to
-	 * a non-const pointer. */
-	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
-	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
-	strm->next_out = (char *)lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
-	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
-	r = BZ2_bzCompress(strm,
-	    (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
-	lastrm->next_in = (const unsigned char *)strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in =
-	    (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
-	    + (uint64_t)(uint32_t)strm->total_in_lo32;
-	lastrm->next_out = (unsigned char *)strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out =
-	    (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
-	    + (uint64_t)(uint32_t)strm->total_out_lo32;
-	switch (r) {
-	case BZ_RUN_OK:     /* Non-finishing */
-	case BZ_FINISH_OK:  /* Finishing: There's more work to do */
-		return (ARCHIVE_OK);
-	case BZ_STREAM_END: /* Finishing: all done */
-		/* Only occurs in finishing case */
-		return (ARCHIVE_EOF);
-	default:
-		/* Any other return value indicates an error */
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Bzip2 compression failed:"
-		    " BZ2_bzCompress() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
-{
-	bz_stream *strm;
-	int r;
-
-	strm = (bz_stream *)lastrm->real_stream;
-	r = BZ2_bzCompressEnd(strm);
-	free(strm);
-	lastrm->real_stream = NULL;
-	lastrm->valid = 0;
-	if (r != BZ_OK) {
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up compressor");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-#else
-static int
-compression_init_encoder_bzip2(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-
-	(void) level; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "bzip2"));
-}
-#endif
-
-#if defined(HAVE_LZMA_H)
-static int
-compression_init_encoder_lzma(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
-	lzma_stream *strm;
-	lzma_options_lzma lzma_opt;
-	int r;
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	if (lzma_lzma_preset(&lzma_opt, level)) {
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	strm = calloc(1, sizeof(*strm));
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for lzma stream");
-		return (ARCHIVE_FATAL);
-	}
-	*strm = lzma_init_data;
-	r = lzma_alone_encoder(strm, &lzma_opt);
-	switch (r) {
-	case LZMA_OK:
-		lastrm->real_stream = strm;
-		lastrm->valid = 1;
-		lastrm->code = compression_code_lzma;
-		lastrm->end = compression_end_lzma;
-		r = ARCHIVE_OK;
-		break;
-	case LZMA_MEM_ERROR:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "Cannot allocate memory");
-		r =  ARCHIVE_FATAL;
-		break;
-        default:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "It's a bug in liblzma");
-		r =  ARCHIVE_FATAL;
-		break;
-	}
-	return (r);
-}
-
-static int
-compression_init_encoder_xz(struct archive *a,
-    struct la_zstream *lastrm, int level, int threads)
-{
-	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
-	lzma_stream *strm;
-	lzma_filter *lzmafilters;
-	lzma_options_lzma lzma_opt;
-	int r;
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-	lzma_mt mt_options;
-#endif
-
-	(void)threads; /* UNUSED (if multi-threaded LZMA library not avail) */
-
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
-	if (strm == NULL) {
-		archive_set_error(a, ENOMEM,
-		    "Can't allocate memory for xz stream");
-		return (ARCHIVE_FATAL);
-	}
-	lzmafilters = (lzma_filter *)(strm+1);
-	if (level > 9)
-		level = 9;
-	if (lzma_lzma_preset(&lzma_opt, level)) {
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library");
-		return (ARCHIVE_FATAL);
-	}
-	lzmafilters[0].id = LZMA_FILTER_LZMA2;
-	lzmafilters[0].options = &lzma_opt;
-	lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
-
-	*strm = lzma_init_data;
-#ifdef HAVE_LZMA_STREAM_ENCODER_MT
-	if (threads > 1) {
-		memset(&mt_options, 0, sizeof(mt_options));
-		mt_options.threads = threads;
-		mt_options.timeout = 300;
-		mt_options.filters = lzmafilters;
-		mt_options.check = LZMA_CHECK_CRC64;
-		r = lzma_stream_encoder_mt(strm, &mt_options);
-	} else
-#endif
-		r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
-	switch (r) {
-	case LZMA_OK:
-		lastrm->real_stream = strm;
-		lastrm->valid = 1;
-		lastrm->code = compression_code_lzma;
-		lastrm->end = compression_end_lzma;
-		r = ARCHIVE_OK;
-		break;
-	case LZMA_MEM_ERROR:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "Cannot allocate memory");
-		r =  ARCHIVE_FATAL;
-		break;
-        default:
-		free(strm);
-		lastrm->real_stream = NULL;
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "It's a bug in liblzma");
-		r =  ARCHIVE_FATAL;
-		break;
-	}
-	return (r);
-}
-
-static int
-compression_code_lzma(struct archive *a,
-    struct la_zstream *lastrm, enum la_zaction action)
-{
-	lzma_stream *strm;
-	int r;
-
-	strm = (lzma_stream *)lastrm->real_stream;
-	strm->next_in = lastrm->next_in;
-	strm->avail_in = lastrm->avail_in;
-	strm->total_in = lastrm->total_in;
-	strm->next_out = lastrm->next_out;
-	strm->avail_out = lastrm->avail_out;
-	strm->total_out = lastrm->total_out;
-	r = lzma_code(strm,
-	    (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
-	lastrm->next_in = strm->next_in;
-	lastrm->avail_in = strm->avail_in;
-	lastrm->total_in = strm->total_in;
-	lastrm->next_out = strm->next_out;
-	lastrm->avail_out = strm->avail_out;
-	lastrm->total_out = strm->total_out;
-	switch (r) {
-	case LZMA_OK:
-		/* Non-finishing case */
-		return (ARCHIVE_OK);
-	case LZMA_STREAM_END:
-		/* This return can only occur in finishing case. */
-		return (ARCHIVE_EOF);
-	case LZMA_MEMLIMIT_ERROR:
-		archive_set_error(a, ENOMEM,
-		    "lzma compression error:"
-		    " %ju MiB would have been needed",
-		    (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
-			/ (1024 * 1024)));
-		return (ARCHIVE_FATAL);
-	default:
-		/* Any other return value indicates an error */
-		archive_set_error(a, ARCHIVE_ERRNO_MISC,
-		    "lzma compression failed:"
-		    " lzma_code() call returned status %d", r);
-		return (ARCHIVE_FATAL);
-	}
-}
-
-static int
-compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
-{
-	lzma_stream *strm;
-
-	(void)a; /* UNUSED */
-	strm = (lzma_stream *)lastrm->real_stream;
-	lzma_end(strm);
-	free(strm);
-	lastrm->valid = 0;
-	lastrm->real_stream = NULL;
-	return (ARCHIVE_OK);
-}
-#else
-static int
-compression_init_encoder_lzma(struct archive *a,
-    struct la_zstream *lastrm, int level)
-{
-
-	(void) level; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "lzma"));
-}
-static int
-compression_init_encoder_xz(struct archive *a,
-    struct la_zstream *lastrm, int level, int threads)
-{
-
-	(void) level; /* UNUSED */
-	(void) threads; /* UNUSED */
-	if (lastrm->valid)
-		compression_end(a, lastrm);
-	return (compression_unsupported_encoder(a, lastrm, "xz"));
-}
-#endif
-
-static int
-xar_compression_init_encoder(struct archive_write *a)
-{
-	struct xar *xar;
-	int r;
-
-	xar = (struct xar *)a->format_data;
-	switch (xar->opt_compression) {
-	case GZIP:
-		r = compression_init_encoder_gzip(
-		    &(a->archive), &(xar->stream),
-		    xar->opt_compression_level, 1);
-		break;
-	case BZIP2:
-		r = compression_init_encoder_bzip2(
-		    &(a->archive), &(xar->stream),
-		    xar->opt_compression_level);
-		break;
-	case LZMA:
-		r = compression_init_encoder_lzma(
-		    &(a->archive), &(xar->stream),
-		    xar->opt_compression_level);
-		break;
-	case XZ:
-		r = compression_init_encoder_xz(
-		    &(a->archive), &(xar->stream),
-		    xar->opt_compression_level, xar->opt_threads);
-		break;
-	default:
-		r = ARCHIVE_OK;
-		break;
-	}
-	if (r == ARCHIVE_OK) {
-		xar->stream.total_in = 0;
-		xar->stream.next_out = xar->wbuff;
-		xar->stream.avail_out = sizeof(xar->wbuff);
-		xar->stream.total_out = 0;
-	}
-
-	return (r);
-}
-
-static int
-compression_code(struct archive *a, struct la_zstream *lastrm,
-    enum la_zaction action)
-{
-	if (lastrm->valid)
-		return (lastrm->code(a, lastrm, action));
-	return (ARCHIVE_OK);
-}
-
-static int
-compression_end(struct archive *a, struct la_zstream *lastrm)
-{
-	if (lastrm->valid)
-		return (lastrm->end(a, lastrm));
-	return (ARCHIVE_OK);
-}
-
-
-static int
-save_xattrs(struct archive_write *a, struct file *file)
-{
-	struct xar *xar;
-	const char *name;
-	const void *value;
-	struct heap_data *heap;
-	size_t size;
-	int count, r;
-
-	xar = (struct xar *)a->format_data;
-	count = archive_entry_xattr_reset(file->entry);
-	if (count == 0)
-		return (ARCHIVE_OK);
-	while (count--) {
-		archive_entry_xattr_next(file->entry,
-		    &name, &value, &size);
-		checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
-		checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
-
-		heap = calloc(1, sizeof(*heap));
-		if (heap == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't allocate memory for xattr");
-			return (ARCHIVE_FATAL);
-		}
-		heap->id = file->ea_idx++;
-		heap->temp_offset = xar->temp_offset;
-		heap->size = size;/* save a extracted size */
-		heap->compression = xar->opt_compression;
-		/* Get a extracted sumcheck value. */
-		checksum_update(&(xar->e_sumwrk), value, size);
-		checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
-
-		/*
-		 * Not compression to xattr is simple way.
-		 */
-		if (heap->compression == NONE) {
-			checksum_update(&(xar->a_sumwrk), value, size);
-			checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
-			if (write_to_temp(a, value, size)
-			    != ARCHIVE_OK) {
-				free(heap);
-				return (ARCHIVE_FATAL);
-			}
-			heap->length = size;
-			/* Add heap to the tail of file->xattr. */
-			heap->next = NULL;
-			*file->xattr.last = heap;
-			file->xattr.last = &(heap->next);
-			/* Next xattr */
-			continue;
-		}
-
-		/*
-		 * Init compression library.
-		 */
-		r = xar_compression_init_encoder(a);
-		if (r != ARCHIVE_OK) {
-			free(heap);
-			return (ARCHIVE_FATAL);
-		}
-
-		xar->stream.next_in = (const unsigned char *)value;
-		xar->stream.avail_in = size;
-		for (;;) {
-			r = compression_code(&(a->archive),
-			    &(xar->stream), ARCHIVE_Z_FINISH);
-			if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
-				free(heap);
-				return (ARCHIVE_FATAL);
-			}
-			size = sizeof(xar->wbuff) - xar->stream.avail_out;
-			checksum_update(&(xar->a_sumwrk),
-			    xar->wbuff, size);
-			if (write_to_temp(a, xar->wbuff, size)
-			    != ARCHIVE_OK) {
-				free(heap);
-				return (ARCHIVE_FATAL);
-			}
-			if (r == ARCHIVE_OK) {
-				xar->stream.next_out = xar->wbuff;
-				xar->stream.avail_out = sizeof(xar->wbuff);
-			} else {
-				checksum_final(&(xar->a_sumwrk),
-				    &(heap->a_sum));
-				heap->length = xar->stream.total_out;
-				/* Add heap to the tail of file->xattr. */
-				heap->next = NULL;
-				*file->xattr.last = heap;
-				file->xattr.last = &(heap->next);
-				break;
-			}
-		}
-		/* Clean up compression library. */
-		r = compression_end(&(a->archive), &(xar->stream));
-		if (r != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-static int
-getalgsize(enum sumalg sumalg)
-{
-	switch (sumalg) {
-	default:
-	case CKSUM_NONE:
-		return (0);
-	case CKSUM_SHA1:
-		return (SHA1_SIZE);
-	case CKSUM_MD5:
-		return (MD5_SIZE);
-	}
-}
-
-static const char *
-getalgname(enum sumalg sumalg)
-{
-	switch (sumalg) {
-	default:
-	case CKSUM_NONE:
-		return (NULL);
-	case CKSUM_SHA1:
-		return (SHA1_NAME);
-	case CKSUM_MD5:
-		return (MD5_NAME);
-	}
-}
-
-#endif /* Support xar format */
diff --git a/c/archive_write_set_format_zip.c b/c/archive_write_set_format_zip.c
deleted file mode 100644
--- a/c/archive_write_set_format_zip.c
+++ /dev/null
@@ -1,1693 +0,0 @@
-/*-
- * Copyright (c) 2008 Anselm Strauss
- * Copyright (c) 2009 Joerg Sonnenberger
- * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Development supported by Google Summer of Code 2008.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 2009-12-29 06:15:32Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-#include "archive.h"
-#include "archive_cryptor_private.h"
-#include "archive_endian.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_hmac_private.h"
-#include "archive_private.h"
-#include "archive_random_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-#ifndef HAVE_ZLIB_H
-#include "archive_crc32.h"
-#endif
-
-#define ZIP_ENTRY_FLAG_ENCRYPTED	(1<<0)
-#define ZIP_ENTRY_FLAG_LENGTH_AT_END	(1<<3)
-#define ZIP_ENTRY_FLAG_UTF8_NAME	(1 << 11)
-
-#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff)
-#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000)
-
-enum compression {
-	COMPRESSION_UNSPECIFIED = -1,
-	COMPRESSION_STORE = 0,
-	COMPRESSION_DEFLATE = 8
-};
-
-#ifdef HAVE_ZLIB_H
-#define COMPRESSION_DEFAULT	COMPRESSION_DEFLATE
-#else
-#define COMPRESSION_DEFAULT	COMPRESSION_STORE
-#endif
-
-enum encryption {
-	ENCRYPTION_NONE	= 0,
-	ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */
-	ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */
-	ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */
-};
-
-#define TRAD_HEADER_SIZE	12
-/*
- * See "WinZip - AES Encryption Information"
- *     http://www.winzip.com/aes_info.htm
- */
-/* Value used in compression method. */
-#define WINZIP_AES_ENCRYPTION	99
-/* A WinZip AES header size which is stored at the beginning of
- * file contents. */
-#define WINZIP_AES128_HEADER_SIZE	(8 + 2)
-#define WINZIP_AES256_HEADER_SIZE	(16 + 2)
-/* AES vendor version. */
-#define AES_VENDOR_AE_1 0x0001
-#define AES_VENDOR_AE_2 0x0002
-/* Authentication code size. */
-#define AUTH_CODE_SIZE		10
-/**/
-#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2)
-
-struct cd_segment {
-	struct cd_segment *next;
-	size_t buff_size;
-	unsigned char *buff;
-	unsigned char *p;
-};
-
-struct trad_enc_ctx {
-	uint32_t keys[3];
-};
-
-struct zip {
-
-	int64_t entry_offset;
-	int64_t entry_compressed_size;
-	int64_t entry_uncompressed_size;
-	int64_t entry_compressed_written;
-	int64_t entry_uncompressed_written;
-	int64_t entry_uncompressed_limit;
-	struct archive_entry *entry;
-	uint32_t entry_crc32;
-	enum compression entry_compression;
-	enum encryption  entry_encryption;
-	int entry_flags;
-	int entry_uses_zip64;
-	int experiments;
-	struct trad_enc_ctx tctx;
-	char tctx_valid;
-	unsigned char trad_chkdat;
-	unsigned aes_vendor;
-	archive_crypto_ctx cctx;
-	char cctx_valid;
-	archive_hmac_sha1_ctx hctx;
-	char hctx_valid;
-
-	unsigned char *file_header;
-	size_t file_header_extra_offset;
-	unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len);
-
-	struct cd_segment *central_directory;
-	struct cd_segment *central_directory_last;
-	size_t central_directory_bytes;
-	size_t central_directory_entries;
-
-	int64_t written_bytes; /* Overall position in file. */
-
-	struct archive_string_conv *opt_sconv;
-	struct archive_string_conv *sconv_default;
-	enum compression requested_compression;
-	int deflate_compression_level;
-	int init_default_conversion;
-	enum encryption  encryption_type;
-
-#define ZIP_FLAG_AVOID_ZIP64 1
-#define ZIP_FLAG_FORCE_ZIP64 2
-#define ZIP_FLAG_EXPERIMENT_xl 4
-	int flags;
-
-#ifdef HAVE_ZLIB_H
-	z_stream stream;
-#endif
-	size_t len_buf;
-	unsigned char *buf;
-};
-
-/* Don't call this min or MIN, since those are already defined
-   on lots of platforms (but not all). */
-#define zipmin(a, b) ((a) > (b) ? (b) : (a))
-
-static ssize_t archive_write_zip_data(struct archive_write *,
-		   const void *buff, size_t s);
-static int archive_write_zip_close(struct archive_write *);
-static int archive_write_zip_free(struct archive_write *);
-static int archive_write_zip_finish_entry(struct archive_write *);
-static int archive_write_zip_header(struct archive_write *,
-	      struct archive_entry *);
-static int archive_write_zip_options(struct archive_write *,
-	      const char *, const char *);
-static unsigned int dos_time(const time_t);
-static size_t path_length(struct archive_entry *);
-static int write_path(struct archive_entry *, struct archive_write *);
-static void copy_path(struct archive_entry *, unsigned char *);
-static struct archive_string_conv *get_sconv(struct archive_write *, struct zip *);
-static int trad_enc_init(struct trad_enc_ctx *, const char *, size_t);
-static unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *,
-    size_t, uint8_t *, size_t);
-static int init_traditional_pkware_encryption(struct archive_write *);
-static int is_traditional_pkware_encryption_supported(void);
-static int init_winzip_aes_encryption(struct archive_write *);
-static int is_winzip_aes_encryption_supported(int encryption);
-
-static unsigned char *
-cd_alloc(struct zip *zip, size_t length)
-{
-	unsigned char *p;
-
-	if (zip->central_directory == NULL
-	    || (zip->central_directory_last->p + length
-		> zip->central_directory_last->buff + zip->central_directory_last->buff_size)) {
-		struct cd_segment *segment = calloc(1, sizeof(*segment));
-		if (segment == NULL)
-			return NULL;
-		segment->buff_size = 64 * 1024;
-		segment->buff = malloc(segment->buff_size);
-		if (segment->buff == NULL) {
-			free(segment);
-			return NULL;
-		}
-		segment->p = segment->buff;
-
-		if (zip->central_directory == NULL) {
-			zip->central_directory
-			    = zip->central_directory_last
-			    = segment;
-		} else {
-			zip->central_directory_last->next = segment;
-			zip->central_directory_last = segment;
-		}
-	}
-
-	p = zip->central_directory_last->p;
-	zip->central_directory_last->p += length;
-	zip->central_directory_bytes += length;
-	return (p);
-}
-
-static unsigned long
-real_crc32(unsigned long crc, const void *buff, size_t len)
-{
-	return crc32(crc, buff, (unsigned int)len);
-}
-
-static unsigned long
-fake_crc32(unsigned long crc, const void *buff, size_t len)
-{
-	(void)crc; /* UNUSED */
-	(void)buff; /* UNUSED */
-	(void)len; /* UNUSED */
-	return 0;
-}
-
-static int
-archive_write_zip_options(struct archive_write *a, const char *key,
-    const char *val)
-{
-	struct zip *zip = a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	if (strcmp(key, "compression") == 0) {
-		/*
-		 * Set compression to use on all future entries.
-		 * This only affects regular files.
-		 */
-		if (val == NULL || val[0] == 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: compression option needs a compression name",
-			    a->format_name);
-		} else if (strcmp(val, "deflate") == 0) {
-#ifdef HAVE_ZLIB_H
-			zip->requested_compression = COMPRESSION_DEFLATE;
-			ret = ARCHIVE_OK;
-#else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "deflate compression not supported");
-#endif
-		} else if (strcmp(val, "store") == 0) {
-			zip->requested_compression = COMPRESSION_STORE;
-			ret = ARCHIVE_OK;
-		}
-		return (ret);
-	} else if (strcmp(key, "compression-level") == 0) {
-		if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') {
-			return ARCHIVE_WARN;
-		}
-
-		if (val[0] == '0') {
-			zip->requested_compression = COMPRESSION_STORE;
-			return ARCHIVE_OK;
-		} else {
-#ifdef HAVE_ZLIB_H
-			zip->requested_compression = COMPRESSION_DEFLATE;
-			zip->deflate_compression_level = val[0] - '0';
-			return ARCHIVE_OK;
-#else
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "deflate compression not supported");
-#endif
-		}
-	} else if (strcmp(key, "encryption") == 0) {
-		if (val == NULL) {
-			zip->encryption_type = ENCRYPTION_NONE;
-			ret = ARCHIVE_OK;
-		} else if (val[0] == '1' || strcmp(val, "traditional") == 0
-		    || strcmp(val, "zipcrypt") == 0
-		    || strcmp(val, "ZipCrypt") == 0) {
-			if (is_traditional_pkware_encryption_supported()) {
-				zip->encryption_type = ENCRYPTION_TRADITIONAL;
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "encryption not supported");
-			}
-		} else if (strcmp(val, "aes128") == 0) {
-			if (is_winzip_aes_encryption_supported(
-			    ENCRYPTION_WINZIP_AES128)) {
-				zip->encryption_type = ENCRYPTION_WINZIP_AES128;
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "encryption not supported");
-			}
-		} else if (strcmp(val, "aes256") == 0) {
-			if (is_winzip_aes_encryption_supported(
-			    ENCRYPTION_WINZIP_AES256)) {
-				zip->encryption_type = ENCRYPTION_WINZIP_AES256;
-				ret = ARCHIVE_OK;
-			} else {
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "encryption not supported");
-			}
-		} else {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: unknown encryption '%s'",
-			    a->format_name, val);
-		}
-		return (ret);
-	} else if (strcmp(key, "experimental") == 0) {
-		if (val == NULL || val[0] == 0) {
-			zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl;
-		} else {
-			zip->flags |= ZIP_FLAG_EXPERIMENT_xl;
-		}
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "fakecrc32") == 0) {
-		/*
-		 * FOR TESTING ONLY:  disable CRC calculation to speed up
-		 * certain complex tests.
-		 */
-		if (val == NULL || val[0] == 0) {
-			zip->crc32func = real_crc32;
-		} else {
-			zip->crc32func = fake_crc32;
-		}
-		return (ARCHIVE_OK);
-	} else if (strcmp(key, "hdrcharset")  == 0) {
-		/*
-		 * Set the character set used in translating filenames.
-		 */
-		if (val == NULL || val[0] == 0) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "%s: hdrcharset option needs a character-set name",
-			    a->format_name);
-		} else {
-			zip->opt_sconv = archive_string_conversion_to_charset(
-			    &a->archive, val, 0);
-			if (zip->opt_sconv != NULL)
-				ret = ARCHIVE_OK;
-			else
-				ret = ARCHIVE_FATAL;
-		}
-		return (ret);
-	} else if (strcmp(key, "zip64") == 0) {
-		/*
-		 * Bias decisions about Zip64: force them to be
-		 * generated in certain cases where they are not
-		 * forbidden or avoid them in certain cases where they
-		 * are not strictly required.
-		 */
-		if (val != NULL && *val != '\0') {
-			zip->flags |= ZIP_FLAG_FORCE_ZIP64;
-			zip->flags &= ~ZIP_FLAG_AVOID_ZIP64;
-		} else {
-			zip->flags &= ~ZIP_FLAG_FORCE_ZIP64;
-			zip->flags |= ZIP_FLAG_AVOID_ZIP64;
-		}
-		return (ARCHIVE_OK);
-	}
-
-	/* Note: The "warn" return is just to inform the options
-	 * supervisor that we didn't handle it.  It will generate
-	 * a suitable error if no one used this option. */
-	return (ARCHIVE_WARN);
-}
-
-int
-archive_write_zip_set_compression_deflate(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	int ret = ARCHIVE_FAILED;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-		ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-		"archive_write_zip_set_compression_deflate");
-	if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		"Can only use archive_write_zip_set_compression_deflate"
-		" with zip format");
-		ret = ARCHIVE_FATAL;
-	} else {
-#ifdef HAVE_ZLIB_H
-		struct zip *zip = a->format_data;
-		zip->requested_compression = COMPRESSION_DEFLATE;
-		ret = ARCHIVE_OK;
-#else
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"deflate compression not supported");
-		ret = ARCHIVE_FAILED;
-#endif
-	}
-	return (ret);
-}
-
-int
-archive_write_zip_set_compression_store(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct zip *zip = a->format_data;
-	int ret = ARCHIVE_FAILED;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-		ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
-		"archive_write_zip_set_compression_deflate");
-	if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			"Can only use archive_write_zip_set_compression_store"
-			" with zip format");
-		ret = ARCHIVE_FATAL;
-	} else {
-		zip->requested_compression = COMPRESSION_STORE;
-		ret = ARCHIVE_OK;
-	}
-	return (ret);
-}
-
-int
-archive_write_set_format_zip(struct archive *_a)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct zip *zip;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
-	    ARCHIVE_STATE_NEW, "archive_write_set_format_zip");
-
-	/* If another format was already registered, unregister it. */
-	if (a->format_free != NULL)
-		(a->format_free)(a);
-
-	zip = (struct zip *) calloc(1, sizeof(*zip));
-	if (zip == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate zip data");
-		return (ARCHIVE_FATAL);
-	}
-
-	/* "Unspecified" lets us choose the appropriate compression. */
-	zip->requested_compression = COMPRESSION_UNSPECIFIED;
-#ifdef HAVE_ZLIB_H
-	zip->deflate_compression_level = Z_DEFAULT_COMPRESSION;
-#endif
-	zip->crc32func = real_crc32;
-
-	/* A buffer used for both compression and encryption. */
-	zip->len_buf = 65536;
-	zip->buf = malloc(zip->len_buf);
-	if (zip->buf == NULL) {
-		free(zip);
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate compression buffer");
-		return (ARCHIVE_FATAL);
-	}
-
-	a->format_data = zip;
-	a->format_name = "zip";
-	a->format_options = archive_write_zip_options;
-	a->format_write_header = archive_write_zip_header;
-	a->format_write_data = archive_write_zip_data;
-	a->format_finish_entry = archive_write_zip_finish_entry;
-	a->format_close = archive_write_zip_close;
-	a->format_free = archive_write_zip_free;
-	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
-	a->archive.archive_format_name = "ZIP";
-
-	return (ARCHIVE_OK);
-}
-
-static int
-is_all_ascii(const char *p)
-{
-	const unsigned char *pp = (const unsigned char *)p;
-
-	while (*pp) {
-		if (*pp++ > 127)
-			return (0);
-	}
-	return (1);
-}
-
-static int
-archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
-{
-	unsigned char local_header[32];
-	unsigned char local_extra[144];
-	struct zip *zip = a->format_data;
-	unsigned char *e;
-	unsigned char *cd_extra;
-	size_t filename_length;
-	const char *slink = NULL;
-	size_t slink_size = 0;
-	struct archive_string_conv *sconv = get_sconv(a, zip);
-	int ret, ret2 = ARCHIVE_OK;
-	mode_t type;
-	int version_needed = 10;
-
-	/* Ignore types of entries that we don't support. */
-	type = archive_entry_filetype(entry);
-	if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) {
-		__archive_write_entry_filetype_unsupported(
-		    &a->archive, entry, "zip");
-		return ARCHIVE_FAILED;
-	};
-
-	/* If we're not using Zip64, reject large files. */
-	if (zip->flags & ZIP_FLAG_AVOID_ZIP64) {
-		/* Reject entries over 4GB. */
-		if (archive_entry_size_is_set(entry)
-		    && (archive_entry_size(entry) > ZIP_4GB_MAX)) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Files > 4GB require Zip64 extensions");
-			return ARCHIVE_FAILED;
-		}
-		/* Reject entries if archive is > 4GB. */
-		if (zip->written_bytes > ZIP_4GB_MAX) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			    "Archives > 4GB require Zip64 extensions");
-			return ARCHIVE_FAILED;
-		}
-	}
-
-	/* Only regular files can have size > 0. */
-	if (type != AE_IFREG)
-		archive_entry_set_size(entry, 0);
-
-
-	/* Reset information from last entry. */
-	zip->entry_offset = zip->written_bytes;
-	zip->entry_uncompressed_limit = INT64_MAX;
-	zip->entry_compressed_size = 0;
-	zip->entry_uncompressed_size = 0;
-	zip->entry_compressed_written = 0;
-	zip->entry_uncompressed_written = 0;
-	zip->entry_flags = 0;
-	zip->entry_uses_zip64 = 0;
-	zip->entry_crc32 = zip->crc32func(0, NULL, 0);
-	zip->entry_encryption = 0;
-	archive_entry_free(zip->entry);
-	zip->entry = NULL;
-
-	if (zip->cctx_valid)
-		archive_encrypto_aes_ctr_release(&zip->cctx);
-	if (zip->hctx_valid)
-		archive_hmac_sha1_cleanup(&zip->hctx);
-	zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0;
-
-	if (type == AE_IFREG
-		    &&(!archive_entry_size_is_set(entry)
-			|| archive_entry_size(entry) > 0)) {
-		switch (zip->encryption_type) {
-		case ENCRYPTION_TRADITIONAL:
-		case ENCRYPTION_WINZIP_AES128:
-		case ENCRYPTION_WINZIP_AES256:
-			zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED;
-			zip->entry_encryption = zip->encryption_type;
-			break;
-		case ENCRYPTION_NONE:
-		default:
-			break;
-		}
-	}
-
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pathname, hardlink and symlink
-	 * are all slash '/', not the Windows path separator '\'. */
-	zip->entry = __la_win_entry_in_posix_pathseparator(entry);
-	if (zip->entry == entry)
-		zip->entry = archive_entry_clone(entry);
-#else
-	zip->entry = archive_entry_clone(entry);
-#endif
-	if (zip->entry == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate zip header data");
-		return (ARCHIVE_FATAL);
-	}
-
-	if (sconv != NULL) {
-		const char *p;
-		size_t len;
-
-		if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for Pathname");
-				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate Pathname '%s' to %s",
-			    archive_entry_pathname(entry),
-			    archive_string_conversion_charset_name(sconv));
-			ret2 = ARCHIVE_WARN;
-		}
-		if (len > 0)
-			archive_entry_set_pathname(zip->entry, p);
-
-		/*
-		 * There is no standard for symlink handling; we convert
-		 * it using the same character-set translation that we use
-		 * for filename.
-		 */
-		if (type == AE_IFLNK) {
-			if (archive_entry_symlink_l(entry, &p, &len, sconv)) {
-				if (errno == ENOMEM) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate memory "
-					    " for Symlink");
-					return (ARCHIVE_FATAL);
-				}
-				/* No error if we can't convert. */
-			} else if (len > 0)
-				archive_entry_set_symlink(zip->entry, p);
-		}
-	}
-
-	/* If filename isn't ASCII and we can use UTF-8, set the UTF-8 flag. */
-	if (!is_all_ascii(archive_entry_pathname(zip->entry))) {
-		if (zip->opt_sconv != NULL) {
-			if (strcmp(archive_string_conversion_charset_name(
-					zip->opt_sconv), "UTF-8") == 0)
-				zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME;
-#if HAVE_NL_LANGINFO
-		} else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
-			zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME;
-#endif
-		}
-	}
-	filename_length = path_length(zip->entry);
-
-	/* Determine appropriate compression and size for this entry. */
-	if (type == AE_IFLNK) {
-		slink = archive_entry_symlink(zip->entry);
-		if (slink != NULL)
-			slink_size = strlen(slink);
-		else
-			slink_size = 0;
-		zip->entry_uncompressed_limit = slink_size;
-		zip->entry_compressed_size = slink_size;
-		zip->entry_uncompressed_size = slink_size;
-		zip->entry_crc32 = zip->crc32func(zip->entry_crc32,
-		    (const unsigned char *)slink, slink_size);
-		zip->entry_compression = COMPRESSION_STORE;
-		version_needed = 20;
-	} else if (type != AE_IFREG) {
-		zip->entry_compression = COMPRESSION_STORE;
-		zip->entry_uncompressed_limit = 0;
-		version_needed = 20;
-	} else if (archive_entry_size_is_set(zip->entry)) {
-		int64_t size = archive_entry_size(zip->entry);
-		int64_t additional_size = 0;
-
-		zip->entry_uncompressed_limit = size;
-		zip->entry_compression = zip->requested_compression;
-		if (zip->entry_compression == COMPRESSION_UNSPECIFIED) {
-			zip->entry_compression = COMPRESSION_DEFAULT;
-		}
-		if (zip->entry_compression == COMPRESSION_STORE) {
-			zip->entry_compressed_size = size;
-			zip->entry_uncompressed_size = size;
-			version_needed = 10;
-		} else {
-			zip->entry_uncompressed_size = size;
-			version_needed = 20;
-		}
-
-		if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
-			switch (zip->entry_encryption) {
-			case ENCRYPTION_TRADITIONAL:
-				additional_size = TRAD_HEADER_SIZE;
-				version_needed = 20;
-				break;
-			case ENCRYPTION_WINZIP_AES128:
-				additional_size = WINZIP_AES128_HEADER_SIZE
-				    + AUTH_CODE_SIZE;
-				version_needed = 20;
-				break;
-			case ENCRYPTION_WINZIP_AES256:
-				additional_size = WINZIP_AES256_HEADER_SIZE
-				    + AUTH_CODE_SIZE;
-				version_needed = 20;
-				break;
-			case ENCRYPTION_NONE:
-			default:
-				break;
-			}
-			if (zip->entry_compression == COMPRESSION_STORE)
-				zip->entry_compressed_size += additional_size;
-		}
-
-		/*
-		 * Set Zip64 extension in any of the following cases
-		 * (this was suggested by discussion on info-zip-dev
-		 * mailing list):
-		 *  = Zip64 is being forced by user
-		 *  = File is over 4GiB uncompressed
-		 *    (including encryption header, if any)
-		 *  = File is close to 4GiB and is being compressed
-		 *    (compression might make file larger)
-		 */
-		if ((zip->flags & ZIP_FLAG_FORCE_ZIP64)
-		    || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX)
-		    || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED
-			&& zip->entry_compression != COMPRESSION_STORE)) {
-			zip->entry_uses_zip64 = 1;
-			version_needed = 45;
-		}
-
-		/* We may know the size, but never the CRC. */
-		zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END;
-	} else {
-		/* We don't know the size. Use the default
-		 * compression unless specified otherwise.
-		 * We enable Zip64 extensions unless we're told not to.
-		 */
-
-		zip->entry_compression = zip->requested_compression;
-		if(zip->entry_compression == COMPRESSION_UNSPECIFIED){
-			zip->entry_compression = COMPRESSION_DEFAULT;
-		}
-
-		zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END;
-		if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) {
-			zip->entry_uses_zip64 = 1;
-			version_needed = 45;
-		} else if (zip->entry_compression == COMPRESSION_STORE) {
-			version_needed = 10;
-		} else {
-			version_needed = 20;
-		}
-
-		if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
-			switch (zip->entry_encryption) {
-			case ENCRYPTION_TRADITIONAL:
-			case ENCRYPTION_WINZIP_AES128:
-			case ENCRYPTION_WINZIP_AES256:
-				if (version_needed < 20)
-					version_needed = 20;
-				break;
-			case ENCRYPTION_NONE:
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Format the local header. */
-	memset(local_header, 0, sizeof(local_header));
-	memcpy(local_header, "PK\003\004", 4);
-	archive_le16enc(local_header + 4, version_needed);
-	archive_le16enc(local_header + 6, zip->entry_flags);
-	if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128
-	    || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)
-		archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION);
-	else
-		archive_le16enc(local_header + 8, zip->entry_compression);
-	archive_le32enc(local_header + 10,
-		dos_time(archive_entry_mtime(zip->entry)));
-	archive_le32enc(local_header + 14, zip->entry_crc32);
-	if (zip->entry_uses_zip64) {
-		/* Zip64 data in the local header "must" include both
-		 * compressed and uncompressed sizes AND those fields
-		 * are included only if these are 0xffffffff;
-		 * THEREFORE these must be set this way, even if we
-		 * know one of them is smaller. */
-		archive_le32enc(local_header + 18, ZIP_4GB_MAX);
-		archive_le32enc(local_header + 22, ZIP_4GB_MAX);
-	} else {
-		archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size);
-		archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size);
-	}
-	archive_le16enc(local_header + 26, (uint16_t)filename_length);
-
-	if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) {
-		if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END)
-			zip->trad_chkdat = local_header[11];
-		else
-			zip->trad_chkdat = local_header[17];
-	}
-
-	/* Format as much of central directory file header as we can: */
-	zip->file_header = cd_alloc(zip, 46);
-	/* If (zip->file_header == NULL) XXXX */
-	++zip->central_directory_entries;
-	memset(zip->file_header, 0, 46);
-	memcpy(zip->file_header, "PK\001\002", 4);
-	/* "Made by PKZip 2.0 on Unix." */
-	archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed);
-	archive_le16enc(zip->file_header + 6, version_needed);
-	archive_le16enc(zip->file_header + 8, zip->entry_flags);
-	if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128
-	    || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)
-		archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION);
-	else
-		archive_le16enc(zip->file_header + 10, zip->entry_compression);
-	archive_le32enc(zip->file_header + 12,
-		dos_time(archive_entry_mtime(zip->entry)));
-	archive_le16enc(zip->file_header + 28, (uint16_t)filename_length);
-	/* Following Info-Zip, store mode in the "external attributes" field. */
-	archive_le32enc(zip->file_header + 38,
-	    ((uint32_t)archive_entry_mode(zip->entry)) << 16);
-	e = cd_alloc(zip, filename_length);
-	/* If (e == NULL) XXXX */
-	copy_path(zip->entry, e);
-
-	/* Format extra data. */
-	memset(local_extra, 0, sizeof(local_extra));
-	e = local_extra;
-
-	/* First, extra blocks that are the same between
-	 * the local file header and the central directory.
-	 * We format them once and then duplicate them. */
-
-	/* UT timestamp, length depends on what timestamps are set. */
-	memcpy(e, "UT", 2);
-	archive_le16enc(e + 2,
-	    1
-	    + (archive_entry_mtime_is_set(entry) ? 4 : 0)
-	    + (archive_entry_atime_is_set(entry) ? 4 : 0)
-	    + (archive_entry_ctime_is_set(entry) ? 4 : 0));
-	e += 4;
-	*e++ =
-	    (archive_entry_mtime_is_set(entry) ? 1 : 0)
-	    | (archive_entry_atime_is_set(entry) ? 2 : 0)
-	    | (archive_entry_ctime_is_set(entry) ? 4 : 0);
-	if (archive_entry_mtime_is_set(entry)) {
-		archive_le32enc(e, (uint32_t)archive_entry_mtime(entry));
-		e += 4;
-	}
-	if (archive_entry_atime_is_set(entry)) {
-		archive_le32enc(e, (uint32_t)archive_entry_atime(entry));
-		e += 4;
-	}
-	if (archive_entry_ctime_is_set(entry)) {
-		archive_le32enc(e, (uint32_t)archive_entry_ctime(entry));
-		e += 4;
-	}
-
-	/* ux Unix extra data, length 11, version 1 */
-	/* TODO: If uid < 64k, use 2 bytes, ditto for gid. */
-	memcpy(e, "ux\013\000\001", 5);
-	e += 5;
-	*e++ = 4; /* Length of following UID */
-	archive_le32enc(e, (uint32_t)archive_entry_uid(entry));
-	e += 4;
-	*e++ = 4; /* Length of following GID */
-	archive_le32enc(e, (uint32_t)archive_entry_gid(entry));
-	e += 4;
-
-	/* AES extra data field: WinZIP AES information, ID=0x9901 */
-	if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED)
-	    && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128
-	        || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) {
-
-		memcpy(e, "\001\231\007\000\001\000AE", 8);
-		/* AES vendor version AE-2 does not store a CRC.
-		 * WinZip 11 uses AE-1, which does store the CRC,
-		 * but it does not store the CRC when the file size
-		 * is less than 20 bytes. So we simulate what
-		 * WinZip 11 does.
-		 * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */
-		if (archive_entry_size_is_set(zip->entry)
-		    && archive_entry_size(zip->entry) < 20) {
-			archive_le16enc(e+4, AES_VENDOR_AE_2);
-			zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */
-		} else
-			zip->aes_vendor = AES_VENDOR_AE_1;
-		e += 8;
-		/* AES encryption strength. */
-		*e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3;
-		/* Actual compression method. */
-		archive_le16enc(e, zip->entry_compression);
-		e += 2;
-	}
-
-	/* Copy UT ,ux, and AES-extra into central directory as well. */
-	zip->file_header_extra_offset = zip->central_directory_bytes;
-	cd_extra = cd_alloc(zip, e - local_extra);
-	memcpy(cd_extra, local_extra, e - local_extra);
-
-	/*
-	 * Following extra blocks vary between local header and
-	 * central directory. These are the local header versions.
-	 * Central directory versions get formatted in
-	 * archive_write_zip_finish_entry() below.
-	 */
-
-	/* "[Zip64 entry] in the local header MUST include BOTH
-	 * original [uncompressed] and compressed size fields." */
-	if (zip->entry_uses_zip64) {
-		unsigned char *zip64_start = e;
-		memcpy(e, "\001\000\020\000", 4);
-		e += 4;
-		archive_le64enc(e, zip->entry_uncompressed_size);
-		e += 8;
-		archive_le64enc(e, zip->entry_compressed_size);
-		e += 8;
-		archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4)));
-	}
-
-	if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) {
-		/* Experimental 'xl' extension to improve streaming. */
-		unsigned char *external_info = e;
-		int included = 7;
-		memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length
-		e += 4;
-		e[0] = included; /* bitmap of included fields */
-		e += 1;
-		if (included & 1) {
-			archive_le16enc(e, /* "Version created by" */
-			    3 * 256 + version_needed);
-			e += 2;
-		}
-		if (included & 2) {
-			archive_le16enc(e, 0); /* internal file attributes */
-			e += 2;
-		}
-		if (included & 4) {
-			archive_le32enc(e,  /* external file attributes */
-			    ((uint32_t)archive_entry_mode(zip->entry)) << 16);
-			e += 4;
-		}
-		if (included & 8) {
-			// Libarchive does not currently support file comments.
-		}
-		archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4)));
-	}
-
-	/* Update local header with size of extra data and write it all out: */
-	archive_le16enc(local_header + 28, (uint16_t)(e - local_extra));
-
-	ret = __archive_write_output(a, local_header, 30);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	zip->written_bytes += 30;
-
-	ret = write_path(zip->entry, a);
-	if (ret <= ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	zip->written_bytes += ret;
-
-	ret = __archive_write_output(a, local_extra, e - local_extra);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	zip->written_bytes += e - local_extra;
-
-	/* For symlinks, write the body now. */
-	if (slink != NULL) {
-		ret = __archive_write_output(a, slink, slink_size);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		zip->entry_compressed_written += slink_size;
-		zip->entry_uncompressed_written += slink_size;
-		zip->written_bytes += slink_size;
-	}
-
-#ifdef HAVE_ZLIB_H
-	if (zip->entry_compression == COMPRESSION_DEFLATE) {
-		zip->stream.zalloc = Z_NULL;
-		zip->stream.zfree = Z_NULL;
-		zip->stream.opaque = Z_NULL;
-		zip->stream.next_out = zip->buf;
-		zip->stream.avail_out = (uInt)zip->len_buf;
-		if (deflateInit2(&zip->stream, zip->deflate_compression_level,
-		    Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
-			archive_set_error(&a->archive, ENOMEM,
-			    "Can't init deflate compressor");
-			return (ARCHIVE_FATAL);
-		}
-	}
-#endif
-
-	return (ret2);
-}
-
-static ssize_t
-archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
-{
-	int ret;
-	struct zip *zip = a->format_data;
-
-	if ((int64_t)s > zip->entry_uncompressed_limit)
-		s = (size_t)zip->entry_uncompressed_limit;
-	zip->entry_uncompressed_written += s;
-
-	if (s == 0) return 0;
-
-	if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
-		switch (zip->entry_encryption) {
-		case ENCRYPTION_TRADITIONAL:
-			/* Initialize traditional PKWARE encryption context. */
-			if (!zip->tctx_valid) {
-				ret = init_traditional_pkware_encryption(a);
-				if (ret != ARCHIVE_OK)
-					return (ret);
-				zip->tctx_valid = 1;
-			}
-			break;
-		case ENCRYPTION_WINZIP_AES128:
-		case ENCRYPTION_WINZIP_AES256:
-			if (!zip->cctx_valid) {
-				ret = init_winzip_aes_encryption(a);
-				if (ret != ARCHIVE_OK)
-					return (ret);
-				zip->cctx_valid = zip->hctx_valid = 1;
-			}
-			break;
-		case ENCRYPTION_NONE:
-		default:
-			break;
-		}
-	}
-
-	switch (zip->entry_compression) {
-	case COMPRESSION_STORE:
-		if (zip->tctx_valid || zip->cctx_valid) {
-			const uint8_t *rb = (const uint8_t *)buff;
-			const uint8_t * const re = rb + s;
-
-			while (rb < re) {
-				size_t l;
-
-				if (zip->tctx_valid) {
-					l = trad_enc_encrypt_update(&zip->tctx,
-					    rb, re - rb,
-					    zip->buf, zip->len_buf);
-				} else {
-					l = zip->len_buf;
-					ret = archive_encrypto_aes_ctr_update(
-					    &zip->cctx,
-					    rb, re - rb, zip->buf, &l);
-					if (ret < 0) {
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_MISC,
-						    "Failed to encrypt file");
-						return (ARCHIVE_FAILED);
-					}
-					archive_hmac_sha1_update(&zip->hctx,
-					    zip->buf, l);
-				}
-				ret = __archive_write_output(a, zip->buf, l);
-				if (ret != ARCHIVE_OK)
-					return (ret);
-				zip->entry_compressed_written += l;
-				zip->written_bytes += l;
-				rb += l;
-			}
-		} else {
-			ret = __archive_write_output(a, buff, s);
-			if (ret != ARCHIVE_OK)
-				return (ret);
-			zip->written_bytes += s;
-			zip->entry_compressed_written += s;
-		}
-		break;
-#if HAVE_ZLIB_H
-	case COMPRESSION_DEFLATE:
-		zip->stream.next_in = (unsigned char*)(uintptr_t)buff;
-		zip->stream.avail_in = (uInt)s;
-		do {
-			ret = deflate(&zip->stream, Z_NO_FLUSH);
-			if (ret == Z_STREAM_ERROR)
-				return (ARCHIVE_FATAL);
-			if (zip->stream.avail_out == 0) {
-				if (zip->tctx_valid) {
-					trad_enc_encrypt_update(&zip->tctx,
-					    zip->buf, zip->len_buf,
-					    zip->buf, zip->len_buf);
-				} else if (zip->cctx_valid) {
-					size_t outl = zip->len_buf;
-					ret = archive_encrypto_aes_ctr_update(
-					    &zip->cctx,
-					    zip->buf, zip->len_buf,
-					    zip->buf, &outl);
-					if (ret < 0) {
-						archive_set_error(&a->archive,
-						    ARCHIVE_ERRNO_MISC,
-						    "Failed to encrypt file");
-						return (ARCHIVE_FAILED);
-					}
-					archive_hmac_sha1_update(&zip->hctx,
-					    zip->buf, zip->len_buf);
-				}
-				ret = __archive_write_output(a, zip->buf,
-					zip->len_buf);
-				if (ret != ARCHIVE_OK)
-					return (ret);
-				zip->entry_compressed_written += zip->len_buf;
-				zip->written_bytes += zip->len_buf;
-				zip->stream.next_out = zip->buf;
-				zip->stream.avail_out = (uInt)zip->len_buf;
-			}
-		} while (zip->stream.avail_in != 0);
-		break;
-#endif
-
-	case COMPRESSION_UNSPECIFIED:
-	default:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid ZIP compression type");
-		return ARCHIVE_FATAL;
-	}
-
-	zip->entry_uncompressed_limit -= s;
-	if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2)
-		zip->entry_crc32 =
-		    zip->crc32func(zip->entry_crc32, buff, (unsigned)s);
-	return (s);
-
-}
-
-static int
-archive_write_zip_finish_entry(struct archive_write *a)
-{
-	struct zip *zip = a->format_data;
-	int ret;
-
-#if HAVE_ZLIB_H
-	if (zip->entry_compression == COMPRESSION_DEFLATE) {
-		for (;;) {
-			size_t remainder;
-
-			ret = deflate(&zip->stream, Z_FINISH);
-			if (ret == Z_STREAM_ERROR)
-				return (ARCHIVE_FATAL);
-			remainder = zip->len_buf - zip->stream.avail_out;
-			if (zip->tctx_valid) {
-				trad_enc_encrypt_update(&zip->tctx,
-				    zip->buf, remainder, zip->buf, remainder);
-			} else if (zip->cctx_valid) {
-				size_t outl = remainder;
-				ret = archive_encrypto_aes_ctr_update(
-				    &zip->cctx, zip->buf, remainder,
-				    zip->buf, &outl);
-				if (ret < 0) {
-					archive_set_error(&a->archive,
-					    ARCHIVE_ERRNO_MISC,
-					    "Failed to encrypt file");
-					return (ARCHIVE_FAILED);
-				}
-				archive_hmac_sha1_update(&zip->hctx,
-				    zip->buf, remainder);
-			}
-			ret = __archive_write_output(a, zip->buf, remainder);
-			if (ret != ARCHIVE_OK)
-				return (ret);
-			zip->entry_compressed_written += remainder;
-			zip->written_bytes += remainder;
-			zip->stream.next_out = zip->buf;
-			if (zip->stream.avail_out != 0)
-				break;
-			zip->stream.avail_out = (uInt)zip->len_buf;
-		}
-		deflateEnd(&zip->stream);
-	}
-#endif
-	if (zip->hctx_valid) {
-		uint8_t hmac[20];
-		size_t hmac_len = 20;
-
-		archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len);
-		ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE);
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		zip->entry_compressed_written += AUTH_CODE_SIZE;
-		zip->written_bytes += AUTH_CODE_SIZE;
-	}
-
-	/* Write trailing data descriptor. */
-	if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) {
-		char d[24];
-		memcpy(d, "PK\007\010", 4);
-		if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2)
-			archive_le32enc(d + 4, 0);/* no CRC.*/
-		else
-			archive_le32enc(d + 4, zip->entry_crc32);
-		if (zip->entry_uses_zip64) {
-			archive_le64enc(d + 8,
-				(uint64_t)zip->entry_compressed_written);
-			archive_le64enc(d + 16,
-				(uint64_t)zip->entry_uncompressed_written);
-			ret = __archive_write_output(a, d, 24);
-			zip->written_bytes += 24;
-		} else {
-			archive_le32enc(d + 8,
-				(uint32_t)zip->entry_compressed_written);
-			archive_le32enc(d + 12,
-				(uint32_t)zip->entry_uncompressed_written);
-			ret = __archive_write_output(a, d, 16);
-			zip->written_bytes += 16;
-		}
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-	}
-
-	/* Append Zip64 extra data to central directory information. */
-	if (zip->entry_compressed_written > ZIP_4GB_MAX
-	    || zip->entry_uncompressed_written > ZIP_4GB_MAX
-	    || zip->entry_offset > ZIP_4GB_MAX) {
-		unsigned char zip64[32];
-		unsigned char *z = zip64, *zd;
-		memcpy(z, "\001\000\000\000", 4);
-		z += 4;
-		if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) {
-			archive_le64enc(z, zip->entry_uncompressed_written);
-			z += 8;
-		}
-		if (zip->entry_compressed_written >= ZIP_4GB_MAX) {
-			archive_le64enc(z, zip->entry_compressed_written);
-			z += 8;
-		}
-		if (zip->entry_offset >= ZIP_4GB_MAX) {
-			archive_le64enc(z, zip->entry_offset);
-			z += 8;
-		}
-		archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4)));
-		zd = cd_alloc(zip, z - zip64);
-		if (zd == NULL) {
-			archive_set_error(&a->archive, ENOMEM,
-				"Can't allocate zip data");
-			return (ARCHIVE_FATAL);
-		}
-		memcpy(zd, zip64, z - zip64);
-		/* Zip64 means version needs to be set to at least 4.5 */
-		if (archive_le16dec(zip->file_header + 6) < 45)
-			archive_le16enc(zip->file_header + 6, 45);
-	}
-
-	/* Fix up central directory file header. */
-	if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2)
-		archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/
-	else
-		archive_le32enc(zip->file_header + 16, zip->entry_crc32);
-	archive_le32enc(zip->file_header + 20,
-		(uint32_t)zipmin(zip->entry_compressed_written,
-				 ZIP_4GB_MAX));
-	archive_le32enc(zip->file_header + 24,
-		(uint32_t)zipmin(zip->entry_uncompressed_written,
-				 ZIP_4GB_MAX));
-	archive_le16enc(zip->file_header + 30,
-	    (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset));
-	archive_le32enc(zip->file_header + 42,
-		(uint32_t)zipmin(zip->entry_offset,
-				 ZIP_4GB_MAX));
-
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_zip_close(struct archive_write *a)
-{
-	uint8_t buff[64];
-	int64_t offset_start, offset_end;
-	struct zip *zip = a->format_data;
-	struct cd_segment *segment;
-	int ret;
-
-	offset_start = zip->written_bytes;
-	segment = zip->central_directory;
-	while (segment != NULL) {
-		ret = __archive_write_output(a,
-		    segment->buff, segment->p - segment->buff);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		zip->written_bytes += segment->p - segment->buff;
-		segment = segment->next;
-	}
-	offset_end = zip->written_bytes;
-
-	/* If central dir info is too large, write Zip64 end-of-cd */
-	if (offset_end - offset_start > ZIP_4GB_MAX
-	    || offset_start > ZIP_4GB_MAX
-	    || zip->central_directory_entries > 0xffffUL
-	    || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) {
-	  /* Zip64 end-of-cd record */
-	  memset(buff, 0, 56);
-	  memcpy(buff, "PK\006\006", 4);
-	  archive_le64enc(buff + 4, 44);
-	  archive_le16enc(buff + 12, 45);
-	  archive_le16enc(buff + 14, 45);
-	  /* This is disk 0 of 0. */
-	  archive_le64enc(buff + 24, zip->central_directory_entries);
-	  archive_le64enc(buff + 32, zip->central_directory_entries);
-	  archive_le64enc(buff + 40, offset_end - offset_start);
-	  archive_le64enc(buff + 48, offset_start);
-	  ret = __archive_write_output(a, buff, 56);
-	  if (ret != ARCHIVE_OK)
-		  return (ARCHIVE_FATAL);
-	  zip->written_bytes += 56;
-
-	  /* Zip64 end-of-cd locator record. */
-	  memset(buff, 0, 20);
-	  memcpy(buff, "PK\006\007", 4);
-	  archive_le32enc(buff + 4, 0);
-	  archive_le64enc(buff + 8, offset_end);
-	  archive_le32enc(buff + 16, 1);
-	  ret = __archive_write_output(a, buff, 20);
-	  if (ret != ARCHIVE_OK)
-		  return (ARCHIVE_FATAL);
-	  zip->written_bytes += 20;
-
-	}
-
-	/* Format and write end of central directory. */
-	memset(buff, 0, sizeof(buff));
-	memcpy(buff, "PK\005\006", 4);
-	archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU,
-		zip->central_directory_entries));
-	archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU,
-		zip->central_directory_entries));
-	archive_le32enc(buff + 12,
-		(uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start)));
-	archive_le32enc(buff + 16,
-		(uint32_t)zipmin(ZIP_4GB_MAX, offset_start));
-	ret = __archive_write_output(a, buff, 22);
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	zip->written_bytes += 22;
-	return (ARCHIVE_OK);
-}
-
-static int
-archive_write_zip_free(struct archive_write *a)
-{
-	struct zip *zip;
-	struct cd_segment *segment;
-
-	zip = a->format_data;
-	while (zip->central_directory != NULL) {
-		segment = zip->central_directory;
-		zip->central_directory = segment->next;
-		free(segment->buff);
-		free(segment);
-	}
-	free(zip->buf);
-	archive_entry_free(zip->entry);
-	if (zip->cctx_valid)
-		archive_encrypto_aes_ctr_release(&zip->cctx);
-	if (zip->hctx_valid)
-		archive_hmac_sha1_cleanup(&zip->hctx);
-	/* TODO: Free opt_sconv, sconv_default */
-
-	free(zip);
-	a->format_data = NULL;
-	return (ARCHIVE_OK);
-}
-
-/* Convert into MSDOS-style date/time. */
-static unsigned int
-dos_time(const time_t unix_time)
-{
-	struct tm *t;
-	unsigned int dt;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
-	struct tm tmbuf;
-#endif
-
-#if defined(HAVE_LOCALTIME_S)
-	t = localtime_s(&tmbuf, &unix_time) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
-	t = localtime_r(&unix_time, &tmbuf);
-#else
-	t = localtime(&unix_time);
-#endif
-
-	/* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */
-	if (t->tm_year < 1980 - 1900)
-		/* Set minimum date/time '1980-01-01 00:00:00'. */
-		dt = 0x00210000U;
-	else if (t->tm_year > 2107 - 1900)
-		/* Set maximum date/time '2107-12-31 23:59:58'. */
-		dt = 0xff9fbf7dU;
-	else {
-		dt = 0;
-		dt += ((t->tm_year - 80) & 0x7f) << 9;
-		dt += ((t->tm_mon + 1) & 0x0f) << 5;
-		dt += (t->tm_mday & 0x1f);
-		dt <<= 16;
-		dt += (t->tm_hour & 0x1f) << 11;
-		dt += (t->tm_min & 0x3f) << 5;
-		dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */
-	}
-	return dt;
-}
-
-static size_t
-path_length(struct archive_entry *entry)
-{
-	mode_t type;
-	const char *path;
-	size_t len;
-
-	type = archive_entry_filetype(entry);
-	path = archive_entry_pathname(entry);
-
-	if (path == NULL)
-		return (0);
-	len = strlen(path);
-	if (type == AE_IFDIR && (path[0] == '\0' || path[len - 1] != '/'))
-		++len; /* Space for the trailing / */
-	return len;
-}
-
-static int
-write_path(struct archive_entry *entry, struct archive_write *archive)
-{
-	int ret;
-	const char *path;
-	mode_t type;
-	size_t written_bytes;
-
-	path = archive_entry_pathname(entry);
-	type = archive_entry_filetype(entry);
-	written_bytes = 0;
-
-	if (path == NULL)
-		return (ARCHIVE_FATAL);
-
-	ret = __archive_write_output(archive, path, strlen(path));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	written_bytes += strlen(path);
-
-	/* Folders are recognized by a trailing slash. */
-	if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) {
-		ret = __archive_write_output(archive, "/", 1);
-		if (ret != ARCHIVE_OK)
-			return (ARCHIVE_FATAL);
-		written_bytes += 1;
-	}
-
-	return ((int)written_bytes);
-}
-
-static void
-copy_path(struct archive_entry *entry, unsigned char *p)
-{
-	const char *path;
-	size_t pathlen;
-	mode_t type;
-
-	path = archive_entry_pathname(entry);
-	pathlen = strlen(path);
-	type = archive_entry_filetype(entry);
-
-	memcpy(p, path, pathlen);
-
-	/* Folders are recognized by a trailing slash. */
-	if ((type == AE_IFDIR) && (path[pathlen - 1] != '/'))
-		p[pathlen] = '/';
-}
-
-
-static struct archive_string_conv *
-get_sconv(struct archive_write *a, struct zip *zip)
-{
-	if (zip->opt_sconv != NULL)
-		return (zip->opt_sconv);
-
-	if (!zip->init_default_conversion) {
-		zip->sconv_default =
-		    archive_string_default_conversion_for_write(&(a->archive));
-		zip->init_default_conversion = 1;
-	}
-	return (zip->sconv_default);
-}
-
-/*
-  Traditional PKWARE Decryption functions.
- */
-
-static void
-trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
-{
-	uint8_t t;
-#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL)
-
-	ctx->keys[0] = CRC32(ctx->keys[0], c);
-	ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1;
-	t = (ctx->keys[1] >> 24) & 0xff;
-	ctx->keys[2] = CRC32(ctx->keys[2], t);
-#undef CRC32
-}
-
-static uint8_t
-trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
-{
-	unsigned temp = ctx->keys[2] | 2;
-	return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
-}
-
-static unsigned
-trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
-    size_t in_len, uint8_t *out, size_t out_len)
-{
-	unsigned i, max;
-
-	max = (unsigned)((in_len < out_len)? in_len: out_len);
-
-	for (i = 0; i < max; i++) {
-		uint8_t t = in[i];
-		out[i] = t ^ trad_enc_decrypt_byte(ctx);
-		trad_enc_update_keys(ctx, t);
-	}
-	return i;
-}
-
-static int
-trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len)
-{
-
-	ctx->keys[0] = 305419896L;
-	ctx->keys[1] = 591751049L;
-	ctx->keys[2] = 878082192L;
-
-	for (;pw_len; --pw_len)
-		trad_enc_update_keys(ctx, *pw++);
-	return 0;
-}
-
-static int
-is_traditional_pkware_encryption_supported(void)
-{
-	uint8_t key[TRAD_HEADER_SIZE];
-
-	if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK)
-		return (0);
-	return (1);
-}
-
-static int
-init_traditional_pkware_encryption(struct archive_write *a)
-{
-	struct zip *zip = a->format_data;
-	const char *passphrase;
-	uint8_t key[TRAD_HEADER_SIZE];
-	uint8_t key_encrypted[TRAD_HEADER_SIZE];
-	int ret;
-
-	passphrase = __archive_write_get_passphrase(a);
-	if (passphrase == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Encryption needs passphrase");
-		return ARCHIVE_FAILED;
-	}
-	if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Can't generate random number for encryption");
-		return ARCHIVE_FATAL;
-	}
-	trad_enc_init(&zip->tctx, passphrase, strlen(passphrase));
-	/* Set the last key code which will be used as a check code
-	 * for verifying passphrase in decryption. */
-	key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat;
-	trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE,
-	    key_encrypted, TRAD_HEADER_SIZE);
-	/* Write encrypted keys in the top of the file content. */
-	ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	zip->written_bytes += TRAD_HEADER_SIZE;
-	zip->entry_compressed_written += TRAD_HEADER_SIZE;
-	return (ret);
-}
-
-static int
-init_winzip_aes_encryption(struct archive_write *a)
-{
-	struct zip *zip = a->format_data;
-	const char *passphrase;
-	size_t key_len, salt_len;
-	uint8_t salt[16 + 2];
-	uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE];
-	int ret;
-
-	passphrase = __archive_write_get_passphrase(a);
-	if (passphrase == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Encryption needs passphrase");
-		return (ARCHIVE_FAILED);
-	}
-	if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) {
-		salt_len = 8;
-		key_len = 16;
-	} else {
-		/* AES 256 */
-		salt_len = 16;
-		key_len = 32;
-	}
-	if (archive_random(salt, salt_len) != ARCHIVE_OK) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Can't generate random number for encryption");
-		return (ARCHIVE_FATAL);
-	}
-	archive_pbkdf2_sha1(passphrase, strlen(passphrase),
-	    salt, salt_len, 1000, derived_key, key_len * 2 + 2);
-
-	ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len);
-	if (ret != 0) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Decryption is unsupported due to lack of crypto library");
-		return (ARCHIVE_FAILED);
-	}
-	ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len,
-	    key_len);
-	if (ret != 0) {
-		archive_encrypto_aes_ctr_release(&zip->cctx);
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Failed to initialize HMAC-SHA1");
-		return (ARCHIVE_FAILED);
-        }
-
-	/* Set a password verification value after the 'salt'. */
-	salt[salt_len] = derived_key[key_len * 2];
-	salt[salt_len + 1] = derived_key[key_len * 2 + 1];
-
-	/* Write encrypted keys in the top of the file content. */
-	ret = __archive_write_output(a, salt, salt_len + 2);
-	if (ret != ARCHIVE_OK)
-		return (ret);
-	zip->written_bytes += salt_len + 2;
-	zip->entry_compressed_written += salt_len + 2;
-
-	return (ARCHIVE_OK);
-}
-
-static int
-is_winzip_aes_encryption_supported(int encryption)
-{
-	size_t key_len, salt_len;
-	uint8_t salt[16 + 2];
-	uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE];
-	archive_crypto_ctx cctx;
-	archive_hmac_sha1_ctx hctx;
-	int ret;
-
-	if (encryption == ENCRYPTION_WINZIP_AES128) {
-		salt_len = 8;
-		key_len = 16;
-	} else {
-		/* AES 256 */
-		salt_len = 16;
-		key_len = 32;
-	}
-	if (archive_random(salt, salt_len) != ARCHIVE_OK)
-		return (0);
-	ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000,
-	    derived_key, key_len * 2 + 2);
-	if (ret != 0)
-		return (0);
-
-	ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len);
-	if (ret != 0)
-		return (0);
-	ret = archive_hmac_sha1_init(&hctx, derived_key + key_len,
-	    key_len);
-	archive_encrypto_aes_ctr_release(&cctx);
-	if (ret != 0)
-		return (0);
-	archive_hmac_sha1_cleanup(&hctx);
-	return (1);
-}
diff --git a/c/archive_write_set_options.c b/c/archive_write_set_options.c
deleted file mode 100644
--- a/c/archive_write_set_options.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-
- * Copyright (c) 2003-2010 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#include "archive_write_private.h"
-#include "archive_options_private.h"
-
-static int	archive_set_format_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-static int	archive_set_filter_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-static int	archive_set_option(struct archive *a,
-		    const char *m, const char *o, const char *v);
-
-int
-archive_write_set_format_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_WRITE_MAGIC, "archive_write_set_format_option",
-	    archive_set_format_option);
-}
-
-int
-archive_write_set_filter_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_WRITE_MAGIC, "archive_write_set_filter_option",
-	    archive_set_filter_option);
-}
-
-int
-archive_write_set_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_option(a, m, o, v,
-	    ARCHIVE_WRITE_MAGIC, "archive_write_set_option",
-	    archive_set_option);
-}
-
-int
-archive_write_set_options(struct archive *a, const char *options)
-{
-	return _archive_set_options(a, options,
-	    ARCHIVE_WRITE_MAGIC, "archive_write_set_options",
-	    archive_set_option);
-}
-
-static int
-archive_set_format_option(struct archive *_a, const char *m, const char *o,
-    const char *v)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-
-	if (a->format_name == NULL)
-		return (m == NULL)?ARCHIVE_FAILED:ARCHIVE_WARN - 1;
-	/* If the format name didn't match, return a special code for
-	 * _archive_set_option[s]. */
-	if (m != NULL && strcmp(m, a->format_name) != 0)
-		return (ARCHIVE_WARN - 1);
-	if (a->format_options == NULL)
-		return (ARCHIVE_WARN);
-	return a->format_options(a, o, v);
-}
-
-static int
-archive_set_filter_option(struct archive *_a, const char *m, const char *o,
-    const char *v)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-	struct archive_write_filter *filter;
-	int r, rv = ARCHIVE_WARN;
-
-	for (filter = a->filter_first; filter != NULL; filter = filter->next_filter) {
-		if (filter->options == NULL)
-			continue;
-		if (m != NULL && strcmp(filter->name, m) != 0)
-			continue;
-
-		r = filter->options(filter, o, v);
-
-		if (r == ARCHIVE_FATAL)
-			return (ARCHIVE_FATAL);
-
-		if (m != NULL)
-			return (r);
-
-		if (r == ARCHIVE_OK)
-			rv = ARCHIVE_OK;
-	}
-	/* If the filter name didn't match, return a special code for
-	 * _archive_set_option[s]. */
-	if (rv == ARCHIVE_WARN && m != NULL)
-		rv = ARCHIVE_WARN - 1;
-	return (rv);
-}
-
-static int
-archive_set_option(struct archive *a, const char *m, const char *o,
-    const char *v)
-{
-	return _archive_set_either_option(a, m, o, v,
-	    archive_set_format_option,
-	    archive_set_filter_option);
-}
diff --git a/c/archive_write_set_passphrase.c b/c/archive_write_set_passphrase.c
deleted file mode 100644
--- a/c/archive_write_set_passphrase.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include "archive_write_private.h"
-
-int
-archive_write_set_passphrase(struct archive *_a, const char *p)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW,
-		"archive_write_set_passphrase");
-
-	if (p == NULL || p[0] == '\0') {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Empty passphrase is unacceptable");
-		return (ARCHIVE_FAILED);
-	}
-	free(a->passphrase);
-	a->passphrase = strdup(p);
-	if (a->passphrase == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate data for passphrase");
-		return (ARCHIVE_FATAL);
-	}
-	return (ARCHIVE_OK);
-}
-
-
-int
-archive_write_set_passphrase_callback(struct archive *_a, void *client_data,
-    archive_passphrase_callback *cb)
-{
-	struct archive_write *a = (struct archive_write *)_a;
-
-	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW,
-		"archive_write_set_passphrase_callback");
-
-	a->passphrase_callback = cb;
-	a->passphrase_client_data = client_data;
-	return (ARCHIVE_OK);
-}
-
-
-const char *
-__archive_write_get_passphrase(struct archive_write *a)
-{
-
-	if (a->passphrase != NULL)
-		return (a->passphrase);
-
-	if (a->passphrase_callback != NULL) {
-		const char *p;
-		p = a->passphrase_callback(&a->archive,
-		    a->passphrase_client_data);
-		if (p != NULL) {
-			a->passphrase = strdup(p);
-			if (a->passphrase == NULL) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate data for passphrase");
-				return (NULL);
-			}
-			return (a->passphrase);
-		}
-	}
-	return (NULL);
-}
diff --git a/c/archive_xxhash.h b/c/archive_xxhash.h
deleted file mode 100644
--- a/c/archive_xxhash.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * Copyright (c) 2014 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef ARCHIVE_XXHASH_H_INCLUDED
-#define ARCHIVE_XXHASH_H_INCLUDED
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-
-typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
-
-struct archive_xxhash {
-	unsigned int  (*XXH32)(const void* input, unsigned int len,
-			unsigned int seed);
-	void*         (*XXH32_init)(unsigned int seed);
-	XXH_errorcode (*XXH32_update)(void* state, const void* input,
-			unsigned int len);
-	unsigned int  (*XXH32_digest)(void* state);
-};
-
-extern const struct archive_xxhash __archive_xxhash;
-
-#endif
diff --git a/c/autoconf-darwin/config.h b/c/autoconf-darwin/config.h
deleted file mode 100644
--- a/c/autoconf-darwin/config.h
+++ /dev/null
@@ -1,1520 +0,0 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Darwin ACL support */
-/* #undef ARCHIVE_ACL_DARWIN */
-
-/* FreeBSD ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD */
-
-/* FreeBSD NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD_NFS4 */
-
-/* Linux POSIX.1e ACL support via libacl */
-/* #undef ARCHIVE_ACL_LIBACL */
-
-/* Linux NFSv4 ACL support via librichacl */
-/* #undef ARCHIVE_ACL_LIBRICHACL */
-
-/* Solaris ACL support */
-/* #undef ARCHIVE_ACL_SUNOS */
-
-/* Solaris NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_SUNOS_NFS4 */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBC */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBMD */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_MBEDTLS */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_OPENSSL */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_WIN */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBC */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBMD */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_MBEDTLS */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_NETTLE */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBMD */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_MBEDTLS */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_WIN */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC2 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBMD */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_MBEDTLS */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_OPENSSL */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_WIN */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC2 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_MBEDTLS */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_OPENSSL */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_WIN */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC2 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBMD */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_MBEDTLS */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_OPENSSL */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_WIN */
-
-/* AIX xattr support */
-/* #undef ARCHIVE_XATTR_AIX */
-
-/* Darwin xattr support */
-/* #undef ARCHIVE_XATTR_DARWIN */
-
-/* FreeBSD xattr support */
-/* #undef ARCHIVE_XATTR_FREEBSD */
-
-/* Linux xattr support */
-/* #undef ARCHIVE_XATTR_LINUX */
-
-/* Version number of bsdcat */
-#define BSDCAT_VERSION_STRING "3.7.1"
-
-/* Version number of bsdcpio */
-#define BSDCPIO_VERSION_STRING "3.7.1"
-
-/* Version number of bsdtar */
-#define BSDTAR_VERSION_STRING "3.7.1"
-
-/* Define to 1 if the system has the type `ace_t'. */
-/* #undef HAVE_ACE_T */
-
-/* Define to 1 if you have the `acl' function. */
-/* #undef HAVE_ACL */
-
-/* Define to 1 if the system has the type `aclent_t'. */
-/* #undef HAVE_ACLENT_T */
-
-/* Define to 1 if you have the `acl_add_flag_np' function. */
-/* #undef HAVE_ACL_ADD_FLAG_NP */
-
-/* Define to 1 if you have the `acl_add_perm' function. */
-/* #undef HAVE_ACL_ADD_PERM */
-
-/* Define to 1 if you have the `acl_clear_flags_np' function. */
-/* #undef HAVE_ACL_CLEAR_FLAGS_NP */
-
-/* Define to 1 if you have the `acl_clear_perms' function. */
-/* #undef HAVE_ACL_CLEAR_PERMS */
-
-/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
-
-/* Define to 1 if you have the `acl_delete_def_file' function. */
-/* #undef HAVE_ACL_DELETE_DEF_FILE */
-
-/* Define to 1 if the system has the type `acl_entry_t'. */
-/* #undef HAVE_ACL_ENTRY_T */
-
-/* Define to 1 if you have the `acl_free' function. */
-/* #undef HAVE_ACL_FREE */
-
-/* Define to 1 if you have the `acl_get_brand_np' function. */
-/* #undef HAVE_ACL_GET_BRAND_NP */
-
-/* Define to 1 if you have the `acl_get_entry' function. */
-/* #undef HAVE_ACL_GET_ENTRY */
-
-/* Define to 1 if you have the `acl_get_entry_type_np' function. */
-/* #undef HAVE_ACL_GET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_get_fd' function. */
-/* #undef HAVE_ACL_GET_FD */
-
-/* Define to 1 if you have the `acl_get_fd_np' function. */
-/* #undef HAVE_ACL_GET_FD_NP */
-
-/* Define to 1 if you have the `acl_get_file' function. */
-/* #undef HAVE_ACL_GET_FILE */
-
-/* Define to 1 if you have the `acl_get_flagset_np' function. */
-/* #undef HAVE_ACL_GET_FLAGSET_NP */
-
-/* Define to 1 if you have the `acl_get_flag_np' function. */
-/* #undef HAVE_ACL_GET_FLAG_NP */
-
-/* Define to 1 if you have the `acl_get_link_np' function. */
-/* #undef HAVE_ACL_GET_LINK_NP */
-
-/* Define to 1 if you have the `acl_get_perm' function. */
-/* #undef HAVE_ACL_GET_PERM */
-
-/* Define to 1 if you have the `acl_get_permset' function. */
-/* #undef HAVE_ACL_GET_PERMSET */
-
-/* Define to 1 if you have the `acl_get_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
-
-/* Define to 1 if you have the `acl_get_qualifier' function. */
-/* #undef HAVE_ACL_GET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_get_tag_type' function. */
-/* #undef HAVE_ACL_GET_TAG_TYPE */
-
-/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
-
-/* Define to 1 if you have the `acl_is_trivial_np' function. */
-/* #undef HAVE_ACL_IS_TRIVIAL_NP */
-
-/* Define to 1 if you have the <acl/libacl.h> header file. */
-/* #undef HAVE_ACL_LIBACL_H */
-
-/* Define to 1 if the system has the type `acl_permset_t'. */
-/* #undef HAVE_ACL_PERMSET_T */
-
-/* Define to 1 if you have the `acl_set_entry_type_np' function. */
-/* #undef HAVE_ACL_SET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_set_fd' function. */
-/* #undef HAVE_ACL_SET_FD */
-
-/* Define to 1 if you have the `acl_set_fd_np' function. */
-/* #undef HAVE_ACL_SET_FD_NP */
-
-/* Define to 1 if you have the `acl_set_file' function. */
-/* #undef HAVE_ACL_SET_FILE */
-
-/* Define to 1 if you have the `acl_set_link_np' function. */
-/* #undef HAVE_ACL_SET_LINK_NP */
-
-/* Define to 1 if you have the `acl_set_qualifier' function. */
-/* #undef HAVE_ACL_SET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_set_tag_type' function. */
-/* #undef HAVE_ACL_SET_TAG_TYPE */
-
-/* Define to 1 if the system has the type `acl_t'. */
-/* #undef HAVE_ACL_T */
-
-/* Define to 1 if the system has the type `acl_tag_t'. */
-/* #undef HAVE_ACL_TAG_T */
-
-/* Define to 1 if you have the `arc4random_buf' function. */
-#define HAVE_ARC4RANDOM_BUF 1
-
-/* Define to 1 if you have the <attr/xattr.h> header file. */
-/* #undef HAVE_ATTR_XATTR_H */
-
-/* Define to 1 if you have the <bcrypt.h> header file. */
-/* #undef HAVE_BCRYPT_H */
-
-/* Define to 1 if you have the <blake2.h> header file. */
-/* #undef HAVE_BLAKE2_H */
-
-/* Define to 1 if you have the <bzlib.h> header file. */
-/* #undef HAVE_BZLIB_H */
-
-/* Define to 1 if you have the `chflags' function. */
-#define HAVE_CHFLAGS 1
-
-/* Define to 1 if you have the `chown' function. */
-#define HAVE_CHOWN 1
-
-/* Define to 1 if you have the `chroot' function. */
-#define HAVE_CHROOT 1
-
-/* cmtime_s function */
-/* #undef HAVE_CMTIME_S */
-
-/* Define to 1 if you have the <copyfile.h> header file. */
-#define HAVE_COPYFILE_H 1
-
-/* Define to 1 if you have the `ctime_r' function. */
-#define HAVE_CTIME_R 1
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the `cygwin_conv_path' function. */
-/* #undef HAVE_CYGWIN_CONV_PATH */
-
-/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACL */
-
-/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_SETACL */
-
-/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_SYNCHRONIZE */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_TYPE_EXTENDED */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_TYPE_NFS4 */
-
-/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_USER */
-
-/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to
-   0 if you don't. */
-/* #undef HAVE_DECL_EXTATTR_NAMESPACE_USER */
-
-/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_GETACL */
-
-/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MAX 1
-
-/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MIN 1
-
-/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MAX 1
-
-/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MIN 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MIN 1
-
-/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_SETACL */
-
-/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SSIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
-   don't. */
-#define HAVE_DECL_STRERROR_R 1
-
-/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT32_MAX 1
-
-/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT64_MAX 1
-
-/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_XATTR_NOFOLLOW */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
-   */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have a dirfd function or macro */
-#define HAVE_DIRFD 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if nl_langinfo supports D_MD_ORDER */
-#define HAVE_D_MD_ORDER 1
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EFTYPE 1
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EILSEQ 1
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <expat.h> header file. */
-/* #undef HAVE_EXPAT_H */
-
-/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
-/* #undef HAVE_EXT2FS_EXT2_FS_H */
-
-/* Define to 1 if you have the `extattr_get_fd' function. */
-/* #undef HAVE_EXTATTR_GET_FD */
-
-/* Define to 1 if you have the `extattr_get_file' function. */
-/* #undef HAVE_EXTATTR_GET_FILE */
-
-/* Define to 1 if you have the `extattr_get_link' function. */
-/* #undef HAVE_EXTATTR_GET_LINK */
-
-/* Define to 1 if you have the `extattr_list_fd' function. */
-/* #undef HAVE_EXTATTR_LIST_FD */
-
-/* Define to 1 if you have the `extattr_list_file' function. */
-/* #undef HAVE_EXTATTR_LIST_FILE */
-
-/* Define to 1 if you have the `extattr_list_link' function. */
-/* #undef HAVE_EXTATTR_LIST_LINK */
-
-/* Define to 1 if you have the `extattr_set_fd' function. */
-/* #undef HAVE_EXTATTR_SET_FD */
-
-/* Define to 1 if you have the `extattr_set_link' function. */
-/* #undef HAVE_EXTATTR_SET_LINK */
-
-/* Define to 1 if you have the `facl' function. */
-/* #undef HAVE_FACL */
-
-/* Define to 1 if you have the `fchdir' function. */
-#define HAVE_FCHDIR 1
-
-/* Define to 1 if you have the `fchflags' function. */
-#define HAVE_FCHFLAGS 1
-
-/* Define to 1 if you have the `fchmod' function. */
-#define HAVE_FCHMOD 1
-
-/* Define to 1 if you have the `fchown' function. */
-#define HAVE_FCHOWN 1
-
-/* Define to 1 if you have the `fcntl' function. */
-#define HAVE_FCNTL 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdopendir' function. */
-#define HAVE_FDOPENDIR 1
-
-/* Define to 1 if you have the `fgetea' function. */
-/* #undef HAVE_FGETEA */
-
-/* Define to 1 if you have the `fgetxattr' function. */
-/* #undef HAVE_FGETXATTR */
-
-/* Define to 1 if you have the `flistea' function. */
-/* #undef HAVE_FLISTEA */
-
-/* Define to 1 if you have the `flistxattr' function. */
-/* #undef HAVE_FLISTXATTR */
-
-/* Define to 1 if you have the `fnmatch' function. */
-#define HAVE_FNMATCH 1
-
-/* Define to 1 if you have the <fnmatch.h> header file. */
-#define HAVE_FNMATCH_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if you have the `fsetea' function. */
-/* #undef HAVE_FSETEA */
-
-/* Define to 1 if you have the `fsetxattr' function. */
-/* #undef HAVE_FSETXATTR */
-
-/* Define to 1 if you have the `fstat' function. */
-#define HAVE_FSTAT 1
-
-/* Define to 1 if you have the `fstatat' function. */
-#define HAVE_FSTATAT 1
-
-/* Define to 1 if you have the `fstatfs' function. */
-#define HAVE_FSTATFS 1
-
-/* Define to 1 if you have the `fstatvfs' function. */
-#define HAVE_FSTATVFS 1
-
-/* Define to 1 if you have the `ftruncate' function. */
-#define HAVE_FTRUNCATE 1
-
-/* Define to 1 if you have the `futimens' function. */
-#define HAVE_FUTIMENS 1
-
-/* Define to 1 if you have the `futimes' function. */
-#define HAVE_FUTIMES 1
-
-/* Define to 1 if you have the `futimesat' function. */
-/* #undef HAVE_FUTIMESAT */
-
-/* Define to 1 if you have the `getea' function. */
-/* #undef HAVE_GETEA */
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `getline' function. */
-#define HAVE_GETLINE 1
-
-/* Platform uses optreset to reset getopt */
-#define HAVE_GETOPT_OPTRESET 1
-
-/* Define to 1 if you have the `getpid' function. */
-#define HAVE_GETPID 1
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getvfsbyname' function. */
-#define HAVE_GETVFSBYNAME 1
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* gmtime_s function */
-/* #undef HAVE_GMTIME_S */
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if you have the iconv() function and it works. */
-/* #undef HAVE_ICONV */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-/* #undef HAVE_ICONV_H */
-
-/* Define to 1 if the system has the type `intmax_t'. */
-#define HAVE_INTMAX_T 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the `lchflags' function. */
-#define HAVE_LCHFLAGS 1
-
-/* Define to 1 if you have the `lchmod' function. */
-#define HAVE_LCHMOD 1
-
-/* Define to 1 if you have the `lchown' function. */
-#define HAVE_LCHOWN 1
-
-/* Define to 1 if you have the `lgetea' function. */
-/* #undef HAVE_LGETEA */
-
-/* Define to 1 if you have the `lgetxattr' function. */
-/* #undef HAVE_LGETXATTR */
-
-/* Define to 1 if you have the `acl' library (-lacl). */
-/* #undef HAVE_LIBACL */
-
-/* Define to 1 if you have the `b2' library (-lb2). */
-/* #undef HAVE_LIBB2 */
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-/* #undef HAVE_LIBBZ2 */
-
-/* Define to 1 if you have the `charset' library (-lcharset). */
-/* #undef HAVE_LIBCHARSET */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-/* #undef HAVE_LIBCRYPTO */
-
-/* Define to 1 if you have the `expat' library (-lexpat). */
-/* #undef HAVE_LIBEXPAT */
-
-/* Define to 1 if you have the `lz4' library (-llz4). */
-/* #undef HAVE_LIBLZ4 */
-
-/* Define to 1 if you have the `lzma' library (-llzma). */
-/* #undef HAVE_LIBLZMA */
-
-/* Define to 1 if you have the `lzo2' library (-llzo2). */
-/* #undef HAVE_LIBLZO2 */
-
-/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */
-/* #undef HAVE_LIBMBEDCRYPTO */
-
-/* Define to 1 if you have the `md' library (-lmd). */
-/* #undef HAVE_LIBMD */
-
-/* Define to 1 if you have the `nettle' library (-lnettle). */
-/* #undef HAVE_LIBNETTLE */
-
-/* Define to 1 if you have the `pcre' library (-lpcre). */
-/* #undef HAVE_LIBPCRE */
-
-/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
-/* #undef HAVE_LIBPCREPOSIX */
-
-/* Define to 1 if you have the `regex' library (-lregex). */
-/* #undef HAVE_LIBREGEX */
-
-/* Define to 1 if you have the `richacl' library (-lrichacl). */
-/* #undef HAVE_LIBRICHACL */
-
-/* Define to 1 if you have the `xml2' library (-lxml2). */
-/* #undef HAVE_LIBXML2 */
-
-/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
-/* #undef HAVE_LIBXML_XMLREADER_H */
-
-/* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
-/* #undef HAVE_LIBXML_XMLWRITER_H */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if you have the `zstd' library (-lzstd). */
-/* #undef HAVE_LIBZSTD */
-
-/* Define to 1 if you have the `zstd' library (-lzstd) with compression
-   support. */
-/* #undef HAVE_LIBZSTD_COMPRESSOR */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `link' function. */
-#define HAVE_LINK 1
-
-/* Define to 1 if you have the `linkat' function. */
-#define HAVE_LINKAT 1
-
-/* Define to 1 if you have the <linux/fiemap.h> header file. */
-/* #undef HAVE_LINUX_FIEMAP_H */
-
-/* Define to 1 if you have the <linux/fs.h> header file. */
-/* #undef HAVE_LINUX_FS_H */
-
-/* Define to 1 if you have the <linux/magic.h> header file. */
-/* #undef HAVE_LINUX_MAGIC_H */
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-/* #undef HAVE_LINUX_TYPES_H */
-
-/* Define to 1 if you have the `listea' function. */
-/* #undef HAVE_LISTEA */
-
-/* Define to 1 if you have the `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistea' function. */
-/* #undef HAVE_LLISTEA */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if you have the <localcharset.h> header file. */
-/* #undef HAVE_LOCALCHARSET_H */
-
-/* Define to 1 if you have the `locale_charset' function. */
-/* #undef HAVE_LOCALE_CHARSET */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* localtime_s function */
-/* #undef HAVE_LOCALTIME_S */
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `lsetea' function. */
-/* #undef HAVE_LSETEA */
-
-/* Define to 1 if you have the `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* Define to 1 if you have the `lstat' function. */
-#define HAVE_LSTAT 1
-
-/* Define to 1 if `lstat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the `lutimes' function. */
-#define HAVE_LUTIMES 1
-
-/* Define to 1 if you have the <lz4hc.h> header file. */
-/* #undef HAVE_LZ4HC_H */
-
-/* Define to 1 if you have the <lz4.h> header file. */
-/* #undef HAVE_LZ4_H */
-
-/* Define to 1 if you have the `LZMA_FILTER_ARM64' macro. */
-/* #undef HAVE_LZMA_FILTER_ARM64 */
-
-/* Define to 1 if you have the <lzma.h> header file. */
-/* #undef HAVE_LZMA_H */
-
-/* Define to 1 if you have the `lzma_stream_encoder_mt' function. */
-/* #undef HAVE_LZMA_STREAM_ENCODER_MT */
-
-/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
-/* #undef HAVE_LZO_LZO1X_H */
-
-/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
-/* #undef HAVE_LZO_LZOCONF_H */
-
-/* Define to 1 if you have the <mbedtls/aes.h> header file. */
-/* #undef HAVE_MBEDTLS_AES_H */
-
-/* Define to 1 if you have the <mbedtls/md.h> header file. */
-/* #undef HAVE_MBEDTLS_MD_H */
-
-/* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
-/* #undef HAVE_MBEDTLS_PKCS5_H */
-
-/* Define to 1 if you have the `mbrtowc' function. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the `mbr_gid_to_uuid' function. */
-/* #undef HAVE_MBR_GID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uid_to_uuid' function. */
-/* #undef HAVE_MBR_UID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uuid_to_id' function. */
-/* #undef HAVE_MBR_UUID_TO_ID */
-
-/* Define to 1 if you have the <md5.h> header file. */
-/* #undef HAVE_MD5_H */
-
-/* Define to 1 if you have the <membership.h> header file. */
-#define HAVE_MEMBERSHIP_H 1
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have the <minix/config.h> header file. */
-/* #undef HAVE_MINIX_CONFIG_H */
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have the `mkfifo' function. */
-#define HAVE_MKFIFO 1
-
-/* Define to 1 if you have the `mknod' function. */
-#define HAVE_MKNOD 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the <nettle/aes.h> header file. */
-/* #undef HAVE_NETTLE_AES_H */
-
-/* Define to 1 if you have the <nettle/hmac.h> header file. */
-/* #undef HAVE_NETTLE_HMAC_H */
-
-/* Define to 1 if you have the <nettle/md5.h> header file. */
-/* #undef HAVE_NETTLE_MD5_H */
-
-/* Define to 1 if you have the <nettle/pbkdf2.h> header file. */
-/* #undef HAVE_NETTLE_PBKDF2_H */
-
-/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
-/* #undef HAVE_NETTLE_RIPEMD160_H */
-
-/* Define to 1 if you have the <nettle/sha.h> header file. */
-/* #undef HAVE_NETTLE_SHA_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the `openat' function. */
-#define HAVE_OPENAT 1
-
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-/* #undef HAVE_OPENSSL_EVP_H */
-
-/* Define to 1 if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
-/* Define to 1 if you have the <pcreposix.h> header file. */
-/* #undef HAVE_PCREPOSIX_H */
-
-/* Define to 1 if you have the `pipe' function. */
-#define HAVE_PIPE 1
-
-/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */
-/* #undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `posix_spawnp' function. */
-#define HAVE_POSIX_SPAWNP 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have a POSIX compatible readdir_r */
-#define HAVE_READDIR_R 1
-
-/* Define to 1 if you have the `readlink' function. */
-#define HAVE_READLINK 1
-
-/* Define to 1 if you have the `readlinkat' function. */
-#define HAVE_READLINKAT 1
-
-/* Define to 1 if you have the `readpassphrase' function. */
-#define HAVE_READPASSPHRASE 1
-
-/* Define to 1 if you have the <readpassphrase.h> header file. */
-#define HAVE_READPASSPHRASE_H 1
-
-/* Define to 1 if you have the <regex.h> header file. */
-/* #undef HAVE_REGEX_H */
-
-/* Define to 1 if you have the `richacl_alloc' function. */
-/* #undef HAVE_RICHACL_ALLOC */
-
-/* Define to 1 if you have the `richacl_equiv_mode' function. */
-/* #undef HAVE_RICHACL_EQUIV_MODE */
-
-/* Define to 1 if you have the `richacl_free' function. */
-/* #undef HAVE_RICHACL_FREE */
-
-/* Define to 1 if you have the `richacl_get_fd' function. */
-/* #undef HAVE_RICHACL_GET_FD */
-
-/* Define to 1 if you have the `richacl_get_file' function. */
-/* #undef HAVE_RICHACL_GET_FILE */
-
-/* Define to 1 if you have the `richacl_set_fd' function. */
-/* #undef HAVE_RICHACL_SET_FD */
-
-/* Define to 1 if you have the `richacl_set_file' function. */
-/* #undef HAVE_RICHACL_SET_FILE */
-
-/* Define to 1 if you have the <ripemd.h> header file. */
-/* #undef HAVE_RIPEMD_H */
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 1
-
-/* Define to 1 if you have the `setxattr' function. */
-/* #undef HAVE_SETXATTR */
-
-/* Define to 1 if you have the <sha256.h> header file. */
-/* #undef HAVE_SHA256_H */
-
-/* Define to 1 if you have the <sha512.h> header file. */
-/* #undef HAVE_SHA512_H */
-
-/* Define to 1 if you have the <sha.h> header file. */
-/* #undef HAVE_SHA_H */
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the <spawn.h> header file. */
-#define HAVE_SPAWN_H 1
-
-/* Define to 1 if you have the `statfs' function. */
-#define HAVE_STATFS 1
-
-/* Define to 1 if you have the `statvfs' function. */
-#define HAVE_STATVFS 1
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strchr' function. */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have `strerror_r'. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `strftime' function. */
-#define HAVE_STRFTIME 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncpy_s' function. */
-/* #undef HAVE_STRNCPY_S */
-
-/* Define to 1 if you have the `strnlen' function. */
-#define HAVE_STRNLEN 1
-
-/* Define to 1 if you have the `strrchr' function. */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if the system has the type `struct richace'. */
-/* #undef HAVE_STRUCT_RICHACE */
-
-/* Define to 1 if the system has the type `struct richacl'. */
-/* #undef HAVE_STRUCT_RICHACL */
-
-/* Define to 1 if the system has the type `struct statfs'. */
-#define HAVE_STRUCT_STATFS 1
-
-/* Define to 1 if `f_iosize' is a member of `struct statfs'. */
-#define HAVE_STRUCT_STATFS_F_IOSIZE 1
-
-/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_NAMEMAX */
-
-/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
-/* #undef HAVE_STRUCT_STATVFS_F_IOSIZE */
-
-/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
-
-/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
-
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-
-/* Define to 1 if `st_flags' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_FLAGS 1
-
-/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
-
-/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */
-
-/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
-
-/* Define to 1 if `st_umtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_UMTIME */
-
-/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if the system has the type `struct vfsconf'. */
-#define HAVE_STRUCT_VFSCONF 1
-
-/* Define to 1 if the system has the type `struct xvfsconf'. */
-/* #undef HAVE_STRUCT_XVFSCONF */
-
-/* Define to 1 if you have the `symlink' function. */
-#define HAVE_SYMLINK 1
-
-/* Define to 1 if you have the <sys/acl.h> header file. */
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/ea.h> header file. */
-/* #undef HAVE_SYS_EA_H */
-
-/* Define to 1 if you have the <sys/extattr.h> header file. */
-/* #undef HAVE_SYS_EXTATTR_H */
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/mkdev.h> header file. */
-/* #undef HAVE_SYS_MKDEV_H */
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-#define HAVE_SYS_MOUNT_H 1
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/queue.h> header file. */
-#define HAVE_SYS_QUEUE_H 1
-
-/* Define to 1 if you have the <sys/richacl.h> header file. */
-/* #undef HAVE_SYS_RICHACL_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/statfs.h> header file. */
-/* #undef HAVE_SYS_STATFS_H */
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-#define HAVE_SYS_STATVFS_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-/* #undef HAVE_SYS_SYSMACROS_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/utime.h> header file. */
-/* #undef HAVE_SYS_UTIME_H */
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#define HAVE_SYS_UTSNAME_H 1
-
-/* Define to 1 if you have the <sys/vfs.h> header file. */
-/* #undef HAVE_SYS_VFS_H */
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the <sys/xattr.h> header file. */
-#define HAVE_SYS_XATTR_H 1
-
-/* Define to 1 if you have the `timegm' function. */
-#define HAVE_TIMEGM 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the `tzset' function. */
-#define HAVE_TZSET 1
-
-/* Define to 1 if the system has the type `uintmax_t'. */
-#define HAVE_UINTMAX_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `unlinkat' function. */
-#define HAVE_UNLINKAT 1
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if the system has the type `unsigned long long'. */
-#define HAVE_UNSIGNED_LONG_LONG 1
-
-/* Define to 1 if the system has the type `unsigned long long int'. */
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimensat' function. */
-#define HAVE_UTIMENSAT 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the <utime.h> header file. */
-#define HAVE_UTIME_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-#define HAVE_VFORK 1
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the `wcrtomb' function. */
-#define HAVE_WCRTOMB 1
-
-/* Define to 1 if you have the `wcscmp' function. */
-#define HAVE_WCSCMP 1
-
-/* Define to 1 if you have the `wcscpy' function. */
-#define HAVE_WCSCPY 1
-
-/* Define to 1 if you have the `wcslen' function. */
-#define HAVE_WCSLEN 1
-
-/* Define to 1 if you have the `wctomb' function. */
-#define HAVE_WCTOMB 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define to 1 if you have the <wincrypt.h> header file. */
-/* #undef HAVE_WINCRYPT_H */
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winioctl.h> header file. */
-/* #undef HAVE_WINIOCTL_H */
-
-/* Define to 1 if you have the `wmemcmp' function. */
-#define HAVE_WMEMCMP 1
-
-/* Define to 1 if you have the `wmemcpy' function. */
-#define HAVE_WMEMCPY 1
-
-/* Define to 1 if you have the `wmemmove' function. */
-#define HAVE_WMEMMOVE 1
-
-/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_EXT2_IOC_GETFLAGS */
-
-/* Define to 1 if you have a working FS_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_FS_IOC_GETFLAGS */
-
-/* Define to 1 if you have the <zlib.h> header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Define to 1 if you have the <zstd.h> header file. */
-/* #undef HAVE_ZSTD_H */
-
-/* Define to 1 if you have the `_fseeki64' function. */
-/* #undef HAVE__FSEEKI64 */
-
-/* Define to 1 if you have the `_get_timezone' function. */
-/* #undef HAVE__GET_TIMEZONE */
-
-/* _mkgmtime function */
-/* #undef HAVE__MKGMTIME */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #undef ICONV_CONST */
-
-/* Version number of libarchive as a single integer */
-#define LIBARCHIVE_VERSION_NUMBER "3007001"
-
-/* Version number of libarchive */
-#define LIBARCHIVE_VERSION_STRING "3.7.1"
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
-   slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
-   */
-/* #undef MAJOR_IN_MKDEV */
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in
-   <sysmacros.h>. */
-/* #undef MAJOR_IN_SYSMACROS */
-
-/* Define to '0x05020000' for Windows Server 2003 APIs. */
-/* #undef NTDDI_VERSION */
-
-/* Name of package */
-#define PACKAGE "libarchive"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "libarchive-discuss@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libarchive"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libarchive 3.7.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libarchive"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.7.1"
-
-/* Define to 1 if PCRE_STATIC needs to be defined. */
-/* #undef PCRE_STATIC */
-
-/* The number of bytes in type int */
-#define SIZEOF_INT 4
-
-/* The number of bytes in type long */
-#define SIZEOF_LONG 8
-
-/* The size of `wchar_t', as computed by sizeof. */
-#define SIZEOF_WCHAR_T 4
-
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
-   required in a freestanding environment). This macro is provided for
-   backward compatibility; new code need not use it. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r returns char *. */
-/* #undef STRERROR_R_CHAR_P */
-
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable general extensions on macOS.  */
-#ifndef _DARWIN_C_SOURCE
-# define _DARWIN_C_SOURCE 1
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable X/Open compliant socket functions that do not require linking
-   with -lxnet on HP-UX 11.11.  */
-#ifndef _HPUX_ALT_XOPEN_SOCKET_API
-# define _HPUX_ALT_XOPEN_SOCKET_API 1
-#endif
-/* Identify the host operating system as Minix.
-   This macro does not affect the system headers' behavior.
-   A future release of Autoconf may stop defining this macro.  */
-#ifndef _MINIX
-/* # undef _MINIX */
-#endif
-/* Enable general extensions on NetBSD.
-   Enable NetBSD compatibility extensions on Minix.  */
-#ifndef _NETBSD_SOURCE
-# define _NETBSD_SOURCE 1
-#endif
-/* Enable OpenBSD compatibility extensions on NetBSD.
-   Oddly enough, this does nothing on OpenBSD.  */
-#ifndef _OPENBSD_SOURCE
-# define _OPENBSD_SOURCE 1
-#endif
-/* Define to 1 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_SOURCE
-/* # undef _POSIX_SOURCE */
-#endif
-/* Define to 2 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_1_SOURCE
-/* # undef _POSIX_1_SOURCE */
-#endif
-/* Enable POSIX-compatible threading on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
-#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
-# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
-#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
-# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
-#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
-# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
-#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
-# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
-#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
-# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
-#ifndef __STDC_WANT_LIB_EXT2__
-# define __STDC_WANT_LIB_EXT2__ 1
-#endif
-/* Enable extensions specified by ISO/IEC 24747:2009.  */
-#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
-# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable X/Open extensions.  Define to 500 only if necessary
-   to make mbstate_t available.  */
-#ifndef _XOPEN_SOURCE
-/* # undef _XOPEN_SOURCE */
-#endif
-
-
-/* Version number of package */
-#define VERSION "3.7.1"
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef WINVER */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT32_T */
-
-/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT64_T */
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT8_T */
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef _WIN32_WINNT */
-
-/* Internal macro for sanity checks */
-#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef gid_t */
-
-/* Define to `unsigned long' if <sys/types.h> does not define. */
-/* #undef id_t */
-
-/* Define to the type of a signed integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int16_t */
-
-/* Define to the type of a signed integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int32_t */
-
-/* Define to the type of a signed integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int64_t */
-
-/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
-   not define. */
-/* #undef intmax_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
-
-/* Define to `long long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef uid_t */
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint16_t */
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint32_t */
-
-/* Define to the type of an unsigned integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint64_t */
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint8_t */
-
-/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
-   do not define. */
-/* #undef uintmax_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef uintptr_t */
-#define HAVE_LIBZ 1
-#define HAVE_ZLIB_H 1
diff --git a/c/autoconf-freebsd/config.h b/c/autoconf-freebsd/config.h
deleted file mode 100644
--- a/c/autoconf-freebsd/config.h
+++ /dev/null
@@ -1,1509 +0,0 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Darwin ACL support */
-/* #undef ARCHIVE_ACL_DARWIN */
-
-/* FreeBSD ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD */
-
-/* FreeBSD NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD_NFS4 */
-
-/* Linux POSIX.1e ACL support via libacl */
-/* #undef ARCHIVE_ACL_LIBACL */
-
-/* Linux NFSv4 ACL support via librichacl */
-/* #undef ARCHIVE_ACL_LIBRICHACL */
-
-/* Solaris ACL support */
-/* #undef ARCHIVE_ACL_SUNOS */
-
-/* Solaris NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_SUNOS_NFS4 */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBC */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_MBEDTLS */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_OPENSSL */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_WIN */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBC */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_MBEDTLS */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_NETTLE */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_MBEDTLS */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_WIN */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC2 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_MBEDTLS */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_OPENSSL */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_WIN */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC2 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_MBEDTLS */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_OPENSSL */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_WIN */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC2 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_MBEDTLS */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_OPENSSL */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_WIN */
-
-/* AIX xattr support */
-/* #undef ARCHIVE_XATTR_AIX */
-
-/* Darwin xattr support */
-/* #undef ARCHIVE_XATTR_DARWIN */
-
-/* FreeBSD xattr support */
-/* #undef ARCHIVE_XATTR_FREEBSD */
-
-/* Linux xattr support */
-/* #undef ARCHIVE_XATTR_LINUX */
-
-/* Version number of bsdcat */
-#define BSDCAT_VERSION_STRING "3.7.1"
-
-/* Version number of bsdcpio */
-#define BSDCPIO_VERSION_STRING "3.7.1"
-
-/* Version number of bsdtar */
-#define BSDTAR_VERSION_STRING "3.7.1"
-
-/* Define to 1 if the system has the type `ace_t'. */
-/* #undef HAVE_ACE_T */
-
-/* Define to 1 if you have the `acl' function. */
-/* #undef HAVE_ACL */
-
-/* Define to 1 if the system has the type `aclent_t'. */
-/* #undef HAVE_ACLENT_T */
-
-/* Define to 1 if you have the `acl_add_flag_np' function. */
-/* #undef HAVE_ACL_ADD_FLAG_NP */
-
-/* Define to 1 if you have the `acl_add_perm' function. */
-/* #undef HAVE_ACL_ADD_PERM */
-
-/* Define to 1 if you have the `acl_clear_flags_np' function. */
-/* #undef HAVE_ACL_CLEAR_FLAGS_NP */
-
-/* Define to 1 if you have the `acl_clear_perms' function. */
-/* #undef HAVE_ACL_CLEAR_PERMS */
-
-/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
-
-/* Define to 1 if you have the `acl_delete_def_file' function. */
-/* #undef HAVE_ACL_DELETE_DEF_FILE */
-
-/* Define to 1 if the system has the type `acl_entry_t'. */
-/* #undef HAVE_ACL_ENTRY_T */
-
-/* Define to 1 if you have the `acl_free' function. */
-/* #undef HAVE_ACL_FREE */
-
-/* Define to 1 if you have the `acl_get_brand_np' function. */
-/* #undef HAVE_ACL_GET_BRAND_NP */
-
-/* Define to 1 if you have the `acl_get_entry' function. */
-/* #undef HAVE_ACL_GET_ENTRY */
-
-/* Define to 1 if you have the `acl_get_entry_type_np' function. */
-/* #undef HAVE_ACL_GET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_get_fd' function. */
-/* #undef HAVE_ACL_GET_FD */
-
-/* Define to 1 if you have the `acl_get_fd_np' function. */
-/* #undef HAVE_ACL_GET_FD_NP */
-
-/* Define to 1 if you have the `acl_get_file' function. */
-/* #undef HAVE_ACL_GET_FILE */
-
-/* Define to 1 if you have the `acl_get_flagset_np' function. */
-/* #undef HAVE_ACL_GET_FLAGSET_NP */
-
-/* Define to 1 if you have the `acl_get_flag_np' function. */
-/* #undef HAVE_ACL_GET_FLAG_NP */
-
-/* Define to 1 if you have the `acl_get_link_np' function. */
-/* #undef HAVE_ACL_GET_LINK_NP */
-
-/* Define to 1 if you have the `acl_get_perm' function. */
-/* #undef HAVE_ACL_GET_PERM */
-
-/* Define to 1 if you have the `acl_get_permset' function. */
-/* #undef HAVE_ACL_GET_PERMSET */
-
-/* Define to 1 if you have the `acl_get_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
-
-/* Define to 1 if you have the `acl_get_qualifier' function. */
-/* #undef HAVE_ACL_GET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_get_tag_type' function. */
-/* #undef HAVE_ACL_GET_TAG_TYPE */
-
-/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
-
-/* Define to 1 if you have the `acl_is_trivial_np' function. */
-/* #undef HAVE_ACL_IS_TRIVIAL_NP */
-
-/* Define to 1 if you have the <acl/libacl.h> header file. */
-/* #undef HAVE_ACL_LIBACL_H */
-
-/* Define to 1 if the system has the type `acl_permset_t'. */
-/* #undef HAVE_ACL_PERMSET_T */
-
-/* Define to 1 if you have the `acl_set_entry_type_np' function. */
-/* #undef HAVE_ACL_SET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_set_fd' function. */
-/* #undef HAVE_ACL_SET_FD */
-
-/* Define to 1 if you have the `acl_set_fd_np' function. */
-/* #undef HAVE_ACL_SET_FD_NP */
-
-/* Define to 1 if you have the `acl_set_file' function. */
-/* #undef HAVE_ACL_SET_FILE */
-
-/* Define to 1 if you have the `acl_set_link_np' function. */
-/* #undef HAVE_ACL_SET_LINK_NP */
-
-/* Define to 1 if you have the `acl_set_qualifier' function. */
-/* #undef HAVE_ACL_SET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_set_tag_type' function. */
-/* #undef HAVE_ACL_SET_TAG_TYPE */
-
-/* Define to 1 if the system has the type `acl_t'. */
-/* #undef HAVE_ACL_T */
-
-/* Define to 1 if the system has the type `acl_tag_t'. */
-/* #undef HAVE_ACL_TAG_T */
-
-/* Define to 1 if you have the `arc4random_buf' function. */
-#define HAVE_ARC4RANDOM_BUF 1
-
-/* Define to 1 if you have the <attr/xattr.h> header file. */
-/* #undef HAVE_ATTR_XATTR_H */
-
-/* Define to 1 if you have the <bcrypt.h> header file. */
-/* #undef HAVE_BCRYPT_H */
-
-/* Define to 1 if you have the <blake2.h> header file. */
-/* #undef HAVE_BLAKE2_H */
-
-/* Define to 1 if you have the <bzlib.h> header file. */
-/* #undef HAVE_BZLIB_H */
-
-/* Define to 1 if you have the `chflags' function. */
-#define HAVE_CHFLAGS 1
-
-/* Define to 1 if you have the `chown' function. */
-#define HAVE_CHOWN 1
-
-/* Define to 1 if you have the `chroot' function. */
-#define HAVE_CHROOT 1
-
-/* cmtime_s function */
-/* #undef HAVE_CMTIME_S */
-
-/* Define to 1 if you have the <copyfile.h> header file. */
-/* #undef HAVE_COPYFILE_H */
-
-/* Define to 1 if you have the `ctime_r' function. */
-#define HAVE_CTIME_R 1
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the `cygwin_conv_path' function. */
-/* #undef HAVE_CYGWIN_CONV_PATH */
-
-/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACL */
-
-/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_SETACL */
-
-/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_SYNCHRONIZE */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_TYPE_EXTENDED */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_TYPE_NFS4 */
-
-/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_USER */
-
-/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to
-   0 if you don't. */
-/* #undef HAVE_DECL_EXTATTR_NAMESPACE_USER */
-
-/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_GETACL */
-
-/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MAX 1
-
-/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MIN 1
-
-/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MAX 1
-
-/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MIN 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MIN 1
-
-/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_SETACL */
-
-/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SSIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
-   don't. */
-#define HAVE_DECL_STRERROR_R 1
-
-/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT32_MAX 1
-
-/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT64_MAX 1
-
-/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_XATTR_NOFOLLOW */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
-   */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have a dirfd function or macro */
-#define HAVE_DIRFD 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if nl_langinfo supports D_MD_ORDER */
-#define HAVE_D_MD_ORDER 1
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EFTYPE 1
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EILSEQ 1
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <expat.h> header file. */
-/* #undef HAVE_EXPAT_H */
-
-/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
-/* #undef HAVE_EXT2FS_EXT2_FS_H */
-
-/* Define to 1 if you have the `extattr_get_fd' function. */
-/* #undef HAVE_EXTATTR_GET_FD */
-
-/* Define to 1 if you have the `extattr_get_file' function. */
-/* #undef HAVE_EXTATTR_GET_FILE */
-
-/* Define to 1 if you have the `extattr_get_link' function. */
-/* #undef HAVE_EXTATTR_GET_LINK */
-
-/* Define to 1 if you have the `extattr_list_fd' function. */
-/* #undef HAVE_EXTATTR_LIST_FD */
-
-/* Define to 1 if you have the `extattr_list_file' function. */
-/* #undef HAVE_EXTATTR_LIST_FILE */
-
-/* Define to 1 if you have the `extattr_list_link' function. */
-/* #undef HAVE_EXTATTR_LIST_LINK */
-
-/* Define to 1 if you have the `extattr_set_fd' function. */
-/* #undef HAVE_EXTATTR_SET_FD */
-
-/* Define to 1 if you have the `extattr_set_link' function. */
-/* #undef HAVE_EXTATTR_SET_LINK */
-
-/* Define to 1 if you have the `facl' function. */
-/* #undef HAVE_FACL */
-
-/* Define to 1 if you have the `fchdir' function. */
-#define HAVE_FCHDIR 1
-
-/* Define to 1 if you have the `fchflags' function. */
-#define HAVE_FCHFLAGS 1
-
-/* Define to 1 if you have the `fchmod' function. */
-#define HAVE_FCHMOD 1
-
-/* Define to 1 if you have the `fchown' function. */
-#define HAVE_FCHOWN 1
-
-/* Define to 1 if you have the `fcntl' function. */
-#define HAVE_FCNTL 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdopendir' function. */
-#define HAVE_FDOPENDIR 1
-
-/* Define to 1 if you have the `fgetea' function. */
-/* #undef HAVE_FGETEA */
-
-/* Define to 1 if you have the `fgetxattr' function. */
-/* #undef HAVE_FGETXATTR */
-
-/* Define to 1 if you have the `flistea' function. */
-/* #undef HAVE_FLISTEA */
-
-/* Define to 1 if you have the `flistxattr' function. */
-/* #undef HAVE_FLISTXATTR */
-
-/* Define to 1 if you have the `fnmatch' function. */
-#define HAVE_FNMATCH 1
-
-/* Define to 1 if you have the <fnmatch.h> header file. */
-#define HAVE_FNMATCH_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if you have the `fsetea' function. */
-/* #undef HAVE_FSETEA */
-
-/* Define to 1 if you have the `fsetxattr' function. */
-/* #undef HAVE_FSETXATTR */
-
-/* Define to 1 if you have the `fstat' function. */
-#define HAVE_FSTAT 1
-
-/* Define to 1 if you have the `fstatat' function. */
-#define HAVE_FSTATAT 1
-
-/* Define to 1 if you have the `fstatfs' function. */
-#define HAVE_FSTATFS 1
-
-/* Define to 1 if you have the `fstatvfs' function. */
-#define HAVE_FSTATVFS 1
-
-/* Define to 1 if you have the `ftruncate' function. */
-#define HAVE_FTRUNCATE 1
-
-/* Define to 1 if you have the `futimens' function. */
-#define HAVE_FUTIMENS 1
-
-/* Define to 1 if you have the `futimes' function. */
-#define HAVE_FUTIMES 1
-
-/* Define to 1 if you have the `futimesat' function. */
-#define HAVE_FUTIMESAT 1
-
-/* Define to 1 if you have the `getea' function. */
-/* #undef HAVE_GETEA */
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `getline' function. */
-#define HAVE_GETLINE 1
-
-/* Platform uses optreset to reset getopt */
-#define HAVE_GETOPT_OPTRESET 1
-
-/* Define to 1 if you have the `getpid' function. */
-#define HAVE_GETPID 1
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getvfsbyname' function. */
-#define HAVE_GETVFSBYNAME 1
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* gmtime_s function */
-/* #undef HAVE_GMTIME_S */
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if you have the iconv() function and it works. */
-/* #undef HAVE_ICONV */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-/* #undef HAVE_ICONV_H */
-
-/* Define to 1 if the system has the type `intmax_t'. */
-#define HAVE_INTMAX_T 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the `lchflags' function. */
-#define HAVE_LCHFLAGS 1
-
-/* Define to 1 if you have the `lchmod' function. */
-#define HAVE_LCHMOD 1
-
-/* Define to 1 if you have the `lchown' function. */
-#define HAVE_LCHOWN 1
-
-/* Define to 1 if you have the `lgetea' function. */
-/* #undef HAVE_LGETEA */
-
-/* Define to 1 if you have the `lgetxattr' function. */
-/* #undef HAVE_LGETXATTR */
-
-/* Define to 1 if you have the `acl' library (-lacl). */
-/* #undef HAVE_LIBACL */
-
-/* Define to 1 if you have the `b2' library (-lb2). */
-/* #undef HAVE_LIBB2 */
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-/* #undef HAVE_LIBBZ2 */
-
-/* Define to 1 if you have the `charset' library (-lcharset). */
-/* #undef HAVE_LIBCHARSET */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-/* #undef HAVE_LIBCRYPTO */
-
-/* Define to 1 if you have the `expat' library (-lexpat). */
-/* #undef HAVE_LIBEXPAT */
-
-/* Define to 1 if you have the `lz4' library (-llz4). */
-/* #undef HAVE_LIBLZ4 */
-
-/* Define to 1 if you have the `lzma' library (-llzma). */
-/* #undef HAVE_LIBLZMA */
-
-/* Define to 1 if you have the `lzo2' library (-llzo2). */
-/* #undef HAVE_LIBLZO2 */
-
-/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */
-/* #undef HAVE_LIBMBEDCRYPTO */
-
-/* Define to 1 if you have the `md' library (-lmd). */
-
-/* Define to 1 if you have the `nettle' library (-lnettle). */
-/* #undef HAVE_LIBNETTLE */
-
-/* Define to 1 if you have the `pcre' library (-lpcre). */
-/* #undef HAVE_LIBPCRE */
-
-/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
-/* #undef HAVE_LIBPCREPOSIX */
-
-/* Define to 1 if you have the `regex' library (-lregex). */
-/* #undef HAVE_LIBREGEX */
-
-/* Define to 1 if you have the `richacl' library (-lrichacl). */
-/* #undef HAVE_LIBRICHACL */
-
-/* Define to 1 if you have the `xml2' library (-lxml2). */
-/* #undef HAVE_LIBXML2 */
-
-/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
-/* #undef HAVE_LIBXML_XMLREADER_H */
-
-/* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
-/* #undef HAVE_LIBXML_XMLWRITER_H */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if you have the `zstd' library (-lzstd). */
-/* #undef HAVE_LIBZSTD */
-
-/* Define to 1 if you have the `zstd' library (-lzstd) with compression
-   support. */
-/* #undef HAVE_LIBZSTD_COMPRESSOR */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `link' function. */
-#define HAVE_LINK 1
-
-/* Define to 1 if you have the `linkat' function. */
-#define HAVE_LINKAT 1
-
-/* Define to 1 if you have the <linux/fiemap.h> header file. */
-/* #undef HAVE_LINUX_FIEMAP_H */
-
-/* Define to 1 if you have the <linux/fs.h> header file. */
-/* #undef HAVE_LINUX_FS_H */
-
-/* Define to 1 if you have the <linux/magic.h> header file. */
-/* #undef HAVE_LINUX_MAGIC_H */
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-/* #undef HAVE_LINUX_TYPES_H */
-
-/* Define to 1 if you have the `listea' function. */
-/* #undef HAVE_LISTEA */
-
-/* Define to 1 if you have the `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistea' function. */
-/* #undef HAVE_LLISTEA */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if you have the <localcharset.h> header file. */
-/* #undef HAVE_LOCALCHARSET_H */
-
-/* Define to 1 if you have the `locale_charset' function. */
-/* #undef HAVE_LOCALE_CHARSET */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* localtime_s function */
-/* #undef HAVE_LOCALTIME_S */
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `lsetea' function. */
-/* #undef HAVE_LSETEA */
-
-/* Define to 1 if you have the `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* Define to 1 if you have the `lstat' function. */
-#define HAVE_LSTAT 1
-
-/* Define to 1 if `lstat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the `lutimes' function. */
-#define HAVE_LUTIMES 1
-
-/* Define to 1 if you have the <lz4hc.h> header file. */
-/* #undef HAVE_LZ4HC_H */
-
-/* Define to 1 if you have the <lz4.h> header file. */
-/* #undef HAVE_LZ4_H */
-
-/* Define to 1 if you have the `LZMA_FILTER_ARM64' macro. */
-/* #undef HAVE_LZMA_FILTER_ARM64 */
-
-/* Define to 1 if you have the <lzma.h> header file. */
-/* #undef HAVE_LZMA_H */
-
-/* Define to 1 if you have the `lzma_stream_encoder_mt' function. */
-/* #undef HAVE_LZMA_STREAM_ENCODER_MT */
-
-/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
-/* #undef HAVE_LZO_LZO1X_H */
-
-/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
-/* #undef HAVE_LZO_LZOCONF_H */
-
-/* Define to 1 if you have the <mbedtls/aes.h> header file. */
-/* #undef HAVE_MBEDTLS_AES_H */
-
-/* Define to 1 if you have the <mbedtls/md.h> header file. */
-/* #undef HAVE_MBEDTLS_MD_H */
-
-/* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
-/* #undef HAVE_MBEDTLS_PKCS5_H */
-
-/* Define to 1 if you have the `mbrtowc' function. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the `mbr_gid_to_uuid' function. */
-/* #undef HAVE_MBR_GID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uid_to_uuid' function. */
-/* #undef HAVE_MBR_UID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uuid_to_id' function. */
-/* #undef HAVE_MBR_UUID_TO_ID */
-
-/* Define to 1 if you have the <md5.h> header file. */
-
-/* Define to 1 if you have the <membership.h> header file. */
-/* #undef HAVE_MEMBERSHIP_H */
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have the <minix/config.h> header file. */
-/* #undef HAVE_MINIX_CONFIG_H */
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have the `mkfifo' function. */
-#define HAVE_MKFIFO 1
-
-/* Define to 1 if you have the `mknod' function. */
-#define HAVE_MKNOD 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the <nettle/aes.h> header file. */
-/* #undef HAVE_NETTLE_AES_H */
-
-/* Define to 1 if you have the <nettle/hmac.h> header file. */
-/* #undef HAVE_NETTLE_HMAC_H */
-
-/* Define to 1 if you have the <nettle/md5.h> header file. */
-/* #undef HAVE_NETTLE_MD5_H */
-
-/* Define to 1 if you have the <nettle/pbkdf2.h> header file. */
-/* #undef HAVE_NETTLE_PBKDF2_H */
-
-/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
-/* #undef HAVE_NETTLE_RIPEMD160_H */
-
-/* Define to 1 if you have the <nettle/sha.h> header file. */
-/* #undef HAVE_NETTLE_SHA_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the `openat' function. */
-#define HAVE_OPENAT 1
-
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-/* #undef HAVE_OPENSSL_EVP_H */
-
-/* Define to 1 if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
-/* Define to 1 if you have the <pcreposix.h> header file. */
-/* #undef HAVE_PCREPOSIX_H */
-
-/* Define to 1 if you have the `pipe' function. */
-#define HAVE_PIPE 1
-
-/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */
-/* #undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `posix_spawnp' function. */
-#define HAVE_POSIX_SPAWNP 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have a POSIX compatible readdir_r */
-#define HAVE_READDIR_R 1
-
-/* Define to 1 if you have the `readlink' function. */
-#define HAVE_READLINK 1
-
-/* Define to 1 if you have the `readlinkat' function. */
-#define HAVE_READLINKAT 1
-
-/* Define to 1 if you have the `readpassphrase' function. */
-#define HAVE_READPASSPHRASE 1
-
-/* Define to 1 if you have the <readpassphrase.h> header file. */
-#define HAVE_READPASSPHRASE_H 1
-
-/* Define to 1 if you have the <regex.h> header file. */
-/* #undef HAVE_REGEX_H */
-
-/* Define to 1 if you have the `richacl_alloc' function. */
-/* #undef HAVE_RICHACL_ALLOC */
-
-/* Define to 1 if you have the `richacl_equiv_mode' function. */
-/* #undef HAVE_RICHACL_EQUIV_MODE */
-
-/* Define to 1 if you have the `richacl_free' function. */
-/* #undef HAVE_RICHACL_FREE */
-
-/* Define to 1 if you have the `richacl_get_fd' function. */
-/* #undef HAVE_RICHACL_GET_FD */
-
-/* Define to 1 if you have the `richacl_get_file' function. */
-/* #undef HAVE_RICHACL_GET_FILE */
-
-/* Define to 1 if you have the `richacl_set_fd' function. */
-/* #undef HAVE_RICHACL_SET_FD */
-
-/* Define to 1 if you have the `richacl_set_file' function. */
-/* #undef HAVE_RICHACL_SET_FILE */
-
-/* Define to 1 if you have the <ripemd.h> header file. */
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 1
-
-/* Define to 1 if you have the `setxattr' function. */
-/* #undef HAVE_SETXATTR */
-
-/* Define to 1 if you have the <sha256.h> header file. */
-
-/* Define to 1 if you have the <sha512.h> header file. */
-
-/* Define to 1 if you have the <sha.h> header file. */
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the <spawn.h> header file. */
-#define HAVE_SPAWN_H 1
-
-/* Define to 1 if you have the `statfs' function. */
-#define HAVE_STATFS 1
-
-/* Define to 1 if you have the `statvfs' function. */
-#define HAVE_STATVFS 1
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strchr' function. */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have `strerror_r'. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `strftime' function. */
-#define HAVE_STRFTIME 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncpy_s' function. */
-/* #undef HAVE_STRNCPY_S */
-
-/* Define to 1 if you have the `strnlen' function. */
-#define HAVE_STRNLEN 1
-
-/* Define to 1 if you have the `strrchr' function. */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if the system has the type `struct richace'. */
-/* #undef HAVE_STRUCT_RICHACE */
-
-/* Define to 1 if the system has the type `struct richacl'. */
-/* #undef HAVE_STRUCT_RICHACL */
-
-/* Define to 1 if the system has the type `struct statfs'. */
-#define HAVE_STRUCT_STATFS 1
-
-/* Define to 1 if `f_iosize' is a member of `struct statfs'. */
-#define HAVE_STRUCT_STATFS_F_IOSIZE 1
-
-/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
-#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
-
-/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
-/* #undef HAVE_STRUCT_STATVFS_F_IOSIZE */
-
-/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
-
-/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
-
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-
-/* Define to 1 if `st_flags' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_FLAGS 1
-
-/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
-
-/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */
-
-/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
-
-/* Define to 1 if `st_umtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_UMTIME */
-
-/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if the system has the type `struct vfsconf'. */
-#define HAVE_STRUCT_VFSCONF 1
-
-/* Define to 1 if the system has the type `struct xvfsconf'. */
-#define HAVE_STRUCT_XVFSCONF 1
-
-/* Define to 1 if you have the `symlink' function. */
-#define HAVE_SYMLINK 1
-
-/* Define to 1 if you have the <sys/acl.h> header file. */
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/ea.h> header file. */
-/* #undef HAVE_SYS_EA_H */
-
-/* Define to 1 if you have the <sys/extattr.h> header file. */
-#define HAVE_SYS_EXTATTR_H 1
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/mkdev.h> header file. */
-/* #undef HAVE_SYS_MKDEV_H */
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-#define HAVE_SYS_MOUNT_H 1
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/queue.h> header file. */
-#define HAVE_SYS_QUEUE_H 1
-
-/* Define to 1 if you have the <sys/richacl.h> header file. */
-/* #undef HAVE_SYS_RICHACL_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/statfs.h> header file. */
-/* #undef HAVE_SYS_STATFS_H */
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-#define HAVE_SYS_STATVFS_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-/* #undef HAVE_SYS_SYSMACROS_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/utime.h> header file. */
-/* #undef HAVE_SYS_UTIME_H */
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#define HAVE_SYS_UTSNAME_H 1
-
-/* Define to 1 if you have the <sys/vfs.h> header file. */
-/* #undef HAVE_SYS_VFS_H */
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the <sys/xattr.h> header file. */
-/* #undef HAVE_SYS_XATTR_H */
-
-/* Define to 1 if you have the `timegm' function. */
-#define HAVE_TIMEGM 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the `tzset' function. */
-#define HAVE_TZSET 1
-
-/* Define to 1 if the system has the type `uintmax_t'. */
-#define HAVE_UINTMAX_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `unlinkat' function. */
-#define HAVE_UNLINKAT 1
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if the system has the type `unsigned long long'. */
-#define HAVE_UNSIGNED_LONG_LONG 1
-
-/* Define to 1 if the system has the type `unsigned long long int'. */
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimensat' function. */
-#define HAVE_UTIMENSAT 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the <utime.h> header file. */
-#define HAVE_UTIME_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-#define HAVE_VFORK 1
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the `wcrtomb' function. */
-#define HAVE_WCRTOMB 1
-
-/* Define to 1 if you have the `wcscmp' function. */
-#define HAVE_WCSCMP 1
-
-/* Define to 1 if you have the `wcscpy' function. */
-#define HAVE_WCSCPY 1
-
-/* Define to 1 if you have the `wcslen' function. */
-#define HAVE_WCSLEN 1
-
-/* Define to 1 if you have the `wctomb' function. */
-#define HAVE_WCTOMB 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define to 1 if you have the <wincrypt.h> header file. */
-/* #undef HAVE_WINCRYPT_H */
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winioctl.h> header file. */
-/* #undef HAVE_WINIOCTL_H */
-
-/* Define to 1 if you have the `wmemcmp' function. */
-#define HAVE_WMEMCMP 1
-
-/* Define to 1 if you have the `wmemcpy' function. */
-#define HAVE_WMEMCPY 1
-
-/* Define to 1 if you have the `wmemmove' function. */
-#define HAVE_WMEMMOVE 1
-
-/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_EXT2_IOC_GETFLAGS */
-
-/* Define to 1 if you have a working FS_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_FS_IOC_GETFLAGS */
-
-/* Define to 1 if you have the <zlib.h> header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Define to 1 if you have the <zstd.h> header file. */
-/* #undef HAVE_ZSTD_H */
-
-/* Define to 1 if you have the `_fseeki64' function. */
-/* #undef HAVE__FSEEKI64 */
-
-/* Define to 1 if you have the `_get_timezone' function. */
-/* #undef HAVE__GET_TIMEZONE */
-
-/* _mkgmtime function */
-/* #undef HAVE__MKGMTIME */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #undef ICONV_CONST */
-
-/* Version number of libarchive as a single integer */
-#define LIBARCHIVE_VERSION_NUMBER "3007001"
-
-/* Version number of libarchive */
-#define LIBARCHIVE_VERSION_STRING "3.7.1"
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
-   slash. */
-#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
-   */
-/* #undef MAJOR_IN_MKDEV */
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in
-   <sysmacros.h>. */
-/* #undef MAJOR_IN_SYSMACROS */
-
-/* Define to '0x05020000' for Windows Server 2003 APIs. */
-/* #undef NTDDI_VERSION */
-
-/* Name of package */
-#define PACKAGE "libarchive"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "libarchive-discuss@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libarchive"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libarchive 3.7.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libarchive"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.7.1"
-
-/* Define to 1 if PCRE_STATIC needs to be defined. */
-/* #undef PCRE_STATIC */
-
-/* The number of bytes in type int */
-#define SIZEOF_INT 4
-
-/* The number of bytes in type long */
-#define SIZEOF_LONG 8
-
-/* The size of `wchar_t', as computed by sizeof. */
-#define SIZEOF_WCHAR_T 4
-
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
-   required in a freestanding environment). This macro is provided for
-   backward compatibility; new code need not use it. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r returns char *. */
-/* #undef STRERROR_R_CHAR_P */
-
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable general extensions on macOS.  */
-#ifndef _DARWIN_C_SOURCE
-# define _DARWIN_C_SOURCE 1
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable X/Open compliant socket functions that do not require linking
-   with -lxnet on HP-UX 11.11.  */
-#ifndef _HPUX_ALT_XOPEN_SOCKET_API
-# define _HPUX_ALT_XOPEN_SOCKET_API 1
-#endif
-/* Identify the host operating system as Minix.
-   This macro does not affect the system headers' behavior.
-   A future release of Autoconf may stop defining this macro.  */
-#ifndef _MINIX
-/* # undef _MINIX */
-#endif
-/* Enable general extensions on NetBSD.
-   Enable NetBSD compatibility extensions on Minix.  */
-#ifndef _NETBSD_SOURCE
-# define _NETBSD_SOURCE 1
-#endif
-/* Enable OpenBSD compatibility extensions on NetBSD.
-   Oddly enough, this does nothing on OpenBSD.  */
-#ifndef _OPENBSD_SOURCE
-# define _OPENBSD_SOURCE 1
-#endif
-/* Define to 1 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_SOURCE
-/* # undef _POSIX_SOURCE */
-#endif
-/* Define to 2 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_1_SOURCE
-/* # undef _POSIX_1_SOURCE */
-#endif
-/* Enable POSIX-compatible threading on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
-#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
-# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
-#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
-# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
-#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
-# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
-#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
-# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
-#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
-# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
-#ifndef __STDC_WANT_LIB_EXT2__
-# define __STDC_WANT_LIB_EXT2__ 1
-#endif
-/* Enable extensions specified by ISO/IEC 24747:2009.  */
-#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
-# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable X/Open extensions.  Define to 500 only if necessary
-   to make mbstate_t available.  */
-#ifndef _XOPEN_SOURCE
-/* # undef _XOPEN_SOURCE */
-#endif
-
-
-/* Version number of package */
-#define VERSION "3.7.1"
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef WINVER */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT32_T */
-
-/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT64_T */
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT8_T */
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef _WIN32_WINNT */
-
-/* Internal macro for sanity checks */
-#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef gid_t */
-
-/* Define to `unsigned long' if <sys/types.h> does not define. */
-/* #undef id_t */
-
-/* Define to the type of a signed integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int16_t */
-
-/* Define to the type of a signed integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int32_t */
-
-/* Define to the type of a signed integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int64_t */
-
-/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
-   not define. */
-/* #undef intmax_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
-
-/* Define to `long long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef uid_t */
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint16_t */
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint32_t */
-
-/* Define to the type of an unsigned integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint64_t */
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint8_t */
-
-/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
-   do not define. */
-/* #undef uintmax_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef uintptr_t */
-#define HAVE_LIBZ 1
-#define HAVE_ZLIB_H 1
diff --git a/c/autoconf-linux/config.h b/c/autoconf-linux/config.h
deleted file mode 100644
--- a/c/autoconf-linux/config.h
+++ /dev/null
@@ -1,1520 +0,0 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Darwin ACL support */
-/* #undef ARCHIVE_ACL_DARWIN */
-
-/* FreeBSD ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD */
-
-/* FreeBSD NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD_NFS4 */
-
-/* Linux POSIX.1e ACL support via libacl */
-/* #undef ARCHIVE_ACL_LIBACL */
-
-/* Linux NFSv4 ACL support via librichacl */
-/* #undef ARCHIVE_ACL_LIBRICHACL */
-
-/* Solaris ACL support */
-/* #undef ARCHIVE_ACL_SUNOS */
-
-/* Solaris NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_SUNOS_NFS4 */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBC */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBMD */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_MBEDTLS */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_OPENSSL */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_WIN */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBC */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBMD */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_MBEDTLS */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_NETTLE */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBMD */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_MBEDTLS */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_WIN */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC2 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBMD */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_MBEDTLS */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_OPENSSL */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_WIN */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC2 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_MBEDTLS */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_OPENSSL */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_WIN */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC2 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBMD */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_MBEDTLS */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_OPENSSL */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_WIN */
-
-/* AIX xattr support */
-/* #undef ARCHIVE_XATTR_AIX */
-
-/* Darwin xattr support */
-/* #undef ARCHIVE_XATTR_DARWIN */
-
-/* FreeBSD xattr support */
-/* #undef ARCHIVE_XATTR_FREEBSD */
-
-/* Linux xattr support */
-/* #undef ARCHIVE_XATTR_LINUX */
-
-/* Version number of bsdcat */
-#define BSDCAT_VERSION_STRING "3.7.1"
-
-/* Version number of bsdcpio */
-#define BSDCPIO_VERSION_STRING "3.7.1"
-
-/* Version number of bsdtar */
-#define BSDTAR_VERSION_STRING "3.7.1"
-
-/* Define to 1 if the system has the type `ace_t'. */
-/* #undef HAVE_ACE_T */
-
-/* Define to 1 if you have the `acl' function. */
-/* #undef HAVE_ACL */
-
-/* Define to 1 if the system has the type `aclent_t'. */
-/* #undef HAVE_ACLENT_T */
-
-/* Define to 1 if you have the `acl_add_flag_np' function. */
-/* #undef HAVE_ACL_ADD_FLAG_NP */
-
-/* Define to 1 if you have the `acl_add_perm' function. */
-/* #undef HAVE_ACL_ADD_PERM */
-
-/* Define to 1 if you have the `acl_clear_flags_np' function. */
-/* #undef HAVE_ACL_CLEAR_FLAGS_NP */
-
-/* Define to 1 if you have the `acl_clear_perms' function. */
-/* #undef HAVE_ACL_CLEAR_PERMS */
-
-/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
-
-/* Define to 1 if you have the `acl_delete_def_file' function. */
-/* #undef HAVE_ACL_DELETE_DEF_FILE */
-
-/* Define to 1 if the system has the type `acl_entry_t'. */
-/* #undef HAVE_ACL_ENTRY_T */
-
-/* Define to 1 if you have the `acl_free' function. */
-/* #undef HAVE_ACL_FREE */
-
-/* Define to 1 if you have the `acl_get_brand_np' function. */
-/* #undef HAVE_ACL_GET_BRAND_NP */
-
-/* Define to 1 if you have the `acl_get_entry' function. */
-/* #undef HAVE_ACL_GET_ENTRY */
-
-/* Define to 1 if you have the `acl_get_entry_type_np' function. */
-/* #undef HAVE_ACL_GET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_get_fd' function. */
-/* #undef HAVE_ACL_GET_FD */
-
-/* Define to 1 if you have the `acl_get_fd_np' function. */
-/* #undef HAVE_ACL_GET_FD_NP */
-
-/* Define to 1 if you have the `acl_get_file' function. */
-/* #undef HAVE_ACL_GET_FILE */
-
-/* Define to 1 if you have the `acl_get_flagset_np' function. */
-/* #undef HAVE_ACL_GET_FLAGSET_NP */
-
-/* Define to 1 if you have the `acl_get_flag_np' function. */
-/* #undef HAVE_ACL_GET_FLAG_NP */
-
-/* Define to 1 if you have the `acl_get_link_np' function. */
-/* #undef HAVE_ACL_GET_LINK_NP */
-
-/* Define to 1 if you have the `acl_get_perm' function. */
-/* #undef HAVE_ACL_GET_PERM */
-
-/* Define to 1 if you have the `acl_get_permset' function. */
-/* #undef HAVE_ACL_GET_PERMSET */
-
-/* Define to 1 if you have the `acl_get_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
-
-/* Define to 1 if you have the `acl_get_qualifier' function. */
-/* #undef HAVE_ACL_GET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_get_tag_type' function. */
-/* #undef HAVE_ACL_GET_TAG_TYPE */
-
-/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
-
-/* Define to 1 if you have the `acl_is_trivial_np' function. */
-/* #undef HAVE_ACL_IS_TRIVIAL_NP */
-
-/* Define to 1 if you have the <acl/libacl.h> header file. */
-/* #undef HAVE_ACL_LIBACL_H */
-
-/* Define to 1 if the system has the type `acl_permset_t'. */
-/* #undef HAVE_ACL_PERMSET_T */
-
-/* Define to 1 if you have the `acl_set_entry_type_np' function. */
-/* #undef HAVE_ACL_SET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_set_fd' function. */
-/* #undef HAVE_ACL_SET_FD */
-
-/* Define to 1 if you have the `acl_set_fd_np' function. */
-/* #undef HAVE_ACL_SET_FD_NP */
-
-/* Define to 1 if you have the `acl_set_file' function. */
-/* #undef HAVE_ACL_SET_FILE */
-
-/* Define to 1 if you have the `acl_set_link_np' function. */
-/* #undef HAVE_ACL_SET_LINK_NP */
-
-/* Define to 1 if you have the `acl_set_qualifier' function. */
-/* #undef HAVE_ACL_SET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_set_tag_type' function. */
-/* #undef HAVE_ACL_SET_TAG_TYPE */
-
-/* Define to 1 if the system has the type `acl_t'. */
-/* #undef HAVE_ACL_T */
-
-/* Define to 1 if the system has the type `acl_tag_t'. */
-/* #undef HAVE_ACL_TAG_T */
-
-/* Define to 1 if you have the `arc4random_buf' function. */
-/* #undef HAVE_ARC4RANDOM_BUF */
-
-/* Define to 1 if you have the <attr/xattr.h> header file. */
-/* #undef HAVE_ATTR_XATTR_H */
-
-/* Define to 1 if you have the <bcrypt.h> header file. */
-/* #undef HAVE_BCRYPT_H */
-
-/* Define to 1 if you have the <blake2.h> header file. */
-/* #undef HAVE_BLAKE2_H */
-
-/* Define to 1 if you have the <bzlib.h> header file. */
-/* #undef HAVE_BZLIB_H */
-
-/* Define to 1 if you have the `chflags' function. */
-/* #undef HAVE_CHFLAGS */
-
-/* Define to 1 if you have the `chown' function. */
-#define HAVE_CHOWN 1
-
-/* Define to 1 if you have the `chroot' function. */
-#define HAVE_CHROOT 1
-
-/* cmtime_s function */
-/* #undef HAVE_CMTIME_S */
-
-/* Define to 1 if you have the <copyfile.h> header file. */
-/* #undef HAVE_COPYFILE_H */
-
-/* Define to 1 if you have the `ctime_r' function. */
-#define HAVE_CTIME_R 1
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the `cygwin_conv_path' function. */
-/* #undef HAVE_CYGWIN_CONV_PATH */
-
-/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACL */
-
-/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_SETACL */
-
-/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_SYNCHRONIZE */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_TYPE_EXTENDED */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_TYPE_NFS4 */
-
-/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_USER */
-
-/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to
-   0 if you don't. */
-/* #undef HAVE_DECL_EXTATTR_NAMESPACE_USER */
-
-/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_GETACL */
-
-/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MAX 1
-
-/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MIN 1
-
-/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MAX 1
-
-/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MIN 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MIN 1
-
-/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_SETACL */
-
-/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SSIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
-   don't. */
-#define HAVE_DECL_STRERROR_R 1
-
-/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT32_MAX 1
-
-/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT64_MAX 1
-
-/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_XATTR_NOFOLLOW */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
-   */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have a dirfd function or macro */
-#define HAVE_DIRFD 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if nl_langinfo supports D_MD_ORDER */
-/* #undef HAVE_D_MD_ORDER */
-
-/* A possible errno value for invalid file format errors */
-/* #undef HAVE_EFTYPE */
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EILSEQ 1
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <expat.h> header file. */
-/* #undef HAVE_EXPAT_H */
-
-/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
-
-/* Define to 1 if you have the `extattr_get_fd' function. */
-/* #undef HAVE_EXTATTR_GET_FD */
-
-/* Define to 1 if you have the `extattr_get_file' function. */
-/* #undef HAVE_EXTATTR_GET_FILE */
-
-/* Define to 1 if you have the `extattr_get_link' function. */
-/* #undef HAVE_EXTATTR_GET_LINK */
-
-/* Define to 1 if you have the `extattr_list_fd' function. */
-/* #undef HAVE_EXTATTR_LIST_FD */
-
-/* Define to 1 if you have the `extattr_list_file' function. */
-/* #undef HAVE_EXTATTR_LIST_FILE */
-
-/* Define to 1 if you have the `extattr_list_link' function. */
-/* #undef HAVE_EXTATTR_LIST_LINK */
-
-/* Define to 1 if you have the `extattr_set_fd' function. */
-/* #undef HAVE_EXTATTR_SET_FD */
-
-/* Define to 1 if you have the `extattr_set_link' function. */
-/* #undef HAVE_EXTATTR_SET_LINK */
-
-/* Define to 1 if you have the `facl' function. */
-/* #undef HAVE_FACL */
-
-/* Define to 1 if you have the `fchdir' function. */
-#define HAVE_FCHDIR 1
-
-/* Define to 1 if you have the `fchflags' function. */
-/* #undef HAVE_FCHFLAGS */
-
-/* Define to 1 if you have the `fchmod' function. */
-#define HAVE_FCHMOD 1
-
-/* Define to 1 if you have the `fchown' function. */
-#define HAVE_FCHOWN 1
-
-/* Define to 1 if you have the `fcntl' function. */
-#define HAVE_FCNTL 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdopendir' function. */
-#define HAVE_FDOPENDIR 1
-
-/* Define to 1 if you have the `fgetea' function. */
-/* #undef HAVE_FGETEA */
-
-/* Define to 1 if you have the `fgetxattr' function. */
-/* #undef HAVE_FGETXATTR */
-
-/* Define to 1 if you have the `flistea' function. */
-/* #undef HAVE_FLISTEA */
-
-/* Define to 1 if you have the `flistxattr' function. */
-/* #undef HAVE_FLISTXATTR */
-
-/* Define to 1 if you have the `fnmatch' function. */
-#define HAVE_FNMATCH 1
-
-/* Define to 1 if you have the <fnmatch.h> header file. */
-#define HAVE_FNMATCH_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if you have the `fsetea' function. */
-/* #undef HAVE_FSETEA */
-
-/* Define to 1 if you have the `fsetxattr' function. */
-/* #undef HAVE_FSETXATTR */
-
-/* Define to 1 if you have the `fstat' function. */
-#define HAVE_FSTAT 1
-
-/* Define to 1 if you have the `fstatat' function. */
-#define HAVE_FSTATAT 1
-
-/* Define to 1 if you have the `fstatfs' function. */
-#define HAVE_FSTATFS 1
-
-/* Define to 1 if you have the `fstatvfs' function. */
-#define HAVE_FSTATVFS 1
-
-/* Define to 1 if you have the `ftruncate' function. */
-#define HAVE_FTRUNCATE 1
-
-/* Define to 1 if you have the `futimens' function. */
-#define HAVE_FUTIMENS 1
-
-/* Define to 1 if you have the `futimes' function. */
-#define HAVE_FUTIMES 1
-
-/* Define to 1 if you have the `futimesat' function. */
-#define HAVE_FUTIMESAT 1
-
-/* Define to 1 if you have the `getea' function. */
-/* #undef HAVE_GETEA */
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `getline' function. */
-#define HAVE_GETLINE 1
-
-/* Platform uses optreset to reset getopt */
-/* #undef HAVE_GETOPT_OPTRESET */
-
-/* Define to 1 if you have the `getpid' function. */
-#define HAVE_GETPID 1
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getvfsbyname' function. */
-/* #undef HAVE_GETVFSBYNAME */
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* gmtime_s function */
-/* #undef HAVE_GMTIME_S */
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if you have the iconv() function and it works. */
-/* #undef HAVE_ICONV */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-/* #undef HAVE_ICONV_H */
-
-/* Define to 1 if the system has the type `intmax_t'. */
-#define HAVE_INTMAX_T 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the `lchflags' function. */
-/* #undef HAVE_LCHFLAGS */
-
-/* Define to 1 if you have the `lchmod' function. */
-#define HAVE_LCHMOD 1
-
-/* Define to 1 if you have the `lchown' function. */
-#define HAVE_LCHOWN 1
-
-/* Define to 1 if you have the `lgetea' function. */
-/* #undef HAVE_LGETEA */
-
-/* Define to 1 if you have the `lgetxattr' function. */
-/* #undef HAVE_LGETXATTR */
-
-/* Define to 1 if you have the `acl' library (-lacl). */
-/* #undef HAVE_LIBACL */
-
-/* Define to 1 if you have the `b2' library (-lb2). */
-/* #undef HAVE_LIBB2 */
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-/* #undef HAVE_LIBBZ2 */
-
-/* Define to 1 if you have the `charset' library (-lcharset). */
-/* #undef HAVE_LIBCHARSET */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-/* #undef HAVE_LIBCRYPTO */
-
-/* Define to 1 if you have the `expat' library (-lexpat). */
-/* #undef HAVE_LIBEXPAT */
-
-/* Define to 1 if you have the `lz4' library (-llz4). */
-/* #undef HAVE_LIBLZ4 */
-
-/* Define to 1 if you have the `lzma' library (-llzma). */
-/* #undef HAVE_LIBLZMA */
-
-/* Define to 1 if you have the `lzo2' library (-llzo2). */
-/* #undef HAVE_LIBLZO2 */
-
-/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */
-/* #undef HAVE_LIBMBEDCRYPTO */
-
-/* Define to 1 if you have the `md' library (-lmd). */
-/* #undef HAVE_LIBMD */
-
-/* Define to 1 if you have the `nettle' library (-lnettle). */
-/* #undef HAVE_LIBNETTLE */
-
-/* Define to 1 if you have the `pcre' library (-lpcre). */
-/* #undef HAVE_LIBPCRE */
-
-/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
-/* #undef HAVE_LIBPCREPOSIX */
-
-/* Define to 1 if you have the `regex' library (-lregex). */
-/* #undef HAVE_LIBREGEX */
-
-/* Define to 1 if you have the `richacl' library (-lrichacl). */
-/* #undef HAVE_LIBRICHACL */
-
-/* Define to 1 if you have the `xml2' library (-lxml2). */
-/* #undef HAVE_LIBXML2 */
-
-/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
-/* #undef HAVE_LIBXML_XMLREADER_H */
-
-/* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
-/* #undef HAVE_LIBXML_XMLWRITER_H */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if you have the `zstd' library (-lzstd). */
-/* #undef HAVE_LIBZSTD */
-
-/* Define to 1 if you have the `zstd' library (-lzstd) with compression
-   support. */
-/* #undef HAVE_LIBZSTD_COMPRESSOR */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `link' function. */
-#define HAVE_LINK 1
-
-/* Define to 1 if you have the `linkat' function. */
-#define HAVE_LINKAT 1
-
-/* Define to 1 if you have the <linux/fiemap.h> header file. */
-#define HAVE_LINUX_FIEMAP_H 1
-
-/* Define to 1 if you have the <linux/fs.h> header file. */
-#define HAVE_LINUX_FS_H 1
-
-/* Define to 1 if you have the <linux/magic.h> header file. */
-#define HAVE_LINUX_MAGIC_H 1
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-#define HAVE_LINUX_TYPES_H 1
-
-/* Define to 1 if you have the `listea' function. */
-/* #undef HAVE_LISTEA */
-
-/* Define to 1 if you have the `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistea' function. */
-/* #undef HAVE_LLISTEA */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if you have the <localcharset.h> header file. */
-/* #undef HAVE_LOCALCHARSET_H */
-
-/* Define to 1 if you have the `locale_charset' function. */
-/* #undef HAVE_LOCALE_CHARSET */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* localtime_s function */
-/* #undef HAVE_LOCALTIME_S */
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `lsetea' function. */
-/* #undef HAVE_LSETEA */
-
-/* Define to 1 if you have the `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* Define to 1 if you have the `lstat' function. */
-#define HAVE_LSTAT 1
-
-/* Define to 1 if `lstat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the `lutimes' function. */
-#define HAVE_LUTIMES 1
-
-/* Define to 1 if you have the <lz4hc.h> header file. */
-/* #undef HAVE_LZ4HC_H */
-
-/* Define to 1 if you have the <lz4.h> header file. */
-/* #undef HAVE_LZ4_H */
-
-/* Define to 1 if you have the `LZMA_FILTER_ARM64' macro. */
-/* #undef HAVE_LZMA_FILTER_ARM64 */
-
-/* Define to 1 if you have the <lzma.h> header file. */
-/* #undef HAVE_LZMA_H */
-
-/* Define to 1 if you have the `lzma_stream_encoder_mt' function. */
-/* #undef HAVE_LZMA_STREAM_ENCODER_MT */
-
-/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
-/* #undef HAVE_LZO_LZO1X_H */
-
-/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
-/* #undef HAVE_LZO_LZOCONF_H */
-
-/* Define to 1 if you have the <mbedtls/aes.h> header file. */
-/* #undef HAVE_MBEDTLS_AES_H */
-
-/* Define to 1 if you have the <mbedtls/md.h> header file. */
-/* #undef HAVE_MBEDTLS_MD_H */
-
-/* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
-/* #undef HAVE_MBEDTLS_PKCS5_H */
-
-/* Define to 1 if you have the `mbrtowc' function. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the `mbr_gid_to_uuid' function. */
-/* #undef HAVE_MBR_GID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uid_to_uuid' function. */
-/* #undef HAVE_MBR_UID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uuid_to_id' function. */
-/* #undef HAVE_MBR_UUID_TO_ID */
-
-/* Define to 1 if you have the <md5.h> header file. */
-/* #undef HAVE_MD5_H */
-
-/* Define to 1 if you have the <membership.h> header file. */
-/* #undef HAVE_MEMBERSHIP_H */
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have the <minix/config.h> header file. */
-/* #undef HAVE_MINIX_CONFIG_H */
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have the `mkfifo' function. */
-#define HAVE_MKFIFO 1
-
-/* Define to 1 if you have the `mknod' function. */
-#define HAVE_MKNOD 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the <nettle/aes.h> header file. */
-/* #undef HAVE_NETTLE_AES_H */
-
-/* Define to 1 if you have the <nettle/hmac.h> header file. */
-/* #undef HAVE_NETTLE_HMAC_H */
-
-/* Define to 1 if you have the <nettle/md5.h> header file. */
-/* #undef HAVE_NETTLE_MD5_H */
-
-/* Define to 1 if you have the <nettle/pbkdf2.h> header file. */
-/* #undef HAVE_NETTLE_PBKDF2_H */
-
-/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
-/* #undef HAVE_NETTLE_RIPEMD160_H */
-
-/* Define to 1 if you have the <nettle/sha.h> header file. */
-/* #undef HAVE_NETTLE_SHA_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the `openat' function. */
-#define HAVE_OPENAT 1
-
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-/* #undef HAVE_OPENSSL_EVP_H */
-
-/* Define to 1 if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
-/* Define to 1 if you have the <pcreposix.h> header file. */
-/* #undef HAVE_PCREPOSIX_H */
-
-/* Define to 1 if you have the `pipe' function. */
-#define HAVE_PIPE 1
-
-/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */
-/* #undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `posix_spawnp' function. */
-#define HAVE_POSIX_SPAWNP 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have a POSIX compatible readdir_r */
-#define HAVE_READDIR_R 1
-
-/* Define to 1 if you have the `readlink' function. */
-#define HAVE_READLINK 1
-
-/* Define to 1 if you have the `readlinkat' function. */
-#define HAVE_READLINKAT 1
-
-/* Define to 1 if you have the `readpassphrase' function. */
-/* #undef HAVE_READPASSPHRASE */
-
-/* Define to 1 if you have the <readpassphrase.h> header file. */
-/* #undef HAVE_READPASSPHRASE_H */
-
-/* Define to 1 if you have the <regex.h> header file. */
-/* #undef HAVE_REGEX_H */
-
-/* Define to 1 if you have the `richacl_alloc' function. */
-/* #undef HAVE_RICHACL_ALLOC */
-
-/* Define to 1 if you have the `richacl_equiv_mode' function. */
-/* #undef HAVE_RICHACL_EQUIV_MODE */
-
-/* Define to 1 if you have the `richacl_free' function. */
-/* #undef HAVE_RICHACL_FREE */
-
-/* Define to 1 if you have the `richacl_get_fd' function. */
-/* #undef HAVE_RICHACL_GET_FD */
-
-/* Define to 1 if you have the `richacl_get_file' function. */
-/* #undef HAVE_RICHACL_GET_FILE */
-
-/* Define to 1 if you have the `richacl_set_fd' function. */
-/* #undef HAVE_RICHACL_SET_FD */
-
-/* Define to 1 if you have the `richacl_set_file' function. */
-/* #undef HAVE_RICHACL_SET_FILE */
-
-/* Define to 1 if you have the <ripemd.h> header file. */
-/* #undef HAVE_RIPEMD_H */
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 1
-
-/* Define to 1 if you have the `setxattr' function. */
-/* #undef HAVE_SETXATTR */
-
-/* Define to 1 if you have the <sha256.h> header file. */
-/* #undef HAVE_SHA256_H */
-
-/* Define to 1 if you have the <sha512.h> header file. */
-/* #undef HAVE_SHA512_H */
-
-/* Define to 1 if you have the <sha.h> header file. */
-/* #undef HAVE_SHA_H */
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the <spawn.h> header file. */
-#define HAVE_SPAWN_H 1
-
-/* Define to 1 if you have the `statfs' function. */
-#define HAVE_STATFS 1
-
-/* Define to 1 if you have the `statvfs' function. */
-#define HAVE_STATVFS 1
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strchr' function. */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have `strerror_r'. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `strftime' function. */
-#define HAVE_STRFTIME 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncpy_s' function. */
-/* #undef HAVE_STRNCPY_S */
-
-/* Define to 1 if you have the `strnlen' function. */
-#define HAVE_STRNLEN 1
-
-/* Define to 1 if you have the `strrchr' function. */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if the system has the type `struct richace'. */
-/* #undef HAVE_STRUCT_RICHACE */
-
-/* Define to 1 if the system has the type `struct richacl'. */
-/* #undef HAVE_STRUCT_RICHACL */
-
-/* Define to 1 if the system has the type `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS */
-
-/* Define to 1 if `f_iosize' is a member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_IOSIZE */
-
-/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_NAMEMAX */
-
-/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
-/* #undef HAVE_STRUCT_STATVFS_F_IOSIZE */
-
-/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */
-
-/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC */
-
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-
-/* Define to 1 if `st_flags' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_FLAGS */
-
-/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */
-
-/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */
-
-/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
-
-/* Define to 1 if `st_umtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_UMTIME */
-
-/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if the system has the type `struct vfsconf'. */
-/* #undef HAVE_STRUCT_VFSCONF */
-
-/* Define to 1 if the system has the type `struct xvfsconf'. */
-/* #undef HAVE_STRUCT_XVFSCONF */
-
-/* Define to 1 if you have the `symlink' function. */
-#define HAVE_SYMLINK 1
-
-/* Define to 1 if you have the <sys/acl.h> header file. */
-/* #undef HAVE_SYS_ACL_H */
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/ea.h> header file. */
-/* #undef HAVE_SYS_EA_H */
-
-/* Define to 1 if you have the <sys/extattr.h> header file. */
-/* #undef HAVE_SYS_EXTATTR_H */
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/mkdev.h> header file. */
-/* #undef HAVE_SYS_MKDEV_H */
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-#define HAVE_SYS_MOUNT_H 1
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/queue.h> header file. */
-#define HAVE_SYS_QUEUE_H 1
-
-/* Define to 1 if you have the <sys/richacl.h> header file. */
-/* #undef HAVE_SYS_RICHACL_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/statfs.h> header file. */
-#define HAVE_SYS_STATFS_H 1
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-#define HAVE_SYS_STATVFS_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-#define HAVE_SYS_SYSMACROS_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/utime.h> header file. */
-/* #undef HAVE_SYS_UTIME_H */
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#define HAVE_SYS_UTSNAME_H 1
-
-/* Define to 1 if you have the <sys/vfs.h> header file. */
-#define HAVE_SYS_VFS_H 1
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the <sys/xattr.h> header file. */
-#define HAVE_SYS_XATTR_H 1
-
-/* Define to 1 if you have the `timegm' function. */
-#define HAVE_TIMEGM 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the `tzset' function. */
-#define HAVE_TZSET 1
-
-/* Define to 1 if the system has the type `uintmax_t'. */
-#define HAVE_UINTMAX_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `unlinkat' function. */
-#define HAVE_UNLINKAT 1
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if the system has the type `unsigned long long'. */
-#define HAVE_UNSIGNED_LONG_LONG 1
-
-/* Define to 1 if the system has the type `unsigned long long int'. */
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimensat' function. */
-#define HAVE_UTIMENSAT 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the <utime.h> header file. */
-#define HAVE_UTIME_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-#define HAVE_VFORK 1
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the `wcrtomb' function. */
-#define HAVE_WCRTOMB 1
-
-/* Define to 1 if you have the `wcscmp' function. */
-#define HAVE_WCSCMP 1
-
-/* Define to 1 if you have the `wcscpy' function. */
-#define HAVE_WCSCPY 1
-
-/* Define to 1 if you have the `wcslen' function. */
-#define HAVE_WCSLEN 1
-
-/* Define to 1 if you have the `wctomb' function. */
-#define HAVE_WCTOMB 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define to 1 if you have the <wincrypt.h> header file. */
-/* #undef HAVE_WINCRYPT_H */
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winioctl.h> header file. */
-/* #undef HAVE_WINIOCTL_H */
-
-/* Define to 1 if you have the `wmemcmp' function. */
-#define HAVE_WMEMCMP 1
-
-/* Define to 1 if you have the `wmemcpy' function. */
-#define HAVE_WMEMCPY 1
-
-/* Define to 1 if you have the `wmemmove' function. */
-#define HAVE_WMEMMOVE 1
-
-/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
-#define HAVE_WORKING_EXT2_IOC_GETFLAGS 1
-
-/* Define to 1 if you have a working FS_IOC_GETFLAGS */
-#define HAVE_WORKING_FS_IOC_GETFLAGS 1
-
-/* Define to 1 if you have the <zlib.h> header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Define to 1 if you have the <zstd.h> header file. */
-/* #undef HAVE_ZSTD_H */
-
-/* Define to 1 if you have the `_fseeki64' function. */
-/* #undef HAVE__FSEEKI64 */
-
-/* Define to 1 if you have the `_get_timezone' function. */
-/* #undef HAVE__GET_TIMEZONE */
-
-/* _mkgmtime function */
-/* #undef HAVE__MKGMTIME */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #undef ICONV_CONST */
-
-/* Version number of libarchive as a single integer */
-#define LIBARCHIVE_VERSION_NUMBER "3007001"
-
-/* Version number of libarchive */
-#define LIBARCHIVE_VERSION_STRING "3.7.1"
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
-   slash. */
-#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
-   */
-/* #undef MAJOR_IN_MKDEV */
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in
-   <sysmacros.h>. */
-#define MAJOR_IN_SYSMACROS 1
-
-/* Define to '0x05020000' for Windows Server 2003 APIs. */
-/* #undef NTDDI_VERSION */
-
-/* Name of package */
-#define PACKAGE "libarchive"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "libarchive-discuss@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libarchive"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libarchive 3.7.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libarchive"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.7.1"
-
-/* Define to 1 if PCRE_STATIC needs to be defined. */
-/* #undef PCRE_STATIC */
-
-/* The number of bytes in type int */
-#define SIZEOF_INT 4
-
-/* The number of bytes in type long */
-#define SIZEOF_LONG 8
-
-/* The size of `wchar_t', as computed by sizeof. */
-#define SIZEOF_WCHAR_T 4
-
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
-   required in a freestanding environment). This macro is provided for
-   backward compatibility; new code need not use it. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r returns char *. */
-#define STRERROR_R_CHAR_P 1
-
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable general extensions on macOS.  */
-#ifndef _DARWIN_C_SOURCE
-# define _DARWIN_C_SOURCE 1
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable X/Open compliant socket functions that do not require linking
-   with -lxnet on HP-UX 11.11.  */
-#ifndef _HPUX_ALT_XOPEN_SOCKET_API
-# define _HPUX_ALT_XOPEN_SOCKET_API 1
-#endif
-/* Identify the host operating system as Minix.
-   This macro does not affect the system headers' behavior.
-   A future release of Autoconf may stop defining this macro.  */
-#ifndef _MINIX
-/* # undef _MINIX */
-#endif
-/* Enable general extensions on NetBSD.
-   Enable NetBSD compatibility extensions on Minix.  */
-#ifndef _NETBSD_SOURCE
-# define _NETBSD_SOURCE 1
-#endif
-/* Enable OpenBSD compatibility extensions on NetBSD.
-   Oddly enough, this does nothing on OpenBSD.  */
-#ifndef _OPENBSD_SOURCE
-# define _OPENBSD_SOURCE 1
-#endif
-/* Define to 1 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_SOURCE
-/* # undef _POSIX_SOURCE */
-#endif
-/* Define to 2 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_1_SOURCE
-/* # undef _POSIX_1_SOURCE */
-#endif
-/* Enable POSIX-compatible threading on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
-#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
-# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
-#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
-# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
-#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
-# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
-#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
-# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
-#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
-# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
-#ifndef __STDC_WANT_LIB_EXT2__
-# define __STDC_WANT_LIB_EXT2__ 1
-#endif
-/* Enable extensions specified by ISO/IEC 24747:2009.  */
-#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
-# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable X/Open extensions.  Define to 500 only if necessary
-   to make mbstate_t available.  */
-#ifndef _XOPEN_SOURCE
-/* # undef _XOPEN_SOURCE */
-#endif
-
-
-/* Version number of package */
-#define VERSION "3.7.1"
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef WINVER */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT32_T */
-
-/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT64_T */
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT8_T */
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-/* #undef _WIN32_WINNT */
-
-/* Internal macro for sanity checks */
-#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef gid_t */
-
-/* Define to `unsigned long' if <sys/types.h> does not define. */
-/* #undef id_t */
-
-/* Define to the type of a signed integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int16_t */
-
-/* Define to the type of a signed integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int32_t */
-
-/* Define to the type of a signed integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int64_t */
-
-/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
-   not define. */
-/* #undef intmax_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
-
-/* Define to `long long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't
-   define. */
-/* #undef uid_t */
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint16_t */
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint32_t */
-
-/* Define to the type of an unsigned integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint64_t */
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint8_t */
-
-/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
-   do not define. */
-/* #undef uintmax_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef uintptr_t */
-#define HAVE_LIBZ 1
-#define HAVE_ZLIB_H 1
diff --git a/c/autoconf-windows/config.h b/c/autoconf-windows/config.h
deleted file mode 100644
--- a/c/autoconf-windows/config.h
+++ /dev/null
@@ -1,1521 +0,0 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Darwin ACL support */
-/* #undef ARCHIVE_ACL_DARWIN */
-
-/* FreeBSD ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD */
-
-/* FreeBSD NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_FREEBSD_NFS4 */
-
-/* Linux POSIX.1e ACL support via libacl */
-/* #undef ARCHIVE_ACL_LIBACL */
-
-/* Linux NFSv4 ACL support via librichacl */
-/* #undef ARCHIVE_ACL_LIBRICHACL */
-
-/* Solaris ACL support */
-/* #undef ARCHIVE_ACL_SUNOS */
-
-/* Solaris NFSv4 ACL support */
-/* #undef ARCHIVE_ACL_SUNOS_NFS4 */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBC */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBMD */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_MBEDTLS */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_MD5_OPENSSL */
-
-/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */
-#define ARCHIVE_CRYPTO_MD5_WIN 1
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBC */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_LIBMD */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_MBEDTLS */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_NETTLE */
-
-/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_RMD160_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBMD */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_MBEDTLS */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA1_OPENSSL */
-
-/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */
-#define ARCHIVE_CRYPTO_SHA1_WIN 1
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC2 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBMD */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_MBEDTLS */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_OPENSSL */
-
-/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA256_WIN */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC2 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_MBEDTLS */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_OPENSSL */
-
-/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA384_WIN */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC2 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBMD supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBMD */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_MBEDTLS supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_MBEDTLS */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_OPENSSL */
-
-/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
-/* #undef ARCHIVE_CRYPTO_SHA512_WIN */
-
-/* AIX xattr support */
-/* #undef ARCHIVE_XATTR_AIX */
-
-/* Darwin xattr support */
-/* #undef ARCHIVE_XATTR_DARWIN */
-
-/* FreeBSD xattr support */
-/* #undef ARCHIVE_XATTR_FREEBSD */
-
-/* Linux xattr support */
-/* #undef ARCHIVE_XATTR_LINUX */
-
-/* Version number of bsdcat */
-#define BSDCAT_VERSION_STRING "3.7.1"
-
-/* Version number of bsdcpio */
-#define BSDCPIO_VERSION_STRING "3.7.1"
-
-/* Version number of bsdtar */
-#define BSDTAR_VERSION_STRING "3.7.1"
-
-/* Define to 1 if the system has the type `ace_t'. */
-/* #undef HAVE_ACE_T */
-
-/* Define to 1 if you have the `acl' function. */
-/* #undef HAVE_ACL */
-
-/* Define to 1 if the system has the type `aclent_t'. */
-/* #undef HAVE_ACLENT_T */
-
-/* Define to 1 if you have the `acl_add_flag_np' function. */
-/* #undef HAVE_ACL_ADD_FLAG_NP */
-
-/* Define to 1 if you have the `acl_add_perm' function. */
-/* #undef HAVE_ACL_ADD_PERM */
-
-/* Define to 1 if you have the `acl_clear_flags_np' function. */
-/* #undef HAVE_ACL_CLEAR_FLAGS_NP */
-
-/* Define to 1 if you have the `acl_clear_perms' function. */
-/* #undef HAVE_ACL_CLEAR_PERMS */
-
-/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
-
-/* Define to 1 if you have the `acl_delete_def_file' function. */
-/* #undef HAVE_ACL_DELETE_DEF_FILE */
-
-/* Define to 1 if the system has the type `acl_entry_t'. */
-/* #undef HAVE_ACL_ENTRY_T */
-
-/* Define to 1 if you have the `acl_free' function. */
-/* #undef HAVE_ACL_FREE */
-
-/* Define to 1 if you have the `acl_get_brand_np' function. */
-/* #undef HAVE_ACL_GET_BRAND_NP */
-
-/* Define to 1 if you have the `acl_get_entry' function. */
-/* #undef HAVE_ACL_GET_ENTRY */
-
-/* Define to 1 if you have the `acl_get_entry_type_np' function. */
-/* #undef HAVE_ACL_GET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_get_fd' function. */
-/* #undef HAVE_ACL_GET_FD */
-
-/* Define to 1 if you have the `acl_get_fd_np' function. */
-/* #undef HAVE_ACL_GET_FD_NP */
-
-/* Define to 1 if you have the `acl_get_file' function. */
-/* #undef HAVE_ACL_GET_FILE */
-
-/* Define to 1 if you have the `acl_get_flagset_np' function. */
-/* #undef HAVE_ACL_GET_FLAGSET_NP */
-
-/* Define to 1 if you have the `acl_get_flag_np' function. */
-/* #undef HAVE_ACL_GET_FLAG_NP */
-
-/* Define to 1 if you have the `acl_get_link_np' function. */
-/* #undef HAVE_ACL_GET_LINK_NP */
-
-/* Define to 1 if you have the `acl_get_perm' function. */
-/* #undef HAVE_ACL_GET_PERM */
-
-/* Define to 1 if you have the `acl_get_permset' function. */
-/* #undef HAVE_ACL_GET_PERMSET */
-
-/* Define to 1 if you have the `acl_get_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
-
-/* Define to 1 if you have the `acl_get_qualifier' function. */
-/* #undef HAVE_ACL_GET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_get_tag_type' function. */
-/* #undef HAVE_ACL_GET_TAG_TYPE */
-
-/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
-
-/* Define to 1 if you have the `acl_is_trivial_np' function. */
-/* #undef HAVE_ACL_IS_TRIVIAL_NP */
-
-/* Define to 1 if you have the <acl/libacl.h> header file. */
-/* #undef HAVE_ACL_LIBACL_H */
-
-/* Define to 1 if the system has the type `acl_permset_t'. */
-/* #undef HAVE_ACL_PERMSET_T */
-
-/* Define to 1 if you have the `acl_set_entry_type_np' function. */
-/* #undef HAVE_ACL_SET_ENTRY_TYPE_NP */
-
-/* Define to 1 if you have the `acl_set_fd' function. */
-/* #undef HAVE_ACL_SET_FD */
-
-/* Define to 1 if you have the `acl_set_fd_np' function. */
-/* #undef HAVE_ACL_SET_FD_NP */
-
-/* Define to 1 if you have the `acl_set_file' function. */
-/* #undef HAVE_ACL_SET_FILE */
-
-/* Define to 1 if you have the `acl_set_link_np' function. */
-/* #undef HAVE_ACL_SET_LINK_NP */
-
-/* Define to 1 if you have the `acl_set_qualifier' function. */
-/* #undef HAVE_ACL_SET_QUALIFIER */
-
-/* Define to 1 if you have the `acl_set_tag_type' function. */
-/* #undef HAVE_ACL_SET_TAG_TYPE */
-
-/* Define to 1 if the system has the type `acl_t'. */
-/* #undef HAVE_ACL_T */
-
-/* Define to 1 if the system has the type `acl_tag_t'. */
-/* #undef HAVE_ACL_TAG_T */
-
-/* Define to 1 if you have the `arc4random_buf' function. */
-/* #undef HAVE_ARC4RANDOM_BUF */
-
-/* Define to 1 if you have the <attr/xattr.h> header file. */
-/* #undef HAVE_ATTR_XATTR_H */
-
-/* Define to 1 if you have the <bcrypt.h> header file. */
-/* #undef HAVE_BCRYPT_H */
-
-/* Define to 1 if you have the <blake2.h> header file. */
-/* #undef HAVE_BLAKE2_H */
-
-/* Define to 1 if you have the <bzlib.h> header file. */
-/* #undef HAVE_BZLIB_H */
-
-/* Define to 1 if you have the `chflags' function. */
-/* #undef HAVE_CHFLAGS */
-
-/* Define to 1 if you have the `chown' function. */
-/* #undef HAVE_CHOWN */
-
-/* Define to 1 if you have the `chroot' function. */
-/* #undef HAVE_CHROOT */
-
-/* cmtime_s function */
-/* #undef HAVE_CMTIME_S */
-
-/* Define to 1 if you have the <copyfile.h> header file. */
-/* #undef HAVE_COPYFILE_H */
-
-/* Define to 1 if you have the `ctime_r' function. */
-/* #undef HAVE_CTIME_R */
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the `cygwin_conv_path' function. */
-/* #undef HAVE_CYGWIN_CONV_PATH */
-
-/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACL */
-
-/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACE_SETACL */
-
-/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_SYNCHRONIZE */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_ACL_TYPE_EXTENDED */
-
-/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_TYPE_NFS4 */
-
-/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_ACL_USER */
-
-/* Define to 1 if you have the declaration of `EXTATTR_NAMESPACE_USER', and to
-   0 if you don't. */
-/* #undef HAVE_DECL_EXTATTR_NAMESPACE_USER */
-
-/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_GETACL */
-
-/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_GETACLCNT */
-
-/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MAX 1
-
-/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT32_MIN 1
-
-/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MAX 1
-
-/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INT64_MIN 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
-   don't. */
-#define HAVE_DECL_INTMAX_MIN 1
-
-/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
-   */
-/* #undef HAVE_DECL_SETACL */
-
-/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_SSIZE_MAX 1
-
-/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
-   don't. */
-#define HAVE_DECL_STRERROR_R 1
-
-/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT32_MAX 1
-
-/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINT64_MAX 1
-
-/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
-   don't. */
-#define HAVE_DECL_UINTMAX_MAX 1
-
-/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_XATTR_NOFOLLOW */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
-   */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have a dirfd function or macro */
-/* #undef HAVE_DIRFD */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if nl_langinfo supports D_MD_ORDER */
-/* #undef HAVE_D_MD_ORDER */
-
-/* A possible errno value for invalid file format errors */
-/* #undef HAVE_EFTYPE */
-
-/* A possible errno value for invalid file format errors */
-#define HAVE_EILSEQ 1
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <expat.h> header file. */
-/* #undef HAVE_EXPAT_H */
-
-/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
-/* #undef HAVE_EXT2FS_EXT2_FS_H */
-
-/* Define to 1 if you have the `extattr_get_fd' function. */
-/* #undef HAVE_EXTATTR_GET_FD */
-
-/* Define to 1 if you have the `extattr_get_file' function. */
-/* #undef HAVE_EXTATTR_GET_FILE */
-
-/* Define to 1 if you have the `extattr_get_link' function. */
-/* #undef HAVE_EXTATTR_GET_LINK */
-
-/* Define to 1 if you have the `extattr_list_fd' function. */
-/* #undef HAVE_EXTATTR_LIST_FD */
-
-/* Define to 1 if you have the `extattr_list_file' function. */
-/* #undef HAVE_EXTATTR_LIST_FILE */
-
-/* Define to 1 if you have the `extattr_list_link' function. */
-/* #undef HAVE_EXTATTR_LIST_LINK */
-
-/* Define to 1 if you have the `extattr_set_fd' function. */
-/* #undef HAVE_EXTATTR_SET_FD */
-
-/* Define to 1 if you have the `extattr_set_link' function. */
-/* #undef HAVE_EXTATTR_SET_LINK */
-
-/* Define to 1 if you have the `facl' function. */
-/* #undef HAVE_FACL */
-
-/* Define to 1 if you have the `fchdir' function. */
-/* #undef HAVE_FCHDIR */
-
-/* Define to 1 if you have the `fchflags' function. */
-/* #undef HAVE_FCHFLAGS */
-
-/* Define to 1 if you have the `fchmod' function. */
-/* #undef HAVE_FCHMOD */
-
-/* Define to 1 if you have the `fchown' function. */
-/* #undef HAVE_FCHOWN */
-
-/* Define to 1 if you have the `fcntl' function. */
-/* #undef HAVE_FCNTL */
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdopendir' function. */
-/* #undef HAVE_FDOPENDIR */
-
-/* Define to 1 if you have the `fgetea' function. */
-/* #undef HAVE_FGETEA */
-
-/* Define to 1 if you have the `fgetxattr' function. */
-/* #undef HAVE_FGETXATTR */
-
-/* Define to 1 if you have the `flistea' function. */
-/* #undef HAVE_FLISTEA */
-
-/* Define to 1 if you have the `flistxattr' function. */
-/* #undef HAVE_FLISTXATTR */
-
-/* Define to 1 if you have the `fnmatch' function. */
-/* #undef HAVE_FNMATCH */
-
-/* Define to 1 if you have the <fnmatch.h> header file. */
-/* #undef HAVE_FNMATCH_H */
-
-/* Define to 1 if you have the `fork' function. */
-/* #undef HAVE_FORK */
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-/* #undef HAVE_FSEEKO */
-
-/* Define to 1 if you have the `fsetea' function. */
-/* #undef HAVE_FSETEA */
-
-/* Define to 1 if you have the `fsetxattr' function. */
-/* #undef HAVE_FSETXATTR */
-
-/* Define to 1 if you have the `fstat' function. */
-#define HAVE_FSTAT 1
-
-/* Define to 1 if you have the `fstatat' function. */
-/* #undef HAVE_FSTATAT */
-
-/* Define to 1 if you have the `fstatfs' function. */
-/* #undef HAVE_FSTATFS */
-
-/* Define to 1 if you have the `fstatvfs' function. */
-/* #undef HAVE_FSTATVFS */
-
-/* Define to 1 if you have the `ftruncate' function. */
-#define HAVE_FTRUNCATE 1
-
-/* Define to 1 if you have the `futimens' function. */
-/* #undef HAVE_FUTIMENS */
-
-/* Define to 1 if you have the `futimes' function. */
-/* #undef HAVE_FUTIMES */
-
-/* Define to 1 if you have the `futimesat' function. */
-/* #undef HAVE_FUTIMESAT */
-
-/* Define to 1 if you have the `getea' function. */
-/* #undef HAVE_GETEA */
-
-/* Define to 1 if you have the `geteuid' function. */
-/* #undef HAVE_GETEUID */
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-/* #undef HAVE_GETGRGID_R */
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-/* #undef HAVE_GETGRNAM_R */
-
-/* Define to 1 if you have the `getline' function. */
-#define HAVE_GETLINE 1
-
-/* Platform uses optreset to reset getopt */
-/* #undef HAVE_GETOPT_OPTRESET */
-
-/* Define to 1 if you have the `getpid' function. */
-#define HAVE_GETPID 1
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-/* #undef HAVE_GETPWNAM_R */
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-/* #undef HAVE_GETPWUID_R */
-
-/* Define to 1 if you have the `getvfsbyname' function. */
-/* #undef HAVE_GETVFSBYNAME */
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the `gmtime_r' function. */
-/* #undef HAVE_GMTIME_R */
-
-/* gmtime_s function */
-/* #undef HAVE_GMTIME_S */
-
-/* Define to 1 if you have the <grp.h> header file. */
-/* #undef HAVE_GRP_H */
-
-/* Define if you have the iconv() function and it works. */
-/* #undef HAVE_ICONV */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-/* #undef HAVE_ICONV_H */
-
-/* Define to 1 if the system has the type `intmax_t'. */
-#define HAVE_INTMAX_T 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-#define HAVE_IO_H 1
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-/* #undef HAVE_LANGINFO_H */
-
-/* Define to 1 if you have the `lchflags' function. */
-/* #undef HAVE_LCHFLAGS */
-
-/* Define to 1 if you have the `lchmod' function. */
-/* #undef HAVE_LCHMOD */
-
-/* Define to 1 if you have the `lchown' function. */
-/* #undef HAVE_LCHOWN */
-
-/* Define to 1 if you have the `lgetea' function. */
-/* #undef HAVE_LGETEA */
-
-/* Define to 1 if you have the `lgetxattr' function. */
-/* #undef HAVE_LGETXATTR */
-
-/* Define to 1 if you have the `acl' library (-lacl). */
-/* #undef HAVE_LIBACL */
-
-/* Define to 1 if you have the `b2' library (-lb2). */
-/* #undef HAVE_LIBB2 */
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-/* #undef HAVE_LIBBZ2 */
-
-/* Define to 1 if you have the `charset' library (-lcharset). */
-/* #undef HAVE_LIBCHARSET */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-/* #undef HAVE_LIBCRYPTO */
-
-/* Define to 1 if you have the `expat' library (-lexpat). */
-/* #undef HAVE_LIBEXPAT */
-
-/* Define to 1 if you have the `lz4' library (-llz4). */
-/* #undef HAVE_LIBLZ4 */
-
-/* Define to 1 if you have the `lzma' library (-llzma). */
-/* #undef HAVE_LIBLZMA */
-
-/* Define to 1 if you have the `lzo2' library (-llzo2). */
-/* #undef HAVE_LIBLZO2 */
-
-/* Define to 1 if you have the `mbedcrypto' library (-lmbedcrypto). */
-/* #undef HAVE_LIBMBEDCRYPTO */
-
-/* Define to 1 if you have the `md' library (-lmd). */
-/* #undef HAVE_LIBMD */
-
-/* Define to 1 if you have the `nettle' library (-lnettle). */
-/* #undef HAVE_LIBNETTLE */
-
-/* Define to 1 if you have the `pcre' library (-lpcre). */
-/* #undef HAVE_LIBPCRE */
-
-/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
-/* #undef HAVE_LIBPCREPOSIX */
-
-/* Define to 1 if you have the `regex' library (-lregex). */
-/* #undef HAVE_LIBREGEX */
-
-/* Define to 1 if you have the `richacl' library (-lrichacl). */
-/* #undef HAVE_LIBRICHACL */
-
-/* Define to 1 if you have the `xml2' library (-lxml2). */
-/* #undef HAVE_LIBXML2 */
-
-/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
-/* #undef HAVE_LIBXML_XMLREADER_H */
-
-/* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
-/* #undef HAVE_LIBXML_XMLWRITER_H */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if you have the `zstd' library (-lzstd). */
-/* #undef HAVE_LIBZSTD */
-
-/* Define to 1 if you have the `zstd' library (-lzstd) with compression
-   support. */
-/* #undef HAVE_LIBZSTD_COMPRESSOR */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `link' function. */
-/* #undef HAVE_LINK */
-
-/* Define to 1 if you have the `linkat' function. */
-/* #undef HAVE_LINKAT */
-
-/* Define to 1 if you have the <linux/fiemap.h> header file. */
-/* #undef HAVE_LINUX_FIEMAP_H */
-
-/* Define to 1 if you have the <linux/fs.h> header file. */
-/* #undef HAVE_LINUX_FS_H */
-
-/* Define to 1 if you have the <linux/magic.h> header file. */
-/* #undef HAVE_LINUX_MAGIC_H */
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-/* #undef HAVE_LINUX_TYPES_H */
-
-/* Define to 1 if you have the `listea' function. */
-/* #undef HAVE_LISTEA */
-
-/* Define to 1 if you have the `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistea' function. */
-/* #undef HAVE_LLISTEA */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if you have the <localcharset.h> header file. */
-/* #undef HAVE_LOCALCHARSET_H */
-
-/* Define to 1 if you have the `locale_charset' function. */
-/* #undef HAVE_LOCALE_CHARSET */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-/* #undef HAVE_LOCALTIME_R */
-
-/* localtime_s function */
-/* #undef HAVE_LOCALTIME_S */
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `lsetea' function. */
-/* #undef HAVE_LSETEA */
-
-/* Define to 1 if you have the `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* Define to 1 if you have the `lstat' function. */
-/* #undef HAVE_LSTAT */
-
-/* Define to 1 if `lstat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-#define HAVE_LSTAT_EMPTY_STRING_BUG 1
-
-/* Define to 1 if you have the `lutimes' function. */
-/* #undef HAVE_LUTIMES */
-
-/* Define to 1 if you have the <lz4hc.h> header file. */
-/* #undef HAVE_LZ4HC_H */
-
-/* Define to 1 if you have the <lz4.h> header file. */
-/* #undef HAVE_LZ4_H */
-
-/* Define to 1 if you have the `LZMA_FILTER_ARM64' macro. */
-/* #undef HAVE_LZMA_FILTER_ARM64 */
-
-/* Define to 1 if you have the <lzma.h> header file. */
-/* #undef HAVE_LZMA_H */
-
-/* Define to 1 if you have the `lzma_stream_encoder_mt' function. */
-/* #undef HAVE_LZMA_STREAM_ENCODER_MT */
-
-/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
-/* #undef HAVE_LZO_LZO1X_H */
-
-/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
-/* #undef HAVE_LZO_LZOCONF_H */
-
-/* Define to 1 if you have the <mbedtls/aes.h> header file. */
-/* #undef HAVE_MBEDTLS_AES_H */
-
-/* Define to 1 if you have the <mbedtls/md.h> header file. */
-/* #undef HAVE_MBEDTLS_MD_H */
-
-/* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
-/* #undef HAVE_MBEDTLS_PKCS5_H */
-
-/* Define to 1 if you have the `mbrtowc' function. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the `mbr_gid_to_uuid' function. */
-/* #undef HAVE_MBR_GID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uid_to_uuid' function. */
-/* #undef HAVE_MBR_UID_TO_UUID */
-
-/* Define to 1 if you have the `mbr_uuid_to_id' function. */
-/* #undef HAVE_MBR_UUID_TO_ID */
-
-/* Define to 1 if you have the <md5.h> header file. */
-/* #undef HAVE_MD5_H */
-
-/* Define to 1 if you have the <membership.h> header file. */
-/* #undef HAVE_MEMBERSHIP_H */
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have the <minix/config.h> header file. */
-/* #undef HAVE_MINIX_CONFIG_H */
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have the `mkfifo' function. */
-/* #undef HAVE_MKFIFO */
-
-/* Define to 1 if you have the `mknod' function. */
-/* #undef HAVE_MKNOD */
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the <nettle/aes.h> header file. */
-/* #undef HAVE_NETTLE_AES_H */
-
-/* Define to 1 if you have the <nettle/hmac.h> header file. */
-/* #undef HAVE_NETTLE_HMAC_H */
-
-/* Define to 1 if you have the <nettle/md5.h> header file. */
-/* #undef HAVE_NETTLE_MD5_H */
-
-/* Define to 1 if you have the <nettle/pbkdf2.h> header file. */
-/* #undef HAVE_NETTLE_PBKDF2_H */
-
-/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
-/* #undef HAVE_NETTLE_RIPEMD160_H */
-
-/* Define to 1 if you have the <nettle/sha.h> header file. */
-/* #undef HAVE_NETTLE_SHA_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-/* #undef HAVE_NL_LANGINFO */
-
-/* Define to 1 if you have the `openat' function. */
-/* #undef HAVE_OPENAT */
-
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-/* #undef HAVE_OPENSSL_EVP_H */
-
-/* Define to 1 if you have the <paths.h> header file. */
-/* #undef HAVE_PATHS_H */
-
-/* Define to 1 if you have the <pcreposix.h> header file. */
-/* #undef HAVE_PCREPOSIX_H */
-
-/* Define to 1 if you have the `pipe' function. */
-/* #undef HAVE_PIPE */
-
-/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */
-/* #undef HAVE_PKCS5_PBKDF2_HMAC_SHA1 */
-
-/* Define to 1 if you have the `poll' function. */
-/* #undef HAVE_POLL */
-
-/* Define to 1 if you have the <poll.h> header file. */
-/* #undef HAVE_POLL_H */
-
-/* Define to 1 if you have the `posix_spawnp' function. */
-/* #undef HAVE_POSIX_SPAWNP */
-
-/* Define to 1 if you have the <pthread.h> header file. */
-/* #undef HAVE_PTHREAD_H */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-/* #undef HAVE_PWD_H */
-
-/* Define to 1 if you have a POSIX compatible readdir_r */
-/* #undef HAVE_READDIR_R */
-
-/* Define to 1 if you have the `readlink' function. */
-/* #undef HAVE_READLINK */
-
-/* Define to 1 if you have the `readlinkat' function. */
-/* #undef HAVE_READLINKAT */
-
-/* Define to 1 if you have the `readpassphrase' function. */
-/* #undef HAVE_READPASSPHRASE */
-
-/* Define to 1 if you have the <readpassphrase.h> header file. */
-/* #undef HAVE_READPASSPHRASE_H */
-
-/* Define to 1 if you have the <regex.h> header file. */
-/* #undef HAVE_REGEX_H */
-
-/* Define to 1 if you have the `richacl_alloc' function. */
-/* #undef HAVE_RICHACL_ALLOC */
-
-/* Define to 1 if you have the `richacl_equiv_mode' function. */
-/* #undef HAVE_RICHACL_EQUIV_MODE */
-
-/* Define to 1 if you have the `richacl_free' function. */
-/* #undef HAVE_RICHACL_FREE */
-
-/* Define to 1 if you have the `richacl_get_fd' function. */
-/* #undef HAVE_RICHACL_GET_FD */
-
-/* Define to 1 if you have the `richacl_get_file' function. */
-/* #undef HAVE_RICHACL_GET_FILE */
-
-/* Define to 1 if you have the `richacl_set_fd' function. */
-/* #undef HAVE_RICHACL_SET_FD */
-
-/* Define to 1 if you have the `richacl_set_file' function. */
-/* #undef HAVE_RICHACL_SET_FILE */
-
-/* Define to 1 if you have the <ripemd.h> header file. */
-/* #undef HAVE_RIPEMD_H */
-
-/* Define to 1 if you have the `select' function. */
-/* #undef HAVE_SELECT */
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 1
-
-/* Define to 1 if you have the `setxattr' function. */
-/* #undef HAVE_SETXATTR */
-
-/* Define to 1 if you have the <sha256.h> header file. */
-/* #undef HAVE_SHA256_H */
-
-/* Define to 1 if you have the <sha512.h> header file. */
-/* #undef HAVE_SHA512_H */
-
-/* Define to 1 if you have the <sha.h> header file. */
-/* #undef HAVE_SHA_H */
-
-/* Define to 1 if you have the `sigaction' function. */
-/* #undef HAVE_SIGACTION */
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the <spawn.h> header file. */
-/* #undef HAVE_SPAWN_H */
-
-/* Define to 1 if you have the `statfs' function. */
-/* #undef HAVE_STATFS */
-
-/* Define to 1 if you have the `statvfs' function. */
-/* #undef HAVE_STATVFS */
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strchr' function. */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have `strerror_r'. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `strftime' function. */
-#define HAVE_STRFTIME 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncpy_s' function. */
-#define HAVE_STRNCPY_S 1
-
-/* Define to 1 if you have the `strnlen' function. */
-#define HAVE_STRNLEN 1
-
-/* Define to 1 if you have the `strrchr' function. */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if the system has the type `struct richace'. */
-/* #undef HAVE_STRUCT_RICHACE */
-
-/* Define to 1 if the system has the type `struct richacl'. */
-/* #undef HAVE_STRUCT_RICHACL */
-
-/* Define to 1 if the system has the type `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS */
-
-/* Define to 1 if `f_iosize' is a member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_IOSIZE */
-
-/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_NAMEMAX */
-
-/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
-/* #undef HAVE_STRUCT_STATVFS_F_IOSIZE */
-
-/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */
-
-/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC */
-
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */
-
-/* Define to 1 if `st_flags' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_FLAGS */
-
-/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */
-
-/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_USEC */
-
-/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
-
-/* Define to 1 if `st_umtime' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_UMTIME */
-
-/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM_TM_GMTOFF */
-
-/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if the system has the type `struct vfsconf'. */
-/* #undef HAVE_STRUCT_VFSCONF */
-
-/* Define to 1 if the system has the type `struct xvfsconf'. */
-/* #undef HAVE_STRUCT_XVFSCONF */
-
-/* Define to 1 if you have the `symlink' function. */
-/* #undef HAVE_SYMLINK */
-
-/* Define to 1 if you have the <sys/acl.h> header file. */
-/* #undef HAVE_SYS_ACL_H */
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-/* #undef HAVE_SYS_CDEFS_H */
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/ea.h> header file. */
-/* #undef HAVE_SYS_EA_H */
-
-/* Define to 1 if you have the <sys/extattr.h> header file. */
-/* #undef HAVE_SYS_EXTATTR_H */
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-/* #undef HAVE_SYS_IOCTL_H */
-
-/* Define to 1 if you have the <sys/mkdev.h> header file. */
-/* #undef HAVE_SYS_MKDEV_H */
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-/* #undef HAVE_SYS_MOUNT_H */
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-/* #undef HAVE_SYS_POLL_H */
-
-/* Define to 1 if you have the <sys/queue.h> header file. */
-/* #undef HAVE_SYS_QUEUE_H */
-
-/* Define to 1 if you have the <sys/richacl.h> header file. */
-/* #undef HAVE_SYS_RICHACL_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define to 1 if you have the <sys/statfs.h> header file. */
-/* #undef HAVE_SYS_STATFS_H */
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-/* #undef HAVE_SYS_STATVFS_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-/* #undef HAVE_SYS_SYSMACROS_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/utime.h> header file. */
-#define HAVE_SYS_UTIME_H 1
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-/* #undef HAVE_SYS_UTSNAME_H */
-
-/* Define to 1 if you have the <sys/vfs.h> header file. */
-/* #undef HAVE_SYS_VFS_H */
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-/* #undef HAVE_SYS_WAIT_H */
-
-/* Define to 1 if you have the <sys/xattr.h> header file. */
-/* #undef HAVE_SYS_XATTR_H */
-
-/* Define to 1 if you have the `timegm' function. */
-/* #undef HAVE_TIMEGM */
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the `tzset' function. */
-#define HAVE_TZSET 1
-
-/* Define to 1 if the system has the type `uintmax_t'. */
-#define HAVE_UINTMAX_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `unlinkat' function. */
-/* #undef HAVE_UNLINKAT */
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if the system has the type `unsigned long long'. */
-#define HAVE_UNSIGNED_LONG_LONG 1
-
-/* Define to 1 if the system has the type `unsigned long long int'. */
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimensat' function. */
-/* #undef HAVE_UTIMENSAT */
-
-/* Define to 1 if you have the `utimes' function. */
-/* #undef HAVE_UTIMES */
-
-/* Define to 1 if you have the <utime.h> header file. */
-#define HAVE_UTIME_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-/* #undef HAVE_VFORK */
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the `wcrtomb' function. */
-#define HAVE_WCRTOMB 1
-
-/* Define to 1 if you have the `wcscmp' function. */
-#define HAVE_WCSCMP 1
-
-/* Define to 1 if you have the `wcscpy' function. */
-#define HAVE_WCSCPY 1
-
-/* Define to 1 if you have the `wcslen' function. */
-#define HAVE_WCSLEN 1
-
-/* Define to 1 if you have the `wctomb' function. */
-#define HAVE_WCTOMB 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define to 1 if you have the <wincrypt.h> header file. */
-#define HAVE_WINCRYPT_H 1
-
-/* Define to 1 if you have the <windows.h> header file. */
-#define HAVE_WINDOWS_H 1
-
-/* Define to 1 if you have the <winioctl.h> header file. */
-#define HAVE_WINIOCTL_H 1
-
-/* Define to 1 if you have the `wmemcmp' function. */
-#define HAVE_WMEMCMP 1
-
-/* Define to 1 if you have the `wmemcpy' function. */
-#define HAVE_WMEMCPY 1
-
-/* Define to 1 if you have the `wmemmove' function. */
-#define HAVE_WMEMMOVE 1
-
-/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_EXT2_IOC_GETFLAGS */
-
-/* Define to 1 if you have a working FS_IOC_GETFLAGS */
-/* #undef HAVE_WORKING_FS_IOC_GETFLAGS */
-
-/* Define to 1 if you have the <zlib.h> header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Define to 1 if you have the <zstd.h> header file. */
-/* #undef HAVE_ZSTD_H */
-
-/* Define to 1 if you have the `_fseeki64' function. */
-#define HAVE__FSEEKI64 1
-
-/* Define to 1 if you have the `_get_timezone' function. */
-/* #undef HAVE__GET_TIMEZONE */
-
-/* _mkgmtime function */
-/* #undef HAVE__MKGMTIME */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #undef ICONV_CONST */
-
-/* Version number of libarchive as a single integer */
-#define LIBARCHIVE_VERSION_NUMBER "3007001"
-
-/* Version number of libarchive */
-#define LIBARCHIVE_VERSION_STRING "3.7.1"
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
-   slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
-   */
-/* #undef MAJOR_IN_MKDEV */
-
-/* Define to 1 if `major', `minor', and `makedev' are declared in
-   <sysmacros.h>. */
-/* #undef MAJOR_IN_SYSMACROS */
-
-/* Define to '0x05020000' for Windows Server 2003 APIs. */
-#define NTDDI_VERSION 0x05020000
-
-/* Name of package */
-#define PACKAGE "libarchive"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "libarchive-discuss@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libarchive"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libarchive 3.7.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libarchive"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.7.1"
-
-/* Define to 1 if PCRE_STATIC needs to be defined. */
-/* #undef PCRE_STATIC */
-
-/* The number of bytes in type int */
-#define SIZEOF_INT 4
-
-/* The number of bytes in type long */
-#define SIZEOF_LONG 4
-
-/* The size of `wchar_t', as computed by sizeof. */
-#define SIZEOF_WCHAR_T 2
-
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
-   required in a freestanding environment). This macro is provided for
-   backward compatibility; new code need not use it. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r returns char *. */
-/* #undef STRERROR_R_CHAR_P */
-
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable general extensions on macOS.  */
-#ifndef _DARWIN_C_SOURCE
-# define _DARWIN_C_SOURCE 1
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable X/Open compliant socket functions that do not require linking
-   with -lxnet on HP-UX 11.11.  */
-#ifndef _HPUX_ALT_XOPEN_SOCKET_API
-# define _HPUX_ALT_XOPEN_SOCKET_API 1
-#endif
-/* Identify the host operating system as Minix.
-   This macro does not affect the system headers' behavior.
-   A future release of Autoconf may stop defining this macro.  */
-#ifndef _MINIX
-/* # undef _MINIX */
-#endif
-/* Enable general extensions on NetBSD.
-   Enable NetBSD compatibility extensions on Minix.  */
-#ifndef _NETBSD_SOURCE
-# define _NETBSD_SOURCE 1
-#endif
-/* Enable OpenBSD compatibility extensions on NetBSD.
-   Oddly enough, this does nothing on OpenBSD.  */
-#ifndef _OPENBSD_SOURCE
-# define _OPENBSD_SOURCE 1
-#endif
-/* Define to 1 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_SOURCE
-/* # undef _POSIX_SOURCE */
-#endif
-/* Define to 2 if needed for POSIX-compatible behavior.  */
-#ifndef _POSIX_1_SOURCE
-/* # undef _POSIX_1_SOURCE */
-#endif
-/* Enable POSIX-compatible threading on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
-#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
-# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
-#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
-# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
-#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
-# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
-#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
-# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
-#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
-# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
-#endif
-/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
-#ifndef __STDC_WANT_LIB_EXT2__
-# define __STDC_WANT_LIB_EXT2__ 1
-#endif
-/* Enable extensions specified by ISO/IEC 24747:2009.  */
-#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
-# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable X/Open extensions.  Define to 500 only if necessary
-   to make mbstate_t available.  */
-#ifndef _XOPEN_SOURCE
-/* # undef _XOPEN_SOURCE */
-#endif
-
-
-/* Version number of package */
-#define VERSION "3.7.1"
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-#define WINVER 0x0502
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT32_T */
-
-/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT64_T */
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
-   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
-   #define below would cause a syntax error. */
-/* #undef _UINT8_T */
-
-/* Define to '0x0502' for Windows Server 2003 APIs. */
-#define _WIN32_WINNT 0x0502
-
-/* Internal macro for sanity checks */
-#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't
-   define. */
-#define gid_t short
-
-/* Define to `unsigned long' if <sys/types.h> does not define. */
-#define id_t unsigned long
-
-/* Define to the type of a signed integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int16_t */
-
-/* Define to the type of a signed integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int32_t */
-
-/* Define to the type of a signed integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef int64_t */
-
-/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
-   not define. */
-/* #undef intmax_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
-
-/* Define to `long long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't
-   define. */
-#define uid_t short
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint16_t */
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint32_t */
-
-/* Define to the type of an unsigned integer type of width exactly 64 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint64_t */
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
-   such a type exists and the standard includes do not define it. */
-/* #undef uint8_t */
-
-/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
-   do not define. */
-/* #undef uintmax_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef uintptr_t */
-#define HAVE_LIBZ 1
-#define HAVE_ZLIB_H 1
diff --git a/c/config_freebsd.h b/c/config_freebsd.h
deleted file mode 100644
--- a/c/config_freebsd.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-
-#include <osreldate.h>
-
-/* FreeBSD 5.0 and later has ACL and extattr support. */
-#if __FreeBSD__ > 4
-#define ARCHIVE_ACL_FREEBSD 1
-#define HAVE_ACL_GET_PERM_NP 1
-#define HAVE_ARC4RANDOM_BUF 1
-#define HAVE_EXTATTR_GET_FILE 1
-#define HAVE_EXTATTR_LIST_FILE 1
-#define HAVE_EXTATTR_SET_FD 1
-#define HAVE_EXTATTR_SET_FILE 1
-#define HAVE_STRUCT_XVFSCONF 1
-#define HAVE_SYS_ACL_H 1
-#define HAVE_SYS_EXTATTR_H 1
-#if __FreeBSD__ > 7
-/* FreeBSD 8.0 and later has NFSv4 ACL support */
-#define ARCHIVE_ACL_FREEBSD_NFS4 1
-#define HAVE_ACL_GET_LINK_NP 1
-#define HAVE_ACL_IS_TRIVIAL_NP 1
-#define HAVE_ACL_SET_LINK_NP 1
-#endif /* __FreeBSD__ > 7 */
-#endif /* __FreeBSD__ > 4 */
-
-#ifdef WITH_OPENSSL
-#define HAVE_LIBCRYPTO 1
-#define HAVE_OPENSSL_EVP_H 1
-#define HAVE_OPENSSL_MD5_H 1
-#define HAVE_OPENSSL_RIPEMD_H 1
-#define HAVE_OPENSSL_SHA_H 1
-#define HAVE_OPENSSL_SHA256_INIT 1
-#define HAVE_OPENSSL_SHA384_INIT 1
-#define HAVE_OPENSSL_SHA512_INIT 1
-#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1
-#define HAVE_SHA256 1
-#define HAVE_SHA384 1
-#define HAVE_SHA512 1
-#else
-#define HAVE_LIBMD 1
-#define HAVE_MD5_H 1
-#define HAVE_MD5INIT 1
-#define HAVE_RIPEMD_H 1
-#define HAVE_SHA_H 1
-#define HAVE_SHA1 1
-#define HAVE_SHA1_INIT 1
-#define HAVE_SHA256 1
-#define HAVE_SHA256_H 1
-#define HAVE_SHA256_INIT 1
-#define HAVE_SHA512 1
-#define HAVE_SHA512_H 1
-#define HAVE_SHA512_INIT 1
-#endif
-
-#define HAVE_BSDXML_H 1
-#define HAVE_BZLIB_H 1
-#define HAVE_CHFLAGS 1
-#define HAVE_CHOWN 1
-#define HAVE_CHROOT 1
-#define HAVE_CTIME_R 1
-#define HAVE_CTYPE_H 1
-#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1
-#define HAVE_DECL_INT32_MAX 1
-#define HAVE_DECL_INT32_MIN 1
-#define HAVE_DECL_INT64_MAX 1
-#define HAVE_DECL_INT64_MIN 1
-#define HAVE_DECL_INTMAX_MAX 1
-#define HAVE_DECL_INTMAX_MIN 1
-#define HAVE_DECL_SIZE_MAX 1
-#define HAVE_DECL_SSIZE_MAX 1
-#define HAVE_DECL_STRERROR_R 1
-#define HAVE_DECL_UINT32_MAX 1
-#define HAVE_DECL_UINT64_MAX 1
-#define HAVE_DECL_UINTMAX_MAX 1
-#define HAVE_DIRENT_H 1
-#define HAVE_DLFCN_H 1
-#define HAVE_D_MD_ORDER 1
-#define HAVE_EFTYPE 1
-#define HAVE_EILSEQ 1
-#define HAVE_ERRNO_H 1
-#define HAVE_FCHDIR 1
-#define HAVE_FCHFLAGS 1
-#define HAVE_FCHMOD 1
-#define HAVE_FCHOWN 1
-#define HAVE_FCNTL 1
-#define HAVE_FCNTL_H 1
-#define HAVE_FDOPENDIR 1
-#define HAVE_FNMATCH 1
-#define HAVE_FNMATCH_H 1
-#define HAVE_FORK 1
-#define HAVE_FSEEKO 1
-#define HAVE_FSTAT 1
-#define HAVE_FSTATAT 1
-#define HAVE_FSTATFS 1
-#define HAVE_FSTATVFS 1
-#define HAVE_FTRUNCATE 1
-#define HAVE_FUTIMES 1
-#define HAVE_FUTIMESAT 1
-#define HAVE_GETEUID 1
-#define HAVE_GETGRGID_R 1
-#define HAVE_GETGRNAM_R 1
-#define HAVE_GETLINE 1
-#define HAVE_GETOPT_OPTRESET 1
-#define HAVE_GETPID 1
-#define HAVE_GETPWNAM_R 1
-#define HAVE_GETPWUID_R 1
-#define HAVE_GETVFSBYNAME 1
-#define HAVE_GMTIME_R 1
-#define HAVE_GRP_H 1
-#define HAVE_INTMAX_T 1
-#define HAVE_INTTYPES_H 1
-#define HAVE_LANGINFO_H 1
-#define HAVE_LCHFLAGS 1
-#define HAVE_LCHMOD 1
-#define HAVE_LCHOWN 1
-#define HAVE_LIBZ 1
-#define HAVE_LIMITS_H 1
-#define HAVE_LINK 1
-#define HAVE_LINKAT 1
-#define HAVE_LOCALE_H 1
-#define HAVE_LOCALTIME_R 1
-#define HAVE_LONG_LONG_INT 1
-#define HAVE_LSTAT 1
-#define HAVE_LUTIMES 1
-#define HAVE_MBRTOWC 1
-#define HAVE_MEMMOVE 1
-#define HAVE_MEMORY_H 1
-#define HAVE_MEMSET 1
-#define HAVE_MKDIR 1
-#define HAVE_MKFIFO 1
-#define HAVE_MKNOD 1
-#define HAVE_MKSTEMP 1
-#define HAVE_NL_LANGINFO 1
-#define HAVE_OPENAT 1
-#define HAVE_PATHS_H 1
-#define HAVE_PIPE 1
-#define HAVE_POLL 1
-#define HAVE_POLL_H 1
-#define HAVE_POSIX_SPAWNP 1
-#define HAVE_PTHREAD_H 1
-#define HAVE_PWD_H 1
-#define HAVE_READDIR_R 1
-#define HAVE_READLINK 1
-#define HAVE_READLINKAT 1
-#define HAVE_READPASSPHRASE 1
-#define HAVE_READPASSPHRASE_H 1
-#define HAVE_REGEX_H 1
-#define HAVE_SELECT 1
-#define HAVE_SETENV 1
-#define HAVE_SETLOCALE 1
-#define HAVE_SIGACTION 1
-#define HAVE_SIGNAL_H 1
-#define HAVE_SPAWN_H 1
-#define HAVE_STATFS 1
-#define HAVE_STATVFS 1
-#define HAVE_STDARG_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRCHR 1
-#define HAVE_STRDUP 1
-#define HAVE_STRERROR 1
-#define HAVE_STRERROR_R 1
-#define HAVE_STRFTIME 1
-#define HAVE_STRINGS_H 1
-#define HAVE_STRING_H 1
-#define HAVE_STRNLEN 1
-#define HAVE_STRRCHR 1
-#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
-#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
-#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-#define HAVE_STRUCT_STAT_ST_FLAGS 1
-#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-#define HAVE_SYMLINK 1
-#define HAVE_SYS_CDEFS_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_MOUNT_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_POLL_H 1
-#define HAVE_SYS_QUEUE_H 1
-#define HAVE_SYS_SELECT_H 1
-#define HAVE_SYS_STATVFS_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_UTSNAME_H 1
-#define HAVE_SYS_WAIT_H 1
-#define HAVE_TIMEGM 1
-#define HAVE_TIME_H 1
-#define HAVE_TZSET 1
-#define HAVE_UINTMAX_T 1
-#define HAVE_UNISTD_H 1
-#define HAVE_UNLINKAT 1
-#define HAVE_UNSETENV 1
-#define HAVE_UNSIGNED_LONG_LONG 1
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-#define HAVE_UTIME 1
-#define HAVE_UTIMES 1
-#define HAVE_UTIME_H 1
-#define HAVE_VFORK 1
-#define HAVE_VPRINTF 1
-#define HAVE_WCHAR_H 1
-#define HAVE_WCHAR_T 1
-#define HAVE_WCRTOMB 1
-#define HAVE_WCSCMP 1
-#define HAVE_WCSCPY 1
-#define HAVE_WCSLEN 1
-#define HAVE_WCTOMB 1
-#define HAVE_WCTYPE_H 1
-#define HAVE_WMEMCMP 1
-#define HAVE_WMEMCPY 1
-#define HAVE_WMEMMOVE 1
-#define HAVE_ZLIB_H 1
-#define HAVE_SYS_TIME_H 1
-
-#if __FreeBSD_version >= 800505
-#define HAVE_LIBLZMA 1
-#define HAVE_LZMA_H 1
-#if __FreeBSD_version >= 1002504
-#define HAVE_LZMA_STREAM_ENCODER_MT 1
-#endif
-#endif
-
-#if __FreeBSD_version >= 1100056
-#define HAVE_FUTIMENS 1
-#define HAVE_UTIMENSAT 1
-#endif
-
-/* FreeBSD 4 and earlier lack intmax_t/uintmax_t */
-#if __FreeBSD__ < 5
-#define intmax_t int64_t
-#define uintmax_t uint64_t
-#endif
-
-/* FreeBSD defines for archive_hash.h */
-#ifdef WITH_OPENSSL
-#define ARCHIVE_CRYPTO_MD5_OPENSSL 1
-#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1
-#define ARCHIVE_CRYPTO_SHA1_OPENSSL
-#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1
-#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1
-#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1
-#else
-#define ARCHIVE_CRYPTO_MD5_LIBMD 1
-#define ARCHIVE_CRYPTO_SHA1_LIBMD 1
-#define ARCHIVE_CRYPTO_SHA256_LIBMD 1
-#define ARCHIVE_CRYPTO_SHA512_LIBMD 1
-#endif
diff --git a/c/filter_fork.h b/c/filter_fork.h
deleted file mode 100644
--- a/c/filter_fork.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * Copyright (c) 2007 Joerg Sonnenberger
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/filter_fork.h 201087 2009-12-28 02:18:26Z kientzle $
- */
-
-#ifndef FILTER_FORK_H
-#define FILTER_FORK_H
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-int
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
-#if defined(_WIN32) && !defined(__CYGWIN__)
-	HANDLE *out_child);
-#else
-	pid_t *out_child);
-#endif
-
-void
-__archive_check_child(int in, int out);
-
-#endif
diff --git a/c/filter_fork_posix.c b/c/filter_fork_posix.c
deleted file mode 100644
--- a/c/filter_fork_posix.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*-
- * Copyright (c) 2007 Joerg Sonnenberger
- * Copyright (c) 2012 Michihiro NAKAJIMA 
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-/* This capability is only available on POSIX systems. */
-#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \
-    (defined(HAVE_FORK) || defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP))
-
-__FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $");
-
-#if defined(HAVE_SYS_TYPES_H)
-#  include <sys/types.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#  include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#  include <string.h>
-#endif
-#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H))
-#  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)
-#    include <sys/select.h>
-#  elif defined(HAVE_UNISTD_H)
-#    include <unistd.h>
-#  endif
-#endif
-#ifdef HAVE_FCNTL_H
-#  include <fcntl.h>
-#endif
-#ifdef HAVE_SPAWN_H
-#  include <spawn.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
-#include "archive.h"
-#include "archive_cmdline_private.h"
-
-#include "filter_fork.h"
-
-int
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
-		pid_t *out_child)
-{
-	pid_t child = -1;
-	int stdin_pipe[2], stdout_pipe[2], tmp;
-#if HAVE_POSIX_SPAWNP
-	posix_spawn_file_actions_t actions;
-	int r;
-#endif
-	struct archive_cmdline *cmdline;
-
-	cmdline = __archive_cmdline_allocate();
-	if (cmdline == NULL)
-		goto state_allocated;
-	if (__archive_cmdline_parse(cmdline, cmd) != ARCHIVE_OK)
-		goto state_allocated;
-
-	if (pipe(stdin_pipe) == -1)
-		goto state_allocated;
-	if (stdin_pipe[0] == 1 /* stdout */) {
-		if ((tmp = dup(stdin_pipe[0])) == -1)
-			goto stdin_opened;
-		close(stdin_pipe[0]);
-		stdin_pipe[0] = tmp;
-	}
-	if (pipe(stdout_pipe) == -1)
-		goto stdin_opened;
-	if (stdout_pipe[1] == 0 /* stdin */) {
-		if ((tmp = dup(stdout_pipe[1])) == -1)
-			goto stdout_opened;
-		close(stdout_pipe[1]);
-		stdout_pipe[1] = tmp;
-	}
-
-#if HAVE_POSIX_SPAWNP
-
-	r = posix_spawn_file_actions_init(&actions);
-	if (r != 0) {
-		errno = r;
-		goto stdout_opened;
-	}
-	r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]);
-	if (r != 0)
-		goto actions_inited;
-	r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[0]);
-	if (r != 0)
-		goto actions_inited;
-	/* Setup for stdin. */
-	r = posix_spawn_file_actions_adddup2(&actions, stdin_pipe[0], 0);
-	if (r != 0)
-		goto actions_inited;
-	if (stdin_pipe[0] != 0 /* stdin */) {
-		r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[0]);
-		if (r != 0)
-			goto actions_inited;
-	}
-	/* Setup for stdout. */
-	r = posix_spawn_file_actions_adddup2(&actions, stdout_pipe[1], 1);
-	if (r != 0)
-		goto actions_inited;
-	if (stdout_pipe[1] != 1 /* stdout */) {
-		r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[1]);
-		if (r != 0)
-			goto actions_inited;
-	}
-	r = posix_spawnp(&child, cmdline->path, &actions, NULL,
-		cmdline->argv, NULL);
-	if (r != 0)
-		goto actions_inited;
-	posix_spawn_file_actions_destroy(&actions);
-
-#else /* HAVE_POSIX_SPAWNP */
-
-#if HAVE_VFORK
-	child = vfork();
-#else
-	child = fork();
-#endif
-	if (child == -1)
-		goto stdout_opened;
-	if (child == 0) {
-		close(stdin_pipe[1]);
-		close(stdout_pipe[0]);
-		if (dup2(stdin_pipe[0], 0 /* stdin */) == -1)
-			_exit(254);
-		if (stdin_pipe[0] != 0 /* stdin */)
-			close(stdin_pipe[0]);
-		if (dup2(stdout_pipe[1], 1 /* stdout */) == -1)
-			_exit(254);
-		if (stdout_pipe[1] != 1 /* stdout */)
-			close(stdout_pipe[1]);
-		execvp(cmdline->path, cmdline->argv);
-		_exit(254);
-	}
-#endif /* HAVE_POSIX_SPAWNP */
-
-	close(stdin_pipe[0]);
-	close(stdout_pipe[1]);
-
-	*child_stdin = stdin_pipe[1];
-	fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
-	*child_stdout = stdout_pipe[0];
-	fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
-	__archive_cmdline_free(cmdline);
-
-	*out_child = child;
-	return ARCHIVE_OK;
-
-#if HAVE_POSIX_SPAWNP
-actions_inited:
-	errno = r;
-	posix_spawn_file_actions_destroy(&actions);
-#endif
-stdout_opened:
-	close(stdout_pipe[0]);
-	close(stdout_pipe[1]);
-stdin_opened:
-	close(stdin_pipe[0]);
-	close(stdin_pipe[1]);
-state_allocated:
-	__archive_cmdline_free(cmdline);
-	return ARCHIVE_FAILED;
-}
-
-void
-__archive_check_child(int in, int out)
-{
-#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H))
-	struct pollfd fds[2];
-	int idx;
-
-	idx = 0;
-	if (in != -1) {
-		fds[idx].fd = in;
-		fds[idx].events = POLLOUT;
-		++idx;
-	}
-	if (out != -1) {
-		fds[idx].fd = out;
-		fds[idx].events = POLLIN;
-		++idx;
-	}
-
-	poll(fds, idx, -1); /* -1 == INFTIM, wait forever */
-#elif defined(HAVE_SELECT)
-	fd_set fds_in, fds_out, fds_error;
-
-	FD_ZERO(&fds_in);
-	FD_ZERO(&fds_out);
-	FD_ZERO(&fds_error);
-	if (out != -1) {
-		FD_SET(out, &fds_in);
-		FD_SET(out, &fds_error);
-	}
-	if (in != -1) {
-		FD_SET(in, &fds_out);
-		FD_SET(in, &fds_error);
-	}
-	select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL);
-#else
-	sleep(1);
-#endif
-}
-
-#endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */
diff --git a/c/filter_fork_windows.c b/c/filter_fork_windows.c
deleted file mode 100644
--- a/c/filter_fork_windows.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*-
- * Copyright (c) 2009-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "archive_platform.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "archive_cmdline_private.h"
-#include "archive_string.h"
-
-#include "filter_fork.h"
-
-#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-/* There are some editions of Windows ("nano server," for example) that
- * do not host user32.dll. If we want to keep running on those editions,
- * we need to delay-load WaitForInputIdle. */
-static void *
-la_GetFunctionUser32(const char *name)
-{
-	static HINSTANCE lib;
-	static int set;
-	if (!set) {
-		set = 1;
-		lib = LoadLibrary(TEXT("user32.dll"));
-	}
-	if (lib == NULL) {
-		return NULL;
-	}
-	return (void *)GetProcAddress(lib, name);
-}
-
-static int
-la_WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds)
-{
-	static DWORD (WINAPI *f)(HANDLE, DWORD);
-	static int set;
-
-	if (!set) {
-		set = 1;
-		f = la_GetFunctionUser32("WaitForInputIdle");
-	}
-
-	if (!f) {
-		/* An inability to wait for input idle is
-		 * not _good_, but it is not catastrophic. */
-		return WAIT_FAILED;
-	}
-	return (*f)(hProcess, dwMilliseconds);
-}
-
-int
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
-		HANDLE *out_child)
-{
-	HANDLE childStdout[2], childStdin[2],childStderr;
-	SECURITY_ATTRIBUTES secAtts;
-	STARTUPINFOA staInfo;
-	PROCESS_INFORMATION childInfo;
-	struct archive_string cmdline;
-	struct archive_string fullpath;
-	struct archive_cmdline *acmd;
-	char *arg0, *ext;
-	int i, l;
-	DWORD fl, fl_old;
-	HANDLE child;
-
-	childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE;
-	childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE;
-	childStderr = INVALID_HANDLE_VALUE;
-	archive_string_init(&cmdline);
-	archive_string_init(&fullpath);
-
-	acmd = __archive_cmdline_allocate();
-	if (acmd == NULL)
-		goto fail;
-	if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK)
-		goto fail;
-
-	/*
-	 * Search the full path of 'path'.
-	 * NOTE: This does not need if we give CreateProcessA 'path' as
-	 * a part of the cmdline and give CreateProcessA NULL as first
-	 * parameter, but I do not like that way.
-	 */
-	ext = strrchr(acmd->path, '.');
-	if (ext == NULL || strlen(ext) > 4)
-		/* 'path' does not have a proper extension, so we have to
-		 * give SearchPath() ".exe" as the extension. */
-		ext = ".exe";
-	else
-		ext = NULL;/* 'path' has an extension. */
-
-	fl = MAX_PATH;
-	do {
-		if (archive_string_ensure(&fullpath, fl) == NULL)
-			goto fail;
-		fl_old = fl;
-		fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s,
-			&arg0);
-	} while (fl != 0 && fl > fl_old);
-	if (fl == 0)
-		goto fail;
-
-	/*
-	 * Make a command line.
-	 */
-	for (l = 0, i = 0;  acmd->argv[i] != NULL; i++) {
-		if (i == 0)
-			continue;
-		l += (int)strlen(acmd->argv[i]) + 1;
-	}
-	if (archive_string_ensure(&cmdline, l + 1) == NULL)
-		goto fail;
-	for (i = 0;  acmd->argv[i] != NULL; i++) {
-		if (i == 0) {
-			const char *p, *sp;
-
-			if ((p = strchr(acmd->argv[i], '/')) != NULL ||
-			    (p = strchr(acmd->argv[i], '\\')) != NULL)
-				p++;
-			else
-				p = acmd->argv[i];
-			if ((sp = strchr(p, ' ')) != NULL)
-				archive_strappend_char(&cmdline, '"');
-			archive_strcat(&cmdline, p);
-			if (sp != NULL)
-				archive_strappend_char(&cmdline, '"');
-		} else {
-			archive_strappend_char(&cmdline, ' ');
-			archive_strcat(&cmdline, acmd->argv[i]);
-		}
-	}
-	if (i <= 1) {
-		const char *sp;
-
-		if ((sp = strchr(arg0, ' ')) != NULL)
-			archive_strappend_char(&cmdline, '"');
-		archive_strcat(&cmdline, arg0);
-		if (sp != NULL)
-			archive_strappend_char(&cmdline, '"');
-	}
-
-	secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
-	secAtts.bInheritHandle = TRUE;
-	secAtts.lpSecurityDescriptor = NULL;
-	if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0)
-		goto fail;
-	if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0))
-		goto fail;
-	if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0)
-		goto fail;
-	if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0))
-		goto fail;
-	if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE),
-	    GetCurrentProcess(), &childStderr, 0, TRUE,
-	    DUPLICATE_SAME_ACCESS) == 0)
-		goto fail;
-
-	memset(&staInfo, 0, sizeof(staInfo));
-	staInfo.cb = sizeof(staInfo);
-	staInfo.hStdError = childStderr;
-	staInfo.hStdOutput = childStdout[1];
-	staInfo.hStdInput = childStdin[0];
-	staInfo.wShowWindow = SW_HIDE;
-	staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-	if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0,
-	      NULL, NULL, &staInfo, &childInfo) == 0)
-		goto fail;
-	la_WaitForInputIdle(childInfo.hProcess, INFINITE);
-	CloseHandle(childInfo.hProcess);
-	CloseHandle(childInfo.hThread);
-
-	*child_stdout = _open_osfhandle((intptr_t)childStdout[0], _O_RDONLY);
-	*child_stdin = _open_osfhandle((intptr_t)childStdin[1], _O_WRONLY);
-	
-	child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
-		childInfo.dwProcessId);
-	if (child == NULL) // INVALID_HANDLE_VALUE ?
-		goto fail;
-
-	*out_child = child;
-
-	CloseHandle(childStdout[1]);
-	CloseHandle(childStdin[0]);
-
-	archive_string_free(&cmdline);
-	archive_string_free(&fullpath);
-	__archive_cmdline_free(acmd);
-	return ARCHIVE_OK;
-
-fail:
-	if (childStdout[0] != INVALID_HANDLE_VALUE)
-		CloseHandle(childStdout[0]);
-	if (childStdout[1] != INVALID_HANDLE_VALUE)
-		CloseHandle(childStdout[1]);
-	if (childStdin[0] != INVALID_HANDLE_VALUE)
-		CloseHandle(childStdin[0]);
-	if (childStdin[1] != INVALID_HANDLE_VALUE)
-		CloseHandle(childStdin[1]);
-	if (childStderr != INVALID_HANDLE_VALUE)
-		CloseHandle(childStderr);
-	archive_string_free(&cmdline);
-	archive_string_free(&fullpath);
-	__archive_cmdline_free(acmd);
-	return ARCHIVE_FAILED;
-}
-#else /* !WINAPI_PARTITION_DESKTOP */
-int
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, HANDLE *out_child)
-{
-	(void)cmd; (void)child_stdin; (void) child_stdout; (void) out_child;
-	return ARCHIVE_FAILED;
-}
-#endif /* !WINAPI_PARTITION_DESKTOP */
-
-void
-__archive_check_child(int in, int out)
-{
-	(void)in; /* UNUSED */
-	(void)out; /* UNUSED */
-	Sleep(100);
-}
-
-#endif /* _WIN32 && !__CYGWIN__ */
diff --git a/c/xxhash.c b/c/xxhash.c
deleted file mode 100644
--- a/c/xxhash.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
-xxHash - Fast Hash algorithm
-Copyright (C) 2012-2014, Yann Collet.
-BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-You can contact the author at :
-- xxHash source repository : http://code.google.com/p/xxhash/
-*/
-#include "archive_platform.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "archive_xxhash.h"
-
-#ifdef HAVE_LIBLZ4
-
-/***************************************
-** Tuning parameters
-****************************************/
-/* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
-** For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
-** If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
-** You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
-*/
-#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
-#  define XXH_USE_UNALIGNED_ACCESS 1
-#endif
-
-/* XXH_ACCEPT_NULL_INPUT_POINTER :
-** If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
-** When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
-** This option has a very small performance cost (only measurable on small inputs).
-** By default, this option is disabled. To enable it, uncomment below define :
-** #define XXH_ACCEPT_NULL_INPUT_POINTER 1
-
-** XXH_FORCE_NATIVE_FORMAT :
-** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
-** Results are therefore identical for little-endian and big-endian CPU.
-** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
-** Should endian-independence be of no importance for your application, you may set the #define below to 1.
-** It will improve speed for Big-endian CPU.
-** This option has no impact on Little_Endian CPU.
-*/
-#define XXH_FORCE_NATIVE_FORMAT 0
-
-/***************************************
-** Compiler Specific Options
-****************************************/
-/* Disable some Visual warning messages */
-#ifdef _MSC_VER  /* Visual Studio */
-#  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
-#endif
-
-#ifdef _MSC_VER    /* Visual Studio */
-#  define FORCE_INLINE __forceinline
-#else
-#  ifdef __GNUC__
-#    define FORCE_INLINE inline __attribute__((always_inline))
-#  else
-#    define FORCE_INLINE inline
-#  endif
-#endif
-
-/***************************************
-** Includes & Memory related functions
-****************************************/
-#define XXH_malloc malloc
-#define XXH_free free
-#define XXH_memcpy memcpy
-
-
-static unsigned int	  XXH32 (const void*, unsigned int, unsigned int);
-static void*		  XXH32_init   (unsigned int);
-static XXH_errorcode	  XXH32_update (void*, const void*, unsigned int);
-static unsigned int	  XXH32_digest (void*);
-/*static int		  XXH32_sizeofState(void);*/
-static XXH_errorcode	  XXH32_resetState(void*, unsigned int);
-#define       XXH32_SIZEOFSTATE 48
-typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
-static unsigned int	  XXH32_intermediateDigest (void*);
-
-/***************************************
-** Basic Types
-****************************************/
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
-# include <stdint.h>
-  typedef uint8_t  BYTE;
-  typedef uint16_t U16;
-  typedef uint32_t U32;
-  typedef  int32_t S32;
-  typedef uint64_t U64;
-#else
-  typedef unsigned char      BYTE;
-  typedef unsigned short     U16;
-  typedef unsigned int       U32;
-  typedef   signed int       S32;
-  typedef unsigned long long U64;
-#endif
-
-#if defined(__GNUC__)  && !defined(XXH_USE_UNALIGNED_ACCESS)
-#  define _PACKED __attribute__ ((packed))
-#else
-#  define _PACKED
-#endif
-
-#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-#  ifdef __IBMC__
-#    pragma pack(1)
-#  else
-#    pragma pack(push, 1)
-#  endif
-#endif
-
-typedef struct _U32_S { U32 v; } _PACKED U32_S;
-
-#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-#  pragma pack(pop)
-#endif
-
-
-/****************************************
-** Compiler-specific Functions and Macros
-*****************************************/
-#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0))
-
-#if GCC_VERSION >= 409
-__attribute__((__no_sanitize_undefined__))
-#else
-#  if defined(__clang__)
-__attribute__((no_sanitize("undefined")))
-#  endif
-#endif
-#if defined(_MSC_VER)
-static __inline U32 A32(const void * x)
-#else
-static inline U32 A32(const void* x)
-#endif
-{
-    return (((const U32_S *)(x))->v);
-}
-
-/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
-#if defined(_MSC_VER)
-#  define XXH_rotl32(x,r) _rotl(x,r)
-#else
-#  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
-#endif
-
-#if defined(_MSC_VER)     /* Visual Studio */
-#  define XXH_swap32 _byteswap_ulong
-#elif GCC_VERSION >= 403
-#  define XXH_swap32 __builtin_bswap32
-#else
-static inline U32 XXH_swap32 (U32 x) {
-    return  ((x << 24) & 0xff000000 ) |
-			((x <<  8) & 0x00ff0000 ) |
-			((x >>  8) & 0x0000ff00 ) |
-			((x >> 24) & 0x000000ff );}
-#endif
-
-
-/***************************************
-** Constants
-****************************************/
-#define PRIME32_1   2654435761U
-#define PRIME32_2   2246822519U
-#define PRIME32_3   3266489917U
-#define PRIME32_4    668265263U
-#define PRIME32_5    374761393U
-
-
-/***************************************
-** Architecture Macros
-****************************************/
-typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
-#ifndef XXH_CPU_LITTLE_ENDIAN   /* It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch */
-    static const int one = 1;
-#   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&one))
-#endif
-
-
-/***************************************
-** Macros
-****************************************/
-#define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    /* use only *after* variable declarations */
-
-
-/*****************************
-** Memory reads
-******************************/
-typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
-
-static
-FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
-{
-    if (align==XXH_unaligned)
-        return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
-    else
-        return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
-}
-
-static
-FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
-
-
-/*****************************
-** Simple Hash Functions
-******************************/
-static
-FORCE_INLINE U32 XXH32_endian_align(const void* input, unsigned int len, U32 seed, XXH_endianess endian, XXH_alignment align)
-{
-    const BYTE* p = (const BYTE*)input;
-    const BYTE* bEnd = p + len;
-    U32 h32;
-#define XXH_get32bits(p) XXH_readLE32_align((const U32*)p, endian, align)
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
-    if (p==NULL) { len=0; bEnd=p=(const BYTE*)(size_t)16; }
-#endif
-
-    if (len>=16)
-    {
-        const BYTE* const limit = bEnd - 16;
-        U32 v1 = seed + PRIME32_1 + PRIME32_2;
-        U32 v2 = seed + PRIME32_2;
-        U32 v3 = seed + 0;
-        U32 v4 = seed - PRIME32_1;
-
-        do
-        {
-            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
-            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
-            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
-            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
-        } while (p<=limit);
-
-        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
-    }
-    else
-    {
-        h32  = seed + PRIME32_5;
-    }
-
-    h32 += (U32) len;
-
-    while (p<=bEnd-4)
-    {
-        h32 += XXH_get32bits(p) * PRIME32_3;
-        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
-        p+=4;
-    }
-
-    while (p<bEnd)
-    {
-        h32 += (*p) * PRIME32_5;
-        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
-        p++;
-    }
-
-    h32 ^= h32 >> 15;
-    h32 *= PRIME32_2;
-    h32 ^= h32 >> 13;
-    h32 *= PRIME32_3;
-    h32 ^= h32 >> 16;
-
-    return h32;
-}
-
-
-U32 XXH32(const void* input, unsigned int len, U32 seed)
-{
-#if 0
-    // Simple version, good for code maintenance, but unfortunately slow for small inputs
-    void* state = XXH32_init(seed);
-    XXH32_update(state, input, len);
-    return XXH32_digest(state);
-#else
-    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
-#  if !defined(XXH_USE_UNALIGNED_ACCESS)
-    if ((((size_t)input) & 3) == 0)   /* Input is aligned, let's leverage the speed advantage */
-    {
-        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-            return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
-        else
-            return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
-    }
-#  endif
-
-    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-        return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
-    else
-        return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
-#endif
-}
-
-/*****************************
-** Advanced Hash Functions
-******************************/
-
-struct XXH_state32_t
-{
-    U64 total_len;
-    U32 seed;
-    U32 v1;
-    U32 v2;
-    U32 v3;
-    U32 v4;
-    int memsize;
-    char memory[16];
-};
-
-#if 0
-static
-int XXH32_sizeofState(void)
-{
-    XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t));   /* A compilation error here means XXH32_SIZEOFSTATE is not large enough */
-    return sizeof(struct XXH_state32_t);
-}
-#endif
-
-static
-XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
-{
-    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-    state->seed = seed;
-    state->v1 = seed + PRIME32_1 + PRIME32_2;
-    state->v2 = seed + PRIME32_2;
-    state->v3 = seed + 0;
-    state->v4 = seed - PRIME32_1;
-    state->total_len = 0;
-    state->memsize = 0;
-    return XXH_OK;
-}
-
-static
-void* XXH32_init (U32 seed)
-{
-    void* state = XXH_malloc (sizeof(struct XXH_state32_t));
-    XXH32_resetState(state, seed);
-    return state;
-}
-
-static
-FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
-{
-    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-    const BYTE* p = (const BYTE*)input;
-    const BYTE* const bEnd = p + len;
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
-    if (input==NULL) return XXH_ERROR;
-#endif
-
-    state->total_len += len;
-
-    if (state->memsize + len < 16)   /* fill in tmp buffer */
-    {
-        XXH_memcpy(state->memory + state->memsize, input, len);
-        state->memsize +=  len;
-        return XXH_OK;
-    }
-
-    if (state->memsize)   /* some data left from previous update */
-    {
-        XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
-        {
-            const U32* p32 = (const U32*)state->memory;
-            state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
-            state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
-            state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
-            state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
-        }
-        p += 16-state->memsize;
-        state->memsize = 0;
-    }
-
-    if (p <= bEnd-16)
-    {
-        const BYTE* const limit = bEnd - 16;
-        U32 v1 = state->v1;
-        U32 v2 = state->v2;
-        U32 v3 = state->v3;
-        U32 v4 = state->v4;
-
-        do
-        {
-            v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
-            v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
-            v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
-            v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
-        } while (p<=limit);
-
-        state->v1 = v1;
-        state->v2 = v2;
-        state->v3 = v3;
-        state->v4 = v4;
-    }
-
-    if (p < bEnd)
-    {
-        XXH_memcpy(state->memory, p, bEnd-p);
-        state->memsize = (int)(bEnd-p);
-    }
-
-    return XXH_OK;
-}
-
-static
-XXH_errorcode XXH32_update (void* state_in, const void* input, unsigned int len)
-{
-    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
-    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-        return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
-    else
-        return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
-}
-
-
-
-static
-FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
-{
-    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-    const BYTE * p = (const BYTE*)state->memory;
-    BYTE* bEnd = (BYTE*)state->memory + state->memsize;
-    U32 h32;
-
-    if (state->total_len >= 16)
-    {
-        h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
-    }
-    else
-    {
-        h32  = state->seed + PRIME32_5;
-    }
-
-    h32 += (U32) state->total_len;
-
-    while (p<=bEnd-4)
-    {
-        h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
-        h32  = XXH_rotl32(h32, 17) * PRIME32_4;
-        p+=4;
-    }
-
-    while (p<bEnd)
-    {
-        h32 += (*p) * PRIME32_5;
-        h32 = XXH_rotl32(h32, 11) * PRIME32_1;
-        p++;
-    }
-
-    h32 ^= h32 >> 15;
-    h32 *= PRIME32_2;
-    h32 ^= h32 >> 13;
-    h32 *= PRIME32_3;
-    h32 ^= h32 >> 16;
-
-    return h32;
-}
-
-static
-U32 XXH32_intermediateDigest (void* state_in)
-{
-    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
-    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-        return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
-    else
-        return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
-}
-
-static
-U32 XXH32_digest (void* state_in)
-{
-    U32 h32 = XXH32_intermediateDigest(state_in);
-
-    XXH_free(state_in);
-
-    return h32;
-}
-
-const
-struct archive_xxhash __archive_xxhash = {
-	XXH32,
-	XXH32_init,
-	XXH32_update,
-	XXH32_digest
-};
-#else
-
-/*
- * Define an empty version of the struct if we aren't using the LZ4 library.
- */
-const
-struct archive_xxhash __archive_xxhash = {
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-#endif /* HAVE_LIBLZ4 */
diff --git a/c/zlib/adler32.c b/c/zlib/adler32.c
deleted file mode 100644
--- a/c/zlib/adler32.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2011, 2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#include "zutil.h"
-
-local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
-
-#define BASE 65521U     /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* use NO_DIVIDE if your processor does not do division in hardware --
-   try it both ways to see which is faster */
-#ifdef NO_DIVIDE
-/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
-   (thank you to John Reiser for pointing this out) */
-#  define CHOP(a) \
-    do { \
-        unsigned long tmp = a >> 16; \
-        a &= 0xffffUL; \
-        a += (tmp << 4) - tmp; \
-    } while (0)
-#  define MOD28(a) \
-    do { \
-        CHOP(a); \
-        if (a >= BASE) a -= BASE; \
-    } while (0)
-#  define MOD(a) \
-    do { \
-        CHOP(a); \
-        MOD28(a); \
-    } while (0)
-#  define MOD63(a) \
-    do { /* this assumes a is not negative */ \
-        z_off64_t tmp = a >> 32; \
-        a &= 0xffffffffL; \
-        a += (tmp << 8) - (tmp << 5) + tmp; \
-        tmp = a >> 16; \
-        a &= 0xffffL; \
-        a += (tmp << 4) - tmp; \
-        tmp = a >> 16; \
-        a &= 0xffffL; \
-        a += (tmp << 4) - tmp; \
-        if (a >= BASE) a -= BASE; \
-    } while (0)
-#else
-#  define MOD(a) a %= BASE
-#  define MOD28(a) a %= BASE
-#  define MOD63(a) a %= BASE
-#endif
-
-/* ========================================================================= */
-uLong ZEXPORT adler32_z(adler, buf, len)
-    uLong adler;
-    const Bytef *buf;
-    z_size_t len;
-{
-    unsigned long sum2;
-    unsigned n;
-
-    /* split Adler-32 into component sums */
-    sum2 = (adler >> 16) & 0xffff;
-    adler &= 0xffff;
-
-    /* in case user likes doing a byte at a time, keep it fast */
-    if (len == 1) {
-        adler += buf[0];
-        if (adler >= BASE)
-            adler -= BASE;
-        sum2 += adler;
-        if (sum2 >= BASE)
-            sum2 -= BASE;
-        return adler | (sum2 << 16);
-    }
-
-    /* initial Adler-32 value (deferred check for len == 1 speed) */
-    if (buf == Z_NULL)
-        return 1L;
-
-    /* in case short lengths are provided, keep it somewhat fast */
-    if (len < 16) {
-        while (len--) {
-            adler += *buf++;
-            sum2 += adler;
-        }
-        if (adler >= BASE)
-            adler -= BASE;
-        MOD28(sum2);            /* only added so many BASE's */
-        return adler | (sum2 << 16);
-    }
-
-    /* do length NMAX blocks -- requires just one modulo operation */
-    while (len >= NMAX) {
-        len -= NMAX;
-        n = NMAX / 16;          /* NMAX is divisible by 16 */
-        do {
-            DO16(buf);          /* 16 sums unrolled */
-            buf += 16;
-        } while (--n);
-        MOD(adler);
-        MOD(sum2);
-    }
-
-    /* do remaining bytes (less than NMAX, still just one modulo) */
-    if (len) {                  /* avoid modulos if none remaining */
-        while (len >= 16) {
-            len -= 16;
-            DO16(buf);
-            buf += 16;
-        }
-        while (len--) {
-            adler += *buf++;
-            sum2 += adler;
-        }
-        MOD(adler);
-        MOD(sum2);
-    }
-
-    /* return recombined sums */
-    return adler | (sum2 << 16);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT adler32(adler, buf, len)
-    uLong adler;
-    const Bytef *buf;
-    uInt len;
-{
-    return adler32_z(adler, buf, len);
-}
-
-/* ========================================================================= */
-local uLong adler32_combine_(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off64_t len2;
-{
-    unsigned long sum1;
-    unsigned long sum2;
-    unsigned rem;
-
-    /* for negative len, return invalid adler32 as a clue for debugging */
-    if (len2 < 0)
-        return 0xffffffffUL;
-
-    /* the derivation of this formula is left as an exercise for the reader */
-    MOD63(len2);                /* assumes len2 >= 0 */
-    rem = (unsigned)len2;
-    sum1 = adler1 & 0xffff;
-    sum2 = rem * sum1;
-    MOD(sum2);
-    sum1 += (adler2 & 0xffff) + BASE - 1;
-    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
-    if (sum1 >= BASE) sum1 -= BASE;
-    if (sum1 >= BASE) sum1 -= BASE;
-    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
-    if (sum2 >= BASE) sum2 -= BASE;
-    return sum1 | (sum2 << 16);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT adler32_combine(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
-
-uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off64_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
diff --git a/c/zlib/compress.c b/c/zlib/compress.c
deleted file mode 100644
--- a/c/zlib/compress.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* compress.c -- compress a memory buffer
- * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#define ZLIB_INTERNAL
-#include "zlib.h"
-
-/* ===========================================================================
-     Compresses the source buffer into the destination buffer. The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
-   destination buffer, which must be at least 0.1% larger than sourceLen plus
-   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-    int level;
-{
-    z_stream stream;
-    int err;
-    const uInt max = (uInt)-1;
-    uLong left;
-
-    left = *destLen;
-    *destLen = 0;
-
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-    stream.opaque = (voidpf)0;
-
-    err = deflateInit(&stream, level);
-    if (err != Z_OK) return err;
-
-    stream.next_out = dest;
-    stream.avail_out = 0;
-    stream.next_in = (z_const Bytef *)source;
-    stream.avail_in = 0;
-
-    do {
-        if (stream.avail_out == 0) {
-            stream.avail_out = left > (uLong)max ? max : (uInt)left;
-            left -= stream.avail_out;
-        }
-        if (stream.avail_in == 0) {
-            stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
-            sourceLen -= stream.avail_in;
-        }
-        err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
-    } while (err == Z_OK);
-
-    *destLen = stream.total_out;
-    deflateEnd(&stream);
-    return err == Z_STREAM_END ? Z_OK : err;
-}
-
-/* ===========================================================================
- */
-int ZEXPORT compress (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-{
-    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
-}
-
-/* ===========================================================================
-     If the default memLevel or windowBits for deflateInit() is changed, then
-   this function needs to be updated.
- */
-uLong ZEXPORT compressBound (sourceLen)
-    uLong sourceLen;
-{
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
-           (sourceLen >> 25) + 13;
-}
diff --git a/c/zlib/crc32.c b/c/zlib/crc32.c
deleted file mode 100644
--- a/c/zlib/crc32.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- *
- * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
- * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
- * tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors.  This results in about a
- * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
- */
-
-/* @(#) $Id$ */
-
-/*
-  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
-  protection on the static variables used to control the first-use generation
-  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
-  first call get_crc_table() to initialize the tables before allowing more than
-  one thread to use crc32().
-
-  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
- */
-
-#ifdef MAKECRCH
-#  include <stdio.h>
-#  ifndef DYNAMIC_CRC_TABLE
-#    define DYNAMIC_CRC_TABLE
-#  endif /* !DYNAMIC_CRC_TABLE */
-#endif /* MAKECRCH */
-
-#include "zutil.h"      /* for STDC and FAR definitions */
-
-/* Definitions for doing the crc four data bytes at a time. */
-#if !defined(NOBYFOUR) && defined(Z_U4)
-#  define BYFOUR
-#endif
-#ifdef BYFOUR
-   local unsigned long crc32_little OF((unsigned long,
-                        const unsigned char FAR *, z_size_t));
-   local unsigned long crc32_big OF((unsigned long,
-                        const unsigned char FAR *, z_size_t));
-#  define TBLS 8
-#else
-#  define TBLS 1
-#endif /* BYFOUR */
-
-/* Local functions for crc concatenation */
-local unsigned long gf2_matrix_times OF((unsigned long *mat,
-                                         unsigned long vec));
-local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
-local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
-
-
-#ifdef DYNAMIC_CRC_TABLE
-
-local volatile int crc_table_empty = 1;
-local z_crc_t FAR crc_table[TBLS][256];
-local void make_crc_table OF((void));
-#ifdef MAKECRCH
-   local void write_table OF((FILE *, const z_crc_t FAR *));
-#endif /* MAKECRCH */
-/*
-  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
-  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
-
-  Polynomials over GF(2) are represented in binary, one bit per coefficient,
-  with the lowest powers in the most significant bit.  Then adding polynomials
-  is just exclusive-or, and multiplying a polynomial by x is a right shift by
-  one.  If we call the above polynomial p, and represent a byte as the
-  polynomial q, also with the lowest power in the most significant bit (so the
-  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
-  where a mod b means the remainder after dividing a by b.
-
-  This calculation is done using the shift-register method of multiplying and
-  taking the remainder.  The register is initialized to zero, and for each
-  incoming bit, x^32 is added mod p to the register if the bit is a one (where
-  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
-  x (which is shifting right by one and adding x^32 mod p if the bit shifted
-  out is a one).  We start with the highest power (least significant bit) of
-  q and repeat for all eight bits of q.
-
-  The first table is simply the CRC of all possible eight bit values.  This is
-  all the information needed to generate CRCs on data a byte at a time for all
-  combinations of CRC register values and incoming bytes.  The remaining tables
-  allow for word-at-a-time CRC calculation for both big-endian and little-
-  endian machines, where a word is four bytes.
-*/
-local void make_crc_table()
-{
-    z_crc_t c;
-    int n, k;
-    z_crc_t poly;                       /* polynomial exclusive-or pattern */
-    /* terms of polynomial defining this crc (except x^32): */
-    static volatile int first = 1;      /* flag to limit concurrent making */
-    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-    /* See if another task is already doing this (not thread-safe, but better
-       than nothing -- significantly reduces duration of vulnerability in
-       case the advice about DYNAMIC_CRC_TABLE is ignored) */
-    if (first) {
-        first = 0;
-
-        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
-        poly = 0;
-        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
-            poly |= (z_crc_t)1 << (31 - p[n]);
-
-        /* generate a crc for every 8-bit value */
-        for (n = 0; n < 256; n++) {
-            c = (z_crc_t)n;
-            for (k = 0; k < 8; k++)
-                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
-            crc_table[0][n] = c;
-        }
-
-#ifdef BYFOUR
-        /* generate crc for each value followed by one, two, and three zeros,
-           and then the byte reversal of those as well as the first table */
-        for (n = 0; n < 256; n++) {
-            c = crc_table[0][n];
-            crc_table[4][n] = ZSWAP32(c);
-            for (k = 1; k < 4; k++) {
-                c = crc_table[0][c & 0xff] ^ (c >> 8);
-                crc_table[k][n] = c;
-                crc_table[k + 4][n] = ZSWAP32(c);
-            }
-        }
-#endif /* BYFOUR */
-
-        crc_table_empty = 0;
-    }
-    else {      /* not first */
-        /* wait for the other guy to finish (not efficient, but rare) */
-        while (crc_table_empty)
-            ;
-    }
-
-#ifdef MAKECRCH
-    /* write out CRC tables to crc32.h */
-    {
-        FILE *out;
-
-        out = fopen("crc32.h", "w");
-        if (out == NULL) return;
-        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
-        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
-        fprintf(out, "local const z_crc_t FAR ");
-        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
-        write_table(out, crc_table[0]);
-#  ifdef BYFOUR
-        fprintf(out, "#ifdef BYFOUR\n");
-        for (k = 1; k < 8; k++) {
-            fprintf(out, "  },\n  {\n");
-            write_table(out, crc_table[k]);
-        }
-        fprintf(out, "#endif\n");
-#  endif /* BYFOUR */
-        fprintf(out, "  }\n};\n");
-        fclose(out);
-    }
-#endif /* MAKECRCH */
-}
-
-#ifdef MAKECRCH
-local void write_table(out, table)
-    FILE *out;
-    const z_crc_t FAR *table;
-{
-    int n;
-
-    for (n = 0; n < 256; n++)
-        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
-                (unsigned long)(table[n]),
-                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
-}
-#endif /* MAKECRCH */
-
-#else /* !DYNAMIC_CRC_TABLE */
-/* ========================================================================
- * Tables of CRC-32s of all single-byte values, made by make_crc_table().
- */
-#include "crc32.h"
-#endif /* DYNAMIC_CRC_TABLE */
-
-/* =========================================================================
- * This function can be used by asm versions of crc32()
- */
-const z_crc_t FAR * ZEXPORT get_crc_table()
-{
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-        make_crc_table();
-#endif /* DYNAMIC_CRC_TABLE */
-    return (const z_crc_t FAR *)crc_table;
-}
-
-/* ========================================================================= */
-#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
-#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
-
-/* ========================================================================= */
-unsigned long ZEXPORT crc32_z(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    z_size_t len;
-{
-    if (buf == Z_NULL) return 0UL;
-
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-        make_crc_table();
-#endif /* DYNAMIC_CRC_TABLE */
-
-#ifdef BYFOUR
-    if (sizeof(void *) == sizeof(ptrdiff_t)) {
-        z_crc_t endian;
-
-        endian = 1;
-        if (*((unsigned char *)(&endian)))
-            return crc32_little(crc, buf, len);
-        else
-            return crc32_big(crc, buf, len);
-    }
-#endif /* BYFOUR */
-    crc = crc ^ 0xffffffffUL;
-    while (len >= 8) {
-        DO8;
-        len -= 8;
-    }
-    if (len) do {
-        DO1;
-    } while (--len);
-    return crc ^ 0xffffffffUL;
-}
-
-/* ========================================================================= */
-unsigned long ZEXPORT crc32(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    uInt len;
-{
-    return crc32_z(crc, buf, len);
-}
-
-#ifdef BYFOUR
-
-/*
-   This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
-   integer pointer type. This violates the strict aliasing rule, where a
-   compiler can assume, for optimization purposes, that two pointers to
-   fundamentally different types won't ever point to the same memory. This can
-   manifest as a problem only if one of the pointers is written to. This code
-   only reads from those pointers. So long as this code remains isolated in
-   this compilation unit, there won't be a problem. For this reason, this code
-   should not be copied and pasted into a compilation unit in which other code
-   writes to the buffer that is passed to these routines.
- */
-
-/* ========================================================================= */
-#define DOLIT4 c ^= *buf4++; \
-        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
-            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
-#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
-
-/* ========================================================================= */
-local unsigned long crc32_little(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    z_size_t len;
-{
-    register z_crc_t c;
-    register const z_crc_t FAR *buf4;
-
-    c = (z_crc_t)crc;
-    c = ~c;
-    while (len && ((ptrdiff_t)buf & 3)) {
-        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
-        len--;
-    }
-
-    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
-    while (len >= 32) {
-        DOLIT32;
-        len -= 32;
-    }
-    while (len >= 4) {
-        DOLIT4;
-        len -= 4;
-    }
-    buf = (const unsigned char FAR *)buf4;
-
-    if (len) do {
-        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
-    } while (--len);
-    c = ~c;
-    return (unsigned long)c;
-}
-
-/* ========================================================================= */
-#define DOBIG4 c ^= *buf4++; \
-        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
-            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
-#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
-
-/* ========================================================================= */
-local unsigned long crc32_big(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    z_size_t len;
-{
-    register z_crc_t c;
-    register const z_crc_t FAR *buf4;
-
-    c = ZSWAP32((z_crc_t)crc);
-    c = ~c;
-    while (len && ((ptrdiff_t)buf & 3)) {
-        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
-        len--;
-    }
-
-    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
-    while (len >= 32) {
-        DOBIG32;
-        len -= 32;
-    }
-    while (len >= 4) {
-        DOBIG4;
-        len -= 4;
-    }
-    buf = (const unsigned char FAR *)buf4;
-
-    if (len) do {
-        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
-    } while (--len);
-    c = ~c;
-    return (unsigned long)(ZSWAP32(c));
-}
-
-#endif /* BYFOUR */
-
-#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
-
-/* ========================================================================= */
-local unsigned long gf2_matrix_times(mat, vec)
-    unsigned long *mat;
-    unsigned long vec;
-{
-    unsigned long sum;
-
-    sum = 0;
-    while (vec) {
-        if (vec & 1)
-            sum ^= *mat;
-        vec >>= 1;
-        mat++;
-    }
-    return sum;
-}
-
-/* ========================================================================= */
-local void gf2_matrix_square(square, mat)
-    unsigned long *square;
-    unsigned long *mat;
-{
-    int n;
-
-    for (n = 0; n < GF2_DIM; n++)
-        square[n] = gf2_matrix_times(mat, mat[n]);
-}
-
-/* ========================================================================= */
-local uLong crc32_combine_(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off64_t len2;
-{
-    int n;
-    unsigned long row;
-    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
-    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
-
-    /* degenerate case (also disallow negative lengths) */
-    if (len2 <= 0)
-        return crc1;
-
-    /* put operator for one zero bit in odd */
-    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
-    row = 1;
-    for (n = 1; n < GF2_DIM; n++) {
-        odd[n] = row;
-        row <<= 1;
-    }
-
-    /* put operator for two zero bits in even */
-    gf2_matrix_square(even, odd);
-
-    /* put operator for four zero bits in odd */
-    gf2_matrix_square(odd, even);
-
-    /* apply len2 zeros to crc1 (first square will put the operator for one
-       zero byte, eight zero bits, in even) */
-    do {
-        /* apply zeros operator for this bit of len2 */
-        gf2_matrix_square(even, odd);
-        if (len2 & 1)
-            crc1 = gf2_matrix_times(even, crc1);
-        len2 >>= 1;
-
-        /* if no more bits set, then done */
-        if (len2 == 0)
-            break;
-
-        /* another iteration of the loop with odd and even swapped */
-        gf2_matrix_square(odd, even);
-        if (len2 & 1)
-            crc1 = gf2_matrix_times(odd, crc1);
-        len2 >>= 1;
-
-        /* if no more bits set, then done */
-    } while (len2 != 0);
-
-    /* return combined crc */
-    crc1 ^= crc2;
-    return crc1;
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
-
-uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off64_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
diff --git a/c/zlib/crc32.h b/c/zlib/crc32.h
deleted file mode 100644
--- a/c/zlib/crc32.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/* crc32.h -- tables for rapid CRC calculation
- * Generated automatically by crc32.c
- */
-
-local const z_crc_t FAR crc_table[TBLS][256] =
-{
-  {
-    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
-    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
-    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
-    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
-    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
-    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
-    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
-    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
-    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
-    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
-    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
-    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
-    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
-    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
-    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
-    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
-    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
-    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
-    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
-    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
-    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
-    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
-    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
-    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
-    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
-    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
-    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
-    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
-    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
-    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
-    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
-    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
-    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
-    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
-    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
-    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
-    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
-    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
-    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
-    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
-    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
-    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
-    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
-    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
-    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
-    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
-    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
-    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
-    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
-    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
-    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
-    0x2d02ef8dUL
-#ifdef BYFOUR
-  },
-  {
-    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
-    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
-    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
-    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
-    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
-    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
-    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
-    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
-    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
-    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
-    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
-    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
-    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
-    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
-    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
-    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
-    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
-    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
-    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
-    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
-    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
-    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
-    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
-    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
-    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
-    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
-    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
-    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
-    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
-    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
-    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
-    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
-    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
-    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
-    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
-    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
-    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
-    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
-    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
-    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
-    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
-    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
-    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
-    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
-    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
-    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
-    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
-    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
-    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
-    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
-    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
-    0x9324fd72UL
-  },
-  {
-    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
-    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
-    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
-    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
-    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
-    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
-    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
-    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
-    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
-    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
-    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
-    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
-    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
-    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
-    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
-    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
-    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
-    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
-    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
-    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
-    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
-    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
-    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
-    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
-    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
-    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
-    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
-    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
-    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
-    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
-    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
-    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
-    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
-    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
-    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
-    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
-    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
-    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
-    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
-    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
-    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
-    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
-    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
-    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
-    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
-    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
-    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
-    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
-    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
-    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
-    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
-    0xbe9834edUL
-  },
-  {
-    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
-    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
-    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
-    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
-    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
-    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
-    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
-    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
-    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
-    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
-    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
-    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
-    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
-    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
-    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
-    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
-    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
-    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
-    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
-    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
-    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
-    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
-    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
-    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
-    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
-    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
-    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
-    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
-    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
-    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
-    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
-    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
-    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
-    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
-    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
-    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
-    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
-    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
-    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
-    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
-    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
-    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
-    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
-    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
-    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
-    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
-    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
-    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
-    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
-    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
-    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
-    0xde0506f1UL
-  },
-  {
-    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
-    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
-    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
-    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
-    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
-    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
-    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
-    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
-    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
-    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
-    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
-    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
-    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
-    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
-    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
-    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
-    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
-    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
-    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
-    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
-    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
-    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
-    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
-    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
-    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
-    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
-    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
-    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
-    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
-    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
-    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
-    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
-    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
-    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
-    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
-    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
-    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
-    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
-    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
-    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
-    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
-    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
-    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
-    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
-    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
-    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
-    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
-    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
-    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
-    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
-    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
-    0x8def022dUL
-  },
-  {
-    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
-    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
-    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
-    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
-    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
-    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
-    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
-    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
-    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
-    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
-    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
-    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
-    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
-    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
-    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
-    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
-    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
-    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
-    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
-    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
-    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
-    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
-    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
-    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
-    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
-    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
-    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
-    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
-    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
-    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
-    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
-    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
-    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
-    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
-    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
-    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
-    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
-    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
-    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
-    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
-    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
-    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
-    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
-    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
-    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
-    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
-    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
-    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
-    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
-    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
-    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
-    0x72fd2493UL
-  },
-  {
-    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
-    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
-    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
-    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
-    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
-    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
-    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
-    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
-    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
-    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
-    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
-    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
-    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
-    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
-    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
-    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
-    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
-    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
-    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
-    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
-    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
-    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
-    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
-    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
-    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
-    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
-    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
-    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
-    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
-    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
-    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
-    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
-    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
-    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
-    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
-    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
-    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
-    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
-    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
-    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
-    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
-    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
-    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
-    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
-    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
-    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
-    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
-    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
-    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
-    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
-    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
-    0xed3498beUL
-  },
-  {
-    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
-    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
-    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
-    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
-    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
-    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
-    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
-    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
-    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
-    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
-    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
-    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
-    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
-    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
-    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
-    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
-    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
-    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
-    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
-    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
-    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
-    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
-    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
-    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
-    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
-    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
-    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
-    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
-    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
-    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
-    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
-    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
-    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
-    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
-    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
-    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
-    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
-    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
-    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
-    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
-    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
-    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
-    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
-    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
-    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
-    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
-    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
-    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
-    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
-    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
-    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
-    0xf10605deUL
-#endif
-  }
-};
diff --git a/c/zlib/deflate.c b/c/zlib/deflate.c
deleted file mode 100644
--- a/c/zlib/deflate.c
+++ /dev/null
@@ -1,2163 +0,0 @@
-/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process depends on being able to identify portions
- *      of the input text which are identical to earlier input (within a
- *      sliding window trailing behind the input currently being processed).
- *
- *      The most straightforward technique turns out to be the fastest for
- *      most input files: try all possible matches and select the longest.
- *      The key feature of this algorithm is that insertions into the string
- *      dictionary are very simple and thus fast, and deletions are avoided
- *      completely. Insertions are performed at each input character, whereas
- *      string matches are performed only when the previous match ends. So it
- *      is preferable to spend more time in matches to allow very fast string
- *      insertions and avoid deletions. The matching algorithm for small
- *      strings is inspired from that of Rabin & Karp. A brute force approach
- *      is used to find longer strings when a small match has been found.
- *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- *      (by Leonid Broukhis).
- *         A previous version of this file used a more sophisticated algorithm
- *      (by Fiala and Greene) which is guaranteed to run in linear amortized
- *      time, but has a larger average cost, uses more memory and is patented.
- *      However the F&G algorithm may be faster for some highly redundant
- *      files if the parameter max_chain_length (described below) is too large.
- *
- *  ACKNOWLEDGEMENTS
- *
- *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- *      I found it in 'freeze' written by Leonid Broukhis.
- *      Thanks to many people for bug reports and testing.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- *      Available in http://tools.ietf.org/html/rfc1951
- *
- *      A description of the Rabin and Karp algorithm is given in the book
- *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- *      Fiala,E.R., and Greene,D.H.
- *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- */
-
-/* @(#) $Id$ */
-
-#include "deflate.h"
-
-const char deflate_copyright[] =
-   " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/* ===========================================================================
- *  Function prototypes.
- */
-typedef enum {
-    need_more,      /* block not completed, need more input or more output */
-    block_done,     /* block flush performed */
-    finish_started, /* finish started, need only more output at next deflate */
-    finish_done     /* finish done, accept no more input or output */
-} block_state;
-
-typedef block_state (*compress_func) OF((deflate_state *s, int flush));
-/* Compression function. Returns the block state after the call. */
-
-local int deflateStateCheck      OF((z_streamp strm));
-local void slide_hash     OF((deflate_state *s));
-local void fill_window    OF((deflate_state *s));
-local block_state deflate_stored OF((deflate_state *s, int flush));
-local block_state deflate_fast   OF((deflate_state *s, int flush));
-#ifndef FASTEST
-local block_state deflate_slow   OF((deflate_state *s, int flush));
-#endif
-local block_state deflate_rle    OF((deflate_state *s, int flush));
-local block_state deflate_huff   OF((deflate_state *s, int flush));
-local void lm_init        OF((deflate_state *s));
-local void putShortMSB    OF((deflate_state *s, uInt b));
-local void flush_pending  OF((z_streamp strm));
-local unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifdef ASMV
-#  pragma message("Assembler code may have bugs -- use at your own risk")
-      void match_init OF((void)); /* asm code initialization */
-      uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#else
-local uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#endif
-
-#ifdef ZLIB_DEBUG
-local  void check_match OF((deflate_state *s, IPos start, IPos match,
-                            int length));
-#endif
-
-/* ===========================================================================
- * Local data
- */
-
-#define NIL 0
-/* Tail of hash chains */
-
-#ifndef TOO_FAR
-#  define TOO_FAR 4096
-#endif
-/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-typedef struct config_s {
-   ush good_length; /* reduce lazy search above this match length */
-   ush max_lazy;    /* do not perform lazy search above this match length */
-   ush nice_length; /* quit search above this match length */
-   ush max_chain;
-   compress_func func;
-} config;
-
-#ifdef FASTEST
-local const config configuration_table[2] = {
-/*      good lazy nice chain */
-/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
-/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
-#else
-local const config configuration_table[10] = {
-/*      good lazy nice chain */
-/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
-/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
-/* 2 */ {4,    5, 16,    8, deflate_fast},
-/* 3 */ {4,    6, 32,   32, deflate_fast},
-
-/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
-/* 5 */ {8,   16, 32,   32, deflate_slow},
-/* 6 */ {8,   16, 128, 128, deflate_slow},
-/* 7 */ {8,   32, 128, 256, deflate_slow},
-/* 8 */ {32, 128, 258, 1024, deflate_slow},
-/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
-#endif
-
-/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
-
-/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
-#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
-
-/* ===========================================================================
- * Update a hash value with the given input byte
- * IN  assertion: all calls to UPDATE_HASH are made with consecutive input
- *    characters, so that a running hash key can be computed from the previous
- *    key instead of complete recalculation each time.
- */
-#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
-
-
-/* ===========================================================================
- * Insert string str in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * If this file is compiled with -DFASTEST, the compression level is forced
- * to 1, and no hash chains are maintained.
- * IN  assertion: all calls to INSERT_STRING are made with consecutive input
- *    characters and the first MIN_MATCH bytes of str are valid (except for
- *    the last MIN_MATCH-1 bytes of the input file).
- */
-#ifdef FASTEST
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    match_head = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#else
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#endif
-
-/* ===========================================================================
- * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
-#define CLEAR_HASH(s) \
-    s->head[s->hash_size-1] = NIL; \
-    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
-
-/* ===========================================================================
- * Slide the hash table when sliding the window down (could be avoided with 32
- * bit values at the expense of memory usage). We slide even when level == 0 to
- * keep the hash table consistent if we switch back to level > 0 later.
- */
-local void slide_hash(s)
-    deflate_state *s;
-{
-    unsigned n, m;
-    Posf *p;
-    uInt wsize = s->w_size;
-
-    n = s->hash_size;
-    p = &s->head[n];
-    do {
-        m = *--p;
-        *p = (Pos)(m >= wsize ? m - wsize : NIL);
-    } while (--n);
-    n = wsize;
-#ifndef FASTEST
-    p = &s->prev[n];
-    do {
-        m = *--p;
-        *p = (Pos)(m >= wsize ? m - wsize : NIL);
-        /* If n is not on any hash chain, prev[n] is garbage but
-         * its value will never be used.
-         */
-    } while (--n);
-#endif
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit_(strm, level, version, stream_size)
-    z_streamp strm;
-    int level;
-    const char *version;
-    int stream_size;
-{
-    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
-                         Z_DEFAULT_STRATEGY, version, stream_size);
-    /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
-                  version, stream_size)
-    z_streamp strm;
-    int  level;
-    int  method;
-    int  windowBits;
-    int  memLevel;
-    int  strategy;
-    const char *version;
-    int stream_size;
-{
-    deflate_state *s;
-    int wrap = 1;
-    static const char my_version[] = ZLIB_VERSION;
-
-    ushf *overlay;
-    /* We overlay pending_buf and d_buf+l_buf. This works since the average
-     * output size for (length,distance) codes is <= 24 bits.
-     */
-
-    if (version == Z_NULL || version[0] != my_version[0] ||
-        stream_size != sizeof(z_stream)) {
-        return Z_VERSION_ERROR;
-    }
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-
-    strm->msg = Z_NULL;
-    if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-#endif
-    }
-    if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zfree = zcfree;
-#endif
-
-#ifdef FASTEST
-    if (level != 0) level = 1;
-#else
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
-
-    if (windowBits < 0) { /* suppress zlib wrapper */
-        wrap = 0;
-        windowBits = -windowBits;
-    }
-#ifdef GZIP
-    else if (windowBits > 15) {
-        wrap = 2;       /* write gzip wrapper instead */
-        windowBits -= 16;
-    }
-#endif
-    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
-        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
-        strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
-        return Z_STREAM_ERROR;
-    }
-    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
-    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
-    if (s == Z_NULL) return Z_MEM_ERROR;
-    strm->state = (struct internal_state FAR *)s;
-    s->strm = strm;
-    s->status = INIT_STATE;     /* to pass state test in deflateReset() */
-
-    s->wrap = wrap;
-    s->gzhead = Z_NULL;
-    s->w_bits = (uInt)windowBits;
-    s->w_size = 1 << s->w_bits;
-    s->w_mask = s->w_size - 1;
-
-    s->hash_bits = (uInt)memLevel + 7;
-    s->hash_size = 1 << s->hash_bits;
-    s->hash_mask = s->hash_size - 1;
-    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
-
-    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
-    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
-    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
-
-    s->high_water = 0;      /* nothing written to s->window yet */
-
-    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
-    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
-    s->pending_buf = (uchf *) overlay;
-    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
-
-    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
-        s->pending_buf == Z_NULL) {
-        s->status = FINISH_STATE;
-        strm->msg = ERR_MSG(Z_MEM_ERROR);
-        deflateEnd (strm);
-        return Z_MEM_ERROR;
-    }
-    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
-    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
-
-    s->level = level;
-    s->strategy = strategy;
-    s->method = (Byte)method;
-
-    return deflateReset(strm);
-}
-
-/* =========================================================================
- * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
- */
-local int deflateStateCheck (strm)
-    z_streamp strm;
-{
-    deflate_state *s;
-    if (strm == Z_NULL ||
-        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
-        return 1;
-    s = strm->state;
-    if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
-#ifdef GZIP
-                                           s->status != GZIP_STATE &&
-#endif
-                                           s->status != EXTRA_STATE &&
-                                           s->status != NAME_STATE &&
-                                           s->status != COMMENT_STATE &&
-                                           s->status != HCRC_STATE &&
-                                           s->status != BUSY_STATE &&
-                                           s->status != FINISH_STATE))
-        return 1;
-    return 0;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
-    z_streamp strm;
-    const Bytef *dictionary;
-    uInt  dictLength;
-{
-    deflate_state *s;
-    uInt str, n;
-    int wrap;
-    unsigned avail;
-    z_const unsigned char *next;
-
-    if (deflateStateCheck(strm) || dictionary == Z_NULL)
-        return Z_STREAM_ERROR;
-    s = strm->state;
-    wrap = s->wrap;
-    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
-        return Z_STREAM_ERROR;
-
-    /* when using zlib wrappers, compute Adler-32 for provided dictionary */
-    if (wrap == 1)
-        strm->adler = adler32(strm->adler, dictionary, dictLength);
-    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
-
-    /* if dictionary would fill window, just replace the history */
-    if (dictLength >= s->w_size) {
-        if (wrap == 0) {            /* already empty otherwise */
-            CLEAR_HASH(s);
-            s->strstart = 0;
-            s->block_start = 0L;
-            s->insert = 0;
-        }
-        dictionary += dictLength - s->w_size;  /* use the tail */
-        dictLength = s->w_size;
-    }
-
-    /* insert dictionary into window and hash */
-    avail = strm->avail_in;
-    next = strm->next_in;
-    strm->avail_in = dictLength;
-    strm->next_in = (z_const Bytef *)dictionary;
-    fill_window(s);
-    while (s->lookahead >= MIN_MATCH) {
-        str = s->strstart;
-        n = s->lookahead - (MIN_MATCH-1);
-        do {
-            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
-#ifndef FASTEST
-            s->prev[str & s->w_mask] = s->head[s->ins_h];
-#endif
-            s->head[s->ins_h] = (Pos)str;
-            str++;
-        } while (--n);
-        s->strstart = str;
-        s->lookahead = MIN_MATCH-1;
-        fill_window(s);
-    }
-    s->strstart += s->lookahead;
-    s->block_start = (long)s->strstart;
-    s->insert = s->lookahead;
-    s->lookahead = 0;
-    s->match_length = s->prev_length = MIN_MATCH-1;
-    s->match_available = 0;
-    strm->next_in = next;
-    strm->avail_in = avail;
-    s->wrap = wrap;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
-    z_streamp strm;
-    Bytef *dictionary;
-    uInt  *dictLength;
-{
-    deflate_state *s;
-    uInt len;
-
-    if (deflateStateCheck(strm))
-        return Z_STREAM_ERROR;
-    s = strm->state;
-    len = s->strstart + s->lookahead;
-    if (len > s->w_size)
-        len = s->w_size;
-    if (dictionary != Z_NULL && len)
-        zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
-    if (dictLength != Z_NULL)
-        *dictLength = len;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateResetKeep (strm)
-    z_streamp strm;
-{
-    deflate_state *s;
-
-    if (deflateStateCheck(strm)) {
-        return Z_STREAM_ERROR;
-    }
-
-    strm->total_in = strm->total_out = 0;
-    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
-    strm->data_type = Z_UNKNOWN;
-
-    s = (deflate_state *)strm->state;
-    s->pending = 0;
-    s->pending_out = s->pending_buf;
-
-    if (s->wrap < 0) {
-        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
-    }
-    s->status =
-#ifdef GZIP
-        s->wrap == 2 ? GZIP_STATE :
-#endif
-        s->wrap ? INIT_STATE : BUSY_STATE;
-    strm->adler =
-#ifdef GZIP
-        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
-#endif
-        adler32(0L, Z_NULL, 0);
-    s->last_flush = Z_NO_FLUSH;
-
-    _tr_init(s);
-
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateReset (strm)
-    z_streamp strm;
-{
-    int ret;
-
-    ret = deflateResetKeep(strm);
-    if (ret == Z_OK)
-        lm_init(strm->state);
-    return ret;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetHeader (strm, head)
-    z_streamp strm;
-    gz_headerp head;
-{
-    if (deflateStateCheck(strm) || strm->state->wrap != 2)
-        return Z_STREAM_ERROR;
-    strm->state->gzhead = head;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflatePending (strm, pending, bits)
-    unsigned *pending;
-    int *bits;
-    z_streamp strm;
-{
-    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-    if (pending != Z_NULL)
-        *pending = strm->state->pending;
-    if (bits != Z_NULL)
-        *bits = strm->state->bi_valid;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflatePrime (strm, bits, value)
-    z_streamp strm;
-    int bits;
-    int value;
-{
-    deflate_state *s;
-    int put;
-
-    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-    s = strm->state;
-    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
-        return Z_BUF_ERROR;
-    do {
-        put = Buf_size - s->bi_valid;
-        if (put > bits)
-            put = bits;
-        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
-        s->bi_valid += put;
-        _tr_flush_bits(s);
-        value >>= put;
-        bits -= put;
-    } while (bits);
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateParams(strm, level, strategy)
-    z_streamp strm;
-    int level;
-    int strategy;
-{
-    deflate_state *s;
-    compress_func func;
-
-    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-    s = strm->state;
-
-#ifdef FASTEST
-    if (level != 0) level = 1;
-#else
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
-    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
-        return Z_STREAM_ERROR;
-    }
-    func = configuration_table[s->level].func;
-
-    if ((strategy != s->strategy || func != configuration_table[level].func) &&
-        s->high_water) {
-        /* Flush the last buffer: */
-        int err = deflate(strm, Z_BLOCK);
-        if (err == Z_STREAM_ERROR)
-            return err;
-        if (strm->avail_out == 0)
-            return Z_BUF_ERROR;
-    }
-    if (s->level != level) {
-        if (s->level == 0 && s->matches != 0) {
-            if (s->matches == 1)
-                slide_hash(s);
-            else
-                CLEAR_HASH(s);
-            s->matches = 0;
-        }
-        s->level = level;
-        s->max_lazy_match   = configuration_table[level].max_lazy;
-        s->good_match       = configuration_table[level].good_length;
-        s->nice_match       = configuration_table[level].nice_length;
-        s->max_chain_length = configuration_table[level].max_chain;
-    }
-    s->strategy = strategy;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
-    z_streamp strm;
-    int good_length;
-    int max_lazy;
-    int nice_length;
-    int max_chain;
-{
-    deflate_state *s;
-
-    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-    s = strm->state;
-    s->good_match = (uInt)good_length;
-    s->max_lazy_match = (uInt)max_lazy;
-    s->nice_match = nice_length;
-    s->max_chain_length = (uInt)max_chain;
-    return Z_OK;
-}
-
-/* =========================================================================
- * For the default windowBits of 15 and memLevel of 8, this function returns
- * a close to exact, as well as small, upper bound on the compressed size.
- * They are coded as constants here for a reason--if the #define's are
- * changed, then this function needs to be changed as well.  The return
- * value for 15 and 8 only works for those exact settings.
- *
- * For any setting other than those defaults for windowBits and memLevel,
- * the value returned is a conservative worst case for the maximum expansion
- * resulting from using fixed blocks instead of stored blocks, which deflate
- * can emit on compressed data for some combinations of the parameters.
- *
- * This function could be more sophisticated to provide closer upper bounds for
- * every combination of windowBits and memLevel.  But even the conservative
- * upper bound of about 14% expansion does not seem onerous for output buffer
- * allocation.
- */
-uLong ZEXPORT deflateBound(strm, sourceLen)
-    z_streamp strm;
-    uLong sourceLen;
-{
-    deflate_state *s;
-    uLong complen, wraplen;
-
-    /* conservative upper bound for compressed data */
-    complen = sourceLen +
-              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
-
-    /* if can't get parameters, return conservative bound plus zlib wrapper */
-    if (deflateStateCheck(strm))
-        return complen + 6;
-
-    /* compute wrapper length */
-    s = strm->state;
-    switch (s->wrap) {
-    case 0:                                 /* raw deflate */
-        wraplen = 0;
-        break;
-    case 1:                                 /* zlib wrapper */
-        wraplen = 6 + (s->strstart ? 4 : 0);
-        break;
-#ifdef GZIP
-    case 2:                                 /* gzip wrapper */
-        wraplen = 18;
-        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
-            Bytef *str;
-            if (s->gzhead->extra != Z_NULL)
-                wraplen += 2 + s->gzhead->extra_len;
-            str = s->gzhead->name;
-            if (str != Z_NULL)
-                do {
-                    wraplen++;
-                } while (*str++);
-            str = s->gzhead->comment;
-            if (str != Z_NULL)
-                do {
-                    wraplen++;
-                } while (*str++);
-            if (s->gzhead->hcrc)
-                wraplen += 2;
-        }
-        break;
-#endif
-    default:                                /* for compiler happiness */
-        wraplen = 6;
-    }
-
-    /* if not default parameters, return conservative bound */
-    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
-        return complen + wraplen;
-
-    /* default settings: return tight bound for that case */
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
-           (sourceLen >> 25) + 13 - 6 + wraplen;
-}
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-local void putShortMSB (s, b)
-    deflate_state *s;
-    uInt b;
-{
-    put_byte(s, (Byte)(b >> 8));
-    put_byte(s, (Byte)(b & 0xff));
-}
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output, except for
- * some deflate_stored() output, goes through this function so some
- * applications may wish to modify it to avoid allocating a large
- * strm->next_out buffer and copying into it. (See also read_buf()).
- */
-local void flush_pending(strm)
-    z_streamp strm;
-{
-    unsigned len;
-    deflate_state *s = strm->state;
-
-    _tr_flush_bits(s);
-    len = s->pending;
-    if (len > strm->avail_out) len = strm->avail_out;
-    if (len == 0) return;
-
-    zmemcpy(strm->next_out, s->pending_out, len);
-    strm->next_out  += len;
-    s->pending_out  += len;
-    strm->total_out += len;
-    strm->avail_out -= len;
-    s->pending      -= len;
-    if (s->pending == 0) {
-        s->pending_out = s->pending_buf;
-    }
-}
-
-/* ===========================================================================
- * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
- */
-#define HCRC_UPDATE(beg) \
-    do { \
-        if (s->gzhead->hcrc && s->pending > (beg)) \
-            strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
-                                s->pending - (beg)); \
-    } while (0)
-
-/* ========================================================================= */
-int ZEXPORT deflate (strm, flush)
-    z_streamp strm;
-    int flush;
-{
-    int old_flush; /* value of flush param for previous deflate call */
-    deflate_state *s;
-
-    if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
-        return Z_STREAM_ERROR;
-    }
-    s = strm->state;
-
-    if (strm->next_out == Z_NULL ||
-        (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
-        (s->status == FINISH_STATE && flush != Z_FINISH)) {
-        ERR_RETURN(strm, Z_STREAM_ERROR);
-    }
-    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
-
-    old_flush = s->last_flush;
-    s->last_flush = flush;
-
-    /* Flush as much pending output as possible */
-    if (s->pending != 0) {
-        flush_pending(strm);
-        if (strm->avail_out == 0) {
-            /* Since avail_out is 0, deflate will be called again with
-             * more output space, but possibly with both pending and
-             * avail_in equal to zero. There won't be anything to do,
-             * but this is not an error situation so make sure we
-             * return OK instead of BUF_ERROR at next call of deflate:
-             */
-            s->last_flush = -1;
-            return Z_OK;
-        }
-
-    /* Make sure there is something to do and avoid duplicate consecutive
-     * flushes. For repeated and useless calls with Z_FINISH, we keep
-     * returning Z_STREAM_END instead of Z_BUF_ERROR.
-     */
-    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
-               flush != Z_FINISH) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* User must not provide more input after the first FINISH: */
-    if (s->status == FINISH_STATE && strm->avail_in != 0) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* Write the header */
-    if (s->status == INIT_STATE) {
-        /* zlib header */
-        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
-        uInt level_flags;
-
-        if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
-            level_flags = 0;
-        else if (s->level < 6)
-            level_flags = 1;
-        else if (s->level == 6)
-            level_flags = 2;
-        else
-            level_flags = 3;
-        header |= (level_flags << 6);
-        if (s->strstart != 0) header |= PRESET_DICT;
-        header += 31 - (header % 31);
-
-        putShortMSB(s, header);
-
-        /* Save the adler32 of the preset dictionary: */
-        if (s->strstart != 0) {
-            putShortMSB(s, (uInt)(strm->adler >> 16));
-            putShortMSB(s, (uInt)(strm->adler & 0xffff));
-        }
-        strm->adler = adler32(0L, Z_NULL, 0);
-        s->status = BUSY_STATE;
-
-        /* Compression must start with an empty pending buffer */
-        flush_pending(strm);
-        if (s->pending != 0) {
-            s->last_flush = -1;
-            return Z_OK;
-        }
-    }
-#ifdef GZIP
-    if (s->status == GZIP_STATE) {
-        /* gzip header */
-        strm->adler = crc32(0L, Z_NULL, 0);
-        put_byte(s, 31);
-        put_byte(s, 139);
-        put_byte(s, 8);
-        if (s->gzhead == Z_NULL) {
-            put_byte(s, 0);
-            put_byte(s, 0);
-            put_byte(s, 0);
-            put_byte(s, 0);
-            put_byte(s, 0);
-            put_byte(s, s->level == 9 ? 2 :
-                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
-                      4 : 0));
-            put_byte(s, OS_CODE);
-            s->status = BUSY_STATE;
-
-            /* Compression must start with an empty pending buffer */
-            flush_pending(strm);
-            if (s->pending != 0) {
-                s->last_flush = -1;
-                return Z_OK;
-            }
-        }
-        else {
-            put_byte(s, (s->gzhead->text ? 1 : 0) +
-                     (s->gzhead->hcrc ? 2 : 0) +
-                     (s->gzhead->extra == Z_NULL ? 0 : 4) +
-                     (s->gzhead->name == Z_NULL ? 0 : 8) +
-                     (s->gzhead->comment == Z_NULL ? 0 : 16)
-                     );
-            put_byte(s, (Byte)(s->gzhead->time & 0xff));
-            put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
-            put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
-            put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
-            put_byte(s, s->level == 9 ? 2 :
-                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
-                      4 : 0));
-            put_byte(s, s->gzhead->os & 0xff);
-            if (s->gzhead->extra != Z_NULL) {
-                put_byte(s, s->gzhead->extra_len & 0xff);
-                put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
-            }
-            if (s->gzhead->hcrc)
-                strm->adler = crc32(strm->adler, s->pending_buf,
-                                    s->pending);
-            s->gzindex = 0;
-            s->status = EXTRA_STATE;
-        }
-    }
-    if (s->status == EXTRA_STATE) {
-        if (s->gzhead->extra != Z_NULL) {
-            ulg beg = s->pending;   /* start of bytes to update crc */
-            uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
-            while (s->pending + left > s->pending_buf_size) {
-                uInt copy = s->pending_buf_size - s->pending;
-                zmemcpy(s->pending_buf + s->pending,
-                        s->gzhead->extra + s->gzindex, copy);
-                s->pending = s->pending_buf_size;
-                HCRC_UPDATE(beg);
-                s->gzindex += copy;
-                flush_pending(strm);
-                if (s->pending != 0) {
-                    s->last_flush = -1;
-                    return Z_OK;
-                }
-                beg = 0;
-                left -= copy;
-            }
-            zmemcpy(s->pending_buf + s->pending,
-                    s->gzhead->extra + s->gzindex, left);
-            s->pending += left;
-            HCRC_UPDATE(beg);
-            s->gzindex = 0;
-        }
-        s->status = NAME_STATE;
-    }
-    if (s->status == NAME_STATE) {
-        if (s->gzhead->name != Z_NULL) {
-            ulg beg = s->pending;   /* start of bytes to update crc */
-            int val;
-            do {
-                if (s->pending == s->pending_buf_size) {
-                    HCRC_UPDATE(beg);
-                    flush_pending(strm);
-                    if (s->pending != 0) {
-                        s->last_flush = -1;
-                        return Z_OK;
-                    }
-                    beg = 0;
-                }
-                val = s->gzhead->name[s->gzindex++];
-                put_byte(s, val);
-            } while (val != 0);
-            HCRC_UPDATE(beg);
-            s->gzindex = 0;
-        }
-        s->status = COMMENT_STATE;
-    }
-    if (s->status == COMMENT_STATE) {
-        if (s->gzhead->comment != Z_NULL) {
-            ulg beg = s->pending;   /* start of bytes to update crc */
-            int val;
-            do {
-                if (s->pending == s->pending_buf_size) {
-                    HCRC_UPDATE(beg);
-                    flush_pending(strm);
-                    if (s->pending != 0) {
-                        s->last_flush = -1;
-                        return Z_OK;
-                    }
-                    beg = 0;
-                }
-                val = s->gzhead->comment[s->gzindex++];
-                put_byte(s, val);
-            } while (val != 0);
-            HCRC_UPDATE(beg);
-        }
-        s->status = HCRC_STATE;
-    }
-    if (s->status == HCRC_STATE) {
-        if (s->gzhead->hcrc) {
-            if (s->pending + 2 > s->pending_buf_size) {
-                flush_pending(strm);
-                if (s->pending != 0) {
-                    s->last_flush = -1;
-                    return Z_OK;
-                }
-            }
-            put_byte(s, (Byte)(strm->adler & 0xff));
-            put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
-            strm->adler = crc32(0L, Z_NULL, 0);
-        }
-        s->status = BUSY_STATE;
-
-        /* Compression must start with an empty pending buffer */
-        flush_pending(strm);
-        if (s->pending != 0) {
-            s->last_flush = -1;
-            return Z_OK;
-        }
-    }
-#endif
-
-    /* Start a new block or continue the current one.
-     */
-    if (strm->avail_in != 0 || s->lookahead != 0 ||
-        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
-        block_state bstate;
-
-        bstate = s->level == 0 ? deflate_stored(s, flush) :
-                 s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
-                 s->strategy == Z_RLE ? deflate_rle(s, flush) :
-                 (*(configuration_table[s->level].func))(s, flush);
-
-        if (bstate == finish_started || bstate == finish_done) {
-            s->status = FINISH_STATE;
-        }
-        if (bstate == need_more || bstate == finish_started) {
-            if (strm->avail_out == 0) {
-                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
-            }
-            return Z_OK;
-            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
-             * of deflate should use the same flush parameter to make sure
-             * that the flush is complete. So we don't have to output an
-             * empty block here, this will be done at next call. This also
-             * ensures that for a very small output buffer, we emit at most
-             * one empty block.
-             */
-        }
-        if (bstate == block_done) {
-            if (flush == Z_PARTIAL_FLUSH) {
-                _tr_align(s);
-            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
-                _tr_stored_block(s, (char*)0, 0L, 0);
-                /* For a full flush, this empty block will be recognized
-                 * as a special marker by inflate_sync().
-                 */
-                if (flush == Z_FULL_FLUSH) {
-                    CLEAR_HASH(s);             /* forget history */
-                    if (s->lookahead == 0) {
-                        s->strstart = 0;
-                        s->block_start = 0L;
-                        s->insert = 0;
-                    }
-                }
-            }
-            flush_pending(strm);
-            if (strm->avail_out == 0) {
-              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
-              return Z_OK;
-            }
-        }
-    }
-
-    if (flush != Z_FINISH) return Z_OK;
-    if (s->wrap <= 0) return Z_STREAM_END;
-
-    /* Write the trailer */
-#ifdef GZIP
-    if (s->wrap == 2) {
-        put_byte(s, (Byte)(strm->adler & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
-        put_byte(s, (Byte)(strm->total_in & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
-    }
-    else
-#endif
-    {
-        putShortMSB(s, (uInt)(strm->adler >> 16));
-        putShortMSB(s, (uInt)(strm->adler & 0xffff));
-    }
-    flush_pending(strm);
-    /* If avail_out is zero, the application will call deflate again
-     * to flush the rest.
-     */
-    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
-    return s->pending != 0 ? Z_OK : Z_STREAM_END;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateEnd (strm)
-    z_streamp strm;
-{
-    int status;
-
-    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-
-    status = strm->state->status;
-
-    /* Deallocate in reverse order of allocations: */
-    TRY_FREE(strm, strm->state->pending_buf);
-    TRY_FREE(strm, strm->state->head);
-    TRY_FREE(strm, strm->state->prev);
-    TRY_FREE(strm, strm->state->window);
-
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-
-    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
-}
-
-/* =========================================================================
- * Copy the source state to the destination state.
- * To simplify the source, this is not supported for 16-bit MSDOS (which
- * doesn't have enough memory anyway to duplicate compression states).
- */
-int ZEXPORT deflateCopy (dest, source)
-    z_streamp dest;
-    z_streamp source;
-{
-#ifdef MAXSEG_64K
-    return Z_STREAM_ERROR;
-#else
-    deflate_state *ds;
-    deflate_state *ss;
-    ushf *overlay;
-
-
-    if (deflateStateCheck(source) || dest == Z_NULL) {
-        return Z_STREAM_ERROR;
-    }
-
-    ss = source->state;
-
-    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
-
-    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
-    if (ds == Z_NULL) return Z_MEM_ERROR;
-    dest->state = (struct internal_state FAR *) ds;
-    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
-    ds->strm = dest;
-
-    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
-    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
-    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
-    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
-    ds->pending_buf = (uchf *) overlay;
-
-    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
-        ds->pending_buf == Z_NULL) {
-        deflateEnd (dest);
-        return Z_MEM_ERROR;
-    }
-    /* following zmemcpy do not work for 16-bit MSDOS */
-    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
-    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
-    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
-    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
-
-    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
-    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
-    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
-
-    ds->l_desc.dyn_tree = ds->dyn_ltree;
-    ds->d_desc.dyn_tree = ds->dyn_dtree;
-    ds->bl_desc.dyn_tree = ds->bl_tree;
-
-    return Z_OK;
-#endif /* MAXSEG_64K */
-}
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read.  All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->next_in buffer and copying from it.
- * (See also flush_pending()).
- */
-local unsigned read_buf(strm, buf, size)
-    z_streamp strm;
-    Bytef *buf;
-    unsigned size;
-{
-    unsigned len = strm->avail_in;
-
-    if (len > size) len = size;
-    if (len == 0) return 0;
-
-    strm->avail_in  -= len;
-
-    zmemcpy(buf, strm->next_in, len);
-    if (strm->state->wrap == 1) {
-        strm->adler = adler32(strm->adler, buf, len);
-    }
-#ifdef GZIP
-    else if (strm->state->wrap == 2) {
-        strm->adler = crc32(strm->adler, buf, len);
-    }
-#endif
-    strm->next_in  += len;
-    strm->total_in += len;
-
-    return len;
-}
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-local void lm_init (s)
-    deflate_state *s;
-{
-    s->window_size = (ulg)2L*s->w_size;
-
-    CLEAR_HASH(s);
-
-    /* Set the default configuration parameters:
-     */
-    s->max_lazy_match   = configuration_table[s->level].max_lazy;
-    s->good_match       = configuration_table[s->level].good_length;
-    s->nice_match       = configuration_table[s->level].nice_length;
-    s->max_chain_length = configuration_table[s->level].max_chain;
-
-    s->strstart = 0;
-    s->block_start = 0L;
-    s->lookahead = 0;
-    s->insert = 0;
-    s->match_length = s->prev_length = MIN_MATCH-1;
-    s->match_available = 0;
-    s->ins_h = 0;
-#ifndef FASTEST
-#ifdef ASMV
-    match_init(); /* initialize the asm code */
-#endif
-#endif
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-#ifndef ASMV
-/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    unsigned chain_length = s->max_chain_length;/* max hash chain length */
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                      /* matched string */
-    register int len;                           /* length of current match */
-    int best_len = (int)s->prev_length;         /* best match length so far */
-    int nice_match = s->nice_match;             /* stop if match long enough */
-    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-        s->strstart - (IPos)MAX_DIST(s) : NIL;
-    /* Stop when cur_match becomes <= limit. To simplify the code,
-     * we prevent matches with the string of window index 0.
-     */
-    Posf *prev = s->prev;
-    uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
-    /* Compare two bytes at a time. Note: this is not always beneficial.
-     * Try with and without -DUNALIGNED_OK to check.
-     */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
-    register ush scan_start = *(ushf*)scan;
-    register ush scan_end   = *(ushf*)(scan+best_len-1);
-#else
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-    register Byte scan_end1  = scan[best_len-1];
-    register Byte scan_end   = scan[best_len];
-#endif
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    /* Do not waste too much time if we already have a good match: */
-    if (s->prev_length >= s->good_match) {
-        chain_length >>= 2;
-    }
-    /* Do not look for matches beyond the end of the input. This is necessary
-     * to make deflate deterministic.
-     */
-    if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    do {
-        Assert(cur_match < s->strstart, "no future");
-        match = s->window + cur_match;
-
-        /* Skip to next match if the match length cannot increase
-         * or if the match length is less than 2.  Note that the checks below
-         * for insufficient lookahead only occur occasionally for performance
-         * reasons.  Therefore uninitialized memory will be accessed, and
-         * conditional jumps will be made that depend on those values.
-         * However the length of the match is limited to the lookahead, so
-         * the output of deflate is not affected by the uninitialized values.
-         */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-        /* This code assumes sizeof(unsigned short) == 2. Do not use
-         * UNALIGNED_OK if your compiler uses a different size.
-         */
-        if (*(ushf*)(match+best_len-1) != scan_end ||
-            *(ushf*)match != scan_start) continue;
-
-        /* It is not necessary to compare scan[2] and match[2] since they are
-         * always equal when the other bytes match, given that the hash keys
-         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
-         * strstart+3, +5, ... up to strstart+257. We check for insufficient
-         * lookahead only every 4th comparison; the 128th check will be made
-         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
-         * necessary to put more guard bytes at the end of the window, or
-         * to check more often for insufficient lookahead.
-         */
-        Assert(scan[2] == match[2], "scan[2]?");
-        scan++, match++;
-        do {
-        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 scan < strend);
-        /* The funny "do {}" generates better code on most compilers */
-
-        /* Here, scan <= window+strstart+257 */
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-        if (*scan == *match) scan++;
-
-        len = (MAX_MATCH - 1) - (int)(strend-scan);
-        scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
-        if (match[best_len]   != scan_end  ||
-            match[best_len-1] != scan_end1 ||
-            *match            != *scan     ||
-            *++match          != scan[1])      continue;
-
-        /* The check at best_len-1 can be removed because it will be made
-         * again later. (This heuristic is not always a win.)
-         * It is not necessary to compare scan[2] and match[2] since they
-         * are always equal when the other bytes match, given that
-         * the hash keys are equal and that HASH_BITS >= 8.
-         */
-        scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
-
-        /* We check for insufficient lookahead only every 8th comparison;
-         * the 256th check will be made at strstart+258.
-         */
-        do {
-        } while (*++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 scan < strend);
-
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-        len = MAX_MATCH - (int)(strend - scan);
-        scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
-        if (len > best_len) {
-            s->match_start = cur_match;
-            best_len = len;
-            if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
-            scan_end = *(ushf*)(scan+best_len-1);
-#else
-            scan_end1  = scan[best_len-1];
-            scan_end   = scan[best_len];
-#endif
-        }
-    } while ((cur_match = prev[cur_match & wmask]) > limit
-             && --chain_length != 0);
-
-    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-    return s->lookahead;
-}
-#endif /* ASMV */
-
-#else /* FASTEST */
-
-/* ---------------------------------------------------------------------------
- * Optimized version for FASTEST only
- */
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    Assert(cur_match < s->strstart, "no future");
-
-    match = s->window + cur_match;
-
-    /* Return failure if the match length is less than 2:
-     */
-    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
-
-    /* The check at best_len-1 can be removed because it will be made
-     * again later. (This heuristic is not always a win.)
-     * It is not necessary to compare scan[2] and match[2] since they
-     * are always equal when the other bytes match, given that
-     * the hash keys are equal and that HASH_BITS >= 8.
-     */
-    scan += 2, match += 2;
-    Assert(*scan == *match, "match[2]?");
-
-    /* We check for insufficient lookahead only every 8th comparison;
-     * the 256th check will be made at strstart+258.
-     */
-    do {
-    } while (*++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             scan < strend);
-
-    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-    len = MAX_MATCH - (int)(strend - scan);
-
-    if (len < MIN_MATCH) return MIN_MATCH - 1;
-
-    s->match_start = cur_match;
-    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
-}
-
-#endif /* FASTEST */
-
-#ifdef ZLIB_DEBUG
-
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
-/* ===========================================================================
- * Check that the match at match_start is indeed a match.
- */
-local void check_match(s, start, match, length)
-    deflate_state *s;
-    IPos start, match;
-    int length;
-{
-    /* check that the match is indeed a match */
-    if (zmemcmp(s->window + match,
-                s->window + start, length) != EQUAL) {
-        fprintf(stderr, " start %u, match %u, length %d\n",
-                start, match, length);
-        do {
-            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
-        } while (--length != 0);
-        z_error("invalid match");
-    }
-    if (z_verbose > 1) {
-        fprintf(stderr,"\\[%d,%d]", start-match, length);
-        do { putc(s->window[start++], stderr); } while (--length != 0);
-    }
-}
-#else
-#  define check_match(s, start, match, length)
-#endif /* ZLIB_DEBUG */
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- *    At least one byte has been read, or avail_in == 0; reads are
- *    performed for at least two bytes (required for the zip translate_eol
- *    option -- not supported here).
- */
-local void fill_window(s)
-    deflate_state *s;
-{
-    unsigned n;
-    unsigned more;    /* Amount of free space at the end of the window. */
-    uInt wsize = s->w_size;
-
-    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
-
-    do {
-        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
-
-        /* Deal with !@#$% 64K limit: */
-        if (sizeof(int) <= 2) {
-            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
-                more = wsize;
-
-            } else if (more == (unsigned)(-1)) {
-                /* Very unlikely, but possible on 16 bit machine if
-                 * strstart == 0 && lookahead == 1 (input done a byte at time)
-                 */
-                more--;
-            }
-        }
-
-        /* If the window is almost full and there is insufficient lookahead,
-         * move the upper half to the lower one to make room in the upper half.
-         */
-        if (s->strstart >= wsize+MAX_DIST(s)) {
-
-            zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more);
-            s->match_start -= wsize;
-            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
-            s->block_start -= (long) wsize;
-            slide_hash(s);
-            more += wsize;
-        }
-        if (s->strm->avail_in == 0) break;
-
-        /* If there was no sliding:
-         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
-         *    more == window_size - lookahead - strstart
-         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
-         * => more >= window_size - 2*WSIZE + 2
-         * In the BIG_MEM or MMAP case (not yet supported),
-         *   window_size == input_size + MIN_LOOKAHEAD  &&
-         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
-         * Otherwise, window_size == 2*WSIZE so more >= 2.
-         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
-         */
-        Assert(more >= 2, "more < 2");
-
-        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
-        s->lookahead += n;
-
-        /* Initialize the hash value now that we have some input: */
-        if (s->lookahead + s->insert >= MIN_MATCH) {
-            uInt str = s->strstart - s->insert;
-            s->ins_h = s->window[str];
-            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
-#if MIN_MATCH != 3
-            Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-            while (s->insert) {
-                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
-#ifndef FASTEST
-                s->prev[str & s->w_mask] = s->head[s->ins_h];
-#endif
-                s->head[s->ins_h] = (Pos)str;
-                str++;
-                s->insert--;
-                if (s->lookahead + s->insert < MIN_MATCH)
-                    break;
-            }
-        }
-        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
-         * but this is not important since only literal bytes will be emitted.
-         */
-
-    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
-
-    /* If the WIN_INIT bytes after the end of the current data have never been
-     * written, then zero those bytes in order to avoid memory check reports of
-     * the use of uninitialized (or uninitialised as Julian writes) bytes by
-     * the longest match routines.  Update the high water mark for the next
-     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
-     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
-     */
-    if (s->high_water < s->window_size) {
-        ulg curr = s->strstart + (ulg)(s->lookahead);
-        ulg init;
-
-        if (s->high_water < curr) {
-            /* Previous high water mark below current data -- zero WIN_INIT
-             * bytes or up to end of window, whichever is less.
-             */
-            init = s->window_size - curr;
-            if (init > WIN_INIT)
-                init = WIN_INIT;
-            zmemzero(s->window + curr, (unsigned)init);
-            s->high_water = curr + init;
-        }
-        else if (s->high_water < (ulg)curr + WIN_INIT) {
-            /* High water mark at or above current data, but below current data
-             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
-             * to end of window, whichever is less.
-             */
-            init = (ulg)curr + WIN_INIT - s->high_water;
-            if (init > s->window_size - s->high_water)
-                init = s->window_size - s->high_water;
-            zmemzero(s->window + s->high_water, (unsigned)init);
-            s->high_water += init;
-        }
-    }
-
-    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
-           "not enough room for search");
-}
-
-/* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
-#define FLUSH_BLOCK_ONLY(s, last) { \
-   _tr_flush_block(s, (s->block_start >= 0L ? \
-                   (charf *)&s->window[(unsigned)s->block_start] : \
-                   (charf *)Z_NULL), \
-                (ulg)((long)s->strstart - s->block_start), \
-                (last)); \
-   s->block_start = s->strstart; \
-   flush_pending(s->strm); \
-   Tracev((stderr,"[FLUSH]")); \
-}
-
-/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, last) { \
-   FLUSH_BLOCK_ONLY(s, last); \
-   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
-}
-
-/* Maximum stored block length in deflate format (not including header). */
-#define MAX_STORED 65535
-
-/* Minimum of a and b. */
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- *
- * In case deflateParams() is used to later switch to a non-zero compression
- * level, s->matches (otherwise unused when storing) keeps track of the number
- * of hash table slides to perform. If s->matches is 1, then one hash table
- * slide will be done when switching. If s->matches is 2, the maximum value
- * allowed here, then the hash table will be cleared, since two or more slides
- * is the same as a clear.
- *
- * deflate_stored() is written to minimize the number of times an input byte is
- * copied. It is most efficient with large input and output buffers, which
- * maximizes the opportunites to have a single copy from next_in to next_out.
- */
-local block_state deflate_stored(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    /* Smallest worthy block size when not flushing or finishing. By default
-     * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
-     * large input and output buffers, the stored block size will be larger.
-     */
-    unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
-
-    /* Copy as many min_block or larger stored blocks directly to next_out as
-     * possible. If flushing, copy the remaining available input to next_out as
-     * stored blocks, if there is enough space.
-     */
-    unsigned len, left, have, last = 0;
-    unsigned used = s->strm->avail_in;
-    do {
-        /* Set len to the maximum size block that we can copy directly with the
-         * available input data and output space. Set left to how much of that
-         * would be copied from what's left in the window.
-         */
-        len = MAX_STORED;       /* maximum deflate stored block length */
-        have = (s->bi_valid + 42) >> 3;         /* number of header bytes */
-        if (s->strm->avail_out < have)          /* need room for header */
-            break;
-            /* maximum stored block length that will fit in avail_out: */
-        have = s->strm->avail_out - have;
-        left = s->strstart - s->block_start;    /* bytes left in window */
-        if (len > (ulg)left + s->strm->avail_in)
-            len = left + s->strm->avail_in;     /* limit len to the input */
-        if (len > have)
-            len = have;                         /* limit len to the output */
-
-        /* If the stored block would be less than min_block in length, or if
-         * unable to copy all of the available input when flushing, then try
-         * copying to the window and the pending buffer instead. Also don't
-         * write an empty block when flushing -- deflate() does that.
-         */
-        if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
-                                flush == Z_NO_FLUSH ||
-                                len != left + s->strm->avail_in))
-            break;
-
-        /* Make a dummy stored block in pending to get the header bytes,
-         * including any pending bits. This also updates the debugging counts.
-         */
-        last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
-        _tr_stored_block(s, (char *)0, 0L, last);
-
-        /* Replace the lengths in the dummy stored block with len. */
-        s->pending_buf[s->pending - 4] = len;
-        s->pending_buf[s->pending - 3] = len >> 8;
-        s->pending_buf[s->pending - 2] = ~len;
-        s->pending_buf[s->pending - 1] = ~len >> 8;
-
-        /* Write the stored block header bytes. */
-        flush_pending(s->strm);
-
-#ifdef ZLIB_DEBUG
-        /* Update debugging counts for the data about to be copied. */
-        s->compressed_len += len << 3;
-        s->bits_sent += len << 3;
-#endif
-
-        /* Copy uncompressed bytes from the window to next_out. */
-        if (left) {
-            if (left > len)
-                left = len;
-            zmemcpy(s->strm->next_out, s->window + s->block_start, left);
-            s->strm->next_out += left;
-            s->strm->avail_out -= left;
-            s->strm->total_out += left;
-            s->block_start += left;
-            len -= left;
-        }
-
-        /* Copy uncompressed bytes directly from next_in to next_out, updating
-         * the check value.
-         */
-        if (len) {
-            read_buf(s->strm, s->strm->next_out, len);
-            s->strm->next_out += len;
-            s->strm->avail_out -= len;
-            s->strm->total_out += len;
-        }
-    } while (last == 0);
-
-    /* Update the sliding window with the last s->w_size bytes of the copied
-     * data, or append all of the copied data to the existing window if less
-     * than s->w_size bytes were copied. Also update the number of bytes to
-     * insert in the hash tables, in the event that deflateParams() switches to
-     * a non-zero compression level.
-     */
-    used -= s->strm->avail_in;      /* number of input bytes directly copied */
-    if (used) {
-        /* If any input was used, then no unused input remains in the window,
-         * therefore s->block_start == s->strstart.
-         */
-        if (used >= s->w_size) {    /* supplant the previous history */
-            s->matches = 2;         /* clear hash */
-            zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
-            s->strstart = s->w_size;
-        }
-        else {
-            if (s->window_size - s->strstart <= used) {
-                /* Slide the window down. */
-                s->strstart -= s->w_size;
-                zmemcpy(s->window, s->window + s->w_size, s->strstart);
-                if (s->matches < 2)
-                    s->matches++;   /* add a pending slide_hash() */
-            }
-            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
-            s->strstart += used;
-        }
-        s->block_start = s->strstart;
-        s->insert += MIN(used, s->w_size - s->insert);
-    }
-    if (s->high_water < s->strstart)
-        s->high_water = s->strstart;
-
-    /* If the last block was written to next_out, then done. */
-    if (last)
-        return finish_done;
-
-    /* If flushing and all input has been consumed, then done. */
-    if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
-        s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
-        return block_done;
-
-    /* Fill the window with any remaining input. */
-    have = s->window_size - s->strstart - 1;
-    if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
-        /* Slide the window down. */
-        s->block_start -= s->w_size;
-        s->strstart -= s->w_size;
-        zmemcpy(s->window, s->window + s->w_size, s->strstart);
-        if (s->matches < 2)
-            s->matches++;           /* add a pending slide_hash() */
-        have += s->w_size;          /* more space now */
-    }
-    if (have > s->strm->avail_in)
-        have = s->strm->avail_in;
-    if (have) {
-        read_buf(s->strm, s->window + s->strstart, have);
-        s->strstart += have;
-    }
-    if (s->high_water < s->strstart)
-        s->high_water = s->strstart;
-
-    /* There was not enough avail_out to write a complete worthy or flushed
-     * stored block to next_out. Write a stored block to pending instead, if we
-     * have enough input for a worthy block, or if flushing and there is enough
-     * room for the remaining input as a stored block in the pending buffer.
-     */
-    have = (s->bi_valid + 42) >> 3;         /* number of header bytes */
-        /* maximum stored block length that will fit in pending: */
-    have = MIN(s->pending_buf_size - have, MAX_STORED);
-    min_block = MIN(have, s->w_size);
-    left = s->strstart - s->block_start;
-    if (left >= min_block ||
-        ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
-         s->strm->avail_in == 0 && left <= have)) {
-        len = MIN(left, have);
-        last = flush == Z_FINISH && s->strm->avail_in == 0 &&
-               len == left ? 1 : 0;
-        _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
-        s->block_start += len;
-        flush_pending(s->strm);
-    }
-
-    /* We've done all we can with the available input and output. */
-    return last ? finish_started : need_more;
-}
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-local block_state deflate_fast(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head;       /* head of the hash chain */
-    int bflush;           /* set if current block must be flushed */
-
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        hash_head = NIL;
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         * At this point we have always match_length < MIN_MATCH
-         */
-        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            s->match_length = longest_match (s, hash_head);
-            /* longest_match() sets match_start */
-        }
-        if (s->match_length >= MIN_MATCH) {
-            check_match(s, s->strstart, s->match_start, s->match_length);
-
-            _tr_tally_dist(s, s->strstart - s->match_start,
-                           s->match_length - MIN_MATCH, bflush);
-
-            s->lookahead -= s->match_length;
-
-            /* Insert new strings in the hash table only if the match length
-             * is not too large. This saves time but degrades compression.
-             */
-#ifndef FASTEST
-            if (s->match_length <= s->max_insert_length &&
-                s->lookahead >= MIN_MATCH) {
-                s->match_length--; /* string at strstart already in table */
-                do {
-                    s->strstart++;
-                    INSERT_STRING(s, s->strstart, hash_head);
-                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
-                     * always MIN_MATCH bytes ahead.
-                     */
-                } while (--s->match_length != 0);
-                s->strstart++;
-            } else
-#endif
-            {
-                s->strstart += s->match_length;
-                s->match_length = 0;
-                s->ins_h = s->window[s->strstart];
-                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
-                Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
-                 * matter since it will be recomputed at next deflate call.
-                 */
-            }
-        } else {
-            /* No match, output a literal byte */
-            Tracevv((stderr,"%c", s->window[s->strstart]));
-            _tr_tally_lit (s, s->window[s->strstart], bflush);
-            s->lookahead--;
-            s->strstart++;
-        }
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
-    if (flush == Z_FINISH) {
-        FLUSH_BLOCK(s, 1);
-        return finish_done;
-    }
-    if (s->last_lit)
-        FLUSH_BLOCK(s, 0);
-    return block_done;
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-local block_state deflate_slow(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head;          /* head of hash chain */
-    int bflush;              /* set if current block must be flushed */
-
-    /* Process the input block. */
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        hash_head = NIL;
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         */
-        s->prev_length = s->match_length, s->prev_match = s->match_start;
-        s->match_length = MIN_MATCH-1;
-
-        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
-            s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            s->match_length = longest_match (s, hash_head);
-            /* longest_match() sets match_start */
-
-            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
-#if TOO_FAR <= 32767
-                || (s->match_length == MIN_MATCH &&
-                    s->strstart - s->match_start > TOO_FAR)
-#endif
-                )) {
-
-                /* If prev_match is also MIN_MATCH, match_start is garbage
-                 * but we will ignore the current match anyway.
-                 */
-                s->match_length = MIN_MATCH-1;
-            }
-        }
-        /* If there was a match at the previous step and the current
-         * match is not better, output the previous match:
-         */
-        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
-            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
-            /* Do not insert strings in hash table beyond this. */
-
-            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
-
-            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
-                           s->prev_length - MIN_MATCH, bflush);
-
-            /* Insert in hash table all strings up to the end of the match.
-             * strstart-1 and strstart are already inserted. If there is not
-             * enough lookahead, the last two strings are not inserted in
-             * the hash table.
-             */
-            s->lookahead -= s->prev_length-1;
-            s->prev_length -= 2;
-            do {
-                if (++s->strstart <= max_insert) {
-                    INSERT_STRING(s, s->strstart, hash_head);
-                }
-            } while (--s->prev_length != 0);
-            s->match_available = 0;
-            s->match_length = MIN_MATCH-1;
-            s->strstart++;
-
-            if (bflush) FLUSH_BLOCK(s, 0);
-
-        } else if (s->match_available) {
-            /* If there was no match at the previous position, output a
-             * single literal. If there was a match but the current match
-             * is longer, truncate the previous match to a single literal.
-             */
-            Tracevv((stderr,"%c", s->window[s->strstart-1]));
-            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-            if (bflush) {
-                FLUSH_BLOCK_ONLY(s, 0);
-            }
-            s->strstart++;
-            s->lookahead--;
-            if (s->strm->avail_out == 0) return need_more;
-        } else {
-            /* There is no previous match to compare with, wait for
-             * the next step to decide.
-             */
-            s->match_available = 1;
-            s->strstart++;
-            s->lookahead--;
-        }
-    }
-    Assert (flush != Z_NO_FLUSH, "no flush?");
-    if (s->match_available) {
-        Tracevv((stderr,"%c", s->window[s->strstart-1]));
-        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-        s->match_available = 0;
-    }
-    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
-    if (flush == Z_FINISH) {
-        FLUSH_BLOCK(s, 1);
-        return finish_done;
-    }
-    if (s->last_lit)
-        FLUSH_BLOCK(s, 0);
-    return block_done;
-}
-#endif /* FASTEST */
-
-/* ===========================================================================
- * For Z_RLE, simply look for runs of bytes, generate matches only of distance
- * one.  Do not maintain a hash table.  (It will be regenerated if this run of
- * deflate switches away from Z_RLE.)
- */
-local block_state deflate_rle(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    int bflush;             /* set if current block must be flushed */
-    uInt prev;              /* byte at distance one to match */
-    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
-
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the longest run, plus one for the unrolled loop.
-         */
-        if (s->lookahead <= MAX_MATCH) {
-            fill_window(s);
-            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* See how many times the previous byte repeats */
-        s->match_length = 0;
-        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
-            scan = s->window + s->strstart - 1;
-            prev = *scan;
-            if (prev == *++scan && prev == *++scan && prev == *++scan) {
-                strend = s->window + s->strstart + MAX_MATCH;
-                do {
-                } while (prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         scan < strend);
-                s->match_length = MAX_MATCH - (uInt)(strend - scan);
-                if (s->match_length > s->lookahead)
-                    s->match_length = s->lookahead;
-            }
-            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
-        }
-
-        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
-        if (s->match_length >= MIN_MATCH) {
-            check_match(s, s->strstart, s->strstart - 1, s->match_length);
-
-            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
-
-            s->lookahead -= s->match_length;
-            s->strstart += s->match_length;
-            s->match_length = 0;
-        } else {
-            /* No match, output a literal byte */
-            Tracevv((stderr,"%c", s->window[s->strstart]));
-            _tr_tally_lit (s, s->window[s->strstart], bflush);
-            s->lookahead--;
-            s->strstart++;
-        }
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    s->insert = 0;
-    if (flush == Z_FINISH) {
-        FLUSH_BLOCK(s, 1);
-        return finish_done;
-    }
-    if (s->last_lit)
-        FLUSH_BLOCK(s, 0);
-    return block_done;
-}
-
-/* ===========================================================================
- * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
- * (It will be regenerated if this run of deflate switches away from Huffman.)
- */
-local block_state deflate_huff(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    int bflush;             /* set if current block must be flushed */
-
-    for (;;) {
-        /* Make sure that we have a literal to write. */
-        if (s->lookahead == 0) {
-            fill_window(s);
-            if (s->lookahead == 0) {
-                if (flush == Z_NO_FLUSH)
-                    return need_more;
-                break;      /* flush the current block */
-            }
-        }
-
-        /* Output a literal byte */
-        s->match_length = 0;
-        Tracevv((stderr,"%c", s->window[s->strstart]));
-        _tr_tally_lit (s, s->window[s->strstart], bflush);
-        s->lookahead--;
-        s->strstart++;
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    s->insert = 0;
-    if (flush == Z_FINISH) {
-        FLUSH_BLOCK(s, 1);
-        return finish_done;
-    }
-    if (s->last_lit)
-        FLUSH_BLOCK(s, 0);
-    return block_done;
-}
diff --git a/c/zlib/deflate.h b/c/zlib/deflate.h
deleted file mode 100644
--- a/c/zlib/deflate.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/* deflate.h -- internal compression state
- * Copyright (C) 1995-2016 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id$ */
-
-#ifndef DEFLATE_H
-#define DEFLATE_H
-
-#include "zutil.h"
-
-/* define NO_GZIP when compiling if you want to disable gzip header and
-   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
-   the crc code when it is not needed.  For shared libraries, gzip encoding
-   should be left enabled. */
-#ifndef NO_GZIP
-#  define GZIP
-#endif
-
-/* ===========================================================================
- * Internal compression state.
- */
-
-#define LENGTH_CODES 29
-/* number of length codes, not counting the special END_BLOCK code */
-
-#define LITERALS  256
-/* number of literal bytes 0..255 */
-
-#define L_CODES (LITERALS+1+LENGTH_CODES)
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-#define D_CODES   30
-/* number of distance codes */
-
-#define BL_CODES  19
-/* number of codes used to transfer the bit lengths */
-
-#define HEAP_SIZE (2*L_CODES+1)
-/* maximum heap size */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define Buf_size 16
-/* size of bit buffer in bi_buf */
-
-#define INIT_STATE    42    /* zlib header -> BUSY_STATE */
-#ifdef GZIP
-#  define GZIP_STATE  57    /* gzip header -> BUSY_STATE | EXTRA_STATE */
-#endif
-#define EXTRA_STATE   69    /* gzip extra block -> NAME_STATE */
-#define NAME_STATE    73    /* gzip file name -> COMMENT_STATE */
-#define COMMENT_STATE 91    /* gzip comment -> HCRC_STATE */
-#define HCRC_STATE   103    /* gzip header CRC -> BUSY_STATE */
-#define BUSY_STATE   113    /* deflate -> FINISH_STATE */
-#define FINISH_STATE 666    /* stream complete */
-/* Stream status */
-
-
-/* Data structure describing a single value and its code string. */
-typedef struct ct_data_s {
-    union {
-        ush  freq;       /* frequency count */
-        ush  code;       /* bit string */
-    } fc;
-    union {
-        ush  dad;        /* father node in Huffman tree */
-        ush  len;        /* length of bit string */
-    } dl;
-} FAR ct_data;
-
-#define Freq fc.freq
-#define Code fc.code
-#define Dad  dl.dad
-#define Len  dl.len
-
-typedef struct static_tree_desc_s  static_tree_desc;
-
-typedef struct tree_desc_s {
-    ct_data *dyn_tree;           /* the dynamic tree */
-    int     max_code;            /* largest code with non zero frequency */
-    const static_tree_desc *stat_desc;  /* the corresponding static tree */
-} FAR tree_desc;
-
-typedef ush Pos;
-typedef Pos FAR Posf;
-typedef unsigned IPos;
-
-/* A Pos is an index in the character window. We use short instead of int to
- * save space in the various tables. IPos is used only for parameter passing.
- */
-
-typedef struct internal_state {
-    z_streamp strm;      /* pointer back to this zlib stream */
-    int   status;        /* as the name implies */
-    Bytef *pending_buf;  /* output still pending */
-    ulg   pending_buf_size; /* size of pending_buf */
-    Bytef *pending_out;  /* next pending byte to output to the stream */
-    ulg   pending;       /* nb of bytes in the pending buffer */
-    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
-    gz_headerp  gzhead;  /* gzip header information to write */
-    ulg   gzindex;       /* where in extra, name, or comment */
-    Byte  method;        /* can only be DEFLATED */
-    int   last_flush;    /* value of flush param for previous deflate call */
-
-                /* used by deflate.c: */
-
-    uInt  w_size;        /* LZ77 window size (32K by default) */
-    uInt  w_bits;        /* log2(w_size)  (8..16) */
-    uInt  w_mask;        /* w_size - 1 */
-
-    Bytef *window;
-    /* Sliding window. Input bytes are read into the second half of the window,
-     * and move to the first half later to keep a dictionary of at least wSize
-     * bytes. With this organization, matches are limited to a distance of
-     * wSize-MAX_MATCH bytes, but this ensures that IO is always
-     * performed with a length multiple of the block size. Also, it limits
-     * the window size to 64K, which is quite useful on MSDOS.
-     * To do: use the user input buffer as sliding window.
-     */
-
-    ulg window_size;
-    /* Actual size of window: 2*wSize, except when the user input buffer
-     * is directly used as sliding window.
-     */
-
-    Posf *prev;
-    /* Link to older string with same hash index. To limit the size of this
-     * array to 64K, this link is maintained only for the last 32K strings.
-     * An index in this array is thus a window index modulo 32K.
-     */
-
-    Posf *head; /* Heads of the hash chains or NIL. */
-
-    uInt  ins_h;          /* hash index of string to be inserted */
-    uInt  hash_size;      /* number of elements in hash table */
-    uInt  hash_bits;      /* log2(hash_size) */
-    uInt  hash_mask;      /* hash_size-1 */
-
-    uInt  hash_shift;
-    /* Number of bits by which ins_h must be shifted at each input
-     * step. It must be such that after MIN_MATCH steps, the oldest
-     * byte no longer takes part in the hash key, that is:
-     *   hash_shift * MIN_MATCH >= hash_bits
-     */
-
-    long block_start;
-    /* Window position at the beginning of the current output block. Gets
-     * negative when the window is moved backwards.
-     */
-
-    uInt match_length;           /* length of best match */
-    IPos prev_match;             /* previous match */
-    int match_available;         /* set if previous match exists */
-    uInt strstart;               /* start of string to insert */
-    uInt match_start;            /* start of matching string */
-    uInt lookahead;              /* number of valid bytes ahead in window */
-
-    uInt prev_length;
-    /* Length of the best match at previous step. Matches not greater than this
-     * are discarded. This is used in the lazy match evaluation.
-     */
-
-    uInt max_chain_length;
-    /* To speed up deflation, hash chains are never searched beyond this
-     * length.  A higher limit improves compression ratio but degrades the
-     * speed.
-     */
-
-    uInt max_lazy_match;
-    /* Attempt to find a better match only when the current match is strictly
-     * smaller than this value. This mechanism is used only for compression
-     * levels >= 4.
-     */
-#   define max_insert_length  max_lazy_match
-    /* Insert new strings in the hash table only if the match length is not
-     * greater than this length. This saves time but degrades compression.
-     * max_insert_length is used only for compression levels <= 3.
-     */
-
-    int level;    /* compression level (1..9) */
-    int strategy; /* favor or force Huffman coding*/
-
-    uInt good_match;
-    /* Use a faster search when the previous match is longer than this */
-
-    int nice_match; /* Stop searching when current match exceeds this */
-
-                /* used by trees.c: */
-    /* Didn't use ct_data typedef below to suppress compiler warning */
-    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
-    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
-    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
-
-    struct tree_desc_s l_desc;               /* desc. for literal tree */
-    struct tree_desc_s d_desc;               /* desc. for distance tree */
-    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
-
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
-    int heap_len;               /* number of elements in the heap */
-    int heap_max;               /* element of largest frequency */
-    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
-     * The same heap array is used to build all trees.
-     */
-
-    uch depth[2*L_CODES+1];
-    /* Depth of each subtree used as tie breaker for trees of equal frequency
-     */
-
-    uchf *l_buf;          /* buffer for literals or lengths */
-
-    uInt  lit_bufsize;
-    /* Size of match buffer for literals/lengths.  There are 4 reasons for
-     * limiting lit_bufsize to 64K:
-     *   - frequencies can be kept in 16 bit counters
-     *   - if compression is not successful for the first block, all input
-     *     data is still in the window so we can still emit a stored block even
-     *     when input comes from standard input.  (This can also be done for
-     *     all blocks if lit_bufsize is not greater than 32K.)
-     *   - if compression is not successful for a file smaller than 64K, we can
-     *     even emit a stored file instead of a stored block (saving 5 bytes).
-     *     This is applicable only for zip (not gzip or zlib).
-     *   - creating new Huffman trees less frequently may not provide fast
-     *     adaptation to changes in the input data statistics. (Take for
-     *     example a binary file with poorly compressible code followed by
-     *     a highly compressible string table.) Smaller buffer sizes give
-     *     fast adaptation but have of course the overhead of transmitting
-     *     trees more frequently.
-     *   - I can't count above 4
-     */
-
-    uInt last_lit;      /* running index in l_buf */
-
-    ushf *d_buf;
-    /* Buffer for distances. To simplify the code, d_buf and l_buf have
-     * the same number of elements. To use different lengths, an extra flag
-     * array would be necessary.
-     */
-
-    ulg opt_len;        /* bit length of current block with optimal trees */
-    ulg static_len;     /* bit length of current block with static trees */
-    uInt matches;       /* number of string matches in current block */
-    uInt insert;        /* bytes at end of window left to insert */
-
-#ifdef ZLIB_DEBUG
-    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
-    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
-#endif
-
-    ush bi_buf;
-    /* Output buffer. bits are inserted starting at the bottom (least
-     * significant bits).
-     */
-    int bi_valid;
-    /* Number of valid bits in bi_buf.  All bits above the last valid bit
-     * are always zero.
-     */
-
-    ulg high_water;
-    /* High water mark offset in window for initialized bytes -- bytes above
-     * this are set to zero in order to avoid memory check warnings when
-     * longest match routines access bytes past the input.  This is then
-     * updated to the new high water mark.
-     */
-
-} FAR deflate_state;
-
-/* Output a byte on the stream.
- * IN assertion: there is enough room in pending_buf.
- */
-#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
-
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
-#define WIN_INIT MAX_MATCH
-/* Number of bytes after end of data in window to initialize in order to avoid
-   memory checker errors from longest match routines */
-
-        /* in trees.c */
-void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
-int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
-void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
-                        ulg stored_len, int last));
-void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
-void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
-void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
-                        ulg stored_len, int last));
-
-#define d_code(dist) \
-   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
-/* Mapping from a distance to a distance code. dist is the distance - 1 and
- * must not have side effects. _dist_code[256] and _dist_code[257] are never
- * used.
- */
-
-#ifndef ZLIB_DEBUG
-/* Inline versions of _tr_tally for speed: */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-  extern uch ZLIB_INTERNAL _length_code[];
-  extern uch ZLIB_INTERNAL _dist_code[];
-#else
-  extern const uch ZLIB_INTERNAL _length_code[];
-  extern const uch ZLIB_INTERNAL _dist_code[];
-#endif
-
-# define _tr_tally_lit(s, c, flush) \
-  { uch cc = (c); \
-    s->d_buf[s->last_lit] = 0; \
-    s->l_buf[s->last_lit++] = cc; \
-    s->dyn_ltree[cc].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-   }
-# define _tr_tally_dist(s, distance, length, flush) \
-  { uch len = (uch)(length); \
-    ush dist = (ush)(distance); \
-    s->d_buf[s->last_lit] = dist; \
-    s->l_buf[s->last_lit++] = len; \
-    dist--; \
-    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
-    s->dyn_dtree[d_code(dist)].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-  }
-#else
-# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
-# define _tr_tally_dist(s, distance, length, flush) \
-              flush = _tr_tally(s, distance, length)
-#endif
-
-#endif /* DEFLATE_H */
diff --git a/c/zlib/gzguts.h b/c/zlib/gzguts.h
deleted file mode 100644
--- a/c/zlib/gzguts.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#ifdef _LARGEFILE64_SOURCE
-#  ifndef _LARGEFILE_SOURCE
-#    define _LARGEFILE_SOURCE 1
-#  endif
-#  ifdef _FILE_OFFSET_BITS
-#    undef _FILE_OFFSET_BITS
-#  endif
-#endif
-
-#ifdef HAVE_HIDDEN
-#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
-#else
-#  define ZLIB_INTERNAL
-#endif
-
-#include <stdio.h>
-#include "zlib.h"
-#ifdef STDC
-#  include <string.h>
-#  include <stdlib.h>
-#  include <limits.h>
-#endif
-
-#ifndef _POSIX_SOURCE
-#  define _POSIX_SOURCE
-#endif
-#include <fcntl.h>
-
-#ifdef _WIN32
-#  include <stddef.h>
-#endif
-
-#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
-#  include <io.h>
-#endif
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#  define WIDECHAR
-#endif
-
-#ifdef WINAPI_FAMILY
-#  define open _open
-#  define read _read
-#  define write _write
-#  define close _close
-#endif
-
-#ifdef NO_DEFLATE       /* for compatibility with old definition */
-#  define NO_GZCOMPRESS
-#endif
-
-#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-
-#if defined(__CYGWIN__)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-
-#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#  ifdef MSDOS
-/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
-   but for now we just assume it doesn't. */
-#    define NO_vsnprintf
-#  endif
-#  ifdef __TURBOC__
-#    define NO_vsnprintf
-#  endif
-#  ifdef WIN32
-/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
-#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
-#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
-#         define vsnprintf _vsnprintf
-#      endif
-#    endif
-#  endif
-#  ifdef __SASC
-#    define NO_vsnprintf
-#  endif
-#  ifdef VMS
-#    define NO_vsnprintf
-#  endif
-#  ifdef __OS400__
-#    define NO_vsnprintf
-#  endif
-#  ifdef __MVS__
-#    define NO_vsnprintf
-#  endif
-#endif
-
-/* unlike snprintf (which is required in C99), _snprintf does not guarantee
-   null termination of the result -- however this is only used in gzlib.c where
-   the result is assured to fit in the space provided */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#  define snprintf _snprintf
-#endif
-
-#ifndef local
-#  define local static
-#endif
-/* since "static" is used to mean two completely different things in C, we
-   define "local" for the non-static meaning of "static", for readability
-   (compile with -Dlocal if your debugger can't find static symbols) */
-
-/* gz* functions always use library allocation functions */
-#ifndef STDC
-  extern voidp  malloc OF((uInt size));
-  extern void   free   OF((voidpf ptr));
-#endif
-
-/* get errno and strerror definition */
-#if defined UNDER_CE
-#  include <windows.h>
-#  define zstrerror() gz_strwinerror((DWORD)GetLastError())
-#else
-#  ifndef NO_STRERROR
-#    include <errno.h>
-#    define zstrerror() strerror(errno)
-#  else
-#    define zstrerror() "stdio error (consult errno)"
-#  endif
-#endif
-
-/* provide prototypes for these when building zlib without LFS */
-#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
-    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
-    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
-    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
-#endif
-
-/* default memLevel */
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-
-/* default i/o buffer size -- double this for output when reading (this and
-   twice this must be able to fit in an unsigned type) */
-#define GZBUFSIZE 8192
-
-/* gzip modes, also provide a little integrity check on the passed structure */
-#define GZ_NONE 0
-#define GZ_READ 7247
-#define GZ_WRITE 31153
-#define GZ_APPEND 1     /* mode set to GZ_WRITE after the file is opened */
-
-/* values for gz_state how */
-#define LOOK 0      /* look for a gzip header */
-#define COPY 1      /* copy input directly */
-#define GZIP 2      /* decompress a gzip stream */
-
-/* internal gzip file state data structure */
-typedef struct {
-        /* exposed contents for gzgetc() macro */
-    struct gzFile_s x;      /* "x" for exposed */
-                            /* x.have: number of bytes available at x.next */
-                            /* x.next: next output data to deliver or write */
-                            /* x.pos: current position in uncompressed data */
-        /* used for both reading and writing */
-    int mode;               /* see gzip modes above */
-    int fd;                 /* file descriptor */
-    char *path;             /* path or fd for error messages */
-    unsigned size;          /* buffer size, zero if not allocated yet */
-    unsigned want;          /* requested buffer size, default is GZBUFSIZE */
-    unsigned char *in;      /* input buffer (double-sized when writing) */
-    unsigned char *out;     /* output buffer (double-sized when reading) */
-    int direct;             /* 0 if processing gzip, 1 if transparent */
-        /* just for reading */
-    int how;                /* 0: get header, 1: copy, 2: decompress */
-    z_off64_t start;        /* where the gzip data started, for rewinding */
-    int eof;                /* true if end of input file reached */
-    int past;               /* true if read requested past end */
-        /* just for writing */
-    int level;              /* compression level */
-    int strategy;           /* compression strategy */
-        /* seek request */
-    z_off64_t skip;         /* amount to skip (already rewound if backwards) */
-    int seek;               /* true if seek request pending */
-        /* error information */
-    int err;                /* error code */
-    char *msg;              /* error message */
-        /* zlib inflate or deflate stream */
-    z_stream strm;          /* stream structure in-place (not a pointer) */
-} gz_state;
-typedef gz_state FAR *gz_statep;
-
-/* shared functions */
-void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
-#if defined UNDER_CE
-char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
-#endif
-
-/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
-   value -- needed when comparing unsigned to z_off64_t, which is signed
-   (possible z_off64_t types off_t, off64_t, and long are all signed) */
-#ifdef INT_MAX
-#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
-#else
-unsigned ZLIB_INTERNAL gz_intmax OF((void));
-#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
-#endif
diff --git a/c/zlib/infback.c b/c/zlib/infback.c
deleted file mode 100644
--- a/c/zlib/infback.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
-   This code is largely copied from inflate.c.  Normally either infback.o or
-   inflate.o would be linked into an application--not both.  The interface
-   with inffast.c is retained so that optimized assembler-coded versions of
-   inflate_fast() can be used with either inflate.c or infback.c.
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-/* function prototypes */
-local void fixedtables OF((struct inflate_state FAR *state));
-
-/*
-   strm provides memory allocation functions in zalloc and zfree, or
-   Z_NULL to use the library memory allocation functions.
-
-   windowBits is in the range 8..15, and window is a user-supplied
-   window and output buffer that is 2**windowBits bytes.
- */
-int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
-z_streamp strm;
-int windowBits;
-unsigned char FAR *window;
-const char *version;
-int stream_size;
-{
-    struct inflate_state FAR *state;
-
-    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-        stream_size != (int)(sizeof(z_stream)))
-        return Z_VERSION_ERROR;
-    if (strm == Z_NULL || window == Z_NULL ||
-        windowBits < 8 || windowBits > 15)
-        return Z_STREAM_ERROR;
-    strm->msg = Z_NULL;                 /* in case we return an error */
-    if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-#endif
-    }
-    if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-    strm->zfree = zcfree;
-#endif
-    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
-                                               sizeof(struct inflate_state));
-    if (state == Z_NULL) return Z_MEM_ERROR;
-    Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (struct internal_state FAR *)state;
-    state->dmax = 32768U;
-    state->wbits = (uInt)windowBits;
-    state->wsize = 1U << windowBits;
-    state->window = window;
-    state->wnext = 0;
-    state->whave = 0;
-    return Z_OK;
-}
-
-/*
-   Return state with length and distance decoding tables and index sizes set to
-   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-   If BUILDFIXED is defined, then instead this routine builds the tables the
-   first time it's called, and returns those tables the first time and
-   thereafter.  This reduces the size of the code by about 2K bytes, in
-   exchange for a little execution time.  However, BUILDFIXED should not be
-   used for threaded applications, since the rewriting of the tables and virgin
-   may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
-    static int virgin = 1;
-    static code *lenfix, *distfix;
-    static code fixed[544];
-
-    /* build fixed huffman tables if first call (may not be thread safe) */
-    if (virgin) {
-        unsigned sym, bits;
-        static code *next;
-
-        /* literal/length table */
-        sym = 0;
-        while (sym < 144) state->lens[sym++] = 8;
-        while (sym < 256) state->lens[sym++] = 9;
-        while (sym < 280) state->lens[sym++] = 7;
-        while (sym < 288) state->lens[sym++] = 8;
-        next = fixed;
-        lenfix = next;
-        bits = 9;
-        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
-        /* distance table */
-        sym = 0;
-        while (sym < 32) state->lens[sym++] = 5;
-        distfix = next;
-        bits = 5;
-        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
-        /* do this just once */
-        virgin = 0;
-    }
-#else /* !BUILDFIXED */
-#   include "inffixed.h"
-#endif /* BUILDFIXED */
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-/* Macros for inflateBack(): */
-
-/* Load returned state from inflate_fast() */
-#define LOAD() \
-    do { \
-        put = strm->next_out; \
-        left = strm->avail_out; \
-        next = strm->next_in; \
-        have = strm->avail_in; \
-        hold = state->hold; \
-        bits = state->bits; \
-    } while (0)
-
-/* Set state from registers for inflate_fast() */
-#define RESTORE() \
-    do { \
-        strm->next_out = put; \
-        strm->avail_out = left; \
-        strm->next_in = next; \
-        strm->avail_in = have; \
-        state->hold = hold; \
-        state->bits = bits; \
-    } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
-    do { \
-        hold = 0; \
-        bits = 0; \
-    } while (0)
-
-/* Assure that some input is available.  If input is requested, but denied,
-   then return a Z_BUF_ERROR from inflateBack(). */
-#define PULL() \
-    do { \
-        if (have == 0) { \
-            have = in(in_desc, &next); \
-            if (have == 0) { \
-                next = Z_NULL; \
-                ret = Z_BUF_ERROR; \
-                goto inf_leave; \
-            } \
-        } \
-    } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflateBack()
-   with an error if there is no input available. */
-#define PULLBYTE() \
-    do { \
-        PULL(); \
-        have--; \
-        hold += (unsigned long)(*next++) << bits; \
-        bits += 8; \
-    } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator.  If there is
-   not enough available input to do that, then return from inflateBack() with
-   an error. */
-#define NEEDBITS(n) \
-    do { \
-        while (bits < (unsigned)(n)) \
-            PULLBYTE(); \
-    } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
-    ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
-    do { \
-        hold >>= (n); \
-        bits -= (unsigned)(n); \
-    } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
-    do { \
-        hold >>= bits & 7; \
-        bits -= bits & 7; \
-    } while (0)
-
-/* Assure that some output space is available, by writing out the window
-   if it's full.  If the write fails, return from inflateBack() with a
-   Z_BUF_ERROR. */
-#define ROOM() \
-    do { \
-        if (left == 0) { \
-            put = state->window; \
-            left = state->wsize; \
-            state->whave = left; \
-            if (out(out_desc, put, left)) { \
-                ret = Z_BUF_ERROR; \
-                goto inf_leave; \
-            } \
-        } \
-    } while (0)
-
-/*
-   strm provides the memory allocation functions and window buffer on input,
-   and provides information on the unused input on return.  For Z_DATA_ERROR
-   returns, strm will also provide an error message.
-
-   in() and out() are the call-back input and output functions.  When
-   inflateBack() needs more input, it calls in().  When inflateBack() has
-   filled the window with output, or when it completes with data in the
-   window, it calls out() to write out the data.  The application must not
-   change the provided input until in() is called again or inflateBack()
-   returns.  The application must not change the window/output buffer until
-   inflateBack() returns.
-
-   in() and out() are called with a descriptor parameter provided in the
-   inflateBack() call.  This parameter can be a structure that provides the
-   information required to do the read or write, as well as accumulated
-   information on the input and output such as totals and check values.
-
-   in() should return zero on failure.  out() should return non-zero on
-   failure.  If either in() or out() fails, than inflateBack() returns a
-   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
-   was in() or out() that caused in the error.  Otherwise,  inflateBack()
-   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
-   error, or Z_MEM_ERROR if it could not allocate memory for the state.
-   inflateBack() can also return Z_STREAM_ERROR if the input parameters
-   are not correct, i.e. strm is Z_NULL or the state was not initialized.
- */
-int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
-z_streamp strm;
-in_func in;
-void FAR *in_desc;
-out_func out;
-void FAR *out_desc;
-{
-    struct inflate_state FAR *state;
-    z_const unsigned char FAR *next;    /* next input */
-    unsigned char FAR *put;     /* next output */
-    unsigned have, left;        /* available input and output */
-    unsigned long hold;         /* bit buffer */
-    unsigned bits;              /* bits in bit buffer */
-    unsigned copy;              /* number of stored or match bytes to copy */
-    unsigned char FAR *from;    /* where to copy match bytes from */
-    code here;                  /* current decoding table entry */
-    code last;                  /* parent table entry */
-    unsigned len;               /* length to copy for repeats, bits to drop */
-    int ret;                    /* return code */
-    static const unsigned short order[19] = /* permutation of code lengths */
-        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-    /* Check that the strm exists and that the state was initialized */
-    if (strm == Z_NULL || strm->state == Z_NULL)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* Reset the state */
-    strm->msg = Z_NULL;
-    state->mode = TYPE;
-    state->last = 0;
-    state->whave = 0;
-    next = strm->next_in;
-    have = next != Z_NULL ? strm->avail_in : 0;
-    hold = 0;
-    bits = 0;
-    put = state->window;
-    left = state->wsize;
-
-    /* Inflate until end of block marked as last */
-    for (;;)
-        switch (state->mode) {
-        case TYPE:
-            /* determine and dispatch block type */
-            if (state->last) {
-                BYTEBITS();
-                state->mode = DONE;
-                break;
-            }
-            NEEDBITS(3);
-            state->last = BITS(1);
-            DROPBITS(1);
-            switch (BITS(2)) {
-            case 0:                             /* stored block */
-                Tracev((stderr, "inflate:     stored block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = STORED;
-                break;
-            case 1:                             /* fixed block */
-                fixedtables(state);
-                Tracev((stderr, "inflate:     fixed codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = LEN;              /* decode codes */
-                break;
-            case 2:                             /* dynamic block */
-                Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = TABLE;
-                break;
-            case 3:
-                strm->msg = (char *)"invalid block type";
-                state->mode = BAD;
-            }
-            DROPBITS(2);
-            break;
-
-        case STORED:
-            /* get and verify stored block length */
-            BYTEBITS();                         /* go to byte boundary */
-            NEEDBITS(32);
-            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = (char *)"invalid stored block lengths";
-                state->mode = BAD;
-                break;
-            }
-            state->length = (unsigned)hold & 0xffff;
-            Tracev((stderr, "inflate:       stored length %u\n",
-                    state->length));
-            INITBITS();
-
-            /* copy stored block from input to output */
-            while (state->length != 0) {
-                copy = state->length;
-                PULL();
-                ROOM();
-                if (copy > have) copy = have;
-                if (copy > left) copy = left;
-                zmemcpy(put, next, copy);
-                have -= copy;
-                next += copy;
-                left -= copy;
-                put += copy;
-                state->length -= copy;
-            }
-            Tracev((stderr, "inflate:       stored end\n"));
-            state->mode = TYPE;
-            break;
-
-        case TABLE:
-            /* get dynamic table entries descriptor */
-            NEEDBITS(14);
-            state->nlen = BITS(5) + 257;
-            DROPBITS(5);
-            state->ndist = BITS(5) + 1;
-            DROPBITS(5);
-            state->ncode = BITS(4) + 4;
-            DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
-            if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = (char *)"too many length or distance symbols";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracev((stderr, "inflate:       table sizes ok\n"));
-
-            /* get code length code lengths (not a typo) */
-            state->have = 0;
-            while (state->have < state->ncode) {
-                NEEDBITS(3);
-                state->lens[order[state->have++]] = (unsigned short)BITS(3);
-                DROPBITS(3);
-            }
-            while (state->have < 19)
-                state->lens[order[state->have++]] = 0;
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 7;
-            ret = inflate_table(CODES, state->lens, 19, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid code lengths set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       code lengths ok\n"));
-
-            /* get length and distance code code lengths */
-            state->have = 0;
-            while (state->have < state->nlen + state->ndist) {
-                for (;;) {
-                    here = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                if (here.val < 16) {
-                    DROPBITS(here.bits);
-                    state->lens[state->have++] = here.val;
-                }
-                else {
-                    if (here.val == 16) {
-                        NEEDBITS(here.bits + 2);
-                        DROPBITS(here.bits);
-                        if (state->have == 0) {
-                            strm->msg = (char *)"invalid bit length repeat";
-                            state->mode = BAD;
-                            break;
-                        }
-                        len = (unsigned)(state->lens[state->have - 1]);
-                        copy = 3 + BITS(2);
-                        DROPBITS(2);
-                    }
-                    else if (here.val == 17) {
-                        NEEDBITS(here.bits + 3);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 3 + BITS(3);
-                        DROPBITS(3);
-                    }
-                    else {
-                        NEEDBITS(here.bits + 7);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 11 + BITS(7);
-                        DROPBITS(7);
-                    }
-                    if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = (char *)"invalid bit length repeat";
-                        state->mode = BAD;
-                        break;
-                    }
-                    while (copy--)
-                        state->lens[state->have++] = (unsigned short)len;
-                }
-            }
-
-            /* handle error breaks in while */
-            if (state->mode == BAD) break;
-
-            /* check for end-of-block code (better have one) */
-            if (state->lens[256] == 0) {
-                strm->msg = (char *)"invalid code -- missing end-of-block";
-                state->mode = BAD;
-                break;
-            }
-
-            /* build code tables -- note: do not change the lenbits or distbits
-               values here (9 and 6) without reading the comments in inftrees.h
-               concerning the ENOUGH constants, which depend on those values */
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 9;
-            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid literal/lengths set";
-                state->mode = BAD;
-                break;
-            }
-            state->distcode = (code const FAR *)(state->next);
-            state->distbits = 6;
-            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
-                            &(state->next), &(state->distbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid distances set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       codes ok\n"));
-            state->mode = LEN;
-
-        case LEN:
-            /* use inflate_fast() if we have enough input and output */
-            if (have >= 6 && left >= 258) {
-                RESTORE();
-                if (state->whave < state->wsize)
-                    state->whave = state->wsize - left;
-                inflate_fast(strm, state->wsize);
-                LOAD();
-                break;
-            }
-
-            /* get a literal, length, or end-of-block code */
-            for (;;) {
-                here = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if (here.op && (here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->lencode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-            }
-            DROPBITS(here.bits);
-            state->length = (unsigned)here.val;
-
-            /* process literal */
-            if (here.op == 0) {
-                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                        "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", here.val));
-                ROOM();
-                *put++ = (unsigned char)(state->length);
-                left--;
-                state->mode = LEN;
-                break;
-            }
-
-            /* process end of block */
-            if (here.op & 32) {
-                Tracevv((stderr, "inflate:         end of block\n"));
-                state->mode = TYPE;
-                break;
-            }
-
-            /* invalid code */
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid literal/length code";
-                state->mode = BAD;
-                break;
-            }
-
-            /* length code -- get extra bits, if any */
-            state->extra = (unsigned)(here.op) & 15;
-            if (state->extra != 0) {
-                NEEDBITS(state->extra);
-                state->length += BITS(state->extra);
-                DROPBITS(state->extra);
-            }
-            Tracevv((stderr, "inflate:         length %u\n", state->length));
-
-            /* get distance code */
-            for (;;) {
-                here = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if ((here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->distcode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-            }
-            DROPBITS(here.bits);
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-            state->offset = (unsigned)here.val;
-
-            /* get distance extra bits, if any */
-            state->extra = (unsigned)(here.op) & 15;
-            if (state->extra != 0) {
-                NEEDBITS(state->extra);
-                state->offset += BITS(state->extra);
-                DROPBITS(state->extra);
-            }
-            if (state->offset > state->wsize - (state->whave < state->wsize ?
-                                                left : 0)) {
-                strm->msg = (char *)"invalid distance too far back";
-                state->mode = BAD;
-                break;
-            }
-            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
-
-            /* copy match from window to output */
-            do {
-                ROOM();
-                copy = state->wsize - state->offset;
-                if (copy < left) {
-                    from = put + copy;
-                    copy = left - copy;
-                }
-                else {
-                    from = put - state->offset;
-                    copy = left;
-                }
-                if (copy > state->length) copy = state->length;
-                state->length -= copy;
-                left -= copy;
-                do {
-                    *put++ = *from++;
-                } while (--copy);
-            } while (state->length != 0);
-            break;
-
-        case DONE:
-            /* inflate stream terminated properly -- write leftover output */
-            ret = Z_STREAM_END;
-            if (left < state->wsize) {
-                if (out(out_desc, state->window, state->wsize - left))
-                    ret = Z_BUF_ERROR;
-            }
-            goto inf_leave;
-
-        case BAD:
-            ret = Z_DATA_ERROR;
-            goto inf_leave;
-
-        default:                /* can't happen, but makes compilers happy */
-            ret = Z_STREAM_ERROR;
-            goto inf_leave;
-        }
-
-    /* Return unused input */
-  inf_leave:
-    strm->next_in = next;
-    strm->avail_in = have;
-    return ret;
-}
-
-int ZEXPORT inflateBackEnd(strm)
-z_streamp strm;
-{
-    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
-        return Z_STREAM_ERROR;
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-    Tracev((stderr, "inflate: end\n"));
-    return Z_OK;
-}
diff --git a/c/zlib/inffast.c b/c/zlib/inffast.c
deleted file mode 100644
--- a/c/zlib/inffast.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* inffast.c -- fast decoding
- * Copyright (C) 1995-2017 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-#ifdef ASMINF
-#  pragma message("Assembler code may have bugs -- use at your own risk")
-#else
-
-/*
-   Decode literal, length, and distance codes and write out the resulting
-   literal and match bytes until either not enough input or output is
-   available, an end-of-block is encountered, or a data error is encountered.
-   When large enough input and output buffers are supplied to inflate(), for
-   example, a 16K input buffer and a 64K output buffer, more than 95% of the
-   inflate execution time is spent in this routine.
-
-   Entry assumptions:
-
-        state->mode == LEN
-        strm->avail_in >= 6
-        strm->avail_out >= 258
-        start >= strm->avail_out
-        state->bits < 8
-
-   On return, state->mode is one of:
-
-        LEN -- ran out of enough output space or enough available input
-        TYPE -- reached end of block code, inflate() to interpret next block
-        BAD -- error in block data
-
-   Notes:
-
-    - The maximum input bits used by a length/distance pair is 15 bits for the
-      length code, 5 bits for the length extra, 15 bits for the distance code,
-      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
-      Therefore if strm->avail_in >= 6, then there is enough input to avoid
-      checking for available input while decoding.
-
-    - The maximum bytes that a single length/distance pair can output is 258
-      bytes, which is the maximum length that can be coded.  inflate_fast()
-      requires strm->avail_out >= 258 for each loop to avoid checking for
-      output space.
- */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start;         /* inflate()'s starting value for strm->avail_out */
-{
-    struct inflate_state FAR *state;
-    z_const unsigned char FAR *in;      /* local strm->next_in */
-    z_const unsigned char FAR *last;    /* have enough input while in < last */
-    unsigned char FAR *out;     /* local strm->next_out */
-    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
-    unsigned char FAR *end;     /* while out < end, enough space available */
-#ifdef INFLATE_STRICT
-    unsigned dmax;              /* maximum distance from zlib header */
-#endif
-    unsigned wsize;             /* window size or zero if not using window */
-    unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
-    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
-    unsigned long hold;         /* local strm->hold */
-    unsigned bits;              /* local strm->bits */
-    code const FAR *lcode;      /* local strm->lencode */
-    code const FAR *dcode;      /* local strm->distcode */
-    unsigned lmask;             /* mask for first level of length codes */
-    unsigned dmask;             /* mask for first level of distance codes */
-    code here;                  /* retrieved table entry */
-    unsigned op;                /* code bits, operation, extra bits, or */
-                                /*  window position, window bytes to copy */
-    unsigned len;               /* match length, unused bytes */
-    unsigned dist;              /* match distance */
-    unsigned char FAR *from;    /* where to copy match from */
-
-    /* copy state to local variables */
-    state = (struct inflate_state FAR *)strm->state;
-    in = strm->next_in;
-    last = in + (strm->avail_in - 5);
-    out = strm->next_out;
-    beg = out - (start - strm->avail_out);
-    end = out + (strm->avail_out - 257);
-#ifdef INFLATE_STRICT
-    dmax = state->dmax;
-#endif
-    wsize = state->wsize;
-    whave = state->whave;
-    wnext = state->wnext;
-    window = state->window;
-    hold = state->hold;
-    bits = state->bits;
-    lcode = state->lencode;
-    dcode = state->distcode;
-    lmask = (1U << state->lenbits) - 1;
-    dmask = (1U << state->distbits) - 1;
-
-    /* decode literals and length/distances until end-of-block or not enough
-       input data or output space */
-    do {
-        if (bits < 15) {
-            hold += (unsigned long)(*in++) << bits;
-            bits += 8;
-            hold += (unsigned long)(*in++) << bits;
-            bits += 8;
-        }
-        here = lcode[hold & lmask];
-      dolen:
-        op = (unsigned)(here.bits);
-        hold >>= op;
-        bits -= op;
-        op = (unsigned)(here.op);
-        if (op == 0) {                          /* literal */
-            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                    "inflate:         literal '%c'\n" :
-                    "inflate:         literal 0x%02x\n", here.val));
-            *out++ = (unsigned char)(here.val);
-        }
-        else if (op & 16) {                     /* length base */
-            len = (unsigned)(here.val);
-            op &= 15;                           /* number of extra bits */
-            if (op) {
-                if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
-                    bits += 8;
-                }
-                len += (unsigned)hold & ((1U << op) - 1);
-                hold >>= op;
-                bits -= op;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", len));
-            if (bits < 15) {
-                hold += (unsigned long)(*in++) << bits;
-                bits += 8;
-                hold += (unsigned long)(*in++) << bits;
-                bits += 8;
-            }
-            here = dcode[hold & dmask];
-          dodist:
-            op = (unsigned)(here.bits);
-            hold >>= op;
-            bits -= op;
-            op = (unsigned)(here.op);
-            if (op & 16) {                      /* distance base */
-                dist = (unsigned)(here.val);
-                op &= 15;                       /* number of extra bits */
-                if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
-                    bits += 8;
-                    if (bits < op) {
-                        hold += (unsigned long)(*in++) << bits;
-                        bits += 8;
-                    }
-                }
-                dist += (unsigned)hold & ((1U << op) - 1);
-#ifdef INFLATE_STRICT
-                if (dist > dmax) {
-                    strm->msg = (char *)"invalid distance too far back";
-                    state->mode = BAD;
-                    break;
-                }
-#endif
-                hold >>= op;
-                bits -= op;
-                Tracevv((stderr, "inflate:         distance %u\n", dist));
-                op = (unsigned)(out - beg);     /* max distance in output */
-                if (dist > op) {                /* see if copy from window */
-                    op = dist - op;             /* distance back in window */
-                    if (op > whave) {
-                        if (state->sane) {
-                            strm->msg =
-                                (char *)"invalid distance too far back";
-                            state->mode = BAD;
-                            break;
-                        }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                        if (len <= op - whave) {
-                            do {
-                                *out++ = 0;
-                            } while (--len);
-                            continue;
-                        }
-                        len -= op - whave;
-                        do {
-                            *out++ = 0;
-                        } while (--op > whave);
-                        if (op == 0) {
-                            from = out - dist;
-                            do {
-                                *out++ = *from++;
-                            } while (--len);
-                            continue;
-                        }
-#endif
-                    }
-                    from = window;
-                    if (wnext == 0) {           /* very common case */
-                        from += wsize - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
-                    }
-                    else if (wnext < op) {      /* wrap around window */
-                        from += wsize + wnext - op;
-                        op -= wnext;
-                        if (op < len) {         /* some from end of window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = window;
-                            if (wnext < len) {  /* some from start of window */
-                                op = wnext;
-                                len -= op;
-                                do {
-                                    *out++ = *from++;
-                                } while (--op);
-                                from = out - dist;      /* rest from output */
-                            }
-                        }
-                    }
-                    else {                      /* contiguous in window */
-                        from += wnext - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
-                    }
-                    while (len > 2) {
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        len -= 3;
-                    }
-                    if (len) {
-                        *out++ = *from++;
-                        if (len > 1)
-                            *out++ = *from++;
-                    }
-                }
-                else {
-                    from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        len -= 3;
-                    } while (len > 2);
-                    if (len) {
-                        *out++ = *from++;
-                        if (len > 1)
-                            *out++ = *from++;
-                    }
-                }
-            }
-            else if ((op & 64) == 0) {          /* 2nd level distance code */
-                here = dcode[here.val + (hold & ((1U << op) - 1))];
-                goto dodist;
-            }
-            else {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-        }
-        else if ((op & 64) == 0) {              /* 2nd level length code */
-            here = lcode[here.val + (hold & ((1U << op) - 1))];
-            goto dolen;
-        }
-        else if (op & 32) {                     /* end-of-block */
-            Tracevv((stderr, "inflate:         end of block\n"));
-            state->mode = TYPE;
-            break;
-        }
-        else {
-            strm->msg = (char *)"invalid literal/length code";
-            state->mode = BAD;
-            break;
-        }
-    } while (in < last && out < end);
-
-    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
-    len = bits >> 3;
-    in -= len;
-    bits -= len << 3;
-    hold &= (1U << bits) - 1;
-
-    /* update state and return */
-    strm->next_in = in;
-    strm->next_out = out;
-    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
-    strm->avail_out = (unsigned)(out < end ?
-                                 257 + (end - out) : 257 - (out - end));
-    state->hold = hold;
-    state->bits = bits;
-    return;
-}
-
-/*
-   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
-   - Using bit fields for code structure
-   - Different op definition to avoid & for extra bits (do & for table bits)
-   - Three separate decoding do-loops for direct, window, and wnext == 0
-   - Special case for distance > 1 copies to do overlapped load and store copy
-   - Explicit branch predictions (based on measured branch probabilities)
-   - Deferring match copy and interspersed it with decoding subsequent codes
-   - Swapping literal/length else
-   - Swapping window/direct else
-   - Larger unrolled copy loops (three is about right)
-   - Moving len -= 3 statement into middle of loop
- */
-
-#endif /* !ASMINF */
diff --git a/c/zlib/inffast.h b/c/zlib/inffast.h
deleted file mode 100644
--- a/c/zlib/inffast.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-2003, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/c/zlib/inffixed.h b/c/zlib/inffixed.h
deleted file mode 100644
--- a/c/zlib/inffixed.h
+++ /dev/null
@@ -1,94 +0,0 @@
-    /* inffixed.h -- table for decoding fixed codes
-     * Generated automatically by makefixed().
-     */
-
-    /* WARNING: this file should *not* be used by applications.
-       It is part of the implementation of this library and is
-       subject to change. Applications should only use zlib.h.
-     */
-
-    static const code lenfix[512] = {
-        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
-        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
-        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
-        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
-        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
-        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
-        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
-        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
-        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
-        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
-        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
-        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
-        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
-        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
-        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
-        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
-        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
-        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
-        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
-        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
-        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
-        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
-        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
-        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
-        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
-        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
-        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
-        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
-        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
-        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
-        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
-        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
-        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
-        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
-        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
-        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
-        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
-        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
-        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
-        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
-        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
-        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
-        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
-        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
-        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
-        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
-        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
-        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
-        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
-        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
-        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
-        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
-        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
-        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
-        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
-        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
-        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
-        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
-        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
-        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
-        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
-        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
-        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
-        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
-        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
-        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
-        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
-        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
-        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
-        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
-        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
-        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
-        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
-        {0,9,255}
-    };
-
-    static const code distfix[32] = {
-        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
-        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
-        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
-        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
-        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
-        {22,5,193},{64,5,0}
-    };
diff --git a/c/zlib/inflate.c b/c/zlib/inflate.c
deleted file mode 100644
--- a/c/zlib/inflate.c
+++ /dev/null
@@ -1,1561 +0,0 @@
-/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * Change history:
- *
- * 1.2.beta0    24 Nov 2002
- * - First version -- complete rewrite of inflate to simplify code, avoid
- *   creation of window when not needed, minimize use of window when it is
- *   needed, make inffast.c even faster, implement gzip decoding, and to
- *   improve code readability and style over the previous zlib inflate code
- *
- * 1.2.beta1    25 Nov 2002
- * - Use pointers for available input and output checking in inffast.c
- * - Remove input and output counters in inffast.c
- * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
- * - Remove unnecessary second byte pull from length extra in inffast.c
- * - Unroll direct copy to three copies per loop in inffast.c
- *
- * 1.2.beta2    4 Dec 2002
- * - Change external routine names to reduce potential conflicts
- * - Correct filename to inffixed.h for fixed tables in inflate.c
- * - Make hbuf[] unsigned char to match parameter type in inflate.c
- * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
- *   to avoid negation problem on Alphas (64 bit) in inflate.c
- *
- * 1.2.beta3    22 Dec 2002
- * - Add comments on state->bits assertion in inffast.c
- * - Add comments on op field in inftrees.h
- * - Fix bug in reuse of allocated window after inflateReset()
- * - Remove bit fields--back to byte structure for speed
- * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
- * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
- * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
- * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
- * - Use local copies of stream next and avail values, as well as local bit
- *   buffer and bit count in inflate()--for speed when inflate_fast() not used
- *
- * 1.2.beta4    1 Jan 2003
- * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
- * - Move a comment on output buffer sizes from inffast.c to inflate.c
- * - Add comments in inffast.c to introduce the inflate_fast() routine
- * - Rearrange window copies in inflate_fast() for speed and simplification
- * - Unroll last copy for window match in inflate_fast()
- * - Use local copies of window variables in inflate_fast() for speed
- * - Pull out common wnext == 0 case for speed in inflate_fast()
- * - Make op and len in inflate_fast() unsigned for consistency
- * - Add FAR to lcode and dcode declarations in inflate_fast()
- * - Simplified bad distance check in inflate_fast()
- * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
- *   source file infback.c to provide a call-back interface to inflate for
- *   programs like gzip and unzip -- uses window as output buffer to avoid
- *   window copying
- *
- * 1.2.beta5    1 Jan 2003
- * - Improved inflateBack() interface to allow the caller to provide initial
- *   input in strm.
- * - Fixed stored blocks bug in inflateBack()
- *
- * 1.2.beta6    4 Jan 2003
- * - Added comments in inffast.c on effectiveness of POSTINC
- * - Typecasting all around to reduce compiler warnings
- * - Changed loops from while (1) or do {} while (1) to for (;;), again to
- *   make compilers happy
- * - Changed type of window in inflateBackInit() to unsigned char *
- *
- * 1.2.beta7    27 Jan 2003
- * - Changed many types to unsigned or unsigned short to avoid warnings
- * - Added inflateCopy() function
- *
- * 1.2.0        9 Mar 2003
- * - Changed inflateBack() interface to provide separate opaque descriptors
- *   for the in() and out() functions
- * - Changed inflateBack() argument and in_func typedef to swap the length
- *   and buffer address return values for the input function
- * - Check next_in and next_out for Z_NULL on entry to inflate()
- *
- * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-#ifdef MAKEFIXED
-#  ifndef BUILDFIXED
-#    define BUILDFIXED
-#  endif
-#endif
-
-/* function prototypes */
-local int inflateStateCheck OF((z_streamp strm));
-local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
-                           unsigned copy));
-#ifdef BUILDFIXED
-   void makefixed OF((void));
-#endif
-local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
-                              unsigned len));
-
-local int inflateStateCheck(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (strm == Z_NULL ||
-        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
-        return 1;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state == Z_NULL || state->strm != strm ||
-        state->mode < HEAD || state->mode > SYNC)
-        return 1;
-    return 0;
-}
-
-int ZEXPORT inflateResetKeep(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    strm->total_in = strm->total_out = state->total = 0;
-    strm->msg = Z_NULL;
-    if (state->wrap)        /* to support ill-conceived Java test suite */
-        strm->adler = state->wrap & 1;
-    state->mode = HEAD;
-    state->last = 0;
-    state->havedict = 0;
-    state->dmax = 32768U;
-    state->head = Z_NULL;
-    state->hold = 0;
-    state->bits = 0;
-    state->lencode = state->distcode = state->next = state->codes;
-    state->sane = 1;
-    state->back = -1;
-    Tracev((stderr, "inflate: reset\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateReset(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    state->wsize = 0;
-    state->whave = 0;
-    state->wnext = 0;
-    return inflateResetKeep(strm);
-}
-
-int ZEXPORT inflateReset2(strm, windowBits)
-z_streamp strm;
-int windowBits;
-{
-    int wrap;
-    struct inflate_state FAR *state;
-
-    /* get the state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* extract wrap request from windowBits parameter */
-    if (windowBits < 0) {
-        wrap = 0;
-        windowBits = -windowBits;
-    }
-    else {
-        wrap = (windowBits >> 4) + 5;
-#ifdef GUNZIP
-        if (windowBits < 48)
-            windowBits &= 15;
-#endif
-    }
-
-    /* set number of window bits, free window if different */
-    if (windowBits && (windowBits < 8 || windowBits > 15))
-        return Z_STREAM_ERROR;
-    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
-        ZFREE(strm, state->window);
-        state->window = Z_NULL;
-    }
-
-    /* update state and reset the rest of it */
-    state->wrap = wrap;
-    state->wbits = (unsigned)windowBits;
-    return inflateReset(strm);
-}
-
-int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
-z_streamp strm;
-int windowBits;
-const char *version;
-int stream_size;
-{
-    int ret;
-    struct inflate_state FAR *state;
-
-    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-        stream_size != (int)(sizeof(z_stream)))
-        return Z_VERSION_ERROR;
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-    strm->msg = Z_NULL;                 /* in case we return an error */
-    if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-#endif
-    }
-    if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zfree = zcfree;
-#endif
-    state = (struct inflate_state FAR *)
-            ZALLOC(strm, 1, sizeof(struct inflate_state));
-    if (state == Z_NULL) return Z_MEM_ERROR;
-    Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (struct internal_state FAR *)state;
-    state->strm = strm;
-    state->window = Z_NULL;
-    state->mode = HEAD;     /* to pass state test in inflateReset2() */
-    ret = inflateReset2(strm, windowBits);
-    if (ret != Z_OK) {
-        ZFREE(strm, state);
-        strm->state = Z_NULL;
-    }
-    return ret;
-}
-
-int ZEXPORT inflateInit_(strm, version, stream_size)
-z_streamp strm;
-const char *version;
-int stream_size;
-{
-    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
-}
-
-int ZEXPORT inflatePrime(strm, bits, value)
-z_streamp strm;
-int bits;
-int value;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (bits < 0) {
-        state->hold = 0;
-        state->bits = 0;
-        return Z_OK;
-    }
-    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
-    value &= (1L << bits) - 1;
-    state->hold += (unsigned)value << state->bits;
-    state->bits += (uInt)bits;
-    return Z_OK;
-}
-
-/*
-   Return state with length and distance decoding tables and index sizes set to
-   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-   If BUILDFIXED is defined, then instead this routine builds the tables the
-   first time it's called, and returns those tables the first time and
-   thereafter.  This reduces the size of the code by about 2K bytes, in
-   exchange for a little execution time.  However, BUILDFIXED should not be
-   used for threaded applications, since the rewriting of the tables and virgin
-   may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
-    static int virgin = 1;
-    static code *lenfix, *distfix;
-    static code fixed[544];
-
-    /* build fixed huffman tables if first call (may not be thread safe) */
-    if (virgin) {
-        unsigned sym, bits;
-        static code *next;
-
-        /* literal/length table */
-        sym = 0;
-        while (sym < 144) state->lens[sym++] = 8;
-        while (sym < 256) state->lens[sym++] = 9;
-        while (sym < 280) state->lens[sym++] = 7;
-        while (sym < 288) state->lens[sym++] = 8;
-        next = fixed;
-        lenfix = next;
-        bits = 9;
-        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
-        /* distance table */
-        sym = 0;
-        while (sym < 32) state->lens[sym++] = 5;
-        distfix = next;
-        bits = 5;
-        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
-        /* do this just once */
-        virgin = 0;
-    }
-#else /* !BUILDFIXED */
-#   include "inffixed.h"
-#endif /* BUILDFIXED */
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-#ifdef MAKEFIXED
-#include <stdio.h>
-
-/*
-   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
-   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
-   those tables to stdout, which would be piped to inffixed.h.  A small program
-   can simply call makefixed to do this:
-
-    void makefixed(void);
-
-    int main(void)
-    {
-        makefixed();
-        return 0;
-    }
-
-   Then that can be linked with zlib built with MAKEFIXED defined and run:
-
-    a.out > inffixed.h
- */
-void makefixed()
-{
-    unsigned low, size;
-    struct inflate_state state;
-
-    fixedtables(&state);
-    puts("    /* inffixed.h -- table for decoding fixed codes");
-    puts("     * Generated automatically by makefixed().");
-    puts("     */");
-    puts("");
-    puts("    /* WARNING: this file should *not* be used by applications.");
-    puts("       It is part of the implementation of this library and is");
-    puts("       subject to change. Applications should only use zlib.h.");
-    puts("     */");
-    puts("");
-    size = 1U << 9;
-    printf("    static const code lenfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 7) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
-               state.lencode[low].bits, state.lencode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-    size = 1U << 5;
-    printf("\n    static const code distfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 6) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
-               state.distcode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-}
-#endif /* MAKEFIXED */
-
-/*
-   Update the window with the last wsize (normally 32K) bytes written before
-   returning.  If window does not exist yet, create it.  This is only called
-   when a window is already in use, or when output has been written during this
-   inflate call, but the end of the deflate stream has not been reached yet.
-   It is also called to create a window for dictionary data when a dictionary
-   is loaded.
-
-   Providing output buffers larger than 32K to inflate() should provide a speed
-   advantage, since only the last 32K of output is copied to the sliding window
-   upon return from inflate(), and since all distances after the first 32K of
-   output will fall in the output data, making match copies simpler and faster.
-   The advantage may be dependent on the size of the processor's data caches.
- */
-local int updatewindow(strm, end, copy)
-z_streamp strm;
-const Bytef *end;
-unsigned copy;
-{
-    struct inflate_state FAR *state;
-    unsigned dist;
-
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* if it hasn't been done already, allocate space for the window */
-    if (state->window == Z_NULL) {
-        state->window = (unsigned char FAR *)
-                        ZALLOC(strm, 1U << state->wbits,
-                               sizeof(unsigned char));
-        if (state->window == Z_NULL) return 1;
-    }
-
-    /* if window not in use yet, initialize */
-    if (state->wsize == 0) {
-        state->wsize = 1U << state->wbits;
-        state->wnext = 0;
-        state->whave = 0;
-    }
-
-    /* copy state->wsize or less output bytes into the circular window */
-    if (copy >= state->wsize) {
-        zmemcpy(state->window, end - state->wsize, state->wsize);
-        state->wnext = 0;
-        state->whave = state->wsize;
-    }
-    else {
-        dist = state->wsize - state->wnext;
-        if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, end - copy, dist);
-        copy -= dist;
-        if (copy) {
-            zmemcpy(state->window, end - copy, copy);
-            state->wnext = copy;
-            state->whave = state->wsize;
-        }
-        else {
-            state->wnext += dist;
-            if (state->wnext == state->wsize) state->wnext = 0;
-            if (state->whave < state->wsize) state->whave += dist;
-        }
-    }
-    return 0;
-}
-
-/* Macros for inflate(): */
-
-/* check function to use adler32() for zlib or crc32() for gzip */
-#ifdef GUNZIP
-#  define UPDATE(check, buf, len) \
-    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
-#else
-#  define UPDATE(check, buf, len) adler32(check, buf, len)
-#endif
-
-/* check macros for header crc */
-#ifdef GUNZIP
-#  define CRC2(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        check = crc32(check, hbuf, 2); \
-    } while (0)
-
-#  define CRC4(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        hbuf[2] = (unsigned char)((word) >> 16); \
-        hbuf[3] = (unsigned char)((word) >> 24); \
-        check = crc32(check, hbuf, 4); \
-    } while (0)
-#endif
-
-/* Load registers with state in inflate() for speed */
-#define LOAD() \
-    do { \
-        put = strm->next_out; \
-        left = strm->avail_out; \
-        next = strm->next_in; \
-        have = strm->avail_in; \
-        hold = state->hold; \
-        bits = state->bits; \
-    } while (0)
-
-/* Restore state from registers in inflate() */
-#define RESTORE() \
-    do { \
-        strm->next_out = put; \
-        strm->avail_out = left; \
-        strm->next_in = next; \
-        strm->avail_in = have; \
-        state->hold = hold; \
-        state->bits = bits; \
-    } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
-    do { \
-        hold = 0; \
-        bits = 0; \
-    } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflate()
-   if there is no input available. */
-#define PULLBYTE() \
-    do { \
-        if (have == 0) goto inf_leave; \
-        have--; \
-        hold += (unsigned long)(*next++) << bits; \
-        bits += 8; \
-    } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator.  If there is
-   not enough available input to do that, then return from inflate(). */
-#define NEEDBITS(n) \
-    do { \
-        while (bits < (unsigned)(n)) \
-            PULLBYTE(); \
-    } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
-    ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
-    do { \
-        hold >>= (n); \
-        bits -= (unsigned)(n); \
-    } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
-    do { \
-        hold >>= bits & 7; \
-        bits -= bits & 7; \
-    } while (0)
-
-/*
-   inflate() uses a state machine to process as much input data and generate as
-   much output data as possible before returning.  The state machine is
-   structured roughly as follows:
-
-    for (;;) switch (state) {
-    ...
-    case STATEn:
-        if (not enough input data or output space to make progress)
-            return;
-        ... make progress ...
-        state = STATEm;
-        break;
-    ...
-    }
-
-   so when inflate() is called again, the same case is attempted again, and
-   if the appropriate resources are provided, the machine proceeds to the
-   next state.  The NEEDBITS() macro is usually the way the state evaluates
-   whether it can proceed or should return.  NEEDBITS() does the return if
-   the requested bits are not available.  The typical use of the BITS macros
-   is:
-
-        NEEDBITS(n);
-        ... do something with BITS(n) ...
-        DROPBITS(n);
-
-   where NEEDBITS(n) either returns from inflate() if there isn't enough
-   input left to load n bits into the accumulator, or it continues.  BITS(n)
-   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
-   the low n bits off the accumulator.  INITBITS() clears the accumulator
-   and sets the number of available bits to zero.  BYTEBITS() discards just
-   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
-   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
-
-   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
-   if there is no input available.  The decoding of variable length codes uses
-   PULLBYTE() directly in order to pull just enough bytes to decode the next
-   code, and no more.
-
-   Some states loop until they get enough input, making sure that enough
-   state information is maintained to continue the loop where it left off
-   if NEEDBITS() returns in the loop.  For example, want, need, and keep
-   would all have to actually be part of the saved state in case NEEDBITS()
-   returns:
-
-    case STATEw:
-        while (want < need) {
-            NEEDBITS(n);
-            keep[want++] = BITS(n);
-            DROPBITS(n);
-        }
-        state = STATEx;
-    case STATEx:
-
-   As shown above, if the next state is also the next case, then the break
-   is omitted.
-
-   A state may also return if there is not enough output space available to
-   complete that state.  Those states are copying stored data, writing a
-   literal byte, and copying a matching string.
-
-   When returning, a "goto inf_leave" is used to update the total counters,
-   update the check value, and determine whether any progress has been made
-   during that inflate() call in order to return the proper return code.
-   Progress is defined as a change in either strm->avail_in or strm->avail_out.
-   When there is a window, goto inf_leave will update the window with the last
-   output written.  If a goto inf_leave occurs in the middle of decompression
-   and there is no window currently, goto inf_leave will create one and copy
-   output to the window for the next call of inflate().
-
-   In this implementation, the flush parameter of inflate() only affects the
-   return code (per zlib.h).  inflate() always writes as much as possible to
-   strm->next_out, given the space available and the provided input--the effect
-   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
-   the allocation of and copying into a sliding window until necessary, which
-   provides the effect documented in zlib.h for Z_FINISH when the entire input
-   stream available.  So the only thing the flush parameter actually does is:
-   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
-   will return Z_BUF_ERROR if it has not reached the end of the stream.
- */
-
-int ZEXPORT inflate(strm, flush)
-z_streamp strm;
-int flush;
-{
-    struct inflate_state FAR *state;
-    z_const unsigned char FAR *next;    /* next input */
-    unsigned char FAR *put;     /* next output */
-    unsigned have, left;        /* available input and output */
-    unsigned long hold;         /* bit buffer */
-    unsigned bits;              /* bits in bit buffer */
-    unsigned in, out;           /* save starting available input and output */
-    unsigned copy;              /* number of stored or match bytes to copy */
-    unsigned char FAR *from;    /* where to copy match bytes from */
-    code here;                  /* current decoding table entry */
-    code last;                  /* parent table entry */
-    unsigned len;               /* length to copy for repeats, bits to drop */
-    int ret;                    /* return code */
-#ifdef GUNZIP
-    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
-#endif
-    static const unsigned short order[19] = /* permutation of code lengths */
-        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
-        (strm->next_in == Z_NULL && strm->avail_in != 0))
-        return Z_STREAM_ERROR;
-
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
-    LOAD();
-    in = have;
-    out = left;
-    ret = Z_OK;
-    for (;;)
-        switch (state->mode) {
-        case HEAD:
-            if (state->wrap == 0) {
-                state->mode = TYPEDO;
-                break;
-            }
-            NEEDBITS(16);
-#ifdef GUNZIP
-            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
-                if (state->wbits == 0)
-                    state->wbits = 15;
-                state->check = crc32(0L, Z_NULL, 0);
-                CRC2(state->check, hold);
-                INITBITS();
-                state->mode = FLAGS;
-                break;
-            }
-            state->flags = 0;           /* expect zlib header */
-            if (state->head != Z_NULL)
-                state->head->done = -1;
-            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
-#else
-            if (
-#endif
-                ((BITS(8) << 8) + (hold >> 8)) % 31) {
-                strm->msg = (char *)"incorrect header check";
-                state->mode = BAD;
-                break;
-            }
-            if (BITS(4) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            DROPBITS(4);
-            len = BITS(4) + 8;
-            if (state->wbits == 0)
-                state->wbits = len;
-            if (len > 15 || len > state->wbits) {
-                strm->msg = (char *)"invalid window size";
-                state->mode = BAD;
-                break;
-            }
-            state->dmax = 1U << len;
-            Tracev((stderr, "inflate:   zlib header ok\n"));
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = hold & 0x200 ? DICTID : TYPE;
-            INITBITS();
-            break;
-#ifdef GUNZIP
-        case FLAGS:
-            NEEDBITS(16);
-            state->flags = (int)(hold);
-            if ((state->flags & 0xff) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            if (state->flags & 0xe000) {
-                strm->msg = (char *)"unknown header flags set";
-                state->mode = BAD;
-                break;
-            }
-            if (state->head != Z_NULL)
-                state->head->text = (int)((hold >> 8) & 1);
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC2(state->check, hold);
-            INITBITS();
-            state->mode = TIME;
-        case TIME:
-            NEEDBITS(32);
-            if (state->head != Z_NULL)
-                state->head->time = hold;
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC4(state->check, hold);
-            INITBITS();
-            state->mode = OS;
-        case OS:
-            NEEDBITS(16);
-            if (state->head != Z_NULL) {
-                state->head->xflags = (int)(hold & 0xff);
-                state->head->os = (int)(hold >> 8);
-            }
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC2(state->check, hold);
-            INITBITS();
-            state->mode = EXLEN;
-        case EXLEN:
-            if (state->flags & 0x0400) {
-                NEEDBITS(16);
-                state->length = (unsigned)(hold);
-                if (state->head != Z_NULL)
-                    state->head->extra_len = (unsigned)hold;
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    CRC2(state->check, hold);
-                INITBITS();
-            }
-            else if (state->head != Z_NULL)
-                state->head->extra = Z_NULL;
-            state->mode = EXTRA;
-        case EXTRA:
-            if (state->flags & 0x0400) {
-                copy = state->length;
-                if (copy > have) copy = have;
-                if (copy) {
-                    if (state->head != Z_NULL &&
-                        state->head->extra != Z_NULL) {
-                        len = state->head->extra_len - state->length;
-                        zmemcpy(state->head->extra + len, next,
-                                len + copy > state->head->extra_max ?
-                                state->head->extra_max - len : copy);
-                    }
-                    if ((state->flags & 0x0200) && (state->wrap & 4))
-                        state->check = crc32(state->check, next, copy);
-                    have -= copy;
-                    next += copy;
-                    state->length -= copy;
-                }
-                if (state->length) goto inf_leave;
-            }
-            state->length = 0;
-            state->mode = NAME;
-        case NAME:
-            if (state->flags & 0x0800) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->name != Z_NULL &&
-                            state->length < state->head->name_max)
-                        state->head->name[state->length++] = (Bytef)len;
-                } while (len && copy < have);
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->name = Z_NULL;
-            state->length = 0;
-            state->mode = COMMENT;
-        case COMMENT:
-            if (state->flags & 0x1000) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->comment != Z_NULL &&
-                            state->length < state->head->comm_max)
-                        state->head->comment[state->length++] = (Bytef)len;
-                } while (len && copy < have);
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->comment = Z_NULL;
-            state->mode = HCRC;
-        case HCRC:
-            if (state->flags & 0x0200) {
-                NEEDBITS(16);
-                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
-                    strm->msg = (char *)"header crc mismatch";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-            }
-            if (state->head != Z_NULL) {
-                state->head->hcrc = (int)((state->flags >> 9) & 1);
-                state->head->done = 1;
-            }
-            strm->adler = state->check = crc32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-            break;
-#endif
-        case DICTID:
-            NEEDBITS(32);
-            strm->adler = state->check = ZSWAP32(hold);
-            INITBITS();
-            state->mode = DICT;
-        case DICT:
-            if (state->havedict == 0) {
-                RESTORE();
-                return Z_NEED_DICT;
-            }
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-        case TYPE:
-            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
-        case TYPEDO:
-            if (state->last) {
-                BYTEBITS();
-                state->mode = CHECK;
-                break;
-            }
-            NEEDBITS(3);
-            state->last = BITS(1);
-            DROPBITS(1);
-            switch (BITS(2)) {
-            case 0:                             /* stored block */
-                Tracev((stderr, "inflate:     stored block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = STORED;
-                break;
-            case 1:                             /* fixed block */
-                fixedtables(state);
-                Tracev((stderr, "inflate:     fixed codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = LEN_;             /* decode codes */
-                if (flush == Z_TREES) {
-                    DROPBITS(2);
-                    goto inf_leave;
-                }
-                break;
-            case 2:                             /* dynamic block */
-                Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = TABLE;
-                break;
-            case 3:
-                strm->msg = (char *)"invalid block type";
-                state->mode = BAD;
-            }
-            DROPBITS(2);
-            break;
-        case STORED:
-            BYTEBITS();                         /* go to byte boundary */
-            NEEDBITS(32);
-            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = (char *)"invalid stored block lengths";
-                state->mode = BAD;
-                break;
-            }
-            state->length = (unsigned)hold & 0xffff;
-            Tracev((stderr, "inflate:       stored length %u\n",
-                    state->length));
-            INITBITS();
-            state->mode = COPY_;
-            if (flush == Z_TREES) goto inf_leave;
-        case COPY_:
-            state->mode = COPY;
-        case COPY:
-            copy = state->length;
-            if (copy) {
-                if (copy > have) copy = have;
-                if (copy > left) copy = left;
-                if (copy == 0) goto inf_leave;
-                zmemcpy(put, next, copy);
-                have -= copy;
-                next += copy;
-                left -= copy;
-                put += copy;
-                state->length -= copy;
-                break;
-            }
-            Tracev((stderr, "inflate:       stored end\n"));
-            state->mode = TYPE;
-            break;
-        case TABLE:
-            NEEDBITS(14);
-            state->nlen = BITS(5) + 257;
-            DROPBITS(5);
-            state->ndist = BITS(5) + 1;
-            DROPBITS(5);
-            state->ncode = BITS(4) + 4;
-            DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
-            if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = (char *)"too many length or distance symbols";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracev((stderr, "inflate:       table sizes ok\n"));
-            state->have = 0;
-            state->mode = LENLENS;
-        case LENLENS:
-            while (state->have < state->ncode) {
-                NEEDBITS(3);
-                state->lens[order[state->have++]] = (unsigned short)BITS(3);
-                DROPBITS(3);
-            }
-            while (state->have < 19)
-                state->lens[order[state->have++]] = 0;
-            state->next = state->codes;
-            state->lencode = (const code FAR *)(state->next);
-            state->lenbits = 7;
-            ret = inflate_table(CODES, state->lens, 19, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid code lengths set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       code lengths ok\n"));
-            state->have = 0;
-            state->mode = CODELENS;
-        case CODELENS:
-            while (state->have < state->nlen + state->ndist) {
-                for (;;) {
-                    here = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                if (here.val < 16) {
-                    DROPBITS(here.bits);
-                    state->lens[state->have++] = here.val;
-                }
-                else {
-                    if (here.val == 16) {
-                        NEEDBITS(here.bits + 2);
-                        DROPBITS(here.bits);
-                        if (state->have == 0) {
-                            strm->msg = (char *)"invalid bit length repeat";
-                            state->mode = BAD;
-                            break;
-                        }
-                        len = state->lens[state->have - 1];
-                        copy = 3 + BITS(2);
-                        DROPBITS(2);
-                    }
-                    else if (here.val == 17) {
-                        NEEDBITS(here.bits + 3);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 3 + BITS(3);
-                        DROPBITS(3);
-                    }
-                    else {
-                        NEEDBITS(here.bits + 7);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 11 + BITS(7);
-                        DROPBITS(7);
-                    }
-                    if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = (char *)"invalid bit length repeat";
-                        state->mode = BAD;
-                        break;
-                    }
-                    while (copy--)
-                        state->lens[state->have++] = (unsigned short)len;
-                }
-            }
-
-            /* handle error breaks in while */
-            if (state->mode == BAD) break;
-
-            /* check for end-of-block code (better have one) */
-            if (state->lens[256] == 0) {
-                strm->msg = (char *)"invalid code -- missing end-of-block";
-                state->mode = BAD;
-                break;
-            }
-
-            /* build code tables -- note: do not change the lenbits or distbits
-               values here (9 and 6) without reading the comments in inftrees.h
-               concerning the ENOUGH constants, which depend on those values */
-            state->next = state->codes;
-            state->lencode = (const code FAR *)(state->next);
-            state->lenbits = 9;
-            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid literal/lengths set";
-                state->mode = BAD;
-                break;
-            }
-            state->distcode = (const code FAR *)(state->next);
-            state->distbits = 6;
-            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
-                            &(state->next), &(state->distbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid distances set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       codes ok\n"));
-            state->mode = LEN_;
-            if (flush == Z_TREES) goto inf_leave;
-        case LEN_:
-            state->mode = LEN;
-        case LEN:
-            if (have >= 6 && left >= 258) {
-                RESTORE();
-                inflate_fast(strm, out);
-                LOAD();
-                if (state->mode == TYPE)
-                    state->back = -1;
-                break;
-            }
-            state->back = 0;
-            for (;;) {
-                here = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if (here.op && (here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->lencode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            state->length = (unsigned)here.val;
-            if ((int)(here.op) == 0) {
-                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                        "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", here.val));
-                state->mode = LIT;
-                break;
-            }
-            if (here.op & 32) {
-                Tracevv((stderr, "inflate:         end of block\n"));
-                state->back = -1;
-                state->mode = TYPE;
-                break;
-            }
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid literal/length code";
-                state->mode = BAD;
-                break;
-            }
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = LENEXT;
-        case LENEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->length += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", state->length));
-            state->was = state->length;
-            state->mode = DIST;
-        case DIST:
-            for (;;) {
-                here = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if ((here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->distcode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-            state->offset = (unsigned)here.val;
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = DISTEXT;
-        case DISTEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->offset += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-#ifdef INFLATE_STRICT
-            if (state->offset > state->dmax) {
-                strm->msg = (char *)"invalid distance too far back";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
-            state->mode = MATCH;
-        case MATCH:
-            if (left == 0) goto inf_leave;
-            copy = out - left;
-            if (state->offset > copy) {         /* copy from window */
-                copy = state->offset - copy;
-                if (copy > state->whave) {
-                    if (state->sane) {
-                        strm->msg = (char *)"invalid distance too far back";
-                        state->mode = BAD;
-                        break;
-                    }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                    Trace((stderr, "inflate.c too far\n"));
-                    copy -= state->whave;
-                    if (copy > state->length) copy = state->length;
-                    if (copy > left) copy = left;
-                    left -= copy;
-                    state->length -= copy;
-                    do {
-                        *put++ = 0;
-                    } while (--copy);
-                    if (state->length == 0) state->mode = LEN;
-                    break;
-#endif
-                }
-                if (copy > state->wnext) {
-                    copy -= state->wnext;
-                    from = state->window + (state->wsize - copy);
-                }
-                else
-                    from = state->window + (state->wnext - copy);
-                if (copy > state->length) copy = state->length;
-            }
-            else {                              /* copy from output */
-                from = put - state->offset;
-                copy = state->length;
-            }
-            if (copy > left) copy = left;
-            left -= copy;
-            state->length -= copy;
-            do {
-                *put++ = *from++;
-            } while (--copy);
-            if (state->length == 0) state->mode = LEN;
-            break;
-        case LIT:
-            if (left == 0) goto inf_leave;
-            *put++ = (unsigned char)(state->length);
-            left--;
-            state->mode = LEN;
-            break;
-        case CHECK:
-            if (state->wrap) {
-                NEEDBITS(32);
-                out -= left;
-                strm->total_out += out;
-                state->total += out;
-                if ((state->wrap & 4) && out)
-                    strm->adler = state->check =
-                        UPDATE(state->check, put - out, out);
-                out = left;
-                if ((state->wrap & 4) && (
-#ifdef GUNZIP
-                     state->flags ? hold :
-#endif
-                     ZSWAP32(hold)) != state->check) {
-                    strm->msg = (char *)"incorrect data check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   check matches trailer\n"));
-            }
-#ifdef GUNZIP
-            state->mode = LENGTH;
-        case LENGTH:
-            if (state->wrap && state->flags) {
-                NEEDBITS(32);
-                if (hold != (state->total & 0xffffffffUL)) {
-                    strm->msg = (char *)"incorrect length check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   length matches trailer\n"));
-            }
-#endif
-            state->mode = DONE;
-        case DONE:
-            ret = Z_STREAM_END;
-            goto inf_leave;
-        case BAD:
-            ret = Z_DATA_ERROR;
-            goto inf_leave;
-        case MEM:
-            return Z_MEM_ERROR;
-        case SYNC:
-        default:
-            return Z_STREAM_ERROR;
-        }
-
-    /*
-       Return from inflate(), updating the total counts and the check value.
-       If there was no progress during the inflate() call, return a buffer
-       error.  Call updatewindow() to create and/or update the window state.
-       Note: a memory error from inflate() is non-recoverable.
-     */
-  inf_leave:
-    RESTORE();
-    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
-            (state->mode < CHECK || flush != Z_FINISH)))
-        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
-            state->mode = MEM;
-            return Z_MEM_ERROR;
-        }
-    in -= strm->avail_in;
-    out -= strm->avail_out;
-    strm->total_in += in;
-    strm->total_out += out;
-    state->total += out;
-    if ((state->wrap & 4) && out)
-        strm->adler = state->check =
-            UPDATE(state->check, strm->next_out - out, out);
-    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
-                      (state->mode == TYPE ? 128 : 0) +
-                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
-    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
-        ret = Z_BUF_ERROR;
-    return ret;
-}
-
-int ZEXPORT inflateEnd(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (inflateStateCheck(strm))
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->window != Z_NULL) ZFREE(strm, state->window);
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-    Tracev((stderr, "inflate: end\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-Bytef *dictionary;
-uInt *dictLength;
-{
-    struct inflate_state FAR *state;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* copy dictionary */
-    if (state->whave && dictionary != Z_NULL) {
-        zmemcpy(dictionary, state->window + state->wnext,
-                state->whave - state->wnext);
-        zmemcpy(dictionary + state->whave - state->wnext,
-                state->window, state->wnext);
-    }
-    if (dictLength != Z_NULL)
-        *dictLength = state->whave;
-    return Z_OK;
-}
-
-int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-const Bytef *dictionary;
-uInt dictLength;
-{
-    struct inflate_state FAR *state;
-    unsigned long dictid;
-    int ret;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->wrap != 0 && state->mode != DICT)
-        return Z_STREAM_ERROR;
-
-    /* check for correct dictionary identifier */
-    if (state->mode == DICT) {
-        dictid = adler32(0L, Z_NULL, 0);
-        dictid = adler32(dictid, dictionary, dictLength);
-        if (dictid != state->check)
-            return Z_DATA_ERROR;
-    }
-
-    /* copy dictionary to window using updatewindow(), which will amend the
-       existing dictionary if appropriate */
-    ret = updatewindow(strm, dictionary + dictLength, dictLength);
-    if (ret) {
-        state->mode = MEM;
-        return Z_MEM_ERROR;
-    }
-    state->havedict = 1;
-    Tracev((stderr, "inflate:   dictionary set\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateGetHeader(strm, head)
-z_streamp strm;
-gz_headerp head;
-{
-    struct inflate_state FAR *state;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
-
-    /* save header structure */
-    state->head = head;
-    head->done = 0;
-    return Z_OK;
-}
-
-/*
-   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
-   or when out of input.  When called, *have is the number of pattern bytes
-   found in order so far, in 0..3.  On return *have is updated to the new
-   state.  If on return *have equals four, then the pattern was found and the
-   return value is how many bytes were read including the last byte of the
-   pattern.  If *have is less than four, then the pattern has not been found
-   yet and the return value is len.  In the latter case, syncsearch() can be
-   called again with more data and the *have state.  *have is initialized to
-   zero for the first call.
- */
-local unsigned syncsearch(have, buf, len)
-unsigned FAR *have;
-const unsigned char FAR *buf;
-unsigned len;
-{
-    unsigned got;
-    unsigned next;
-
-    got = *have;
-    next = 0;
-    while (next < len && got < 4) {
-        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
-            got++;
-        else if (buf[next])
-            got = 0;
-        else
-            got = 4 - got;
-        next++;
-    }
-    *have = got;
-    return next;
-}
-
-int ZEXPORT inflateSync(strm)
-z_streamp strm;
-{
-    unsigned len;               /* number of bytes to look at or looked at */
-    unsigned long in, out;      /* temporary to save total_in and total_out */
-    unsigned char buf[4];       /* to restore bit buffer to byte string */
-    struct inflate_state FAR *state;
-
-    /* check parameters */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
-
-    /* if first time, start search in bit buffer */
-    if (state->mode != SYNC) {
-        state->mode = SYNC;
-        state->hold <<= state->bits & 7;
-        state->bits -= state->bits & 7;
-        len = 0;
-        while (state->bits >= 8) {
-            buf[len++] = (unsigned char)(state->hold);
-            state->hold >>= 8;
-            state->bits -= 8;
-        }
-        state->have = 0;
-        syncsearch(&(state->have), buf, len);
-    }
-
-    /* search available input */
-    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
-    strm->avail_in -= len;
-    strm->next_in += len;
-    strm->total_in += len;
-
-    /* return no joy or set up to restart inflate() on a new block */
-    if (state->have != 4) return Z_DATA_ERROR;
-    in = strm->total_in;  out = strm->total_out;
-    inflateReset(strm);
-    strm->total_in = in;  strm->total_out = out;
-    state->mode = TYPE;
-    return Z_OK;
-}
-
-/*
-   Returns true if inflate is currently at the end of a block generated by
-   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
-   implementation to provide an additional safety check. PPP uses
-   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
-   block. When decompressing, PPP checks that at the end of input packet,
-   inflate is waiting for these length bytes.
- */
-int ZEXPORT inflateSyncPoint(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    return state->mode == STORED && state->bits == 0;
-}
-
-int ZEXPORT inflateCopy(dest, source)
-z_streamp dest;
-z_streamp source;
-{
-    struct inflate_state FAR *state;
-    struct inflate_state FAR *copy;
-    unsigned char FAR *window;
-    unsigned wsize;
-
-    /* check input */
-    if (inflateStateCheck(source) || dest == Z_NULL)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)source->state;
-
-    /* allocate space */
-    copy = (struct inflate_state FAR *)
-           ZALLOC(source, 1, sizeof(struct inflate_state));
-    if (copy == Z_NULL) return Z_MEM_ERROR;
-    window = Z_NULL;
-    if (state->window != Z_NULL) {
-        window = (unsigned char FAR *)
-                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
-        if (window == Z_NULL) {
-            ZFREE(source, copy);
-            return Z_MEM_ERROR;
-        }
-    }
-
-    /* copy state */
-    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
-    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
-    copy->strm = dest;
-    if (state->lencode >= state->codes &&
-        state->lencode <= state->codes + ENOUGH - 1) {
-        copy->lencode = copy->codes + (state->lencode - state->codes);
-        copy->distcode = copy->codes + (state->distcode - state->codes);
-    }
-    copy->next = copy->codes + (state->next - state->codes);
-    if (window != Z_NULL) {
-        wsize = 1U << state->wbits;
-        zmemcpy(window, state->window, wsize);
-    }
-    copy->window = window;
-    dest->state = (struct internal_state FAR *)copy;
-    return Z_OK;
-}
-
-int ZEXPORT inflateUndermine(strm, subvert)
-z_streamp strm;
-int subvert;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-    state->sane = !subvert;
-    return Z_OK;
-#else
-    (void)subvert;
-    state->sane = 1;
-    return Z_DATA_ERROR;
-#endif
-}
-
-int ZEXPORT inflateValidate(strm, check)
-z_streamp strm;
-int check;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (check)
-        state->wrap |= 4;
-    else
-        state->wrap &= ~4;
-    return Z_OK;
-}
-
-long ZEXPORT inflateMark(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm))
-        return -(1L << 16);
-    state = (struct inflate_state FAR *)strm->state;
-    return (long)(((unsigned long)((long)state->back)) << 16) +
-        (state->mode == COPY ? state->length :
-            (state->mode == MATCH ? state->was - state->length : 0));
-}
-
-unsigned long ZEXPORT inflateCodesUsed(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (inflateStateCheck(strm)) return (unsigned long)-1;
-    state = (struct inflate_state FAR *)strm->state;
-    return (unsigned long)(state->next - state->codes);
-}
diff --git a/c/zlib/inflate.h b/c/zlib/inflate.h
deleted file mode 100644
--- a/c/zlib/inflate.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* define NO_GZIP when compiling if you want to disable gzip header and
-   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
-   the crc code when it is not needed.  For shared libraries, gzip decoding
-   should be left enabled. */
-#ifndef NO_GZIP
-#  define GUNZIP
-#endif
-
-/* Possible inflate modes between inflate() calls */
-typedef enum {
-    HEAD = 16180,   /* i: waiting for magic header */
-    FLAGS,      /* i: waiting for method and flags (gzip) */
-    TIME,       /* i: waiting for modification time (gzip) */
-    OS,         /* i: waiting for extra flags and operating system (gzip) */
-    EXLEN,      /* i: waiting for extra length (gzip) */
-    EXTRA,      /* i: waiting for extra bytes (gzip) */
-    NAME,       /* i: waiting for end of file name (gzip) */
-    COMMENT,    /* i: waiting for end of comment (gzip) */
-    HCRC,       /* i: waiting for header crc (gzip) */
-    DICTID,     /* i: waiting for dictionary check value */
-    DICT,       /* waiting for inflateSetDictionary() call */
-        TYPE,       /* i: waiting for type bits, including last-flag bit */
-        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
-        STORED,     /* i: waiting for stored size (length and complement) */
-        COPY_,      /* i/o: same as COPY below, but only first time in */
-        COPY,       /* i/o: waiting for input or output to copy stored block */
-        TABLE,      /* i: waiting for dynamic block table lengths */
-        LENLENS,    /* i: waiting for code length code lengths */
-        CODELENS,   /* i: waiting for length/lit and distance code lengths */
-            LEN_,       /* i: same as LEN below, but only first time in */
-            LEN,        /* i: waiting for length/lit/eob code */
-            LENEXT,     /* i: waiting for length extra bits */
-            DIST,       /* i: waiting for distance code */
-            DISTEXT,    /* i: waiting for distance extra bits */
-            MATCH,      /* o: waiting for output space to copy string */
-            LIT,        /* o: waiting for output space to write literal */
-    CHECK,      /* i: waiting for 32-bit check value */
-    LENGTH,     /* i: waiting for 32-bit length (gzip) */
-    DONE,       /* finished check, done -- remain here until reset */
-    BAD,        /* got a data error -- remain here until reset */
-    MEM,        /* got an inflate() memory error -- remain here until reset */
-    SYNC        /* looking for synchronization bytes to restart inflate() */
-} inflate_mode;
-
-/*
-    State transitions between above modes -
-
-    (most modes can go to BAD or MEM on error -- not shown for clarity)
-
-    Process header:
-        HEAD -> (gzip) or (zlib) or (raw)
-        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
-                  HCRC -> TYPE
-        (zlib) -> DICTID or TYPE
-        DICTID -> DICT -> TYPE
-        (raw) -> TYPEDO
-    Read deflate blocks:
-            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
-            STORED -> COPY_ -> COPY -> TYPE
-            TABLE -> LENLENS -> CODELENS -> LEN_
-            LEN_ -> LEN
-    Read deflate codes in fixed or dynamic block:
-                LEN -> LENEXT or LIT or TYPE
-                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
-                LIT -> LEN
-    Process trailer:
-        CHECK -> LENGTH -> DONE
- */
-
-/* State maintained between inflate() calls -- approximately 7K bytes, not
-   including the allocated sliding window, which is up to 32K bytes. */
-struct inflate_state {
-    z_streamp strm;             /* pointer back to this zlib stream */
-    inflate_mode mode;          /* current inflate mode */
-    int last;                   /* true if processing last block */
-    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip,
-                                   bit 2 true to validate check value */
-    int havedict;               /* true if dictionary provided */
-    int flags;                  /* gzip header method and flags (0 if zlib) */
-    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
-    unsigned long check;        /* protected copy of check value */
-    unsigned long total;        /* protected copy of output count */
-    gz_headerp head;            /* where to save gzip header information */
-        /* sliding window */
-    unsigned wbits;             /* log base 2 of requested window size */
-    unsigned wsize;             /* window size or zero if not using window */
-    unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
-    unsigned char FAR *window;  /* allocated sliding window, if needed */
-        /* bit accumulator */
-    unsigned long hold;         /* input bit accumulator */
-    unsigned bits;              /* number of bits in "in" */
-        /* for string and stored block copying */
-    unsigned length;            /* literal or length of data to copy */
-    unsigned offset;            /* distance back to copy string from */
-        /* for table and code decoding */
-    unsigned extra;             /* extra bits needed */
-        /* fixed and dynamic code tables */
-    code const FAR *lencode;    /* starting table for length/literal codes */
-    code const FAR *distcode;   /* starting table for distance codes */
-    unsigned lenbits;           /* index bits for lencode */
-    unsigned distbits;          /* index bits for distcode */
-        /* dynamic table building */
-    unsigned ncode;             /* number of code length code lengths */
-    unsigned nlen;              /* number of length code lengths */
-    unsigned ndist;             /* number of distance code lengths */
-    unsigned have;              /* number of code lengths in lens[] */
-    code FAR *next;             /* next available space in codes[] */
-    unsigned short lens[320];   /* temporary storage for code lengths */
-    unsigned short work[288];   /* work area for code table building */
-    code codes[ENOUGH];         /* space for code tables */
-    int sane;                   /* if false, allow invalid distance too far */
-    int back;                   /* bits back of last unprocessed length/lit */
-    unsigned was;               /* initial length of match */
-};
diff --git a/c/zlib/inftrees.c b/c/zlib/inftrees.c
deleted file mode 100644
--- a/c/zlib/inftrees.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2017 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-
-#define MAXBITS 15
-
-const char inflate_copyright[] =
-   " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/*
-   Build a set of tables to decode the provided canonical Huffman code.
-   The code lengths are lens[0..codes-1].  The result starts at *table,
-   whose indices are 0..2^bits-1.  work is a writable array of at least
-   lens shorts, which is used as a work area.  type is the type of code
-   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
-   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
-   on return points to the next available entry's address.  bits is the
-   requested root table index bits, and on return it is the actual root
-   table index bits.  It will differ if the request is greater than the
-   longest code or if it is less than the shortest code.
- */
-int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
-codetype type;
-unsigned short FAR *lens;
-unsigned codes;
-code FAR * FAR *table;
-unsigned FAR *bits;
-unsigned short FAR *work;
-{
-    unsigned len;               /* a code's length in bits */
-    unsigned sym;               /* index of code symbols */
-    unsigned min, max;          /* minimum and maximum code lengths */
-    unsigned root;              /* number of index bits for root table */
-    unsigned curr;              /* number of index bits for current table */
-    unsigned drop;              /* code bits to drop for sub-table */
-    int left;                   /* number of prefix codes available */
-    unsigned used;              /* code entries in table used */
-    unsigned huff;              /* Huffman code */
-    unsigned incr;              /* for incrementing code, index */
-    unsigned fill;              /* index for replicating entries */
-    unsigned low;               /* low bits for current root entry */
-    unsigned mask;              /* mask for low root bits */
-    code here;                  /* table entry for duplication */
-    code FAR *next;             /* next available space in table */
-    const unsigned short FAR *base;     /* base value table to use */
-    const unsigned short FAR *extra;    /* extra bits table to use */
-    unsigned match;             /* use base and extra for symbol >= match */
-    unsigned short count[MAXBITS+1];    /* number of codes of each length */
-    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
-    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
-        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
-    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577, 0, 0};
-    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
-        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
-        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
-        28, 28, 29, 29, 64, 64};
-
-    /*
-       Process a set of code lengths to create a canonical Huffman code.  The
-       code lengths are lens[0..codes-1].  Each length corresponds to the
-       symbols 0..codes-1.  The Huffman code is generated by first sorting the
-       symbols by length from short to long, and retaining the symbol order
-       for codes with equal lengths.  Then the code starts with all zero bits
-       for the first code of the shortest length, and the codes are integer
-       increments for the same length, and zeros are appended as the length
-       increases.  For the deflate format, these bits are stored backwards
-       from their more natural integer increment ordering, and so when the
-       decoding tables are built in the large loop below, the integer codes
-       are incremented backwards.
-
-       This routine assumes, but does not check, that all of the entries in
-       lens[] are in the range 0..MAXBITS.  The caller must assure this.
-       1..MAXBITS is interpreted as that code length.  zero means that that
-       symbol does not occur in this code.
-
-       The codes are sorted by computing a count of codes for each length,
-       creating from that a table of starting indices for each length in the
-       sorted table, and then entering the symbols in order in the sorted
-       table.  The sorted table is work[], with that space being provided by
-       the caller.
-
-       The length counts are used for other purposes as well, i.e. finding
-       the minimum and maximum length codes, determining if there are any
-       codes at all, checking for a valid set of lengths, and looking ahead
-       at length counts to determine sub-table sizes when building the
-       decoding tables.
-     */
-
-    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
-    for (len = 0; len <= MAXBITS; len++)
-        count[len] = 0;
-    for (sym = 0; sym < codes; sym++)
-        count[lens[sym]]++;
-
-    /* bound code lengths, force root to be within code lengths */
-    root = *bits;
-    for (max = MAXBITS; max >= 1; max--)
-        if (count[max] != 0) break;
-    if (root > max) root = max;
-    if (max == 0) {                     /* no symbols to code at all */
-        here.op = (unsigned char)64;    /* invalid code marker */
-        here.bits = (unsigned char)1;
-        here.val = (unsigned short)0;
-        *(*table)++ = here;             /* make a table to force an error */
-        *(*table)++ = here;
-        *bits = 1;
-        return 0;     /* no symbols, but wait for decoding to report error */
-    }
-    for (min = 1; min < max; min++)
-        if (count[min] != 0) break;
-    if (root < min) root = min;
-
-    /* check for an over-subscribed or incomplete set of lengths */
-    left = 1;
-    for (len = 1; len <= MAXBITS; len++) {
-        left <<= 1;
-        left -= count[len];
-        if (left < 0) return -1;        /* over-subscribed */
-    }
-    if (left > 0 && (type == CODES || max != 1))
-        return -1;                      /* incomplete set */
-
-    /* generate offsets into symbol table for each length for sorting */
-    offs[1] = 0;
-    for (len = 1; len < MAXBITS; len++)
-        offs[len + 1] = offs[len] + count[len];
-
-    /* sort symbols by length, by symbol order within each length */
-    for (sym = 0; sym < codes; sym++)
-        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
-
-    /*
-       Create and fill in decoding tables.  In this loop, the table being
-       filled is at next and has curr index bits.  The code being used is huff
-       with length len.  That code is converted to an index by dropping drop
-       bits off of the bottom.  For codes where len is less than drop + curr,
-       those top drop + curr - len bits are incremented through all values to
-       fill the table with replicated entries.
-
-       root is the number of index bits for the root table.  When len exceeds
-       root, sub-tables are created pointed to by the root entry with an index
-       of the low root bits of huff.  This is saved in low to check for when a
-       new sub-table should be started.  drop is zero when the root table is
-       being filled, and drop is root when sub-tables are being filled.
-
-       When a new sub-table is needed, it is necessary to look ahead in the
-       code lengths to determine what size sub-table is needed.  The length
-       counts are used for this, and so count[] is decremented as codes are
-       entered in the tables.
-
-       used keeps track of how many table entries have been allocated from the
-       provided *table space.  It is checked for LENS and DIST tables against
-       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
-       the initial root table size constants.  See the comments in inftrees.h
-       for more information.
-
-       sym increments through all symbols, and the loop terminates when
-       all codes of length max, i.e. all codes, have been processed.  This
-       routine permits incomplete codes, so another loop after this one fills
-       in the rest of the decoding tables with invalid code markers.
-     */
-
-    /* set up for code type */
-    switch (type) {
-    case CODES:
-        base = extra = work;    /* dummy value--not used */
-        match = 20;
-        break;
-    case LENS:
-        base = lbase;
-        extra = lext;
-        match = 257;
-        break;
-    default:    /* DISTS */
-        base = dbase;
-        extra = dext;
-        match = 0;
-    }
-
-    /* initialize state for loop */
-    huff = 0;                   /* starting code */
-    sym = 0;                    /* starting code symbol */
-    len = min;                  /* starting code length */
-    next = *table;              /* current table to fill in */
-    curr = root;                /* current table index bits */
-    drop = 0;                   /* current bits to drop from code for index */
-    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
-    used = 1U << root;          /* use root table entries */
-    mask = used - 1;            /* mask for comparing low */
-
-    /* check available table space */
-    if ((type == LENS && used > ENOUGH_LENS) ||
-        (type == DISTS && used > ENOUGH_DISTS))
-        return 1;
-
-    /* process all codes and make table entries */
-    for (;;) {
-        /* create table entry */
-        here.bits = (unsigned char)(len - drop);
-        if (work[sym] + 1U < match) {
-            here.op = (unsigned char)0;
-            here.val = work[sym];
-        }
-        else if (work[sym] >= match) {
-            here.op = (unsigned char)(extra[work[sym] - match]);
-            here.val = base[work[sym] - match];
-        }
-        else {
-            here.op = (unsigned char)(32 + 64);         /* end of block */
-            here.val = 0;
-        }
-
-        /* replicate for those indices with low len bits equal to huff */
-        incr = 1U << (len - drop);
-        fill = 1U << curr;
-        min = fill;                 /* save offset to next table */
-        do {
-            fill -= incr;
-            next[(huff >> drop) + fill] = here;
-        } while (fill != 0);
-
-        /* backwards increment the len-bit code huff */
-        incr = 1U << (len - 1);
-        while (huff & incr)
-            incr >>= 1;
-        if (incr != 0) {
-            huff &= incr - 1;
-            huff += incr;
-        }
-        else
-            huff = 0;
-
-        /* go to next symbol, update count, len */
-        sym++;
-        if (--(count[len]) == 0) {
-            if (len == max) break;
-            len = lens[work[sym]];
-        }
-
-        /* create new sub-table if needed */
-        if (len > root && (huff & mask) != low) {
-            /* if first time, transition to sub-tables */
-            if (drop == 0)
-                drop = root;
-
-            /* increment past last table */
-            next += min;            /* here min is 1 << curr */
-
-            /* determine length of next table */
-            curr = len - drop;
-            left = (int)(1 << curr);
-            while (curr + drop < max) {
-                left -= count[curr + drop];
-                if (left <= 0) break;
-                curr++;
-                left <<= 1;
-            }
-
-            /* check for enough space */
-            used += 1U << curr;
-            if ((type == LENS && used > ENOUGH_LENS) ||
-                (type == DISTS && used > ENOUGH_DISTS))
-                return 1;
-
-            /* point entry in root table to sub-table */
-            low = huff & mask;
-            (*table)[low].op = (unsigned char)curr;
-            (*table)[low].bits = (unsigned char)root;
-            (*table)[low].val = (unsigned short)(next - *table);
-        }
-    }
-
-    /* fill in remaining table entry if code is incomplete (guaranteed to have
-       at most one remaining entry, since if the code is incomplete, the
-       maximum code length that was allowed to get this far is one bit) */
-    if (huff != 0) {
-        here.op = (unsigned char)64;            /* invalid code marker */
-        here.bits = (unsigned char)(len - drop);
-        here.val = (unsigned short)0;
-        next[huff] = here;
-    }
-
-    /* set return parameters */
-    *table += used;
-    *bits = root;
-    return 0;
-}
diff --git a/c/zlib/inftrees.h b/c/zlib/inftrees.h
deleted file mode 100644
--- a/c/zlib/inftrees.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2005, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Structure for decoding tables.  Each entry provides either the
-   information needed to do the operation requested by the code that
-   indexed that table entry, or it provides a pointer to another
-   table that indexes more bits of the code.  op indicates whether
-   the entry is a pointer to another table, a literal, a length or
-   distance, an end-of-block, or an invalid code.  For a table
-   pointer, the low four bits of op is the number of index bits of
-   that table.  For a length or distance, the low four bits of op
-   is the number of extra bits to get after the code.  bits is
-   the number of bits in this code or part of the code to drop off
-   of the bit buffer.  val is the actual byte to output in the case
-   of a literal, the base length or distance, or the offset from
-   the current table to the next table.  Each entry is four bytes. */
-typedef struct {
-    unsigned char op;           /* operation, extra bits, table bits */
-    unsigned char bits;         /* bits in this part of the code */
-    unsigned short val;         /* offset in table or code value */
-} code;
-
-/* op values as set by inflate_table():
-    00000000 - literal
-    0000tttt - table link, tttt != 0 is the number of table index bits
-    0001eeee - length or distance, eeee is the number of extra bits
-    01100000 - end of block
-    01000000 - invalid code
- */
-
-/* Maximum size of the dynamic table.  The maximum number of code structures is
-   1444, which is the sum of 852 for literal/length codes and 592 for distance
-   codes.  These values were found by exhaustive searches using the program
-   examples/enough.c found in the zlib distribtution.  The arguments to that
-   program are the number of symbols, the initial root table size, and the
-   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
-   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
-   The initial root table size (9 or 6) is found in the fifth argument of the
-   inflate_table() calls in inflate.c and infback.c.  If the root table size is
-   changed, then these maximum sizes would be need to be recalculated and
-   updated. */
-#define ENOUGH_LENS 852
-#define ENOUGH_DISTS 592
-#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
-
-/* Type of code to build for inflate_table() */
-typedef enum {
-    CODES,
-    LENS,
-    DISTS
-} codetype;
-
-int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
-                             unsigned codes, code FAR * FAR *table,
-                             unsigned FAR *bits, unsigned short FAR *work));
diff --git a/c/zlib/trees.c b/c/zlib/trees.c
deleted file mode 100644
--- a/c/zlib/trees.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2017 Jean-loup Gailly
- * detect_data_type() function provided freely by Cosmin Truta, 2006
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process uses several Huffman trees. The more
- *      common source values are represented by shorter bit sequences.
- *
- *      Each code tree is stored in a compressed form which is itself
- * a Huffman encoding of the lengths of all the code strings (in
- * ascending order by source values).  The actual code strings are
- * reconstructed from the lengths in the inflate process, as described
- * in the deflate specification.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
- *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
- *
- *      Storer, James A.
- *          Data Compression:  Methods and Theory, pp. 49-50.
- *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
- *
- *      Sedgewick, R.
- *          Algorithms, p290.
- *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
- */
-
-/* @(#) $Id$ */
-
-/* #define GEN_TREES_H */
-
-#include "deflate.h"
-
-#ifdef ZLIB_DEBUG
-#  include <ctype.h>
-#endif
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define REP_3_6      16
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-#define REPZ_3_10    17
-/* repeat a zero length 3-10 times  (3 bits of repeat count) */
-
-#define REPZ_11_138  18
-/* repeat a zero length 11-138 times  (7 bits of repeat count) */
-
-local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
-   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
-
-local const int extra_dbits[D_CODES] /* extra bits for each distance code */
-   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
-   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
-
-local const uch bl_order[BL_CODES]
-   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-/* non ANSI compilers may not accept trees.h */
-
-local ct_data static_ltree[L_CODES+2];
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-local ct_data static_dtree[D_CODES];
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-uch _dist_code[DIST_CODE_LEN];
-/* Distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-uch _length_code[MAX_MATCH-MIN_MATCH+1];
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-local int base_length[LENGTH_CODES];
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-local int base_dist[D_CODES];
-/* First normalized distance for each code (0 = distance of 1) */
-
-#else
-#  include "trees.h"
-#endif /* GEN_TREES_H */
-
-struct static_tree_desc_s {
-    const ct_data *static_tree;  /* static tree or NULL */
-    const intf *extra_bits;      /* extra bits for each code or NULL */
-    int     extra_base;          /* base index for extra_bits */
-    int     elems;               /* max number of elements in the tree */
-    int     max_length;          /* max bit length for the codes */
-};
-
-local const static_tree_desc  static_l_desc =
-{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
-
-local const static_tree_desc  static_d_desc =
-{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
-
-local const static_tree_desc  static_bl_desc =
-{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
-
-/* ===========================================================================
- * Local (static) routines in this file.
- */
-
-local void tr_static_init OF((void));
-local void init_block     OF((deflate_state *s));
-local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
-local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
-local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
-local void build_tree     OF((deflate_state *s, tree_desc *desc));
-local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local int  build_bl_tree  OF((deflate_state *s));
-local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
-                              int blcodes));
-local void compress_block OF((deflate_state *s, const ct_data *ltree,
-                              const ct_data *dtree));
-local int  detect_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
-local void bi_windup      OF((deflate_state *s));
-local void bi_flush       OF((deflate_state *s));
-
-#ifdef GEN_TREES_H
-local void gen_trees_header OF((void));
-#endif
-
-#ifndef ZLIB_DEBUG
-#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
-   /* Send a code of the given tree. c and tree must not have side effects */
-
-#else /* !ZLIB_DEBUG */
-#  define send_code(s, c, tree) \
-     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
-       send_bits(s, tree[c].Code, tree[c].Len); }
-#endif
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-#define put_short(s, w) { \
-    put_byte(s, (uch)((w) & 0xff)); \
-    put_byte(s, (uch)((ush)(w) >> 8)); \
-}
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-#ifdef ZLIB_DEBUG
-local void send_bits      OF((deflate_state *s, int value, int length));
-
-local void send_bits(s, value, length)
-    deflate_state *s;
-    int value;  /* value to send */
-    int length; /* number of bits */
-{
-    Tracevv((stderr," l %2d v %4x ", length, value));
-    Assert(length > 0 && length <= 15, "invalid length");
-    s->bits_sent += (ulg)length;
-
-    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
-     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
-     * unused bits in value.
-     */
-    if (s->bi_valid > (int)Buf_size - length) {
-        s->bi_buf |= (ush)value << s->bi_valid;
-        put_short(s, s->bi_buf);
-        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
-        s->bi_valid += length - Buf_size;
-    } else {
-        s->bi_buf |= (ush)value << s->bi_valid;
-        s->bi_valid += length;
-    }
-}
-#else /* !ZLIB_DEBUG */
-
-#define send_bits(s, value, length) \
-{ int len = length;\
-  if (s->bi_valid > (int)Buf_size - len) {\
-    int val = (int)value;\
-    s->bi_buf |= (ush)val << s->bi_valid;\
-    put_short(s, s->bi_buf);\
-    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
-    s->bi_valid += len - Buf_size;\
-  } else {\
-    s->bi_buf |= (ush)(value) << s->bi_valid;\
-    s->bi_valid += len;\
-  }\
-}
-#endif /* ZLIB_DEBUG */
-
-
-/* the arguments must not have side effects */
-
-/* ===========================================================================
- * Initialize the various 'constant' tables.
- */
-local void tr_static_init()
-{
-#if defined(GEN_TREES_H) || !defined(STDC)
-    static int static_init_done = 0;
-    int n;        /* iterates over tree elements */
-    int bits;     /* bit counter */
-    int length;   /* length value */
-    int code;     /* code value */
-    int dist;     /* distance index */
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    if (static_init_done) return;
-
-    /* For some embedded targets, global variables are not initialized: */
-#ifdef NO_INIT_GLOBAL_POINTERS
-    static_l_desc.static_tree = static_ltree;
-    static_l_desc.extra_bits = extra_lbits;
-    static_d_desc.static_tree = static_dtree;
-    static_d_desc.extra_bits = extra_dbits;
-    static_bl_desc.extra_bits = extra_blbits;
-#endif
-
-    /* Initialize the mapping length (0..255) -> length code (0..28) */
-    length = 0;
-    for (code = 0; code < LENGTH_CODES-1; code++) {
-        base_length[code] = length;
-        for (n = 0; n < (1<<extra_lbits[code]); n++) {
-            _length_code[length++] = (uch)code;
-        }
-    }
-    Assert (length == 256, "tr_static_init: length != 256");
-    /* Note that the length 255 (match length 258) can be represented
-     * in two different ways: code 284 + 5 bits or code 285, so we
-     * overwrite length_code[255] to use the best encoding:
-     */
-    _length_code[length-1] = (uch)code;
-
-    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
-    dist = 0;
-    for (code = 0 ; code < 16; code++) {
-        base_dist[code] = dist;
-        for (n = 0; n < (1<<extra_dbits[code]); n++) {
-            _dist_code[dist++] = (uch)code;
-        }
-    }
-    Assert (dist == 256, "tr_static_init: dist != 256");
-    dist >>= 7; /* from now on, all distances are divided by 128 */
-    for ( ; code < D_CODES; code++) {
-        base_dist[code] = dist << 7;
-        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
-            _dist_code[256 + dist++] = (uch)code;
-        }
-    }
-    Assert (dist == 256, "tr_static_init: 256+dist != 512");
-
-    /* Construct the codes of the static literal tree */
-    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
-    n = 0;
-    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
-    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
-    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
-    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
-    /* Codes 286 and 287 do not exist, but we must include them in the
-     * tree construction to get a canonical Huffman tree (longest code
-     * all ones)
-     */
-    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
-
-    /* The static distance tree is trivial: */
-    for (n = 0; n < D_CODES; n++) {
-        static_dtree[n].Len = 5;
-        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
-    }
-    static_init_done = 1;
-
-#  ifdef GEN_TREES_H
-    gen_trees_header();
-#  endif
-#endif /* defined(GEN_TREES_H) || !defined(STDC) */
-}
-
-/* ===========================================================================
- * Genererate the file trees.h describing the static trees.
- */
-#ifdef GEN_TREES_H
-#  ifndef ZLIB_DEBUG
-#    include <stdio.h>
-#  endif
-
-#  define SEPARATOR(i, last, width) \
-      ((i) == (last)? "\n};\n\n" :    \
-       ((i) % (width) == (width)-1 ? ",\n" : ", "))
-
-void gen_trees_header()
-{
-    FILE *header = fopen("trees.h", "w");
-    int i;
-
-    Assert (header != NULL, "Can't open trees.h");
-    fprintf(header,
-            "/* header created automatically with -DGEN_TREES_H */\n\n");
-
-    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
-    for (i = 0; i < L_CODES+2; i++) {
-        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
-                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
-    }
-
-    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
-                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
-    }
-
-    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
-    for (i = 0; i < DIST_CODE_LEN; i++) {
-        fprintf(header, "%2u%s", _dist_code[i],
-                SEPARATOR(i, DIST_CODE_LEN-1, 20));
-    }
-
-    fprintf(header,
-        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
-    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
-        fprintf(header, "%2u%s", _length_code[i],
-                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
-    }
-
-    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
-    for (i = 0; i < LENGTH_CODES; i++) {
-        fprintf(header, "%1u%s", base_length[i],
-                SEPARATOR(i, LENGTH_CODES-1, 20));
-    }
-
-    fprintf(header, "local const int base_dist[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-        fprintf(header, "%5u%s", base_dist[i],
-                SEPARATOR(i, D_CODES-1, 10));
-    }
-
-    fclose(header);
-}
-#endif /* GEN_TREES_H */
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-void ZLIB_INTERNAL _tr_init(s)
-    deflate_state *s;
-{
-    tr_static_init();
-
-    s->l_desc.dyn_tree = s->dyn_ltree;
-    s->l_desc.stat_desc = &static_l_desc;
-
-    s->d_desc.dyn_tree = s->dyn_dtree;
-    s->d_desc.stat_desc = &static_d_desc;
-
-    s->bl_desc.dyn_tree = s->bl_tree;
-    s->bl_desc.stat_desc = &static_bl_desc;
-
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-#ifdef ZLIB_DEBUG
-    s->compressed_len = 0L;
-    s->bits_sent = 0L;
-#endif
-
-    /* Initialize the first block of the first file: */
-    init_block(s);
-}
-
-/* ===========================================================================
- * Initialize a new block.
- */
-local void init_block(s)
-    deflate_state *s;
-{
-    int n; /* iterates over tree elements */
-
-    /* Initialize the trees. */
-    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
-    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
-    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
-
-    s->dyn_ltree[END_BLOCK].Freq = 1;
-    s->opt_len = s->static_len = 0L;
-    s->last_lit = s->matches = 0;
-}
-
-#define SMALLEST 1
-/* Index within the heap array of least frequent node in the Huffman tree */
-
-
-/* ===========================================================================
- * Remove the smallest element from the heap and recreate the heap with
- * one less element. Updates heap and heap_len.
- */
-#define pqremove(s, tree, top) \
-{\
-    top = s->heap[SMALLEST]; \
-    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
-    pqdownheap(s, tree, SMALLEST); \
-}
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
-   (tree[n].Freq < tree[m].Freq || \
-   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-local void pqdownheap(s, tree, k)
-    deflate_state *s;
-    ct_data *tree;  /* the tree to restore */
-    int k;               /* node to move down */
-{
-    int v = s->heap[k];
-    int j = k << 1;  /* left son of k */
-    while (j <= s->heap_len) {
-        /* Set j to the smallest of the two sons: */
-        if (j < s->heap_len &&
-            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
-            j++;
-        }
-        /* Exit if v is smaller than both sons */
-        if (smaller(tree, v, s->heap[j], s->depth)) break;
-
-        /* Exchange v with the smallest son */
-        s->heap[k] = s->heap[j];  k = j;
-
-        /* And continue down the tree, setting j to the left son of k */
-        j <<= 1;
-    }
-    s->heap[k] = v;
-}
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- *    above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- *     array bl_count contains the frequencies for each bit length.
- *     The length opt_len is updated; static_len is also updated if stree is
- *     not null.
- */
-local void gen_bitlen(s, desc)
-    deflate_state *s;
-    tree_desc *desc;    /* the tree descriptor */
-{
-    ct_data *tree        = desc->dyn_tree;
-    int max_code         = desc->max_code;
-    const ct_data *stree = desc->stat_desc->static_tree;
-    const intf *extra    = desc->stat_desc->extra_bits;
-    int base             = desc->stat_desc->extra_base;
-    int max_length       = desc->stat_desc->max_length;
-    int h;              /* heap index */
-    int n, m;           /* iterate over the tree elements */
-    int bits;           /* bit length */
-    int xbits;          /* extra bits */
-    ush f;              /* frequency */
-    int overflow = 0;   /* number of elements with bit length too large */
-
-    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
-
-    /* In a first pass, compute the optimal bit lengths (which may
-     * overflow in the case of the bit length tree).
-     */
-    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
-
-    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
-        n = s->heap[h];
-        bits = tree[tree[n].Dad].Len + 1;
-        if (bits > max_length) bits = max_length, overflow++;
-        tree[n].Len = (ush)bits;
-        /* We overwrite tree[n].Dad which is no longer needed */
-
-        if (n > max_code) continue; /* not a leaf node */
-
-        s->bl_count[bits]++;
-        xbits = 0;
-        if (n >= base) xbits = extra[n-base];
-        f = tree[n].Freq;
-        s->opt_len += (ulg)f * (unsigned)(bits + xbits);
-        if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
-    }
-    if (overflow == 0) return;
-
-    Tracev((stderr,"\nbit length overflow\n"));
-    /* This happens for example on obj2 and pic of the Calgary corpus */
-
-    /* Find the first bit length which could increase: */
-    do {
-        bits = max_length-1;
-        while (s->bl_count[bits] == 0) bits--;
-        s->bl_count[bits]--;      /* move one leaf down the tree */
-        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
-        s->bl_count[max_length]--;
-        /* The brother of the overflow item also moves one step up,
-         * but this does not affect bl_count[max_length]
-         */
-        overflow -= 2;
-    } while (overflow > 0);
-
-    /* Now recompute all bit lengths, scanning in increasing frequency.
-     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
-     * lengths instead of fixing only the wrong ones. This idea is taken
-     * from 'ar' written by Haruhiko Okumura.)
-     */
-    for (bits = max_length; bits != 0; bits--) {
-        n = s->bl_count[bits];
-        while (n != 0) {
-            m = s->heap[--h];
-            if (m > max_code) continue;
-            if ((unsigned) tree[m].Len != (unsigned) bits) {
-                Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
-                s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
-                tree[m].Len = (ush)bits;
-            }
-            n--;
-        }
-    }
-}
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- *     zero code length.
- */
-local void gen_codes (tree, max_code, bl_count)
-    ct_data *tree;             /* the tree to decorate */
-    int max_code;              /* largest code with non zero frequency */
-    ushf *bl_count;            /* number of codes at each bit length */
-{
-    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
-    unsigned code = 0;         /* running code value */
-    int bits;                  /* bit index */
-    int n;                     /* code index */
-
-    /* The distribution counts are first used to generate the code values
-     * without bit reversal.
-     */
-    for (bits = 1; bits <= MAX_BITS; bits++) {
-        code = (code + bl_count[bits-1]) << 1;
-        next_code[bits] = (ush)code;
-    }
-    /* Check that the bit counts in bl_count are consistent. The last code
-     * must be all ones.
-     */
-    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
-            "inconsistent bit counts");
-    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
-
-    for (n = 0;  n <= max_code; n++) {
-        int len = tree[n].Len;
-        if (len == 0) continue;
-        /* Now reverse the bits */
-        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
-
-        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
-             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
-    }
-}
-
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- *     and corresponding code. The length opt_len is updated; static_len is
- *     also updated if stree is not null. The field max_code is set.
- */
-local void build_tree(s, desc)
-    deflate_state *s;
-    tree_desc *desc; /* the tree descriptor */
-{
-    ct_data *tree         = desc->dyn_tree;
-    const ct_data *stree  = desc->stat_desc->static_tree;
-    int elems             = desc->stat_desc->elems;
-    int n, m;          /* iterate over heap elements */
-    int max_code = -1; /* largest code with non zero frequency */
-    int node;          /* new node being created */
-
-    /* Construct the initial heap, with least frequent element in
-     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
-     * heap[0] is not used.
-     */
-    s->heap_len = 0, s->heap_max = HEAP_SIZE;
-
-    for (n = 0; n < elems; n++) {
-        if (tree[n].Freq != 0) {
-            s->heap[++(s->heap_len)] = max_code = n;
-            s->depth[n] = 0;
-        } else {
-            tree[n].Len = 0;
-        }
-    }
-
-    /* The pkzip format requires that at least one distance code exists,
-     * and that at least one bit should be sent even if there is only one
-     * possible code. So to avoid special checks later on we force at least
-     * two codes of non zero frequency.
-     */
-    while (s->heap_len < 2) {
-        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
-        tree[node].Freq = 1;
-        s->depth[node] = 0;
-        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
-        /* node is 0 or 1 so it does not have extra bits */
-    }
-    desc->max_code = max_code;
-
-    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
-     * establish sub-heaps of increasing lengths:
-     */
-    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
-
-    /* Construct the Huffman tree by repeatedly combining the least two
-     * frequent nodes.
-     */
-    node = elems;              /* next internal node of the tree */
-    do {
-        pqremove(s, tree, n);  /* n = node of least frequency */
-        m = s->heap[SMALLEST]; /* m = node of next least frequency */
-
-        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
-        s->heap[--(s->heap_max)] = m;
-
-        /* Create a new node father of n and m */
-        tree[node].Freq = tree[n].Freq + tree[m].Freq;
-        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
-                                s->depth[n] : s->depth[m]) + 1);
-        tree[n].Dad = tree[m].Dad = (ush)node;
-#ifdef DUMP_BL_TREE
-        if (tree == s->bl_tree) {
-            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
-                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
-        }
-#endif
-        /* and insert the new node in the heap */
-        s->heap[SMALLEST] = node++;
-        pqdownheap(s, tree, SMALLEST);
-
-    } while (s->heap_len >= 2);
-
-    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
-
-    /* At this point, the fields freq and dad are set. We can now
-     * generate the bit lengths.
-     */
-    gen_bitlen(s, (tree_desc *)desc);
-
-    /* The field len is now set, we can generate the bit codes */
-    gen_codes ((ct_data *)tree, max_code, s->bl_count);
-}
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-local void scan_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree;   /* the tree to be scanned */
-    int max_code;    /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    if (nextlen == 0) max_count = 138, min_count = 3;
-    tree[max_code+1].Len = (ush)0xffff; /* guard */
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            s->bl_tree[curlen].Freq += count;
-        } else if (curlen != 0) {
-            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
-            s->bl_tree[REP_3_6].Freq++;
-        } else if (count <= 10) {
-            s->bl_tree[REPZ_3_10].Freq++;
-        } else {
-            s->bl_tree[REPZ_11_138].Freq++;
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-local void send_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree; /* the tree to be scanned */
-    int max_code;       /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    /* tree[max_code+1].Len = -1; */  /* guard already set */
-    if (nextlen == 0) max_count = 138, min_count = 3;
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
-
-        } else if (curlen != 0) {
-            if (curlen != prevlen) {
-                send_code(s, curlen, s->bl_tree); count--;
-            }
-            Assert(count >= 3 && count <= 6, " 3_6?");
-            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
-
-        } else if (count <= 10) {
-            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
-
-        } else {
-            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-local int build_bl_tree(s)
-    deflate_state *s;
-{
-    int max_blindex;  /* index of last bit length code of non zero freq */
-
-    /* Determine the bit length frequencies for literal and distance trees */
-    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
-    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
-
-    /* Build the bit length tree: */
-    build_tree(s, (tree_desc *)(&(s->bl_desc)));
-    /* opt_len now includes the length of the tree representations, except
-     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
-     */
-
-    /* Determine the number of bit length codes to send. The pkzip format
-     * requires that at least 4 bit length codes be sent. (appnote.txt says
-     * 3 but the actual value used is 4.)
-     */
-    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
-        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
-    }
-    /* Update opt_len to include the bit length tree and counts */
-    s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;
-    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
-            s->opt_len, s->static_len));
-
-    return max_blindex;
-}
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-local void send_all_trees(s, lcodes, dcodes, blcodes)
-    deflate_state *s;
-    int lcodes, dcodes, blcodes; /* number of codes for each tree */
-{
-    int rank;                    /* index in bl_order */
-
-    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
-    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
-            "too many codes");
-    Tracev((stderr, "\nbl counts: "));
-    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
-    send_bits(s, dcodes-1,   5);
-    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
-    for (rank = 0; rank < blcodes; rank++) {
-        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
-        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
-    }
-    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
-    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
-    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-}
-
-/* ===========================================================================
- * Send a stored block
- */
-void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
-    deflate_state *s;
-    charf *buf;       /* input block */
-    ulg stored_len;   /* length of input block */
-    int last;         /* one if this is the last block for a file */
-{
-    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
-    bi_windup(s);        /* align on byte boundary */
-    put_short(s, (ush)stored_len);
-    put_short(s, (ush)~stored_len);
-    zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
-    s->pending += stored_len;
-#ifdef ZLIB_DEBUG
-    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
-    s->compressed_len += (stored_len + 4) << 3;
-    s->bits_sent += 2*16;
-    s->bits_sent += stored_len<<3;
-#endif
-}
-
-/* ===========================================================================
- * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
- */
-void ZLIB_INTERNAL _tr_flush_bits(s)
-    deflate_state *s;
-{
-    bi_flush(s);
-}
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- */
-void ZLIB_INTERNAL _tr_align(s)
-    deflate_state *s;
-{
-    send_bits(s, STATIC_TREES<<1, 3);
-    send_code(s, END_BLOCK, static_ltree);
-#ifdef ZLIB_DEBUG
-    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
-#endif
-    bi_flush(s);
-}
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and write out the encoded block.
- */
-void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
-    deflate_state *s;
-    charf *buf;       /* input block, or NULL if too old */
-    ulg stored_len;   /* length of input block */
-    int last;         /* one if this is the last block for a file */
-{
-    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
-    int max_blindex = 0;  /* index of last bit length code of non zero freq */
-
-    /* Build the Huffman trees unless a stored block is forced */
-    if (s->level > 0) {
-
-        /* Check if the file is binary or text */
-        if (s->strm->data_type == Z_UNKNOWN)
-            s->strm->data_type = detect_data_type(s);
-
-        /* Construct the literal and distance trees */
-        build_tree(s, (tree_desc *)(&(s->l_desc)));
-        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
-                s->static_len));
-
-        build_tree(s, (tree_desc *)(&(s->d_desc)));
-        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
-                s->static_len));
-        /* At this point, opt_len and static_len are the total bit lengths of
-         * the compressed block data, excluding the tree representations.
-         */
-
-        /* Build the bit length tree for the above two trees, and get the index
-         * in bl_order of the last bit length code to send.
-         */
-        max_blindex = build_bl_tree(s);
-
-        /* Determine the best encoding. Compute the block lengths in bytes. */
-        opt_lenb = (s->opt_len+3+7)>>3;
-        static_lenb = (s->static_len+3+7)>>3;
-
-        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
-                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
-                s->last_lit));
-
-        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
-
-    } else {
-        Assert(buf != (char*)0, "lost buf");
-        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
-    }
-
-#ifdef FORCE_STORED
-    if (buf != (char*)0) { /* force stored block */
-#else
-    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
-                       /* 4: two words for the lengths */
-#endif
-        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
-         * Otherwise we can't have processed more than WSIZE input bytes since
-         * the last block flush, because compression would have been
-         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
-         * transform a block into a stored block.
-         */
-        _tr_stored_block(s, buf, stored_len, last);
-
-#ifdef FORCE_STATIC
-    } else if (static_lenb >= 0) { /* force static trees */
-#else
-    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
-#endif
-        send_bits(s, (STATIC_TREES<<1)+last, 3);
-        compress_block(s, (const ct_data *)static_ltree,
-                       (const ct_data *)static_dtree);
-#ifdef ZLIB_DEBUG
-        s->compressed_len += 3 + s->static_len;
-#endif
-    } else {
-        send_bits(s, (DYN_TREES<<1)+last, 3);
-        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
-                       max_blindex+1);
-        compress_block(s, (const ct_data *)s->dyn_ltree,
-                       (const ct_data *)s->dyn_dtree);
-#ifdef ZLIB_DEBUG
-        s->compressed_len += 3 + s->opt_len;
-#endif
-    }
-    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
-    /* The above check is made mod 2^32, for files larger than 512 MB
-     * and uLong implemented on 32 bits.
-     */
-    init_block(s);
-
-    if (last) {
-        bi_windup(s);
-#ifdef ZLIB_DEBUG
-        s->compressed_len += 7;  /* align on byte boundary */
-#endif
-    }
-    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
-           s->compressed_len-7*last));
-}
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-int ZLIB_INTERNAL _tr_tally (s, dist, lc)
-    deflate_state *s;
-    unsigned dist;  /* distance of matched string */
-    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
-{
-    s->d_buf[s->last_lit] = (ush)dist;
-    s->l_buf[s->last_lit++] = (uch)lc;
-    if (dist == 0) {
-        /* lc is the unmatched char */
-        s->dyn_ltree[lc].Freq++;
-    } else {
-        s->matches++;
-        /* Here, lc is the match length - MIN_MATCH */
-        dist--;             /* dist = match distance - 1 */
-        Assert((ush)dist < (ush)MAX_DIST(s) &&
-               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
-               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
-
-        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
-        s->dyn_dtree[d_code(dist)].Freq++;
-    }
-
-#ifdef TRUNCATE_BLOCK
-    /* Try to guess if it is profitable to stop the current block here */
-    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
-        /* Compute an upper bound for the compressed length */
-        ulg out_length = (ulg)s->last_lit*8L;
-        ulg in_length = (ulg)((long)s->strstart - s->block_start);
-        int dcode;
-        for (dcode = 0; dcode < D_CODES; dcode++) {
-            out_length += (ulg)s->dyn_dtree[dcode].Freq *
-                (5L+extra_dbits[dcode]);
-        }
-        out_length >>= 3;
-        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
-               s->last_lit, in_length, out_length,
-               100L - out_length*100L/in_length));
-        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
-    }
-#endif
-    return (s->last_lit == s->lit_bufsize-1);
-    /* We avoid equality with lit_bufsize because of wraparound at 64K
-     * on 16 bit machines and because stored blocks are restricted to
-     * 64K-1 bytes.
-     */
-}
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-local void compress_block(s, ltree, dtree)
-    deflate_state *s;
-    const ct_data *ltree; /* literal tree */
-    const ct_data *dtree; /* distance tree */
-{
-    unsigned dist;      /* distance of matched string */
-    int lc;             /* match length or unmatched char (if dist == 0) */
-    unsigned lx = 0;    /* running index in l_buf */
-    unsigned code;      /* the code to send */
-    int extra;          /* number of extra bits to send */
-
-    if (s->last_lit != 0) do {
-        dist = s->d_buf[lx];
-        lc = s->l_buf[lx++];
-        if (dist == 0) {
-            send_code(s, lc, ltree); /* send a literal byte */
-            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
-        } else {
-            /* Here, lc is the match length - MIN_MATCH */
-            code = _length_code[lc];
-            send_code(s, code+LITERALS+1, ltree); /* send the length code */
-            extra = extra_lbits[code];
-            if (extra != 0) {
-                lc -= base_length[code];
-                send_bits(s, lc, extra);       /* send the extra length bits */
-            }
-            dist--; /* dist is now the match distance - 1 */
-            code = d_code(dist);
-            Assert (code < D_CODES, "bad d_code");
-
-            send_code(s, code, dtree);       /* send the distance code */
-            extra = extra_dbits[code];
-            if (extra != 0) {
-                dist -= (unsigned)base_dist[code];
-                send_bits(s, dist, extra);   /* send the extra distance bits */
-            }
-        } /* literal or match pair ? */
-
-        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
-        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
-               "pendingBuf overflow");
-
-    } while (lx < s->last_lit);
-
-    send_code(s, END_BLOCK, ltree);
-}
-
-/* ===========================================================================
- * Check if the data type is TEXT or BINARY, using the following algorithm:
- * - TEXT if the two conditions below are satisfied:
- *    a) There are no non-portable control characters belonging to the
- *       "black list" (0..6, 14..25, 28..31).
- *    b) There is at least one printable character belonging to the
- *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
- * - BINARY otherwise.
- * - The following partially-portable control characters form a
- *   "gray list" that is ignored in this detection algorithm:
- *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
- * IN assertion: the fields Freq of dyn_ltree are set.
- */
-local int detect_data_type(s)
-    deflate_state *s;
-{
-    /* black_mask is the bit mask of black-listed bytes
-     * set bits 0..6, 14..25, and 28..31
-     * 0xf3ffc07f = binary 11110011111111111100000001111111
-     */
-    unsigned long black_mask = 0xf3ffc07fUL;
-    int n;
-
-    /* Check for non-textual ("black-listed") bytes. */
-    for (n = 0; n <= 31; n++, black_mask >>= 1)
-        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
-            return Z_BINARY;
-
-    /* Check for textual ("white-listed") bytes. */
-    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
-            || s->dyn_ltree[13].Freq != 0)
-        return Z_TEXT;
-    for (n = 32; n < LITERALS; n++)
-        if (s->dyn_ltree[n].Freq != 0)
-            return Z_TEXT;
-
-    /* There are no "black-listed" or "white-listed" bytes:
-     * this stream either is empty or has tolerated ("gray-listed") bytes only.
-     */
-    return Z_BINARY;
-}
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-local unsigned bi_reverse(code, len)
-    unsigned code; /* the value to invert */
-    int len;       /* its bit length */
-{
-    register unsigned res = 0;
-    do {
-        res |= code & 1;
-        code >>= 1, res <<= 1;
-    } while (--len > 0);
-    return res >> 1;
-}
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-local void bi_flush(s)
-    deflate_state *s;
-{
-    if (s->bi_valid == 16) {
-        put_short(s, s->bi_buf);
-        s->bi_buf = 0;
-        s->bi_valid = 0;
-    } else if (s->bi_valid >= 8) {
-        put_byte(s, (Byte)s->bi_buf);
-        s->bi_buf >>= 8;
-        s->bi_valid -= 8;
-    }
-}
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-local void bi_windup(s)
-    deflate_state *s;
-{
-    if (s->bi_valid > 8) {
-        put_short(s, s->bi_buf);
-    } else if (s->bi_valid > 0) {
-        put_byte(s, (Byte)s->bi_buf);
-    }
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-#ifdef ZLIB_DEBUG
-    s->bits_sent = (s->bits_sent+7) & ~7;
-#endif
-}
diff --git a/c/zlib/trees.h b/c/zlib/trees.h
deleted file mode 100644
--- a/c/zlib/trees.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* header created automatically with -DGEN_TREES_H */
-
-local const ct_data static_ltree[L_CODES+2] = {
-{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
-{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
-{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
-{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
-{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
-{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
-{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
-{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
-{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
-{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
-{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
-{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
-{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
-{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
-{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
-{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
-{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
-{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
-{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
-{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
-{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
-{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
-{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
-{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
-{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
-{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
-{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
-{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
-{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
-{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
-{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
-{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
-{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
-{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
-{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
-{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
-{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
-{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
-{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
-{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
-{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
-{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
-{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
-{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
-{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
-{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
-{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
-{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
-{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
-{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
-{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
-{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
-{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
-{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
-{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
-{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
-{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
-{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
-};
-
-local const ct_data static_dtree[D_CODES] = {
-{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
-{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
-{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
-{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
-{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
-{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
-};
-
-const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
- 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
- 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
-10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
-18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
-};
-
-const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
- 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
-13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
-17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
-19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
-22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
-};
-
-local const int base_length[LENGTH_CODES] = {
-0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
-64, 80, 96, 112, 128, 160, 192, 224, 0
-};
-
-local const int base_dist[D_CODES] = {
-    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
-   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
- 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
-};
-
diff --git a/c/zlib/uncompr.c b/c/zlib/uncompr.c
deleted file mode 100644
--- a/c/zlib/uncompr.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#define ZLIB_INTERNAL
-#include "zlib.h"
-
-/* ===========================================================================
-     Decompresses the source buffer into the destination buffer.  *sourceLen is
-   the byte length of the source buffer. Upon entry, *destLen is the total size
-   of the destination buffer, which must be large enough to hold the entire
-   uncompressed data. (The size of the uncompressed data must have been saved
-   previously by the compressor and transmitted to the decompressor by some
-   mechanism outside the scope of this compression library.) Upon exit,
-   *destLen is the size of the decompressed data and *sourceLen is the number
-   of source bytes consumed. Upon return, source + *sourceLen points to the
-   first unused input byte.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
-   Z_DATA_ERROR if the input data was corrupted, including if the input data is
-   an incomplete zlib stream.
-*/
-int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong *sourceLen;
-{
-    z_stream stream;
-    int err;
-    const uInt max = (uInt)-1;
-    uLong len, left;
-    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
-
-    len = *sourceLen;
-    if (*destLen) {
-        left = *destLen;
-        *destLen = 0;
-    }
-    else {
-        left = 1;
-        dest = buf;
-    }
-
-    stream.next_in = (z_const Bytef *)source;
-    stream.avail_in = 0;
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-    stream.opaque = (voidpf)0;
-
-    err = inflateInit(&stream);
-    if (err != Z_OK) return err;
-
-    stream.next_out = dest;
-    stream.avail_out = 0;
-
-    do {
-        if (stream.avail_out == 0) {
-            stream.avail_out = left > (uLong)max ? max : (uInt)left;
-            left -= stream.avail_out;
-        }
-        if (stream.avail_in == 0) {
-            stream.avail_in = len > (uLong)max ? max : (uInt)len;
-            len -= stream.avail_in;
-        }
-        err = inflate(&stream, Z_NO_FLUSH);
-    } while (err == Z_OK);
-
-    *sourceLen -= len + stream.avail_in;
-    if (dest != buf)
-        *destLen = stream.total_out;
-    else if (stream.total_out && err == Z_BUF_ERROR)
-        left = 1;
-
-    inflateEnd(&stream);
-    return err == Z_STREAM_END ? Z_OK :
-           err == Z_NEED_DICT ? Z_DATA_ERROR  :
-           err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
-           err;
-}
-
-int ZEXPORT uncompress (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-{
-    return uncompress2(dest, destLen, source, &sourceLen);
-}
diff --git a/c/zlib/zconf.h b/c/zlib/zconf.h
deleted file mode 100644
--- a/c/zlib/zconf.h
+++ /dev/null
@@ -1,534 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#ifndef ZCONF_H
-#define ZCONF_H
-
-/*
- * If you *really* need a unique prefix for all types and library functions,
- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
- * Even better than compiling with -DZ_PREFIX would be to use configure to set
- * this permanently in zconf.h using "./configure --zprefix".
- */
-#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
-#  define Z_PREFIX_SET
-
-/* all linked symbols and init macros */
-#  define _dist_code            z__dist_code
-#  define _length_code          z__length_code
-#  define _tr_align             z__tr_align
-#  define _tr_flush_bits        z__tr_flush_bits
-#  define _tr_flush_block       z__tr_flush_block
-#  define _tr_init              z__tr_init
-#  define _tr_stored_block      z__tr_stored_block
-#  define _tr_tally             z__tr_tally
-#  define adler32               z_adler32
-#  define adler32_combine       z_adler32_combine
-#  define adler32_combine64     z_adler32_combine64
-#  define adler32_z             z_adler32_z
-#  ifndef Z_SOLO
-#    define compress              z_compress
-#    define compress2             z_compress2
-#    define compressBound         z_compressBound
-#  endif
-#  define crc32                 z_crc32
-#  define crc32_combine         z_crc32_combine
-#  define crc32_combine64       z_crc32_combine64
-#  define crc32_z               z_crc32_z
-#  define deflate               z_deflate
-#  define deflateBound          z_deflateBound
-#  define deflateCopy           z_deflateCopy
-#  define deflateEnd            z_deflateEnd
-#  define deflateGetDictionary  z_deflateGetDictionary
-#  define deflateInit           z_deflateInit
-#  define deflateInit2          z_deflateInit2
-#  define deflateInit2_         z_deflateInit2_
-#  define deflateInit_          z_deflateInit_
-#  define deflateParams         z_deflateParams
-#  define deflatePending        z_deflatePending
-#  define deflatePrime          z_deflatePrime
-#  define deflateReset          z_deflateReset
-#  define deflateResetKeep      z_deflateResetKeep
-#  define deflateSetDictionary  z_deflateSetDictionary
-#  define deflateSetHeader      z_deflateSetHeader
-#  define deflateTune           z_deflateTune
-#  define deflate_copyright     z_deflate_copyright
-#  define get_crc_table         z_get_crc_table
-#  ifndef Z_SOLO
-#    define gz_error              z_gz_error
-#    define gz_intmax             z_gz_intmax
-#    define gz_strwinerror        z_gz_strwinerror
-#    define gzbuffer              z_gzbuffer
-#    define gzclearerr            z_gzclearerr
-#    define gzclose               z_gzclose
-#    define gzclose_r             z_gzclose_r
-#    define gzclose_w             z_gzclose_w
-#    define gzdirect              z_gzdirect
-#    define gzdopen               z_gzdopen
-#    define gzeof                 z_gzeof
-#    define gzerror               z_gzerror
-#    define gzflush               z_gzflush
-#    define gzfread               z_gzfread
-#    define gzfwrite              z_gzfwrite
-#    define gzgetc                z_gzgetc
-#    define gzgetc_               z_gzgetc_
-#    define gzgets                z_gzgets
-#    define gzoffset              z_gzoffset
-#    define gzoffset64            z_gzoffset64
-#    define gzopen                z_gzopen
-#    define gzopen64              z_gzopen64
-#    ifdef _WIN32
-#      define gzopen_w              z_gzopen_w
-#    endif
-#    define gzprintf              z_gzprintf
-#    define gzputc                z_gzputc
-#    define gzputs                z_gzputs
-#    define gzread                z_gzread
-#    define gzrewind              z_gzrewind
-#    define gzseek                z_gzseek
-#    define gzseek64              z_gzseek64
-#    define gzsetparams           z_gzsetparams
-#    define gztell                z_gztell
-#    define gztell64              z_gztell64
-#    define gzungetc              z_gzungetc
-#    define gzvprintf             z_gzvprintf
-#    define gzwrite               z_gzwrite
-#  endif
-#  define inflate               z_inflate
-#  define inflateBack           z_inflateBack
-#  define inflateBackEnd        z_inflateBackEnd
-#  define inflateBackInit       z_inflateBackInit
-#  define inflateBackInit_      z_inflateBackInit_
-#  define inflateCodesUsed      z_inflateCodesUsed
-#  define inflateCopy           z_inflateCopy
-#  define inflateEnd            z_inflateEnd
-#  define inflateGetDictionary  z_inflateGetDictionary
-#  define inflateGetHeader      z_inflateGetHeader
-#  define inflateInit           z_inflateInit
-#  define inflateInit2          z_inflateInit2
-#  define inflateInit2_         z_inflateInit2_
-#  define inflateInit_          z_inflateInit_
-#  define inflateMark           z_inflateMark
-#  define inflatePrime          z_inflatePrime
-#  define inflateReset          z_inflateReset
-#  define inflateReset2         z_inflateReset2
-#  define inflateResetKeep      z_inflateResetKeep
-#  define inflateSetDictionary  z_inflateSetDictionary
-#  define inflateSync           z_inflateSync
-#  define inflateSyncPoint      z_inflateSyncPoint
-#  define inflateUndermine      z_inflateUndermine
-#  define inflateValidate       z_inflateValidate
-#  define inflate_copyright     z_inflate_copyright
-#  define inflate_fast          z_inflate_fast
-#  define inflate_table         z_inflate_table
-#  ifndef Z_SOLO
-#    define uncompress            z_uncompress
-#    define uncompress2           z_uncompress2
-#  endif
-#  define zError                z_zError
-#  ifndef Z_SOLO
-#    define zcalloc               z_zcalloc
-#    define zcfree                z_zcfree
-#  endif
-#  define zlibCompileFlags      z_zlibCompileFlags
-#  define zlibVersion           z_zlibVersion
-
-/* all zlib typedefs in zlib.h and zconf.h */
-#  define Byte                  z_Byte
-#  define Bytef                 z_Bytef
-#  define alloc_func            z_alloc_func
-#  define charf                 z_charf
-#  define free_func             z_free_func
-#  ifndef Z_SOLO
-#    define gzFile                z_gzFile
-#  endif
-#  define gz_header             z_gz_header
-#  define gz_headerp            z_gz_headerp
-#  define in_func               z_in_func
-#  define intf                  z_intf
-#  define out_func              z_out_func
-#  define uInt                  z_uInt
-#  define uIntf                 z_uIntf
-#  define uLong                 z_uLong
-#  define uLongf                z_uLongf
-#  define voidp                 z_voidp
-#  define voidpc                z_voidpc
-#  define voidpf                z_voidpf
-
-/* all zlib structs in zlib.h and zconf.h */
-#  define gz_header_s           z_gz_header_s
-#  define internal_state        z_internal_state
-
-#endif
-
-#if defined(__MSDOS__) && !defined(MSDOS)
-#  define MSDOS
-#endif
-#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
-#  define OS2
-#endif
-#if defined(_WINDOWS) && !defined(WINDOWS)
-#  define WINDOWS
-#endif
-#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
-#  ifndef WIN32
-#    define WIN32
-#  endif
-#endif
-#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
-#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
-#    ifndef SYS16BIT
-#      define SYS16BIT
-#    endif
-#  endif
-#endif
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- */
-#ifdef SYS16BIT
-#  define MAXSEG_64K
-#endif
-#ifdef MSDOS
-#  define UNALIGNED_OK
-#endif
-
-#ifdef __STDC_VERSION__
-#  ifndef STDC
-#    define STDC
-#  endif
-#  if __STDC_VERSION__ >= 199901L
-#    ifndef STDC99
-#      define STDC99
-#    endif
-#  endif
-#endif
-#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
-#  define STDC
-#endif
-
-#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
-#  define STDC
-#endif
-
-#ifndef STDC
-#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const       /* note: need a more gentle solution here */
-#  endif
-#endif
-
-#if defined(ZLIB_CONST) && !defined(z_const)
-#  define z_const const
-#else
-#  define z_const
-#endif
-
-#ifdef Z_SOLO
-   typedef unsigned long z_size_t;
-#else
-#  define z_longlong long long
-#  if defined(NO_SIZE_T)
-     typedef unsigned NO_SIZE_T z_size_t;
-#  elif defined(STDC)
-#    include <stddef.h>
-     typedef size_t z_size_t;
-#  else
-     typedef unsigned long z_size_t;
-#  endif
-#  undef z_longlong
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-#ifndef Z_ARG /* function prototypes for stdarg */
-#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#    define Z_ARG(args)  args
-#  else
-#    define Z_ARG(args)  ()
-#  endif
-#endif
-
-/* The following definitions for FAR are needed only for MSDOS mixed
- * model programming (small or medium model with some far allocations).
- * This was tested only with MSC; for other MSDOS compilers you may have
- * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
- * just define FAR to be empty.
- */
-#ifdef SYS16BIT
-#  if defined(M_I86SM) || defined(M_I86MM)
-     /* MSC small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef _MSC_VER
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#  if (defined(__SMALL__) || defined(__MEDIUM__))
-     /* Turbo C small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef __BORLANDC__
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#endif
-
-#if defined(WINDOWS) || defined(WIN32)
-   /* If building or using zlib as a DLL, define ZLIB_DLL.
-    * This is not mandatory, but it offers a little performance increase.
-    */
-#  ifdef ZLIB_DLL
-#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
-#      ifdef ZLIB_INTERNAL
-#        define ZEXTERN extern __declspec(dllexport)
-#      else
-#        define ZEXTERN extern __declspec(dllimport)
-#      endif
-#    endif
-#  endif  /* ZLIB_DLL */
-   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
-    * define ZLIB_WINAPI.
-    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
-    */
-#  ifdef ZLIB_WINAPI
-#    ifdef FAR
-#      undef FAR
-#    endif
-#    include <windows.h>
-     /* No need for _export, use ZLIB.DEF instead. */
-     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
-#    define ZEXPORT WINAPI
-#    ifdef WIN32
-#      define ZEXPORTVA WINAPIV
-#    else
-#      define ZEXPORTVA FAR CDECL
-#    endif
-#  endif
-#endif
-
-#if defined (__BEOS__)
-#  ifdef ZLIB_DLL
-#    ifdef ZLIB_INTERNAL
-#      define ZEXPORT   __declspec(dllexport)
-#      define ZEXPORTVA __declspec(dllexport)
-#    else
-#      define ZEXPORT   __declspec(dllimport)
-#      define ZEXPORTVA __declspec(dllimport)
-#    endif
-#  endif
-#endif
-
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-#if !defined(__MACTYPES__)
-typedef unsigned char  Byte;  /* 8 bits */
-#endif
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-#ifdef SMALL_MEDIUM
-   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
-#  define Bytef Byte FAR
-#else
-   typedef Byte  FAR Bytef;
-#endif
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void const *voidpc;
-   typedef void FAR   *voidpf;
-   typedef void       *voidp;
-#else
-   typedef Byte const *voidpc;
-   typedef Byte FAR   *voidpf;
-   typedef Byte       *voidp;
-#endif
-
-#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
-#  include <limits.h>
-#  if (UINT_MAX == 0xffffffffUL)
-#    define Z_U4 unsigned
-#  elif (ULONG_MAX == 0xffffffffUL)
-#    define Z_U4 unsigned long
-#  elif (USHRT_MAX == 0xffffffffUL)
-#    define Z_U4 unsigned short
-#  endif
-#endif
-
-#ifdef Z_U4
-   typedef Z_U4 z_crc_t;
-#else
-   typedef unsigned long z_crc_t;
-#endif
-
-#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
-#  define Z_HAVE_UNISTD_H
-#endif
-
-#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
-#  define Z_HAVE_STDARG_H
-#endif
-
-#ifdef STDC
-#  ifndef Z_SOLO
-#    include <sys/types.h>      /* for off_t */
-#  endif
-#endif
-
-#if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#  ifndef Z_SOLO
-#    include <stdarg.h>         /* for va_list */
-#  endif
-#endif
-
-#ifdef _WIN32
-#  ifndef Z_SOLO
-#    include <stddef.h>         /* for wchar_t */
-#  endif
-#endif
-
-/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
- * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
- * though the former does not conform to the LFS document), but considering
- * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
- * equivalently requesting no 64-bit operations
- */
-#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
-#  undef _LARGEFILE64_SOURCE
-#endif
-
-#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
-#  define Z_HAVE_UNISTD_H
-#endif
-#ifndef Z_SOLO
-#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
-#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
-#    ifdef VMS
-#      include <unixio.h>       /* for off_t */
-#    endif
-#    ifndef z_off_t
-#      define z_off_t off_t
-#    endif
-#  endif
-#endif
-
-#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
-#  define Z_LFS64
-#endif
-
-#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
-#  define Z_LARGE64
-#endif
-
-#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
-#  define Z_WANT64
-#endif
-
-#if !defined(SEEK_SET) && !defined(Z_SOLO)
-#  define SEEK_SET        0       /* Seek from beginning of file.  */
-#  define SEEK_CUR        1       /* Seek from current position.  */
-#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
-#endif
-
-#ifndef z_off_t
-#  define z_off_t long
-#endif
-
-#if !defined(_WIN32) && defined(Z_LARGE64)
-#  define z_off64_t off64_t
-#else
-#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
-#    define z_off64_t __int64
-#  else
-#    define z_off64_t z_off_t
-#  endif
-#endif
-
-/* MVS linker does not support external names larger than 8 bytes */
-#if defined(__MVS__)
-  #pragma map(deflateInit_,"DEIN")
-  #pragma map(deflateInit2_,"DEIN2")
-  #pragma map(deflateEnd,"DEEND")
-  #pragma map(deflateBound,"DEBND")
-  #pragma map(inflateInit_,"ININ")
-  #pragma map(inflateInit2_,"ININ2")
-  #pragma map(inflateEnd,"INEND")
-  #pragma map(inflateSync,"INSY")
-  #pragma map(inflateSetDictionary,"INSEDI")
-  #pragma map(compressBound,"CMBND")
-  #pragma map(inflate_table,"INTABL")
-  #pragma map(inflate_fast,"INFA")
-  #pragma map(inflate_copyright,"INCOPY")
-#endif
-
-#endif /* ZCONF_H */
diff --git a/c/zlib/zlib.h b/c/zlib/zlib.h
deleted file mode 100644
--- a/c/zlib/zlib.h
+++ /dev/null
@@ -1,1912 +0,0 @@
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.11, January 15th, 2017
-
-  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  jloup@gzip.org          madler@alumni.caltech.edu
-
-
-  The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
-  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
-*/
-
-#ifndef ZLIB_H
-#define ZLIB_H
-
-#include "zconf.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ZLIB_VERSION "1.2.11"
-#define ZLIB_VERNUM 0x12b0
-#define ZLIB_VER_MAJOR 1
-#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 11
-#define ZLIB_VER_SUBREVISION 0
-
-/*
-    The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed data.
-  This version of the library supports only one compression method (deflation)
-  but other algorithms will be added later and will have the same stream
-  interface.
-
-    Compression can be done in a single step if the buffers are large enough,
-  or can be done by repeated calls of the compression function.  In the latter
-  case, the application must provide more input and/or consume the output
-  (providing more output space) before each call.
-
-    The compressed data format used by default by the in-memory functions is
-  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
-  around a deflate stream, which is itself documented in RFC 1951.
-
-    The library also supports reading and writing files in gzip (.gz) format
-  with an interface similar to that of stdio using the functions that start
-  with "gz".  The gzip format is different from the zlib format.  gzip is a
-  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
-
-    This library can optionally read and write gzip and raw deflate streams in
-  memory as well.
-
-    The zlib format was designed to be compact and fast for use in memory
-  and on communications channels.  The gzip format was designed for single-
-  file compression on file systems, has a larger header than zlib to maintain
-  directory information, and uses a different, slower check method than zlib.
-
-    The library does not install any signal handler.  The decoder checks
-  the consistency of the compressed data, so the library should never crash
-  even in the case of corrupted input.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    z_const Bytef *next_in;     /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total number of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte will go here */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total number of bytes output so far */
-
-    z_const char *msg;  /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidpf     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: binary or text
-                           for deflate, or the decoding state for inflate */
-    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */
-    uLong   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream FAR *z_streamp;
-
-/*
-     gzip header information passed to and from zlib routines.  See RFC 1952
-  for more details on the meanings of these fields.
-*/
-typedef struct gz_header_s {
-    int     text;       /* true if compressed data believed to be text */
-    uLong   time;       /* modification time */
-    int     xflags;     /* extra flags (not used when writing a gzip file) */
-    int     os;         /* operating system */
-    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
-    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
-    uInt    extra_max;  /* space at extra (only when reading header) */
-    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
-    uInt    name_max;   /* space at name (only when reading header) */
-    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
-    uInt    comm_max;   /* space at comment (only when reading header) */
-    int     hcrc;       /* true if there was or will be a header crc */
-    int     done;       /* true when done reading gzip header (not used
-                           when writing a gzip file) */
-} gz_header;
-
-typedef gz_header FAR *gz_headerp;
-
-/*
-     The application must update next_in and avail_in when avail_in has dropped
-   to zero.  It must update next_out and avail_out when avail_out has dropped
-   to zero.  The application must initialize zalloc, zfree and opaque before
-   calling the init function.  All other fields are set by the compression
-   library and must not be updated by the application.
-
-     The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree.  This can be useful for custom
-   memory management.  The compression library attaches no meaning to the
-   opaque value.
-
-     zalloc must return Z_NULL if there is not enough memory for the object.
-   If zlib is used in a multi-threaded application, zalloc and zfree must be
-   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are
-   Z_NULL on entry to the initialization function, they are set to internal
-   routines that use the standard library functions malloc() and free().
-
-     On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this if
-   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
-   returned by zalloc for objects of exactly 65536 bytes *must* have their
-   offset normalized to zero.  The default allocation function provided by this
-   library ensures this (see zutil.c).  To reduce memory requirements and avoid
-   any allocation of 64K objects, at the expense of compression ratio, compile
-   the library with -DMAX_WBITS=14 (see zconf.h).
-
-     The fields total_in and total_out can be used for statistics or progress
-   reports.  After compression, total_in holds the total size of the
-   uncompressed data and may be saved for use by the decompressor (particularly
-   if the decompressor wants to decompress everything in a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1
-#define Z_SYNC_FLUSH    2
-#define Z_FULL_FLUSH    3
-#define Z_FINISH        4
-#define Z_BLOCK         5
-#define Z_TREES         6
-/* Allowed flush values; see deflate() and inflate() below for details */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_NEED_DICT     2
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative values
- * are errors, positive values are used for special but normal events.
- */
-
-#define Z_NO_COMPRESSION         0
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_RLE                 3
-#define Z_FIXED               4
-#define Z_DEFAULT_STRATEGY    0
-/* compression strategy; see deflateInit2() below for details */
-
-#define Z_BINARY   0
-#define Z_TEXT     1
-#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
-#define Z_UNKNOWN  2
-/* Possible values of the data_type field for deflate() */
-
-#define Z_DEFLATED   8
-/* The deflate compression method (the only one supported in this version) */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-#define zlib_version zlibVersion()
-/* for compatibility with versions < 1.0.2 */
-
-
-                        /* basic functions */
-
-ZEXTERN const char * ZEXPORT zlibVersion OF((void));
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is not
-   compatible with the zlib.h header file used by the application.  This check
-   is automatically made by deflateInit and inflateInit.
- */
-
-/*
-ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
-
-     Initializes the internal stream state for compression.  The fields
-   zalloc, zfree and opaque must be initialized before by the caller.  If
-   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
-   allocation functions.
-
-     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at all
-   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
-   requests a default compromise between speed and compression (currently
-   equivalent to level 6).
-
-     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if level is not a valid compression level, or
-   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
-   if there is no error message.  deflateInit does not perform any compression:
-   this will be done by deflate().
-*/
-
-
-ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
-/*
-    deflate compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full.  It may introduce
-  some output latency (reading input without producing any output) except when
-  forced to flush.
-
-    The detailed semantics are as follows.  deflate performs one or both of the
-  following actions:
-
-  - Compress more input starting at next_in and update next_in and avail_in
-    accordingly.  If not all input can be processed (because there is not
-    enough room in the output buffer), next_in and avail_in are updated and
-    processing will resume at this point for the next call of deflate().
-
-  - Generate more output starting at next_out and update next_out and avail_out
-    accordingly.  This action is forced if the parameter flush is non zero.
-    Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary.  Some output may be provided even if
-    flush is zero.
-
-    Before the call of deflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming more
-  output, and updating avail_in or avail_out accordingly; avail_out should
-  never be zero before the call.  The application can consume the compressed
-  output when it wants, for example when the output buffer is full (avail_out
-  == 0), or after each call of deflate().  If deflate returns Z_OK and with
-  zero avail_out, it must be called again after making room in the output
-  buffer because there might be more output pending. See deflatePending(),
-  which can be used if desired to determine whether or not there is more ouput
-  in that case.
-
-    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
-  decide how much data to accumulate before producing output, in order to
-  maximize compression.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
-  flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far.  (In
-  particular avail_in is zero after the call if enough output space has been
-  provided before the call.) Flushing may degrade compression for some
-  compression algorithms and so it should be used only when necessary.  This
-  completes the current deflate block and follows it with an empty stored block
-  that is three bits plus filler bits to the next byte, followed by four bytes
-  (00 00 ff ff).
-
-    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
-  output buffer, but the output is not aligned to a byte boundary.  All of the
-  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
-  This completes the current deflate block and follows it with an empty fixed
-  codes block that is 10 bits long.  This assures that enough bytes are output
-  in order for the decompressor to finish the block before the empty fixed
-  codes block.
-
-    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
-  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
-  seven bits of the current block are held to be written as the next byte after
-  the next deflate block is completed.  In this case, the decompressor may not
-  be provided enough bits at this point in order to complete decompression of
-  the data provided so far to the compressor.  It may need to wait for the next
-  block to be emitted.  This is for advanced applications that need to control
-  the emission of deflate blocks.
-
-    If flush is set to Z_FULL_FLUSH, all output is flushed as with
-  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
-  restart from this point if previous compressed data has been damaged or if
-  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
-  compression.
-
-    If deflate returns with avail_out == 0, this function must be called again
-  with the same value of the flush parameter and more output space (updated
-  avail_out), until the flush is complete (deflate returns with non-zero
-  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
-  avail_out is greater than six to avoid repeated flush markers due to
-  avail_out == 0 on return.
-
-    If the parameter flush is set to Z_FINISH, pending input is processed,
-  pending output is flushed and deflate returns with Z_STREAM_END if there was
-  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this
-  function must be called again with Z_FINISH and more output space (updated
-  avail_out) but no more input data, until it returns with Z_STREAM_END or an
-  error.  After deflate has returned Z_STREAM_END, the only possible operations
-  on the stream are deflateReset or deflateEnd.
-
-    Z_FINISH can be used in the first deflate call after deflateInit if all the
-  compression is to be done in a single step.  In order to complete in one
-  call, avail_out must be at least the value returned by deflateBound (see
-  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough
-  output space is provided, deflate will not return Z_STREAM_END, and it must
-  be called again as described above.
-
-    deflate() sets strm->adler to the Adler-32 checksum of all input read
-  so far (that is, total_in bytes).  If a gzip stream is being generated, then
-  strm->adler will be the CRC-32 checksum of the input read so far.  (See
-  deflateInit2 below.)
-
-    deflate() may update strm->data_type if it can make a good guess about
-  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is
-  considered binary.  This field is only for information purposes and does not
-  affect the compression algorithm in any manner.
-
-    deflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if all input has been
-  consumed and all output has been produced (only when flush is set to
-  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
-  if next_in or next_out was Z_NULL or the state was inadvertently written over
-  by the application), or Z_BUF_ERROR if no progress is possible (for example
-  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and
-  deflate() can be called again with more input and more output space to
-  continue compressing.
-*/
-
-
-ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any pending
-   output.
-
-     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
-   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
-   prematurely (some input or output was discarded).  In the error case, msg
-   may be set but then points to a static string (which must not be
-   deallocated).
-*/
-
-
-/*
-ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
-
-     Initializes the internal stream state for decompression.  The fields
-   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
-   the caller.  In the current version of inflate, the provided input is not
-   read or consumed.  The allocation of a sliding window will be deferred to
-   the first call of inflate (if the decompression does not complete on the
-   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates
-   them to use default allocation functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
-   invalid, such as a null pointer to the structure.  msg is set to null if
-   there is no error message.  inflateInit does not perform any decompression.
-   Actual decompression will be done by inflate().  So next_in, and avail_in,
-   next_out, and avail_out are unused and unchanged.  The current
-   implementation of inflateInit() does not process any header information --
-   that is deferred until inflate() is called.
-*/
-
-
-ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
-/*
-    inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full.  It may introduce
-  some output latency (reading input without producing any output) except when
-  forced to flush.
-
-  The detailed semantics are as follows.  inflate performs one or both of the
-  following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly.  If not all input can be processed (because there is not
-    enough room in the output buffer), then next_in and avail_in are updated
-    accordingly, and processing will resume at this point for the next call of
-    inflate().
-
-  - Generate more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() provides as much output as possible, until there is
-    no more input data or no more space in the output buffer (see below about
-    the flush parameter).
-
-    Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming more
-  output, and updating the next_* and avail_* values accordingly.  If the
-  caller of inflate() does not provide both available input and available
-  output space, it is possible that there will be no progress made.  The
-  application can consume the uncompressed output when it wants, for example
-  when the output buffer is full (avail_out == 0), or after each call of
-  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
-  called again after making room in the output buffer because there might be
-  more output pending.
-
-    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
-  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
-  output as possible to the output buffer.  Z_BLOCK requests that inflate()
-  stop if and when it gets to the next deflate block boundary.  When decoding
-  the zlib or gzip format, this will cause inflate() to return immediately
-  after the header and before the first block.  When doing a raw inflate,
-  inflate() will go ahead and process the first block, and will return when it
-  gets to the end of that block, or when it runs out of data.
-
-    The Z_BLOCK option assists in appending to or combining deflate streams.
-  To assist in this, on return inflate() always sets strm->data_type to the
-  number of unused bits in the last byte taken from strm->next_in, plus 64 if
-  inflate() is currently decoding the last block in the deflate stream, plus
-  128 if inflate() returned immediately after decoding an end-of-block code or
-  decoding the complete header up to just before the first byte of the deflate
-  stream.  The end-of-block will not be indicated until all of the uncompressed
-  data from that block has been written to strm->next_out.  The number of
-  unused bits may in general be greater than seven, except when bit 7 of
-  data_type is set, in which case the number of unused bits will be less than
-  eight.  data_type is set as noted here every time inflate() returns for all
-  flush options, and so can be used to determine the amount of currently
-  consumed input in bits.
-
-    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
-  end of each deflate block header is reached, before any actual data in that
-  block is decoded.  This allows the caller to determine the length of the
-  deflate block header for later use in random access within a deflate block.
-  256 is added to the value of strm->data_type when inflate() returns
-  immediately after reaching the end of the deflate block header.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error.  However if all decompression is to be performed in a single step (a
-  single call of inflate), the parameter flush should be set to Z_FINISH.  In
-  this case all pending input is processed and all pending output is flushed;
-  avail_out must be large enough to hold all of the uncompressed data for the
-  operation to complete.  (The size of the uncompressed data may have been
-  saved by the compressor for this purpose.)  The use of Z_FINISH is not
-  required to perform an inflation in one step.  However it may be used to
-  inform inflate that a faster approach can be used for the single inflate()
-  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
-  stream completes, which reduces inflate's memory footprint.  If the stream
-  does not complete, either because not all of the stream is provided or not
-  enough output space is provided, then a sliding window will be allocated and
-  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
-  been used.
-
-     In this implementation, inflate() always flushes as much output as
-  possible to the output buffer, and always uses the faster approach on the
-  first call.  So the effects of the flush parameter in this implementation are
-  on the return value of inflate() as noted below, when inflate() returns early
-  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
-  memory for a sliding window when Z_FINISH is used.
-
-     If a preset dictionary is needed after this call (see inflateSetDictionary
-  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
-  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
-  strm->adler to the Adler-32 checksum of all output produced so far (that is,
-  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
-  below.  At the end of the stream, inflate() checks that its computed Adler-32
-  checksum is equal to that saved by the compressor and returns Z_STREAM_END
-  only if the checksum is correct.
-
-    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
-  deflate data.  The header type is detected automatically, if requested when
-  initializing with inflateInit2().  Any information contained in the gzip
-  header is not retained unless inflateGetHeader() is used.  When processing
-  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
-  produced so far.  The CRC-32 is checked against the gzip trailer, as is the
-  uncompressed length, modulo 2^32.
-
-    inflate() returns Z_OK if some progress has been made (more input processed
-  or more output produced), Z_STREAM_END if the end of the compressed data has
-  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
-  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect check
-  value, in which case strm->msg points to a string with a more specific
-  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
-  next_in or next_out was Z_NULL, or the state was inadvertently written over
-  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
-  if no progress was possible or if there was not enough room in the output
-  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
-  inflate() can be called again with more input and more output space to
-  continue decompressing.  If Z_DATA_ERROR is returned, the application may
-  then call inflateSync() to look for a good compression block if a partial
-  recovery of the data is to be attempted.
-*/
-
-
-ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any pending
-   output.
-
-     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
-   was inconsistent.
-*/
-
-
-                        /* Advanced functions */
-
-/*
-    The following functions are needed only in some special applications.
-*/
-
-/*
-ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
-                                     int  level,
-                                     int  method,
-                                     int  windowBits,
-                                     int  memLevel,
-                                     int  strategy));
-
-     This is another version of deflateInit with more compression options.  The
-   fields next_in, zalloc, zfree and opaque must be initialized before by the
-   caller.
-
-     The method parameter is the compression method.  It must be Z_DEFLATED in
-   this version of the library.
-
-     The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library.  Larger values of this parameter result in better
-   compression at the expense of memory usage.  The default value is 15 if
-   deflateInit is used instead.
-
-     For the current implementation of deflate(), a windowBits value of 8 (a
-   window size of 256 bytes) is not supported.  As a result, a request for 8
-   will result in 9 (a 512-byte window).  In that case, providing 8 to
-   inflateInit2() will result in an error when the zlib header with 9 is
-   checked against the initialization of inflate().  The remedy is to not use 8
-   with deflateInit2() with this initialization, or at least in that case use 9
-   with inflateInit2().
-
-     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
-   determines the window size.  deflate() will then generate raw deflate data
-   with no zlib header or trailer, and will not compute a check value.
-
-     windowBits can also be greater than 15 for optional gzip encoding.  Add
-   16 to windowBits to write a simple gzip header and trailer around the
-   compressed data instead of a zlib wrapper.  The gzip header will have no
-   file name, no extra data, no comment, no modification time (set to zero), no
-   header crc, and the operating system will be set to the appropriate value,
-   if the operating system was determined at compile time.  If a gzip stream is
-   being written, strm->adler is a CRC-32 instead of an Adler-32.
-
-     For raw deflate or gzip encoding, a request for a 256-byte window is
-   rejected as invalid, since only the zlib header provides a means of
-   transmitting the window size to the decompressor.
-
-     The memLevel parameter specifies how much memory should be allocated
-   for the internal compression state.  memLevel=1 uses minimum memory but is
-   slow and reduces compression ratio; memLevel=9 uses maximum memory for
-   optimal speed.  The default value is 8.  See zconf.h for total memory usage
-   as a function of windowBits and memLevel.
-
-     The strategy parameter is used to tune the compression algorithm.  Use the
-   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
-   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
-   string match), or Z_RLE to limit match distances to one (run-length
-   encoding).  Filtered data consists mostly of small values with a somewhat
-   random distribution.  In this case, the compression algorithm is tuned to
-   compress them better.  The effect of Z_FILTERED is to force more Huffman
-   coding and less string matching; it is somewhat intermediate between
-   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
-   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
-   strategy parameter only affects the compression ratio but not the
-   correctness of the compressed output even if it is not set appropriately.
-   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
-   decoder for special applications.
-
-     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
-   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
-   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
-   set to null if there is no error message.  deflateInit2 does not perform any
-   compression: this will be done by deflate().
-*/
-
-ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output.  When using the zlib format, this
-   function must be called immediately after deflateInit, deflateInit2 or
-   deflateReset, and before any call of deflate.  When doing raw deflate, this
-   function must be called either before any call of deflate, or immediately
-   after the completion of a deflate block, i.e. after all input has been
-   consumed and all output has been delivered when using any of the flush
-   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
-   compressor and decompressor must use exactly the same dictionary (see
-   inflateSetDictionary).
-
-     The dictionary should consist of strings (byte sequences) that are likely
-   to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary.  Using a
-   dictionary is most useful when the data to be compressed is short and can be
-   predicted with good accuracy; the data can then be compressed better than
-   with the default empty dictionary.
-
-     Depending on the size of the compression data structures selected by
-   deflateInit or deflateInit2, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size
-   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
-   useful should be put at the end of the dictionary, not at the front.  In
-   addition, the current implementation of deflate will use at most the window
-   size minus 262 bytes of the provided dictionary.
-
-     Upon return of this function, strm->adler is set to the Adler-32 value
-   of the dictionary; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor.  (The Adler-32 value
-   applies to the whole dictionary even if only a subset of the dictionary is
-   actually used by the compressor.) If a raw deflate was requested, then the
-   Adler-32 value is not computed and strm->adler is not set.
-
-     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
-   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
-   inconsistent (for example if deflate has already been called for this stream
-   or if not at a block boundary for raw deflate).  deflateSetDictionary does
-   not perform any compression: this will be done by deflate().
-*/
-
-ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
-                                             Bytef *dictionary,
-                                             uInt  *dictLength));
-/*
-     Returns the sliding dictionary being maintained by deflate.  dictLength is
-   set to the number of bytes in the dictionary, and that many bytes are copied
-   to dictionary.  dictionary must have enough space, where 32768 bytes is
-   always enough.  If deflateGetDictionary() is called with dictionary equal to
-   Z_NULL, then only the dictionary length is returned, and nothing is copied.
-   Similary, if dictLength is Z_NULL, then it is not set.
-
-     deflateGetDictionary() may return a length less than the window size, even
-   when more than the window size in input has been provided. It may return up
-   to 258 bytes less in that case, due to how zlib's implementation of deflate
-   manages the sliding window and lookahead for matches, where matches can be
-   up to 258 bytes long. If the application needs the last window-size bytes of
-   input, then that would need to be saved by the application outside of zlib.
-
-     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
-   stream state is inconsistent.
-*/
-
-ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when several compression strategies will be
-   tried, for example when there are several ways of pre-processing the input
-   data with a filter.  The streams that will be discarded should then be freed
-   by calling deflateEnd.  Note that deflateCopy duplicates the internal
-   compression state which can be quite large, so this strategy is slow and can
-   consume lots of memory.
-
-     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
-   destination.
-*/
-
-ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to deflateEnd followed by deflateInit, but
-   does not free and reallocate the internal compression state.  The stream
-   will leave the compression level and any other attributes that may have been
-   set unchanged.
-
-     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL).
-*/
-
-ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
-                                      int level,
-                                      int strategy));
-/*
-     Dynamically update the compression level and compression strategy.  The
-   interpretation of level and strategy is as in deflateInit2().  This can be
-   used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different strategy.
-   If the compression approach (which is a function of the level) or the
-   strategy is changed, and if any input has been consumed in a previous
-   deflate() call, then the input available so far is compressed with the old
-   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches
-   for the compression levels 0, 1..3, and 4..9 respectively.  The new level
-   and strategy will take effect at the next call of deflate().
-
-     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
-   not have enough output space to complete, then the parameter change will not
-   take effect.  In this case, deflateParams() can be called again with the
-   same parameters and more output space to try again.
-
-     In order to assure a change in the parameters on the first try, the
-   deflate stream should be flushed using deflate() with Z_BLOCK or other flush
-   request until strm.avail_out is not zero, before calling deflateParams().
-   Then no more input data should be provided before the deflateParams() call.
-   If this is done, the old level and strategy will be applied to the data
-   compressed before deflateParams(), and the new level and strategy will be
-   applied to the the data compressed after deflateParams().
-
-     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
-   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
-   there was not enough output space to complete the compression of the
-   available input data before a change in the strategy or approach.  Note that
-   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return
-   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
-   retried with more output space.
-*/
-
-ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
-                                    int good_length,
-                                    int max_lazy,
-                                    int nice_length,
-                                    int max_chain));
-/*
-     Fine tune deflate's internal compression parameters.  This should only be
-   used by someone who understands the algorithm used by zlib's deflate for
-   searching for the best matching string, and even then only by the most
-   fanatic optimizer trying to squeeze out the last compressed bit for their
-   specific input data.  Read the deflate.c source code for the meaning of the
-   max_lazy, good_length, nice_length, and max_chain parameters.
-
-     deflateTune() can be called after deflateInit() or deflateInit2(), and
-   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
- */
-
-ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
-                                       uLong sourceLen));
-/*
-     deflateBound() returns an upper bound on the compressed size after
-   deflation of sourceLen bytes.  It must be called after deflateInit() or
-   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
-   to allocate an output buffer for deflation in a single pass, and so would be
-   called before deflate().  If that first deflate() call is provided the
-   sourceLen input bytes, an output buffer allocated to the size returned by
-   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
-   to return Z_STREAM_END.  Note that it is possible for the compressed size to
-   be larger than the value returned by deflateBound() if flush options other
-   than Z_FINISH or Z_NO_FLUSH are used.
-*/
-
-ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
-                                       unsigned *pending,
-                                       int *bits));
-/*
-     deflatePending() returns the number of bytes and bits of output that have
-   been generated, but not yet provided in the available output.  The bytes not
-   provided would be due to the available output space having being consumed.
-   The number of bits of output not provided are between 0 and 7, where they
-   await more bits to join them in order to fill out a full byte.  If pending
-   or bits are Z_NULL, then those values are not set.
-
-     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
- */
-
-ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
-/*
-     deflatePrime() inserts bits in the deflate output stream.  The intent
-   is that this function is used to start off the deflate output with the bits
-   leftover from a previous deflate stream when appending to it.  As such, this
-   function can only be used for raw deflate, and must be used before the first
-   deflate() call after a deflateInit2() or deflateReset().  bits must be less
-   than or equal to 16, and that many of the least significant bits of value
-   will be inserted in the output.
-
-     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
-   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
-   source stream state was inconsistent.
-*/
-
-ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
-                                         gz_headerp head));
-/*
-     deflateSetHeader() provides gzip header information for when a gzip
-   stream is requested by deflateInit2().  deflateSetHeader() may be called
-   after deflateInit2() or deflateReset() and before the first call of
-   deflate().  The text, time, os, extra field, name, and comment information
-   in the provided gz_header structure are written to the gzip header (xflag is
-   ignored -- the extra flags are set according to the compression level).  The
-   caller must assure that, if not Z_NULL, name and comment are terminated with
-   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
-   available there.  If hcrc is true, a gzip header crc is included.  Note that
-   the current versions of the command-line version of gzip (up through version
-   1.3.x) do not support header crc's, and will report that it is a "multi-part
-   gzip file" and give up.
-
-     If deflateSetHeader is not used, the default gzip header has text false,
-   the time set to zero, and os set to 255, with no extra, name, or comment
-   fields.  The gzip header is returned to the default state by deflateReset().
-
-     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-/*
-ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
-                                     int  windowBits));
-
-     This is another version of inflateInit with an extra parameter.  The
-   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
-   before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library.  The default value is 15 if inflateInit is used
-   instead.  windowBits must be greater than or equal to the windowBits value
-   provided to deflateInit2() while compressing, or it must be equal to 15 if
-   deflateInit2() was not used.  If a compressed stream with a larger window
-   size is given as input, inflate() will return with the error code
-   Z_DATA_ERROR instead of trying to allocate a larger window.
-
-     windowBits can also be zero to request that inflate use the window size in
-   the zlib header of the compressed stream.
-
-     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
-   determines the window size.  inflate() will then process raw deflate data,
-   not looking for a zlib or gzip header, not generating a check value, and not
-   looking for any check values for comparison at the end of the stream.  This
-   is for use with other formats that use the deflate compressed data format
-   such as zip.  Those formats provide their own check values.  If a custom
-   format is developed using the raw deflate format for compressed data, it is
-   recommended that a check value such as an Adler-32 or a CRC-32 be applied to
-   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
-   most applications, the zlib format should be used as is.  Note that comments
-   above on the use in deflateInit2() applies to the magnitude of windowBits.
-
-     windowBits can also be greater than 15 for optional gzip decoding.  Add
-   32 to windowBits to enable zlib and gzip decoding with automatic header
-   detection, or add 16 to decode only the gzip format (the zlib format will
-   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
-   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see
-   below), inflate() will not automatically decode concatenated gzip streams.
-   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state
-   would need to be reset to continue decoding a subsequent gzip stream.
-
-     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
-   invalid, such as a null pointer to the structure.  msg is set to null if
-   there is no error message.  inflateInit2 does not perform any decompression
-   apart from possibly reading the zlib header if present: actual decompression
-   will be done by inflate().  (So next_in and avail_in may be modified, but
-   next_out and avail_out are unused and unchanged.) The current implementation
-   of inflateInit2() does not process any header information -- that is
-   deferred until inflate() is called.
-*/
-
-ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the decompression dictionary from the given uncompressed byte
-   sequence.  This function must be called immediately after a call of inflate,
-   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
-   can be determined from the Adler-32 value returned by that call of inflate.
-   The compressor and decompressor must use exactly the same dictionary (see
-   deflateSetDictionary).  For raw inflate, this function can be called at any
-   time to set the dictionary.  If the provided dictionary is smaller than the
-   window and there is already data in the window, then the provided dictionary
-   will amend what's there.  The application must insure that the dictionary
-   that was used for compression is provided.
-
-     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
-   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
-   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect Adler-32 value).  inflateSetDictionary does not
-   perform any decompression: this will be done by subsequent calls of
-   inflate().
-*/
-
-ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
-                                             Bytef *dictionary,
-                                             uInt  *dictLength));
-/*
-     Returns the sliding dictionary being maintained by inflate.  dictLength is
-   set to the number of bytes in the dictionary, and that many bytes are copied
-   to dictionary.  dictionary must have enough space, where 32768 bytes is
-   always enough.  If inflateGetDictionary() is called with dictionary equal to
-   Z_NULL, then only the dictionary length is returned, and nothing is copied.
-   Similary, if dictLength is Z_NULL, then it is not set.
-
-     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
-   stream state is inconsistent.
-*/
-
-ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
-/*
-     Skips invalid compressed data until a possible full flush point (see above
-   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
-   available input is skipped.  No output is provided.
-
-     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
-   All full flush points have this pattern, but not all occurrences of this
-   pattern are full flush points.
-
-     inflateSync returns Z_OK if a possible full flush point has been found,
-   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
-   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
-   In the success case, the application may save the current current value of
-   total_in which indicates where valid compressed data was found.  In the
-   error case, the application may repeatedly call inflateSync, providing more
-   input each time, until success or end of the input data.
-*/
-
-ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when randomly accessing a large stream.  The
-   first pass through the stream can periodically record the inflate state,
-   allowing restarting inflate at those points when randomly accessing the
-   stream.
-
-     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
-   destination.
-*/
-
-ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate the internal decompression state.  The
-   stream will keep attributes that may have been set by inflateInit2.
-
-     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL).
-*/
-
-ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
-                                      int windowBits));
-/*
-     This function is the same as inflateReset, but it also permits changing
-   the wrap and window size requests.  The windowBits parameter is interpreted
-   the same as it is for inflateInit2.  If the window size is changed, then the
-   memory allocated for the window is freed, and the window will be reallocated
-   by inflate() if needed.
-
-     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
-   the windowBits parameter is invalid.
-*/
-
-ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
-/*
-     This function inserts bits in the inflate input stream.  The intent is
-   that this function is used to start inflating at a bit position in the
-   middle of a byte.  The provided bits will be used before any bytes are used
-   from next_in.  This function should only be used with raw inflate, and
-   should be used before the first inflate() call after inflateInit2() or
-   inflateReset().  bits must be less than or equal to 16, and that many of the
-   least significant bits of value will be inserted in the input.
-
-     If bits is negative, then the input stream bit buffer is emptied.  Then
-   inflatePrime() can be called again to put bits in the buffer.  This is used
-   to clear out bits leftover after feeding inflate a block description prior
-   to feeding inflate codes.
-
-     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
-/*
-     This function returns two values, one in the lower 16 bits of the return
-   value, and the other in the remaining upper bits, obtained by shifting the
-   return value down 16 bits.  If the upper value is -1 and the lower value is
-   zero, then inflate() is currently decoding information outside of a block.
-   If the upper value is -1 and the lower value is non-zero, then inflate is in
-   the middle of a stored block, with the lower value equaling the number of
-   bytes from the input remaining to copy.  If the upper value is not -1, then
-   it is the number of bits back from the current bit position in the input of
-   the code (literal or length/distance pair) currently being processed.  In
-   that case the lower value is the number of bytes already emitted for that
-   code.
-
-     A code is being processed if inflate is waiting for more input to complete
-   decoding of the code, or if it has completed decoding but is waiting for
-   more output space to write the literal or match data.
-
-     inflateMark() is used to mark locations in the input data for random
-   access, which may be at bit positions, and to note those cases where the
-   output of a code may span boundaries of random access blocks.  The current
-   location in the input stream can be determined from avail_in and data_type
-   as noted in the description for the Z_BLOCK flush parameter for inflate.
-
-     inflateMark returns the value noted above, or -65536 if the provided
-   source stream state was inconsistent.
-*/
-
-ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
-                                         gz_headerp head));
-/*
-     inflateGetHeader() requests that gzip header information be stored in the
-   provided gz_header structure.  inflateGetHeader() may be called after
-   inflateInit2() or inflateReset(), and before the first call of inflate().
-   As inflate() processes the gzip stream, head->done is zero until the header
-   is completed, at which time head->done is set to one.  If a zlib stream is
-   being decoded, then head->done is set to -1 to indicate that there will be
-   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
-   used to force inflate() to return immediately after header processing is
-   complete and before any actual data is decompressed.
-
-     The text, time, xflags, and os fields are filled in with the gzip header
-   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
-   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
-   contains the maximum number of bytes to write to extra.  Once done is true,
-   extra_len contains the actual extra field length, and extra contains the
-   extra field, or that field truncated if extra_max is less than extra_len.
-   If name is not Z_NULL, then up to name_max characters are written there,
-   terminated with a zero unless the length is greater than name_max.  If
-   comment is not Z_NULL, then up to comm_max characters are written there,
-   terminated with a zero unless the length is greater than comm_max.  When any
-   of extra, name, or comment are not Z_NULL and the respective field is not
-   present in the header, then that field is set to Z_NULL to signal its
-   absence.  This allows the use of deflateSetHeader() with the returned
-   structure to duplicate the header.  However if those fields are set to
-   allocated memory, then the application will need to save those pointers
-   elsewhere so that they can be eventually freed.
-
-     If inflateGetHeader is not used, then the header information is simply
-   discarded.  The header is always checked for validity, including the header
-   CRC if present.  inflateReset() will reset the process to discard the header
-   information.  The application would need to call inflateGetHeader() again to
-   retrieve the header from the next gzip stream.
-
-     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-/*
-ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
-                                        unsigned char FAR *window));
-
-     Initialize the internal stream state for decompression using inflateBack()
-   calls.  The fields zalloc, zfree and opaque in strm must be initialized
-   before the call.  If zalloc and zfree are Z_NULL, then the default library-
-   derived memory allocation routines are used.  windowBits is the base two
-   logarithm of the window size, in the range 8..15.  window is a caller
-   supplied buffer of that size.  Except for special applications where it is
-   assured that deflate was used with small window sizes, windowBits must be 15
-   and a 32K byte window must be supplied to be able to decompress general
-   deflate streams.
-
-     See inflateBack() for the usage of these routines.
-
-     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
-   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
-   allocated, or Z_VERSION_ERROR if the version of the library does not match
-   the version of the header file.
-*/
-
-typedef unsigned (*in_func) OF((void FAR *,
-                                z_const unsigned char FAR * FAR *));
-typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
-
-ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
-                                    in_func in, void FAR *in_desc,
-                                    out_func out, void FAR *out_desc));
-/*
-     inflateBack() does a raw inflate with a single call using a call-back
-   interface for input and output.  This is potentially more efficient than
-   inflate() for file i/o applications, in that it avoids copying between the
-   output and the sliding window by simply making the window itself the output
-   buffer.  inflate() can be faster on modern CPUs when used with large
-   buffers.  inflateBack() trusts the application to not change the output
-   buffer passed by the output function, at least until inflateBack() returns.
-
-     inflateBackInit() must be called first to allocate the internal state
-   and to initialize the state with the user-provided window buffer.
-   inflateBack() may then be used multiple times to inflate a complete, raw
-   deflate stream with each call.  inflateBackEnd() is then called to free the
-   allocated state.
-
-     A raw deflate stream is one with no zlib or gzip header or trailer.
-   This routine would normally be used in a utility that reads zip or gzip
-   files and writes out uncompressed files.  The utility would decode the
-   header and process the trailer on its own, hence this routine expects only
-   the raw deflate stream to decompress.  This is different from the default
-   behavior of inflate(), which expects a zlib header and trailer around the
-   deflate stream.
-
-     inflateBack() uses two subroutines supplied by the caller that are then
-   called by inflateBack() for input and output.  inflateBack() calls those
-   routines until it reads a complete deflate stream and writes out all of the
-   uncompressed data, or until it encounters an error.  The function's
-   parameters and return types are defined above in the in_func and out_func
-   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
-   number of bytes of provided input, and a pointer to that input in buf.  If
-   there is no input available, in() must return zero -- buf is ignored in that
-   case -- and inflateBack() will return a buffer error.  inflateBack() will
-   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
-   out() should return zero on success, or non-zero on failure.  If out()
-   returns non-zero, inflateBack() will return with an error.  Neither in() nor
-   out() are permitted to change the contents of the window provided to
-   inflateBackInit(), which is also the buffer that out() uses to write from.
-   The length written by out() will be at most the window size.  Any non-zero
-   amount of input may be provided by in().
-
-     For convenience, inflateBack() can be provided input on the first call by
-   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
-   in() will be called.  Therefore strm->next_in must be initialized before
-   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
-   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
-   must also be initialized, and then if strm->avail_in is not zero, input will
-   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
-
-     The in_desc and out_desc parameters of inflateBack() is passed as the
-   first parameter of in() and out() respectively when they are called.  These
-   descriptors can be optionally used to pass any information that the caller-
-   supplied in() and out() functions need to do their job.
-
-     On return, inflateBack() will set strm->next_in and strm->avail_in to
-   pass back any unused input that was provided by the last in() call.  The
-   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
-   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
-   in the deflate stream (in which case strm->msg is set to indicate the nature
-   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
-   In the case of Z_BUF_ERROR, an input or output error can be distinguished
-   using strm->next_in which will be Z_NULL only if in() returned an error.  If
-   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
-   non-zero.  (in() will always be called before out(), so strm->next_in is
-   assured to be defined if out() returns non-zero.)  Note that inflateBack()
-   cannot return Z_OK.
-*/
-
-ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
-/*
-     All memory allocated by inflateBackInit() is freed.
-
-     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
-   state was inconsistent.
-*/
-
-ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
-/* Return flags indicating compile-time options.
-
-    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
-     1.0: size of uInt
-     3.2: size of uLong
-     5.4: size of voidpf (pointer)
-     7.6: size of z_off_t
-
-    Compiler, assembler, and debug options:
-     8: ZLIB_DEBUG
-     9: ASMV or ASMINF -- use ASM code
-     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
-     11: 0 (reserved)
-
-    One-time table building (smaller code, but not thread-safe if true):
-     12: BUILDFIXED -- build static block decoding tables when needed
-     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
-     14,15: 0 (reserved)
-
-    Library content (indicates missing functionality):
-     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
-                          deflate code when not needed)
-     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
-                    and decode gzip streams (to avoid linking crc code)
-     18-19: 0 (reserved)
-
-    Operation variations (changes in library functionality):
-     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
-     21: FASTEST -- deflate algorithm with only one, lowest compression level
-     22,23: 0 (reserved)
-
-    The sprintf variant used by gzprintf (zero is best):
-     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
-     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
-     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
-
-    Remainder:
-     27-31: 0 (reserved)
- */
-
-#ifndef Z_SOLO
-
-                        /* utility functions */
-
-/*
-     The following utility functions are implemented on top of the basic
-   stream-oriented functions.  To simplify the interface, some default options
-   are assumed (compression level and memory usage, standard memory allocation
-   functions).  The source code of these utility functions can be modified if
-   you need special options.
-*/
-
-ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
-                                 const Bytef *source, uLong sourceLen));
-/*
-     Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer.  Upon entry, destLen is the total size
-   of the destination buffer, which must be at least the value returned by
-   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
-   compressed data.  compress() is equivalent to compress2() with a level
-   parameter of Z_DEFAULT_COMPRESSION.
-
-     compress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer.
-*/
-
-ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
-                                  const Bytef *source, uLong sourceLen,
-                                  int level));
-/*
-     Compresses the source buffer into the destination buffer.  The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer.  Upon entry, destLen is the total size of the
-   destination buffer, which must be at least the value returned by
-   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
-   compressed data.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-
-ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
-/*
-     compressBound() returns an upper bound on the compressed size after
-   compress() or compress2() on sourceLen bytes.  It would be used before a
-   compress() or compress2() call to allocate the destination buffer.
-*/
-
-ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
-                                   const Bytef *source, uLong sourceLen));
-/*
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer.  Upon entry, destLen is the total size
-   of the destination buffer, which must be large enough to hold the entire
-   uncompressed data.  (The size of the uncompressed data must have been saved
-   previously by the compressor and transmitted to the decompressor by some
-   mechanism outside the scope of this compression library.) Upon exit, destLen
-   is the actual size of the uncompressed data.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
-   the case where there is not enough room, uncompress() will fill the output
-   buffer with the uncompressed data up to that point.
-*/
-
-ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
-                                    const Bytef *source, uLong *sourceLen));
-/*
-     Same as uncompress, except that sourceLen is a pointer, where the
-   length of the source is *sourceLen.  On return, *sourceLen is the number of
-   source bytes consumed.
-*/
-
-                        /* gzip file access functions */
-
-/*
-     This library supports reading and writing files in gzip (.gz) format with
-   an interface similar to that of stdio, using the functions that start with
-   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
-   wrapper, documented in RFC 1952, wrapped around a deflate stream.
-*/
-
-typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
-
-/*
-ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
-
-     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
-   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
-   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
-   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
-   for fixed code compression as in "wb9F".  (See the description of
-   deflateInit2 for more information about the strategy parameter.)  'T' will
-   request transparent writing or appending with no compression and not using
-   the gzip format.
-
-     "a" can be used instead of "w" to request that the gzip stream that will
-   be written be appended to the file.  "+" will result in an error, since
-   reading and writing to the same gzip file is not supported.  The addition of
-   "x" when writing will create the file exclusively, which fails if the file
-   already exists.  On systems that support it, the addition of "e" when
-   reading or writing will set the flag to close the file on an execve() call.
-
-     These functions, as well as gzip, will read and decode a sequence of gzip
-   streams in a file.  The append function of gzopen() can be used to create
-   such a file.  (Also see gzflush() for another way to do this.)  When
-   appending, gzopen does not test whether the file begins with a gzip stream,
-   nor does it look for the end of the gzip streams to begin appending.  gzopen
-   will simply append a gzip stream to the existing file.
-
-     gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.  When
-   reading, this will be detected automatically by looking for the magic two-
-   byte gzip header.
-
-     gzopen returns NULL if the file could not be opened, if there was
-   insufficient memory to allocate the gzFile state, or if an invalid mode was
-   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
-   errno can be checked to determine if the reason gzopen failed was that the
-   file could not be opened.
-*/
-
-ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
-/*
-     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
-   are obtained from calls like open, dup, creat, pipe or fileno (if the file
-   has been previously opened with fopen).  The mode parameter is as in gzopen.
-
-     The next call of gzclose on the returned gzFile will also close the file
-   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
-   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
-   mode);.  The duplicated descriptor should be saved to avoid a leak, since
-   gzdopen does not close fd if it fails.  If you are using fileno() to get the
-   file descriptor from a FILE *, then you will have to use dup() to avoid
-   double-close()ing the file descriptor.  Both gzclose() and fclose() will
-   close the associated file descriptor, so they need to have different file
-   descriptors.
-
-     gzdopen returns NULL if there was insufficient memory to allocate the
-   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
-   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
-   used until the next gz* read, write, seek, or close operation, so gzdopen
-   will not detect if fd is invalid (unless fd is -1).
-*/
-
-ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
-/*
-     Set the internal buffer size used by this library's functions.  The
-   default buffer size is 8192 bytes.  This function must be called after
-   gzopen() or gzdopen(), and before any other calls that read or write the
-   file.  The buffer memory allocation is always deferred to the first read or
-   write.  Three times that size in buffer space is allocated.  A larger buffer
-   size of, for example, 64K or 128K bytes will noticeably increase the speed
-   of decompression (reading).
-
-     The new buffer size also affects the maximum length for gzprintf().
-
-     gzbuffer() returns 0 on success, or -1 on failure, such as being called
-   too late.
-*/
-
-ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
-/*
-     Dynamically update the compression level or strategy.  See the description
-   of deflateInit2 for the meaning of these parameters.  Previously provided
-   data is flushed before the parameter change.
-
-     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
-   opened for writing, Z_ERRNO if there is an error writing the flushed data,
-   or Z_MEM_ERROR if there is a memory allocation error.
-*/
-
-ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
-/*
-     Reads the given number of uncompressed bytes from the compressed file.  If
-   the input file is not in gzip format, gzread copies the given number of
-   bytes into the buffer directly from the file.
-
-     After reaching the end of a gzip stream in the input, gzread will continue
-   to read, looking for another gzip stream.  Any number of gzip streams may be
-   concatenated in the input file, and will all be decompressed by gzread().
-   If something other than a gzip stream is encountered after a gzip stream,
-   that remaining trailing garbage is ignored (and no error is returned).
-
-     gzread can be used to read a gzip file that is being concurrently written.
-   Upon reaching the end of the input, gzread will return with the available
-   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
-   gzclearerr can be used to clear the end of file indicator in order to permit
-   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
-   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
-   middle of a gzip stream.  Note that gzread does not return -1 in the event
-   of an incomplete gzip stream.  This error is deferred until gzclose(), which
-   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
-   stream.  Alternatively, gzerror can be used before gzclose to detect this
-   case.
-
-     gzread returns the number of uncompressed bytes actually read, less than
-   len for end of file, or -1 for error.  If len is too large to fit in an int,
-   then nothing is read, -1 is returned, and the error state is set to
-   Z_STREAM_ERROR.
-*/
-
-ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
-                                     gzFile file));
-/*
-     Read up to nitems items of size size from file to buf, otherwise operating
-   as gzread() does.  This duplicates the interface of stdio's fread(), with
-   size_t request and return types.  If the library defines size_t, then
-   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned
-   integer type that can contain a pointer.
-
-     gzfread() returns the number of full items read of size size, or zero if
-   the end of the file was reached and a full item could not be read, or if
-   there was an error.  gzerror() must be consulted if zero is returned in
-   order to determine if there was an error.  If the multiplication of size and
-   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
-   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
-
-     In the event that the end of file is reached and only a partial item is
-   available at the end, i.e. the remaining uncompressed data length is not a
-   multiple of size, then the final partial item is nevetheless read into buf
-   and the end-of-file flag is set.  The length of the partial item read is not
-   provided, but could be inferred from the result of gztell().  This behavior
-   is the same as the behavior of fread() implementations in common libraries,
-   but it prevents the direct use of gzfread() to read a concurrently written
-   file, reseting and retrying on end-of-file, when size is not 1.
-*/
-
-ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
-                                voidpc buf, unsigned len));
-/*
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of uncompressed bytes written or 0 in case of
-   error.
-*/
-
-ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
-                                      z_size_t nitems, gzFile file));
-/*
-     gzfwrite() writes nitems items of size size from buf to file, duplicating
-   the interface of stdio's fwrite(), with size_t request and return types.  If
-   the library defines size_t, then z_size_t is identical to size_t.  If not,
-   then z_size_t is an unsigned integer type that can contain a pointer.
-
-     gzfwrite() returns the number of full items written of size size, or zero
-   if there was an error.  If the multiplication of size and nitems overflows,
-   i.e. the product does not fit in a z_size_t, then nothing is written, zero
-   is returned, and the error state is set to Z_STREAM_ERROR.
-*/
-
-ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
-/*
-     Converts, formats, and writes the arguments to the compressed file under
-   control of the format string, as in fprintf.  gzprintf returns the number of
-   uncompressed bytes actually written, or a negative zlib error code in case
-   of error.  The number of uncompressed bytes written is limited to 8191, or
-   one less than the buffer size given to gzbuffer().  The caller should assure
-   that this limit is not exceeded.  If it is exceeded, then gzprintf() will
-   return an error (0) with nothing written.  In this case, there may also be a
-   buffer overflow with unpredictable consequences, which is possible only if
-   zlib was compiled with the insecure functions sprintf() or vsprintf()
-   because the secure snprintf() or vsnprintf() functions were not available.
-   This can be determined using zlibCompileFlags().
-*/
-
-ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
-/*
-     Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-
-     gzputs returns the number of characters written, or -1 in case of error.
-*/
-
-ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
-/*
-     Reads bytes from the compressed file until len-1 characters are read, or a
-   newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  If any characters are read or if len == 1, the
-   string is terminated with a null character.  If no characters are read due
-   to an end-of-file or len < 1, then the buffer is left untouched.
-
-     gzgets returns buf which is a null-terminated string, or it returns NULL
-   for end-of-file or in case of error.  If there was an error, the contents at
-   buf are indeterminate.
-*/
-
-ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
-/*
-     Writes c, converted to an unsigned char, into the compressed file.  gzputc
-   returns the value that was written, or -1 in case of error.
-*/
-
-ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
-/*
-     Reads one byte from the compressed file.  gzgetc returns this byte or -1
-   in case of end of file or error.  This is implemented as a macro for speed.
-   As such, it does not do all of the checking the other functions do.  I.e.
-   it does not check to see if file is NULL, nor whether the structure file
-   points to has been clobbered or not.
-*/
-
-ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
-/*
-     Push one character back onto the stream to be read as the first character
-   on the next read.  At least one character of push-back is allowed.
-   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
-   fail if c is -1, and may fail if a character has been pushed but not read
-   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
-   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
-   The pushed character will be discarded if the stream is repositioned with
-   gzseek() or gzrewind().
-*/
-
-ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
-/*
-     Flushes all pending output into the compressed file.  The parameter flush
-   is as in the deflate() function.  The return value is the zlib error number
-   (see function gzerror below).  gzflush is only permitted when writing.
-
-     If the flush parameter is Z_FINISH, the remaining data is written and the
-   gzip stream is completed in the output.  If gzwrite() is called again, a new
-   gzip stream will be started in the output.  gzread() is able to read such
-   concatenated gzip streams.
-
-     gzflush should be called only when strictly necessary because it will
-   degrade compression if called too often.
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
-                                   z_off_t offset, int whence));
-
-     Sets the starting position for the next gzread or gzwrite on the given
-   compressed file.  The offset represents a number of bytes in the
-   uncompressed data stream.  The whence parameter is defined as in lseek(2);
-   the value SEEK_END is not supported.
-
-     If the file is opened for reading, this function is emulated but can be
-   extremely slow.  If the file is opened for writing, only forward seeks are
-   supported; gzseek then compresses a sequence of zeroes up to the new
-   starting position.
-
-     gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error, in
-   particular if the file is opened for writing and the new starting position
-   would be before the current position.
-*/
-
-ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
-/*
-     Rewinds the given file. This function is supported only for reading.
-
-     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
-
-     Returns the starting position for the next gzread or gzwrite on the given
-   compressed file.  This position represents a number of bytes in the
-   uncompressed data stream, and is zero when starting, even if appending or
-   reading a gzip stream from the middle of a file using gzdopen().
-
-     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
-
-     Returns the current offset in the file being read or written.  This offset
-   includes the count of bytes that precede the gzip stream, for example when
-   appending or when using gzdopen() for reading.  When reading, the offset
-   does not include as yet unused buffered input.  This information can be used
-   for a progress indicator.  On error, gzoffset() returns -1.
-*/
-
-ZEXTERN int ZEXPORT gzeof OF((gzFile file));
-/*
-     Returns true (1) if the end-of-file indicator has been set while reading,
-   false (0) otherwise.  Note that the end-of-file indicator is set only if the
-   read tried to go past the end of the input, but came up short.  Therefore,
-   just like feof(), gzeof() may return false even if there is no more data to
-   read, in the event that the last read request was for the exact number of
-   bytes remaining in the input file.  This will happen if the input file size
-   is an exact multiple of the buffer size.
-
-     If gzeof() returns true, then the read functions will return no more data,
-   unless the end-of-file indicator is reset by gzclearerr() and the input file
-   has grown since the previous end of file was detected.
-*/
-
-ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
-/*
-     Returns true (1) if file is being copied directly while reading, or false
-   (0) if file is a gzip stream being decompressed.
-
-     If the input file is empty, gzdirect() will return true, since the input
-   does not contain a gzip stream.
-
-     If gzdirect() is used immediately after gzopen() or gzdopen() it will
-   cause buffers to be allocated to allow reading the file to determine if it
-   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
-   gzdirect().
-
-     When writing, gzdirect() returns true (1) if transparent writing was
-   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
-   gzdirect() is not needed when writing.  Transparent writing must be
-   explicitly requested, so the application already knows the answer.  When
-   linking statically, using gzdirect() will include all of the zlib code for
-   gzip file reading and decompression, which may not be desired.)
-*/
-
-ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
-/*
-     Flushes all pending output if necessary, closes the compressed file and
-   deallocates the (de)compression state.  Note that once file is closed, you
-   cannot call gzerror with file, since its structures have been deallocated.
-   gzclose must not be called more than once on the same file, just as free
-   must not be called more than once on the same allocation.
-
-     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
-   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
-   last read ended in the middle of a gzip stream, or Z_OK on success.
-*/
-
-ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
-ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
-/*
-     Same as gzclose(), but gzclose_r() is only for use when reading, and
-   gzclose_w() is only for use when writing or appending.  The advantage to
-   using these instead of gzclose() is that they avoid linking in zlib
-   compression or decompression code that is not used when only reading or only
-   writing respectively.  If gzclose() is used, then both compression and
-   decompression code will be included the application when linking to a static
-   zlib library.
-*/
-
-ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
-/*
-     Returns the error message for the last error which occurred on the given
-   compressed file.  errnum is set to zlib error number.  If an error occurred
-   in the file system and not in the compression library, errnum is set to
-   Z_ERRNO and the application may consult errno to get the exact error code.
-
-     The application must not modify the returned string.  Future calls to
-   this function may invalidate the previously returned string.  If file is
-   closed, then the string previously returned by gzerror will no longer be
-   available.
-
-     gzerror() should be used to distinguish errors from end-of-file for those
-   functions above that do not distinguish those cases in their return values.
-*/
-
-ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
-/*
-     Clears the error and end-of-file flags for file.  This is analogous to the
-   clearerr() function in stdio.  This is useful for continuing to read a gzip
-   file that is being written concurrently.
-*/
-
-#endif /* !Z_SOLO */
-
-                        /* checksum functions */
-
-/*
-     These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the compression
-   library.
-*/
-
-ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum.  If buf is Z_NULL, this function returns the
-   required initial value for the checksum.
-
-     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
-   much faster.
-
-   Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
-                                    z_size_t len));
-/*
-     Same as adler32(), but with a size_t length.
-*/
-
-/*
-ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
-                                          z_off_t len2));
-
-     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
-   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
-   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
-   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
-   that the z_off_t type (like off_t) is a signed integer.  If len2 is
-   negative, the result has no meaning or utility.
-*/
-
-ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
-/*
-     Update a running CRC-32 with the bytes buf[0..len-1] and return the
-   updated CRC-32.  If buf is Z_NULL, this function returns the required
-   initial value for the crc.  Pre- and post-conditioning (one's complement) is
-   performed within this function so it shouldn't be done by the application.
-
-   Usage example:
-
-     uLong crc = crc32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       crc = crc32(crc, buffer, length);
-     }
-     if (crc != original_crc) error();
-*/
-
-ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
-                                  z_size_t len));
-/*
-     Same as crc32(), but with a size_t length.
-*/
-
-/*
-ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
-
-     Combine two CRC-32 check values into one.  For two sequences of bytes,
-   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
-   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
-   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
-   len2.
-*/
-
-
-                        /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
-                                         unsigned char FAR *window,
-                                         const char *version,
-                                         int stream_size));
-#ifdef Z_PREFIX_SET
-#  define z_deflateInit(strm, level) \
-          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define z_inflateInit(strm) \
-          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define z_inflateInit2(strm, windowBits) \
-          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
-                        (int)sizeof(z_stream))
-#  define z_inflateBackInit(strm, windowBits, window) \
-          inflateBackInit_((strm), (windowBits), (window), \
-                           ZLIB_VERSION, (int)sizeof(z_stream))
-#else
-#  define deflateInit(strm, level) \
-          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define inflateInit(strm) \
-          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
-#  define inflateInit2(strm, windowBits) \
-          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
-                        (int)sizeof(z_stream))
-#  define inflateBackInit(strm, windowBits, window) \
-          inflateBackInit_((strm), (windowBits), (window), \
-                           ZLIB_VERSION, (int)sizeof(z_stream))
-#endif
-
-#ifndef Z_SOLO
-
-/* gzgetc() macro and its supporting function and exposed data structure.  Note
- * that the real internal state is much larger than the exposed structure.
- * This abbreviated structure exposes just enough for the gzgetc() macro.  The
- * user should not mess with these exposed elements, since their names or
- * behavior could change in the future, perhaps even capriciously.  They can
- * only be used by the gzgetc() macro.  You have been warned.
- */
-struct gzFile_s {
-    unsigned have;
-    unsigned char *next;
-    z_off64_t pos;
-};
-ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
-#ifdef Z_PREFIX_SET
-#  undef z_gzgetc
-#  define z_gzgetc(g) \
-          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
-#else
-#  define gzgetc(g) \
-          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
-#endif
-
-/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
- * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
- * both are true, the application gets the *64 functions, and the regular
- * functions are changed to 64 bits) -- in case these are set on systems
- * without large file support, _LFS64_LARGEFILE must also be true
- */
-#ifdef Z_LARGE64
-   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
-   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
-   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
-   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
-#endif
-
-#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
-#  ifdef Z_PREFIX_SET
-#    define z_gzopen z_gzopen64
-#    define z_gzseek z_gzseek64
-#    define z_gztell z_gztell64
-#    define z_gzoffset z_gzoffset64
-#    define z_adler32_combine z_adler32_combine64
-#    define z_crc32_combine z_crc32_combine64
-#  else
-#    define gzopen gzopen64
-#    define gzseek gzseek64
-#    define gztell gztell64
-#    define gzoffset gzoffset64
-#    define adler32_combine adler32_combine64
-#    define crc32_combine crc32_combine64
-#  endif
-#  ifndef Z_LARGE64
-     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
-     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
-     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
-     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-#  endif
-#else
-   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
-   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
-   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
-   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-#endif
-
-#else /* Z_SOLO */
-
-   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-
-#endif /* !Z_SOLO */
-
-/* undocumented functions */
-ZEXTERN const char   * ZEXPORT zError           OF((int));
-ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
-ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
-ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
-ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
-ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));
-ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
-ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
-ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
-                                            const char *mode));
-#endif
-#if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#  ifndef Z_SOLO
-ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
-                                                  const char *format,
-                                                  va_list va));
-#  endif
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ZLIB_H */
diff --git a/c/zlib/zutil.c b/c/zlib/zutil.c
deleted file mode 100644
--- a/c/zlib/zutil.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2017 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#include "zutil.h"
-#ifndef Z_SOLO
-#  include "gzguts.h"
-#endif
-
-z_const char * const z_errmsg[10] = {
-    (z_const char *)"need dictionary",     /* Z_NEED_DICT       2  */
-    (z_const char *)"stream end",          /* Z_STREAM_END      1  */
-    (z_const char *)"",                    /* Z_OK              0  */
-    (z_const char *)"file error",          /* Z_ERRNO         (-1) */
-    (z_const char *)"stream error",        /* Z_STREAM_ERROR  (-2) */
-    (z_const char *)"data error",          /* Z_DATA_ERROR    (-3) */
-    (z_const char *)"insufficient memory", /* Z_MEM_ERROR     (-4) */
-    (z_const char *)"buffer error",        /* Z_BUF_ERROR     (-5) */
-    (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
-    (z_const char *)""
-};
-
-
-const char * ZEXPORT zlibVersion()
-{
-    return ZLIB_VERSION;
-}
-
-uLong ZEXPORT zlibCompileFlags()
-{
-    uLong flags;
-
-    flags = 0;
-    switch ((int)(sizeof(uInt))) {
-    case 2:     break;
-    case 4:     flags += 1;     break;
-    case 8:     flags += 2;     break;
-    default:    flags += 3;
-    }
-    switch ((int)(sizeof(uLong))) {
-    case 2:     break;
-    case 4:     flags += 1 << 2;        break;
-    case 8:     flags += 2 << 2;        break;
-    default:    flags += 3 << 2;
-    }
-    switch ((int)(sizeof(voidpf))) {
-    case 2:     break;
-    case 4:     flags += 1 << 4;        break;
-    case 8:     flags += 2 << 4;        break;
-    default:    flags += 3 << 4;
-    }
-    switch ((int)(sizeof(z_off_t))) {
-    case 2:     break;
-    case 4:     flags += 1 << 6;        break;
-    case 8:     flags += 2 << 6;        break;
-    default:    flags += 3 << 6;
-    }
-#ifdef ZLIB_DEBUG
-    flags += 1 << 8;
-#endif
-#if defined(ASMV) || defined(ASMINF)
-    flags += 1 << 9;
-#endif
-#ifdef ZLIB_WINAPI
-    flags += 1 << 10;
-#endif
-#ifdef BUILDFIXED
-    flags += 1 << 12;
-#endif
-#ifdef DYNAMIC_CRC_TABLE
-    flags += 1 << 13;
-#endif
-#ifdef NO_GZCOMPRESS
-    flags += 1L << 16;
-#endif
-#ifdef NO_GZIP
-    flags += 1L << 17;
-#endif
-#ifdef PKZIP_BUG_WORKAROUND
-    flags += 1L << 20;
-#endif
-#ifdef FASTEST
-    flags += 1L << 21;
-#endif
-#if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#  ifdef NO_vsnprintf
-    flags += 1L << 25;
-#    ifdef HAS_vsprintf_void
-    flags += 1L << 26;
-#    endif
-#  else
-#    ifdef HAS_vsnprintf_void
-    flags += 1L << 26;
-#    endif
-#  endif
-#else
-    flags += 1L << 24;
-#  ifdef NO_snprintf
-    flags += 1L << 25;
-#    ifdef HAS_sprintf_void
-    flags += 1L << 26;
-#    endif
-#  else
-#    ifdef HAS_snprintf_void
-    flags += 1L << 26;
-#    endif
-#  endif
-#endif
-    return flags;
-}
-
-#ifdef ZLIB_DEBUG
-#include <stdlib.h>
-#  ifndef verbose
-#    define verbose 0
-#  endif
-int ZLIB_INTERNAL z_verbose = verbose;
-
-void ZLIB_INTERNAL z_error (m)
-    char *m;
-{
-    fprintf(stderr, "%s\n", m);
-    exit(1);
-}
-#endif
-
-/* exported to allow conversion of error code to string for compress() and
- * uncompress()
- */
-const char * ZEXPORT zError(err)
-    int err;
-{
-    return ERR_MSG(err);
-}
-
-#if defined(_WIN32_WCE)
-    /* The Microsoft C Run-Time Library for Windows CE doesn't have
-     * errno.  We define it as a global variable to simplify porting.
-     * Its value is always 0 and should not be used.
-     */
-    int errno = 0;
-#endif
-
-#ifndef HAVE_MEMCPY
-
-void ZLIB_INTERNAL zmemcpy(dest, source, len)
-    Bytef* dest;
-    const Bytef* source;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = *source++; /* ??? to be unrolled */
-    } while (--len != 0);
-}
-
-int ZLIB_INTERNAL zmemcmp(s1, s2, len)
-    const Bytef* s1;
-    const Bytef* s2;
-    uInt  len;
-{
-    uInt j;
-
-    for (j = 0; j < len; j++) {
-        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
-    }
-    return 0;
-}
-
-void ZLIB_INTERNAL zmemzero(dest, len)
-    Bytef* dest;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = 0;  /* ??? to be unrolled */
-    } while (--len != 0);
-}
-#endif
-
-#ifndef Z_SOLO
-
-#ifdef SYS16BIT
-
-#ifdef __TURBOC__
-/* Turbo C in 16-bit mode */
-
-#  define MY_ZCALLOC
-
-/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
- * and farmalloc(64K) returns a pointer with an offset of 8, so we
- * must fix the pointer. Warning: the pointer must be put back to its
- * original form in order to free it, use zcfree().
- */
-
-#define MAX_PTR 10
-/* 10*64K = 640K */
-
-local int next_ptr = 0;
-
-typedef struct ptr_table_s {
-    voidpf org_ptr;
-    voidpf new_ptr;
-} ptr_table;
-
-local ptr_table table[MAX_PTR];
-/* This table is used to remember the original form of pointers
- * to large buffers (64K). Such pointers are normalized with a zero offset.
- * Since MSDOS is not a preemptive multitasking OS, this table is not
- * protected from concurrent access. This hack doesn't work anyway on
- * a protected system like OS/2. Use Microsoft C instead.
- */
-
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
-    voidpf buf;
-    ulg bsize = (ulg)items*size;
-
-    (void)opaque;
-
-    /* If we allocate less than 65520 bytes, we assume that farmalloc
-     * will return a usable pointer which doesn't have to be normalized.
-     */
-    if (bsize < 65520L) {
-        buf = farmalloc(bsize);
-        if (*(ush*)&buf != 0) return buf;
-    } else {
-        buf = farmalloc(bsize + 16L);
-    }
-    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
-    table[next_ptr].org_ptr = buf;
-
-    /* Normalize the pointer to seg:0 */
-    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
-    *(ush*)&buf = 0;
-    table[next_ptr++].new_ptr = buf;
-    return buf;
-}
-
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
-{
-    int n;
-
-    (void)opaque;
-
-    if (*(ush*)&ptr != 0) { /* object < 64K */
-        farfree(ptr);
-        return;
-    }
-    /* Find the original pointer */
-    for (n = 0; n < next_ptr; n++) {
-        if (ptr != table[n].new_ptr) continue;
-
-        farfree(table[n].org_ptr);
-        while (++n < next_ptr) {
-            table[n-1] = table[n];
-        }
-        next_ptr--;
-        return;
-    }
-    Assert(0, "zcfree: ptr not found");
-}
-
-#endif /* __TURBOC__ */
-
-
-#ifdef M_I86
-/* Microsoft C in 16-bit mode */
-
-#  define MY_ZCALLOC
-
-#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
-#  define _halloc  halloc
-#  define _hfree   hfree
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
-{
-    (void)opaque;
-    return _halloc((long)items, size);
-}
-
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
-{
-    (void)opaque;
-    _hfree(ptr);
-}
-
-#endif /* M_I86 */
-
-#endif /* SYS16BIT */
-
-
-#ifndef MY_ZCALLOC /* Any system without a special alloc function */
-
-#ifndef STDC
-extern voidp  malloc OF((uInt size));
-extern voidp  calloc OF((uInt items, uInt size));
-extern void   free   OF((voidpf ptr));
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
-    voidpf opaque;
-    unsigned items;
-    unsigned size;
-{
-    (void)opaque;
-    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
-                              (voidpf)calloc(items, size);
-}
-
-void ZLIB_INTERNAL zcfree (opaque, ptr)
-    voidpf opaque;
-    voidpf ptr;
-{
-    (void)opaque;
-    free(ptr);
-}
-
-#endif /* MY_ZCALLOC */
-
-#endif /* !Z_SOLO */
diff --git a/c/zlib/zutil.h b/c/zlib/zutil.h
deleted file mode 100644
--- a/c/zlib/zutil.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id$ */
-
-#ifndef ZUTIL_H
-#define ZUTIL_H
-
-#ifdef HAVE_HIDDEN
-#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
-#else
-#  define ZLIB_INTERNAL
-#endif
-
-#include "zlib.h"
-
-#if defined(STDC) && !defined(Z_SOLO)
-#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
-#    include <stddef.h>
-#  endif
-#  include <string.h>
-#  include <stdlib.h>
-#endif
-
-#ifdef Z_SOLO
-   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
-#endif
-
-#ifndef local
-#  define local static
-#endif
-/* since "static" is used to mean two completely different things in C, we
-   define "local" for the non-static meaning of "static", for readability
-   (compile with -Dlocal if your debugger can't find static symbols) */
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
-/* (size given to avoid silly warnings with Visual C++) */
-
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
-
-#define ERR_RETURN(strm,err) \
-  return (strm->msg = ERR_MSG(err), (err))
-/* To be used only when the state is known to be valid */
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
-#  define OS_CODE  0x00
-#  ifndef Z_SOLO
-#    if defined(__TURBOC__) || defined(__BORLANDC__)
-#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
-         /* Allow compilation with ANSI keywords only enabled */
-         void _Cdecl farfree( void *block );
-         void *_Cdecl farmalloc( unsigned long nbytes );
-#      else
-#        include <alloc.h>
-#      endif
-#    else /* MSC or DJGPP */
-#      include <malloc.h>
-#    endif
-#  endif
-#endif
-
-#ifdef AMIGA
-#  define OS_CODE  1
-#endif
-
-#if defined(VAXC) || defined(VMS)
-#  define OS_CODE  2
-#  define F_OPEN(name, mode) \
-     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
-#endif
-
-#ifdef __370__
-#  if __TARGET_LIB__ < 0x20000000
-#    define OS_CODE 4
-#  elif __TARGET_LIB__ < 0x40000000
-#    define OS_CODE 11
-#  else
-#    define OS_CODE 8
-#  endif
-#endif
-
-#if defined(ATARI) || defined(atarist)
-#  define OS_CODE  5
-#endif
-
-#ifdef OS2
-#  define OS_CODE  6
-#  if defined(M_I86) && !defined(Z_SOLO)
-#    include <malloc.h>
-#  endif
-#endif
-
-#if defined(MACOS) || defined(TARGET_OS_MAC)
-#  define OS_CODE  7
-#  ifndef Z_SOLO
-#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#      include <unix.h> /* for fdopen */
-#    else
-#      ifndef fdopen
-#        define fdopen(fd,mode) NULL /* No fdopen() */
-#      endif
-#    endif
-#  endif
-#endif
-
-#ifdef __acorn
-#  define OS_CODE 13
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-#  define OS_CODE  10
-#endif
-
-#ifdef _BEOS_
-#  define OS_CODE  16
-#endif
-
-#ifdef __TOS_OS400__
-#  define OS_CODE 18
-#endif
-
-#ifdef __APPLE__
-#  define OS_CODE 19
-#endif
-
-#if defined(_BEOS_) || defined(RISCOS)
-#  define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
-#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
-#  if defined(_WIN32_WCE)
-#    define fdopen(fd,mode) NULL /* No fdopen() */
-#    ifndef _PTRDIFF_T_DEFINED
-       typedef int ptrdiff_t;
-#      define _PTRDIFF_T_DEFINED
-#    endif
-#  else
-#    define fdopen(fd,type)  _fdopen(fd,type)
-#  endif
-#endif
-
-#if defined(__BORLANDC__) && !defined(MSDOS)
-  #pragma warn -8004
-  #pragma warn -8008
-  #pragma warn -8066
-#endif
-
-/* provide prototypes for these when building zlib without LFS */
-#if !defined(_WIN32) && \
-    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
-    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-#endif
-
-        /* common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  3     /* assume Unix */
-#endif
-
-#ifndef F_OPEN
-#  define F_OPEN(name, mode) fopen((name), (mode))
-#endif
-
-         /* functions */
-
-#if defined(pyr) || defined(Z_SOLO)
-#  define NO_MEMCPY
-#endif
-#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
- /* Use our own functions for small and medium model with MSC <= 5.0.
-  * You may have to use the same strategy for Borland C (untested).
-  * The __SC__ check is for Symantec.
-  */
-#  define NO_MEMCPY
-#endif
-#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
-#  define HAVE_MEMCPY
-#endif
-#ifdef HAVE_MEMCPY
-#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
-#    define zmemcpy _fmemcpy
-#    define zmemcmp _fmemcmp
-#    define zmemzero(dest, len) _fmemset(dest, 0, len)
-#  else
-#    define zmemcpy memcpy
-#    define zmemcmp memcmp
-#    define zmemzero(dest, len) memset(dest, 0, len)
-#  endif
-#else
-   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
-   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
-   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
-#endif
-
-/* Diagnostic functions */
-#ifdef ZLIB_DEBUG
-#  include <stdio.h>
-   extern int ZLIB_INTERNAL z_verbose;
-   extern void ZLIB_INTERNAL z_error OF((char *m));
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
-#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
-#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-#ifndef Z_SOLO
-   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
-                                    unsigned size));
-   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
-#endif
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
-#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-
-/* Reverse the bytes in a 32-bit value */
-#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
-                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
-
-#endif /* ZUTIL_H */
diff --git a/libarchive.cabal b/libarchive.cabal
--- a/libarchive.cabal
+++ b/libarchive.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               libarchive
-version:            3.0.4.2
+version:            3.0.5.0
 license:            BSD-3-Clause
 license-file:       LICENSE
 copyright:          Copyright: (c) 2018-2020 Vanessa McHale
@@ -15,14 +15,6 @@
 category:           Codec
 build-type:         Custom
 extra-source-files:
-    ./c/autoconf-darwin/config.h
-    ./c/autoconf-linux/config.h
-    ./c/autoconf-freebsd/config.h
-    ./c/autoconf-windows/config.h
-    ./c/*.c
-    ./c/*.h
-    ./c/zlib/*.c
-    ./c/zlib/*.h
     test/data/aarch64-linux-dist.tar
 
 extra-doc-files:
@@ -114,179 +106,15 @@
     if impl(ghc >=8.10)
         ghc-options: -Wunused-packages
 
-    if !flag(system-libarchive)
-        include-dirs: c
-
-    if !flag(system-libarchive)
-        cc-options:   -std=c11 -DHAVE_CONFIG_H
-        c-sources:
-            ./c/archive_acl.c
-            ./c/archive_blake2sp_ref.c
-            ./c/archive_blake2s_ref.c
-            ./c/archive_check_magic.c
-            ./c/archive_cmdline.c
-            ./c/archive_cryptor.c
-            ./c/archive_digest.c
-            ./c/archive_disk_acl_darwin.c
-            ./c/archive_disk_acl_freebsd.c
-            ./c/archive_disk_acl_linux.c
-            ./c/archive_disk_acl_sunos.c
-            ./c/archive_entry.c
-            ./c/archive_entry_copy_bhfi.c
-            ./c/archive_entry_copy_stat.c
-            ./c/archive_entry_link_resolver.c
-            ./c/archive_entry_sparse.c
-            ./c/archive_entry_stat.c
-            ./c/archive_entry_strmode.c
-            ./c/archive_entry_xattr.c
-            ./c/archive_getdate.c
-            ./c/archive_hmac.c
-            ./c/archive_match.c
-            ./c/archive_options.c
-            ./c/archive_pack_dev.c
-            ./c/archive_pathmatch.c
-            ./c/archive_ppmd7.c
-            ./c/archive_ppmd8.c
-            ./c/archive_random.c
-            ./c/archive_rb.c
-            ./c/archive_read_add_passphrase.c
-            ./c/archive_read_append_filter.c
-            ./c/archive_read.c
-            ./c/archive_read_data_into_fd.c
-            ./c/archive_read_disk_entry_from_file.c
-            ./c/archive_read_disk_posix.c
-            ./c/archive_read_disk_set_standard_lookup.c
-            ./c/archive_read_disk_windows.c
-            ./c/archive_read_extract2.c
-            ./c/archive_read_extract.c
-            ./c/archive_read_open_fd.c
-            ./c/archive_read_open_file.c
-            ./c/archive_read_open_filename.c
-            ./c/archive_read_open_memory.c
-            ./c/archive_read_set_format.c
-            ./c/archive_read_set_options.c
-            ./c/archive_read_support_filter_all.c
-            ./c/archive_read_support_filter_by_code.c
-            ./c/archive_read_support_filter_bzip2.c
-            ./c/archive_read_support_filter_compress.c
-            ./c/archive_read_support_filter_grzip.c
-            ./c/archive_read_support_filter_gzip.c
-            ./c/archive_read_support_filter_lrzip.c
-            ./c/archive_read_support_filter_lz4.c
-            ./c/archive_read_support_filter_lzop.c
-            ./c/archive_read_support_filter_none.c
-            ./c/archive_read_support_filter_program.c
-            ./c/archive_read_support_filter_rpm.c
-            ./c/archive_read_support_filter_uu.c
-            ./c/archive_read_support_filter_xz.c
-            ./c/archive_read_support_filter_zstd.c
-            ./c/archive_read_support_format_7zip.c
-            ./c/archive_read_support_format_all.c
-            ./c/archive_read_support_format_ar.c
-            ./c/archive_read_support_format_by_code.c
-            ./c/archive_read_support_format_cab.c
-            ./c/archive_read_support_format_cpio.c
-            ./c/archive_read_support_format_empty.c
-            ./c/archive_read_support_format_iso9660.c
-            ./c/archive_read_support_format_lha.c
-            ./c/archive_read_support_format_mtree.c
-            ./c/archive_read_support_format_rar5.c
-            ./c/archive_read_support_format_rar.c
-            ./c/archive_read_support_format_raw.c
-            ./c/archive_read_support_format_tar.c
-            ./c/archive_read_support_format_warc.c
-            ./c/archive_read_support_format_xar.c
-            ./c/archive_read_support_format_zip.c
-            ./c/archive_string.c
-            ./c/archive_string_sprintf.c
-            ./c/archive_util.c
-            ./c/archive_version_details.c
-            ./c/archive_virtual.c
-            ./c/archive_windows.c
-            ./c/archive_write_add_filter_b64encode.c
-            ./c/archive_write_add_filter_by_name.c
-            ./c/archive_write_add_filter_bzip2.c
-            ./c/archive_write_add_filter.c
-            ./c/archive_write_add_filter_compress.c
-            ./c/archive_write_add_filter_grzip.c
-            ./c/archive_write_add_filter_gzip.c
-            ./c/archive_write_add_filter_lrzip.c
-            ./c/archive_write_add_filter_lz4.c
-            ./c/archive_write_add_filter_lzop.c
-            ./c/archive_write_add_filter_none.c
-            ./c/archive_write_add_filter_program.c
-            ./c/archive_write_add_filter_uuencode.c
-            ./c/archive_write_add_filter_xz.c
-            ./c/archive_write_add_filter_zstd.c
-            ./c/archive_write.c
-            ./c/archive_write_disk_posix.c
-            ./c/archive_write_disk_set_standard_lookup.c
-            ./c/archive_write_disk_windows.c
-            ./c/archive_write_open_fd.c
-            ./c/archive_write_open_file.c
-            ./c/archive_write_open_filename.c
-            ./c/archive_write_open_memory.c
-            ./c/archive_write_set_format_7zip.c
-            ./c/archive_write_set_format_ar.c
-            ./c/archive_write_set_format_by_name.c
-            ./c/archive_write_set_format.c
-            ./c/archive_write_set_format_cpio.c
-            ./c/archive_write_set_format_cpio_binary.c
-            ./c/archive_write_set_format_cpio_newc.c
-            ./c/archive_write_set_format_cpio_odc.c
-            ./c/archive_write_set_format_filter_by_ext.c
-            ./c/archive_write_set_format_gnutar.c
-            ./c/archive_write_set_format_iso9660.c
-            ./c/archive_write_set_format_mtree.c
-            ./c/archive_write_set_format_pax.c
-            ./c/archive_write_set_format_raw.c
-            ./c/archive_write_set_format_shar.c
-            ./c/archive_write_set_format_ustar.c
-            ./c/archive_write_set_format_v7tar.c
-            ./c/archive_write_set_format_warc.c
-            ./c/archive_write_set_format_xar.c
-            ./c/archive_write_set_format_zip.c
-            ./c/archive_write_set_options.c
-            ./c/archive_write_set_passphrase.c
-            ./c/filter_fork_posix.c
-            ./c/filter_fork_windows.c
-            ./c/xxhash.c
-            ./c/zlib/adler32.c
-            ./c/zlib/crc32.c
-            ./c/zlib/deflate.c
-            ./c/zlib/inffast.c
-            ./c/zlib/zutil.c
-            ./c/zlib/compress.c
-            ./c/zlib/infback.c
-            ./c/zlib/inflate.c
-            ./c/zlib/inftrees.c
-            ./c/zlib/trees.c
-            ./c/zlib/uncompr.c
-
-        include-dirs: c/ c/zlib/
-
-        if os(osx)
-            include-dirs: c/autoconf-darwin
-
-        else
-            if os(linux)
-                include-dirs: c/autoconf-linux
-
-            else
-                if os(freebsd)
-                    include-dirs: c/autoconf-freebsd
-
-                else
-                    if os(windows)
-                        include-dirs: c/autoconf-windows
-
-                    else
-                        buildable:     False
-                        build-depends: unbuildable <0
-
+    if flag(system-libarchive)
+        pkgconfig-depends: libarchive >=3.8.2 && <4.0
     else
-        pkgconfig-depends: libarchive (==3.6.0 || >3.6.0) && <4.0
+        build-depends: libarchive-clib >=3.8.2 && <4.0
 
+    includes:
+        archive.h
+        archive_entry.h
+
 executable archive
     main-is:          Main.hs
     hs-source-dirs:   exe
@@ -302,7 +130,7 @@
         libarchive,
         lzma-static,
         time,
-        zlib ^>=0.6.2.2
+        zlib ^>=0.7.1.1
 
     if flag(no-exe)
         buildable: False
@@ -333,6 +161,10 @@
         composition-prelude >=2.0.5.0,
         pathological-bytestrings
 
+    if os(windows)
+        build-depends:
+            hspec-core
+
     if flag(low-memory)
         cpp-options: -DLOW_MEMORY
 
@@ -361,7 +193,7 @@
         libarchive,
         criterion,
         bytestring,
-        tar,
+        tar >=0.6.0.0,
         temporary
 
     if impl(ghc >=8.0)
diff --git a/src/Codec/Archive/Foreign/Archive.chs b/src/Codec/Archive/Foreign/Archive.chs
--- a/src/Codec/Archive/Foreign/Archive.chs
+++ b/src/Codec/Archive/Foreign/Archive.chs
@@ -12,6 +12,23 @@
                                      , archiveBzlibVersion
                                      , archiveLiblz4Version
                                      , archiveLibzstdVersion
+                                     , archiveLiblzo2Version
+                                     , archiveLibexpatVersion
+                                     , archiveLibbsdxmlVersion
+                                     , archiveLibxml2Version
+                                     , archiveMbedtlsVersion
+                                     , archiveNettleVersion
+                                     , archiveOpensslVersion
+                                     , archiveLibmdVersion
+                                     , archiveCommoncryptoVersion
+                                     , archiveCngVersion
+                                     , archiveWincryptVersion
+                                     , archiveLibrichaclVersion
+                                     , archiveLibaclVersion
+                                     , archiveLibattrVersion
+                                     , archiveLibiconvVersion
+                                     , archiveLibpcreVersion
+                                     , archiveLibpcre2Version
                                      -- * Miscellany
                                      , archiveErrorString
                                      , archiveFormatName
@@ -162,6 +179,10 @@
                                      , archiveWriteSetFormatFilterByExtDef
                                      , archiveWriteZipSetCompressionDeflate
                                      , archiveWriteZipSetCompressionStore
+                                     , archiveWriteZipSetCompressionLzma
+                                     , archiveWriteZipSetCompressionXz
+                                     , archiveWriteZipSetCompressionBzip2
+                                     , archiveWriteZipSetCompressionZstd
                                      , archiveWriteOpen2
                                      , archiveWriteOpenFd
                                      , archiveWriteOpenFilenameW
@@ -412,6 +433,23 @@
 {# fun archive_bzlib_version as ^ {} -> `CString' #}
 {# fun archive_liblz4_version as ^ {} -> `CString' #}
 {# fun archive_libzstd_version as ^ {} -> `CString' #}
+{# fun archive_liblzo2_version as ^ {} -> `CString' #}
+{# fun archive_libexpat_version as ^ {} -> `CString' #}
+{# fun archive_libbsdxml_version as ^ {} -> `CString' #}
+{# fun archive_libxml2_version as ^ {} -> `CString' #}
+{# fun archive_mbedtls_version as ^ {} -> `CString' #}
+{# fun archive_nettle_version as ^ {} -> `CString' #}
+{# fun archive_openssl_version as ^ {} -> `CString' #}
+{# fun archive_libmd_version as ^ {} -> `CString' #}
+{# fun archive_commoncrypto_version as ^ {} -> `CString' #}
+{# fun archive_cng_version as ^ {} -> `CString' #}
+{# fun archive_wincrypt_version as ^ {} -> `CString' #}
+{# fun archive_librichacl_version as ^ {} -> `CString' #}
+{# fun archive_libacl_version as ^ {} -> `CString' #}
+{# fun archive_libattr_version as ^ {} -> `CString' #}
+{# fun archive_libiconv_version as ^ {} -> `CString' #}
+{# fun archive_libpcre_version as ^ {} -> `CString' #}
+{# fun archive_libpcre2_version as ^ {} -> `CString' #}
 
 {# fun archive_error_string as ^ { `ArchivePtr' } -> `CString' #}
 {# fun archive_format_name as ^ { `ArchivePtr' } -> `CString' #}
@@ -565,6 +603,10 @@
 {# fun archive_write_set_format_filter_by_ext_def as ^ { `ArchivePtr', `CString', `CString' } -> `ArchiveResult' #}
 {# fun archive_write_zip_set_compression_deflate as ^ { `ArchivePtr' } -> `ArchiveResult' #}
 {# fun archive_write_zip_set_compression_store as ^ { `ArchivePtr' } -> `ArchiveResult' #}
+{# fun archive_write_zip_set_compression_lzma as ^ { `ArchivePtr' } -> `ArchiveResult' #}
+{# fun archive_write_zip_set_compression_xz as ^ { `ArchivePtr' } -> `ArchiveResult' #}
+{# fun archive_write_zip_set_compression_bzip2 as ^ { `ArchivePtr' } -> `ArchiveResult' #}
+{# fun archive_write_zip_set_compression_zstd as ^ { `ArchivePtr' } -> `ArchiveResult' #}
 {# fun archive_write_open as ^ { `ArchivePtr'
                                , castPtr `Ptr a'
                                , castFunPtr `FunPtr (ArchiveOpenCallbackRaw a)'
