packages feed

libarchive 3.0.4.2 → 3.0.5.0

raw patch · 200 files changed

+61/−147099 lines, 200 filesdep +hspec-coredep +libarchive-clibdep −unbuildabledep ~tardep ~zlibnew-uploader

Dependencies added: hspec-core, libarchive-clib

Dependencies removed: unbuildable

Dependency ranges changed: tar, zlib

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # libarchive +# 3.0.5.0++  * use libarchive-clib package+ # 3.0.4.2    * Package bounds for Hackage
bench/Bench.hs view
@@ -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
− c/archive.h
@@ -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 */
− c/archive_acl.c
@@ -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)++;-}
− c/archive_acl_private.h
@@ -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 */
− c/archive_blake2.h
@@ -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
− c/archive_blake2_impl.h
@@ -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
− c/archive_blake2s_ref.c
@@ -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
− c/archive_blake2sp_ref.c
@@ -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
− c/archive_check_magic.c
@@ -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;-}
− c/archive_cmdline.c
@@ -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);-}-
− c/archive_cmdline_private.h
@@ -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
− c/archive_crc32.h
@@ -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
− c/archive_cryptor.c
@@ -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,-};
− c/archive_cryptor_private.h
@@ -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
− c/archive_digest.c
@@ -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-};
− c/archive_digest_private.h
@@ -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
− c/archive_disk_acl_darwin.c
@@ -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 */
− c/archive_disk_acl_freebsd.c
@@ -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 */
− c/archive_disk_acl_linux.c
@@ -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 */
− c/archive_disk_acl_sunos.c
@@ -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 */
− c/archive_endian.h
@@ -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
− c/archive_entry.c
@@ -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
− c/archive_entry.h
@@ -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 */
− c/archive_entry_copy_bhfi.c
@@ -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
− c/archive_entry_copy_stat.c
@@ -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);-}
− c/archive_entry_link_resolver.c
@@ -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);-}
− c/archive_entry_locale.h
@@ -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 */
− c/archive_entry_private.h
@@ -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 */
− c/archive_entry_sparse.c
@@ -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- */
− c/archive_entry_stat.c
@@ -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);-}
− c/archive_entry_strmode.c
@@ -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);-}
− c/archive_entry_xattr.c
@@ -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- */
− c/archive_getdate.c
@@ -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) */
− c/archive_getdate.h
@@ -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
− c/archive_hmac.c
@@ -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,-};
− c/archive_hmac_private.h
@@ -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 */
− c/archive_match.c
@@ -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);-}-
− c/archive_openssl_evp_private.h
@@ -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
− c/archive_openssl_hmac_private.h
@@ -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
− c/archive_options.c
@@ -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;-}-
− c/archive_options_private.h
@@ -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
− c/archive_pack_dev.c
@@ -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);-}
− c/archive_pack_dev.h
@@ -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 */
− c/archive_pathmatch.c
@@ -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));-}
− c/archive_pathmatch.h
@@ -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
− c/archive_platform.h
@@ -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 */
− c/archive_platform_acl.h
@@ -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 */
− c/archive_platform_xattr.h
@@ -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 */
− c/archive_ppmd7.c
@@ -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-};
− c/archive_ppmd7_private.h
@@ -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
− c/archive_ppmd8.c
@@ -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,-};
− c/archive_ppmd8_private.h
@@ -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
− c/archive_ppmd_private.h
@@ -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
− c/archive_private.h
@@ -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
− c/archive_random.c
@@ -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 */
− c/archive_random_private.h
@@ -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 */
− c/archive_rb.c
@@ -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;-}
− c/archive_rb.h
@@ -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_*/
− c/archive_read.c
@@ -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;-}
− c/archive_read_add_passphrase.c
@@ -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);-}
− c/archive_read_append_filter.c
@@ -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;-}
− c/archive_read_data_into_fd.c
@@ -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);-}
− c/archive_read_disk_entry_from_file.c
@@ -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__) */-
− c/archive_read_disk_posix.c
@@ -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
− c/archive_read_disk_private.h
@@ -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
− c/archive_read_disk_set_standard_lookup.c
@@ -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__) */
− c/archive_read_disk_windows.c
@@ -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
− c/archive_read_extract.c
@@ -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));-}
− c/archive_read_extract2.c
@@ -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);-	}-}
− c/archive_read_open_fd.c
@@ -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);-}
− c/archive_read_open_file.c
@@ -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);-}
− c/archive_read_open_filename.c
@@ -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);-}
− c/archive_read_open_memory.c
@@ -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);-}
− c/archive_read_private.h
@@ -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
− c/archive_read_set_format.c
@@ -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;-}
− c/archive_read_set_options.c
@@ -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);-}
− c/archive_read_support_filter_all.c
@@ -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);-}
− c/archive_read_support_filter_by_code.c
@@ -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);-}
− c/archive_read_support_filter_bzip2.c
@@ -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 */
− c/archive_read_support_filter_compress.c
@@ -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]);-}
− c/archive_read_support_filter_grzip.c
@@ -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);-}
− c/archive_read_support_filter_gzip.c
@@ -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 */
− c/archive_read_support_filter_lrzip.c
@@ -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);-}
− c/archive_read_support_filter_lz4.c
@@ -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 */
− c/archive_read_support_filter_lzop.c
@@ -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
− c/archive_read_support_filter_none.c
@@ -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);-}
− c/archive_read_support_filter_program.c
@@ -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);-}
− c/archive_read_support_filter_rpm.c
@@ -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);-}-
− c/archive_read_support_filter_uu.c
@@ -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);-}-
− c/archive_read_support_filter_xz.c
@@ -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 */
− c/archive_read_support_filter_zstd.c
@@ -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 */
− c/archive_read_support_format_7zip.c
@@ -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);-}-
− c/archive_read_support_format_all.c
@@ -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);-}
− c/archive_read_support_format_ar.c
@@ -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);-}
− c/archive_read_support_format_by_code.c
@@ -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);-}
− c/archive_read_support_format_cab.c
@@ -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);-}
− c/archive_read_support_format_cpio.c
@@ -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);-}
− c/archive_read_support_format_empty.c
@@ -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);-}
− c/archive_read_support_format_iso9660.c
@@ -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
− c/archive_read_support_format_lha.c
@@ -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));-}-
− c/archive_read_support_format_mtree.c
@@ -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;-	}-}
− c/archive_read_support_format_rar.c
@@ -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);-}
− c/archive_read_support_format_rar5.c
@@ -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;-}
− c/archive_read_support_format_raw.c
@@ -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);-}
− c/archive_read_support_format_tar.c
@@ -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);-}
− c/archive_read_support_format_warc.c
@@ -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 */
− c/archive_read_support_format_xar.c
@@ -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 */
− c/archive_read_support_format_zip.c
@@ -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:*/
− c/archive_string.c
@@ -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);-}
− c/archive_string.h
@@ -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
− c/archive_string_composition.h
@@ -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 */-
− c/archive_string_sprintf.c
@@ -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);-		}-	}-}
− c/archive_util.c
@@ -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);-}
− c/archive_version_details.c
@@ -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-}
− c/archive_virtual.c
@@ -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));-}
− c/archive_windows.c
@@ -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__ */
− c/archive_windows.h
@@ -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 */
− c/archive_write.c
@@ -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;-}
− c/archive_write_add_filter.c
@@ -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);-}
− c/archive_write_add_filter_b64encode.c
@@ -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);-}-
− c/archive_write_add_filter_by_name.c
@@ -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);-}
− c/archive_write_add_filter_bzip2.c
@@ -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 */
− c/archive_write_add_filter_compress.c
@@ -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);-}
− c/archive_write_add_filter_grzip.c
@@ -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);-}
− c/archive_write_add_filter_gzip.c
@@ -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 */
− c/archive_write_add_filter_lrzip.c
@@ -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);-}
− c/archive_write_add_filter_lz4.c
@@ -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 */
− c/archive_write_add_filter_lzop.c
@@ -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
− c/archive_write_add_filter_none.c
@@ -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);-}
− c/archive_write_add_filter_program.c
@@ -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;-}-
− c/archive_write_add_filter_uuencode.c
@@ -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);-}-
− c/archive_write_add_filter_xz.c
@@ -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 */
− c/archive_write_add_filter_zstd.c
@@ -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 */
− c/archive_write_disk_posix.c
@@ -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__ */-
− c/archive_write_disk_private.h
@@ -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
− c/archive_write_disk_set_standard_lookup.c
@@ -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;-}
− c/archive_write_disk_windows.c
@@ -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__ */-
− c/archive_write_open_fd.c
@@ -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);-}
− c/archive_write_open_file.c
@@ -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);-}
− c/archive_write_open_filename.c
@@ -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);-}
− c/archive_write_open_memory.c
@@ -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);-}
− c/archive_write_private.h
@@ -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
− c/archive_write_set_format.c
@@ -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));-	}-}
− c/archive_write_set_format_7zip.c
@@ -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);-}--
− c/archive_write_set_format_ar.c
@@ -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);-}
− c/archive_write_set_format_by_name.c
@@ -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);-}
− c/archive_write_set_format_cpio.c
@@ -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);-}
− c/archive_write_set_format_cpio_binary.c
@@ -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));-}
− c/archive_write_set_format_cpio_newc.c
@@ -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));-}
− c/archive_write_set_format_cpio_odc.c
@@ -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));-}
− c/archive_write_set_format_filter_by_ext.c
@@ -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);-}----
− c/archive_write_set_format_gnutar.c
@@ -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);-}
− c/archive_write_set_format_iso9660.c
@@ -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 */-
− c/archive_write_set_format_mtree.c
@@ -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);-}
− c/archive_write_set_format_pax.c
@@ -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;-}
− c/archive_write_set_format_private.h
@@ -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
− c/archive_write_set_format_raw.c
@@ -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);-}
− c/archive_write_set_format_shar.c
@@ -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);-}
− c/archive_write_set_format_ustar.c
@@ -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);-}
− c/archive_write_set_format_v7tar.c
@@ -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);-}
− c/archive_write_set_format_warc.c
@@ -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 */
− c/archive_write_set_format_xar.c
@@ -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 */
− c/archive_write_set_format_zip.c
@@ -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);-}
− c/archive_write_set_options.c
@@ -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);-}
− c/archive_write_set_passphrase.c
@@ -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);-}
− c/archive_xxhash.h
@@ -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
− c/autoconf-darwin/config.h
@@ -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
− c/autoconf-freebsd/config.h
@@ -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
− c/autoconf-linux/config.h
@@ -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
− c/autoconf-windows/config.h
@@ -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
− c/config_freebsd.h
@@ -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
− c/filter_fork.h
@@ -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
− c/filter_fork_posix.c
@@ -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) */
− c/filter_fork_windows.c
@@ -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__ */
− c/xxhash.c
@@ -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 */
− c/zlib/adler32.c
@@ -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);-}
− c/zlib/compress.c
@@ -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;-}
− c/zlib/crc32.c
@@ -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);-}
− c/zlib/crc32.h
@@ -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-  }-};
− c/zlib/deflate.c
@@ -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;-}
− c/zlib/deflate.h
@@ -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 */
− c/zlib/gzguts.h
@@ -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
− c/zlib/infback.c
@@ -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;-}
− c/zlib/inffast.c
@@ -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 */
− c/zlib/inffast.h
@@ -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));
− c/zlib/inffixed.h
@@ -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}-    };
− c/zlib/inflate.c
@@ -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);-}
− c/zlib/inflate.h
@@ -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 */-};
− c/zlib/inftrees.c
@@ -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;-}
− c/zlib/inftrees.h
@@ -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));
− c/zlib/trees.c
@@ -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-}
− c/zlib/trees.h
@@ -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-};-
− c/zlib/uncompr.c
@@ -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);-}
− c/zlib/zconf.h
@@ -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 */
− c/zlib/zlib.h
@@ -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 */
− c/zlib/zutil.c
@@ -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 */
− c/zlib/zutil.h
@@ -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 */
libarchive.cabal view
@@ -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)
src/Codec/Archive/Foreign/Archive.chs view
@@ -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)'