summaryrefslogtreecommitdiff
path: root/archivers/libarchive/files/libarchive
diff options
context:
space:
mode:
Diffstat (limited to 'archivers/libarchive/files/libarchive')
-rw-r--r--archivers/libarchive/files/libarchive/archive.h592
-rw-r--r--archivers/libarchive/files/libarchive/archive_endian.h14
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry.315
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry.c83
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry.h89
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_link_resolver.c40
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_private.h21
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_strmode.c5
-rw-r--r--archivers/libarchive/files/libarchive/archive_read.323
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_data_into_fd.c12
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_extract.c28
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_compression_bzip2.c32
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_compression_program.c20
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_ar.c8
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c59
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c663
-rw-r--r--archivers/libarchive/files/libarchive/archive_read_support_format_tar.c2
-rw-r--r--archivers/libarchive/files/libarchive/archive_string.c8
-rw-r--r--archivers/libarchive/files/libarchive/archive_windows.c188
-rw-r--r--archivers/libarchive/files/libarchive/archive_windows.h152
-rw-r--r--archivers/libarchive/files/libarchive/archive_write.36
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk.34
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_disk.c163
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_compression_program.c19
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_ar.c11
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_pax.c79
-rw-r--r--archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c68
-rw-r--r--archivers/libarchive/files/libarchive/config_freebsd.h3
-rw-r--r--archivers/libarchive/files/libarchive/config_windows.h1198
-rw-r--r--archivers/libarchive/files/libarchive/filter_fork.c5
-rw-r--r--archivers/libarchive/files/libarchive/libarchive-formats.58
-rw-r--r--archivers/libarchive/files/libarchive/mtree.59
-rw-r--r--archivers/libarchive/files/libarchive/test/list.h3
-rw-r--r--archivers/libarchive/files/libarchive/test/main.c60
-rw-r--r--archivers/libarchive/files/libarchive/test/test_entry.c5
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_mtree.c10
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.c66
-rw-r--r--archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.tar.uu38
-rw-r--r--archivers/libarchive/files/libarchive/test/test_tar_filenames.c34
-rw-r--r--archivers/libarchive/files/libarchive/test/test_tar_large.c5
-rw-r--r--archivers/libarchive/files/libarchive/test/test_ustar_filenames.c183
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_disk_hardlink.c16
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_ar.c3
-rw-r--r--archivers/libarchive/files/libarchive/test/test_write_format_tar_ustar.c342
44 files changed, 3481 insertions, 911 deletions
diff --git a/archivers/libarchive/files/libarchive/archive.h b/archivers/libarchive/files/libarchive/archive.h
new file mode 100644
index 00000000000..6bfe81eb24a
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive.h
@@ -0,0 +1,592 @@
+/*-
+ * 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: src/lib/libarchive/archive.h.in,v 1.49 2008/03/14 22:19:50 kientzle Exp $
+ */
+
+#ifndef ARCHIVE_H_INCLUDED
+#define ARCHIVE_H_INCLUDED
+
+/*
+ * 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.
+ */
+
+#include <sys/types.h> /* Linux requires this for off_t */
+#if !defined(__WATCOMC__) && !defined(_MSC_VER)
+/* Header unavailable on Watcom C or MS Visual C++. */
+#include <inttypes.h> /* int64_t, etc. */
+#endif
+#include <stdio.h> /* For FILE * */
+
+/* Get appropriate definitions of standard POSIX-style types. */
+/* These should match the types used in 'struct stat' */
+#ifdef _WIN32
+#define __LA_SSIZE_T long
+#define __LA_UID_T unsigned int
+#define __LA_GID_T unsigned int
+#else
+#include <unistd.h> /* ssize_t, uid_t, and gid_t */
+#define __LA_SSIZE_T ssize_t
+#define __LA_UID_T uid_t
+#define __LA_GID_T gid_t
+#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 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 __attribute__((dllimport)) extern
+# else
+# define __LA_DECL __declspec(dllimport)
+# endif
+# endif
+#else
+/* Static libraries or non-Windows needs no special declaration. */
+# define __LA_DECL
+#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.
+ */
+
+/*
+ * 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 >= 2012108.
+ *
+ * This single-number format was introduced with libarchive 1.9.0 in
+ * the libarchive 1.x family and libarchive 2.2.4 in the libarchive
+ * 2.x family. The following may be useful if you really want to do
+ * feature detection for earlier libarchive versions (which defined
+ * ARCHIVE_API_VERSION and ARCHIVE_API_FEATURE instead):
+ *
+ * #ifndef ARCHIVE_VERSION_NUMBER
+ * #define ARCHIVE_VERSION_NUMBER \
+ * (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
+ * #endif
+ */
+#define ARCHIVE_VERSION_NUMBER 2005004
+__LA_DECL int archive_version_number(void);
+
+/*
+ * Textual name/version of the library, useful for version displays.
+ */
+#define ARCHIVE_VERSION_STRING "libarchive 2.5.4b"
+__LA_DECL const char * archive_version_string(void);
+
+#if ARCHIVE_VERSION_NUMBER < 3000000
+/*
+ * Deprecated; these are older names that will be removed in favor of
+ * the simpler definitions above.
+ */
+#define ARCHIVE_VERSION_STAMP ARCHIVE_VERSION_NUMBER
+__LA_DECL int archive_version_stamp(void);
+#define ARCHIVE_LIBRARY_VERSION ARCHIVE_VERSION_STRING
+__LA_DECL const char * archive_version(void);
+#define ARCHIVE_API_VERSION (ARCHIVE_VERSION_NUMBER / 1000000)
+__LA_DECL int archive_api_version(void);
+#define ARCHIVE_API_FEATURE ((ARCHIVE_VERSION_NUMBER / 1000) % 1000)
+__LA_DECL int archive_api_feature(void);
+#endif
+
+#if ARCHIVE_VERSION_NUMBER < 3000000
+/* This should never have been here in the first place. */
+/* Legacy of old tar assumptions, will be removed in libarchive 3.0. */
+#define ARCHIVE_BYTES_PER_RECORD 512
+#define ARCHIVE_DEFAULT_BYTES_PER_BLOCK 10240
+#endif
+
+/* 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 */
+#if ARCHIVE_VERSION_NUMBER < 2000000
+typedef __LA_SSIZE_T archive_skip_callback(struct archive *, void *_client_data,
+ size_t request);
+#else
+typedef off_t archive_skip_callback(struct archive *, void *_client_data,
+ off_t request);
+#endif
+/* 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);
+
+/*
+ * Codes for archive_compression.
+ */
+#define ARCHIVE_COMPRESSION_NONE 0
+#define ARCHIVE_COMPRESSION_GZIP 1
+#define ARCHIVE_COMPRESSION_BZIP2 2
+#define ARCHIVE_COMPRESSION_COMPRESS 3
+#define ARCHIVE_COMPRESSION_PROGRAM 4
+
+/*
+ * 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 formts. (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_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_MTREE_V1 (ARCHIVE_FORMAT_MTREE | 1)
+#define ARCHIVE_FORMAT_MTREE_V2 (ARCHIVE_FORMAT_MTREE | 2)
+
+/*-
+ * 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_finish 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.
+ */
+__LA_DECL int archive_read_support_compression_all(struct archive *);
+__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
+__LA_DECL int archive_read_support_compression_compress(struct archive *);
+__LA_DECL int archive_read_support_compression_gzip(struct archive *);
+__LA_DECL int archive_read_support_compression_none(struct archive *);
+__LA_DECL int archive_read_support_compression_program(struct archive *,
+ const char *command);
+
+__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_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_mtree(struct archive *);
+__LA_DECL int archive_read_support_format_tar(struct archive *);
+__LA_DECL int archive_read_support_format_zip(struct archive *);
+
+
+/* Open the archive using callbacks for archive I/O. */
+__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);
+/* 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);
+/* Read an archive that's stored in memory. */
+__LA_DECL int archive_read_open_memory(struct archive *,
+ 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, 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 **);
+
+/*
+ * Retrieve the byte offset in UNCOMPRESSED data where last-read
+ * header started.
+ */
+__LA_DECL int64_t archive_read_header_position(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);
+/*
+ * 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, off_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_buffer(struct archive *, void *buffer,
+ __LA_SSIZE_T len);
+__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
+
+/*-
+ * 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)
+
+__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 *,
+ dev_t, ino_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_finish will call archive_read_close for you. */
+#if ARCHIVE_VERSION_NUMBER >= 2000000
+__LA_DECL int archive_read_finish(struct archive *);
+#else
+/* Temporarily allow library to compile with either 1.x or 2.0 API. */
+/* Erroneously declared to return void in libarchive 1.x */
+__LA_DECL void archive_read_finish(struct archive *);
+#endif
+
+/*-
+ * To create an archive:
+ * 1) Ask archive_write_new for a 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_finish 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 *, dev_t, ino_t);
+
+__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
+__LA_DECL int archive_write_set_compression_compress(struct archive *);
+__LA_DECL int archive_write_set_compression_gzip(struct archive *);
+__LA_DECL int archive_write_set_compression_none(struct archive *);
+__LA_DECL int archive_write_set_compression_program(struct archive *,
+ const char *cmd);
+/* 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_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_newc(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_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_open(struct archive *, void *,
+ archive_open_callback *, archive_write_callback *,
+ archive_close_callback *);
+__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
+__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
+/* A deprecated synonym for archive_write_open_filename() */
+__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
+__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 *);
+#if ARCHIVE_VERSION_NUMBER >= 2000000
+__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *, const void *, size_t);
+#else
+/* Temporarily allow library to compile with either 1.x or 2.0 API. */
+/* This was erroneously declared to return "int" in libarchive 1.x. */
+__LA_DECL int archive_write_data(struct archive *, const void *, size_t);
+#endif
+__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *, const void *, size_t, off_t);
+__LA_DECL int archive_write_finish_entry(struct archive *);
+__LA_DECL int archive_write_close(struct archive *);
+#if ARCHIVE_VERSION_NUMBER >= 2000000
+__LA_DECL int archive_write_finish(struct archive *);
+#else
+/* Temporarily allow library to compile with either 1.x or 2.0 API. */
+/* Return value was incorrect in libarchive 1.x. */
+__LA_DECL void archive_write_finish(struct archive *);
+#endif
+
+/*-
+ * 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 should set
+ * the compression and format to use.
+ * 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_finish 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 *,
+ dev_t, ino_t);
+/* Set flags to control how the next item gets created. */
+__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_GID_T (*)(void *, const char *, __LA_GID_T),
+ void (* /* cleanup */)(void *));
+__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
+ void * /* private_data */,
+ __LA_UID_T (*)(void *, const char *, __LA_UID_T),
+ void (* /* cleanup */)(void *));
+
+/*
+ * Accessor functions to read/set various information in
+ * the struct archive object:
+ */
+/* Bytes written after compression or read before decompression. */
+__LA_DECL int64_t archive_position_compressed(struct archive *);
+/* Bytes written to compressor or read from decompressor. */
+__LA_DECL int64_t archive_position_uncompressed(struct archive *);
+
+__LA_DECL const char *archive_compression_name(struct archive *);
+__LA_DECL int archive_compression(struct archive *);
+__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_DECL void archive_copy_error(struct archive *dest,
+ struct archive *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* This is meaningless outside of this header. */
+#undef __LA_DECL
+
+#endif /* !ARCHIVE_H_INCLUDED */
diff --git a/archivers/libarchive/files/libarchive/archive_endian.h b/archivers/libarchive/files/libarchive/archive_endian.h
index 259f5de91ea..61af4161c37 100644
--- a/archivers/libarchive/files/libarchive/archive_endian.h
+++ b/archivers/libarchive/files/libarchive/archive_endian.h
@@ -28,9 +28,23 @@
* Borrowed from FreeBSD's <sys/endian.h>
*/
+/* Note: This is a purely internal header! */
+/* Do not use this outside of libarchive internal code! */
+
#ifndef ARCHIVE_ENDIAN_H_INCLUDED
#define ARCHIVE_ENDIAN_H_INCLUDED
+
+/* Watcom C++ doesn't support 'inline' in C code. (For any version?) */
+#if defined( __WATCOMC__ )
+ #define inline
+#endif
+
+/* Visual C++ 6.0 doesn't support 'inline' in C code. (Does VC7? VC8?) */
+#if defined(_MSC_VER)
+ #define inline
+#endif
+
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
static inline uint16_t
diff --git a/archivers/libarchive/files/libarchive/archive_entry.3 b/archivers/libarchive/files/libarchive/archive_entry.3
index 8d96de1fbf4..e2d4ab11770 100644
--- a/archivers/libarchive/files/libarchive/archive_entry.3
+++ b/archivers/libarchive/files/libarchive/archive_entry.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.17 2008/03/14 23:00:53 kientzle Exp $
.\"
-.Dd December 15, 2003
+.Dd May 12, 2008
.Dt archive_entry 3
.Os
.Sh NAME
@@ -40,6 +40,7 @@
.Nm archive_entry_atime_nsec ,
.Nm archive_entry_clear ,
.Nm archive_entry_clone ,
+.Nm archive_entry_copy_fflags_text ,
.Nm archive_entry_copy_fflags_text_w ,
.Nm archive_entry_copy_gname ,
.Nm archive_entry_copy_gname_w ,
@@ -48,6 +49,7 @@
.Nm archive_entry_copy_link ,
.Nm archive_entry_copy_link_w ,
.Nm archive_entry_copy_pathname_w ,
+.Nm archive_entry_copy_sourcepath ,
.Nm archive_entry_copy_stat ,
.Nm archive_entry_copy_symlink ,
.Nm archive_entry_copy_symlink_w ,
@@ -95,6 +97,7 @@
.Nm archive_entry_set_uid ,
.Nm archive_entry_set_uname ,
.Nm archive_entry_size ,
+.Nm archive_entry_sourcepath ,
.Nm archive_entry_stat ,
.Nm archive_entry_symlink ,
.Nm archive_entry_uid ,
@@ -156,6 +159,8 @@
.Fn archive_entry_clear "struct archive_entry *"
.Ft struct archive_entry *
.Fn archive_entry_clone "struct archive_entry *"
+.Ft const char * *
+.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const char *"
.Ft const wchar_t *
.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const wchar_t *"
.Ft void
@@ -167,6 +172,8 @@
.Ft void
.Fn archive_entry_copy_hardlink_w "struct archive_entry *" "const wchar_t *"
.Ft void
+.Fn archive_entry_copy_sourcepath "struct archive_entry *" "const char *"
+.Ft void
.Fn archive_entry_copy_pathname_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_stat "struct archive_entry *" "const struct stat *"
@@ -270,6 +277,8 @@
.Fn archive_entry_set_uname "struct archive_entry *" "const char *"
.Ft int64_t
.Fn archive_entry_size "struct archive_entry *"
+.Ft const char *
+.Fn archive_entry_sourcepath "struct archive_entry *"
.Ft const struct stat *
.Fn archive_entry_stat "struct archive_entry *"
.Ft const char *
@@ -376,8 +385,10 @@ will be ignored.
.Pp
The canonical text format is a comma-separated list of flag names.
The
+.Fn archive_entry_copy_fflags_text
+and
.Fn archive_entry_copy_fflags_text_w
-function parses the provided text and sets the internal bitmap values.
+functions parse the provided text and sets the internal bitmap values.
This is a platform-specific operation; names that are not meaningful
on the current platform will be ignored.
The function returns a pointer to the start of the first name that was not
diff --git a/archivers/libarchive/files/libarchive/archive_entry.c b/archivers/libarchive/files/libarchive/archive_entry.c
index acc57291d45..210685af2b3 100644
--- a/archivers/libarchive/files/libarchive/archive_entry.c
+++ b/archivers/libarchive/files/libarchive/archive_entry.c
@@ -155,6 +155,7 @@ aes_clean(struct aes *aes)
}
archive_string_free(&(aes->aes_mbs));
archive_string_free(&(aes->aes_utf8));
+ aes->aes_set = 0;
}
static void
@@ -162,6 +163,7 @@ aes_copy(struct aes *dest, struct aes *src)
{
wchar_t *wp;
+ dest->aes_set = src->aes_set;
archive_string_copy(&(dest->aes_mbs), &(src->aes_mbs));
archive_string_copy(&(dest->aes_utf8), &(src->aes_utf8));
@@ -178,25 +180,28 @@ aes_copy(struct aes *dest, struct aes *src)
static const char *
aes_get_utf8(struct aes *aes)
{
- if (aes->aes_utf8.s == NULL || aes->aes_utf8.length == 0) {
- if (aes->aes_wcs == NULL)
- return (NULL);
- if (archive_strappend_w_utf8(&(aes->aes_utf8), aes->aes_wcs) == NULL)
- return (NULL);
+ if (aes->aes_set & AES_SET_UTF8)
+ return (aes->aes_utf8.s);
+ if ((aes->aes_set & AES_SET_WCS)
+ && archive_strappend_w_utf8(&(aes->aes_utf8), aes->aes_wcs) != NULL) {
+ aes->aes_set |= AES_SET_UTF8;
+ return (aes->aes_utf8.s);
}
- return (aes->aes_utf8.s);
+ return (NULL);
}
static const char *
aes_get_mbs(struct aes *aes)
{
/* If we already have an MBS form, return that immediately. */
- if (aes->aes_mbs.s != NULL && aes->aes_mbs.length != 0)
+ if (aes->aes_set & AES_SET_MBS)
return (aes->aes_mbs.s);
/* If there's a WCS form, try converting with the native locale. */
- if (aes->aes_wcs != NULL
- && archive_strappend_w_mbs(&(aes->aes_mbs), aes->aes_wcs) != NULL)
+ if ((aes->aes_set & AES_SET_WCS)
+ && archive_strappend_w_mbs(&(aes->aes_mbs), aes->aes_wcs) != NULL) {
+ aes->aes_set |= AES_SET_MBS;
return (aes->aes_mbs.s);
+ }
/* We'll use UTF-8 for MBS if all else fails. */
return (aes_get_utf8(aes));
}
@@ -208,10 +213,10 @@ aes_get_wcs(struct aes *aes)
int r;
/* Return WCS form if we already have it. */
- if (aes->aes_wcs != NULL)
+ if (aes->aes_set & AES_SET_WCS)
return (aes->aes_wcs);
- if (aes->aes_mbs.s != NULL && aes->aes_mbs.length > 0) {
+ if (aes->aes_set & AES_SET_MBS) {
/* Try converting MBS to WCS using native locale. */
/*
* No single byte will be more than one wide character,
@@ -224,14 +229,17 @@ aes_get_wcs(struct aes *aes)
__archive_errx(1, "No memory for aes_get_wcs()");
r = mbstowcs(w, aes->aes_mbs.s, wcs_length);
w[wcs_length] = 0;
- if (r > 0)
+ if (r > 0) {
+ aes->aes_set |= AES_SET_WCS;
return (aes->aes_wcs = w);
+ }
free(w);
}
- if (aes->aes_utf8.s != NULL && aes->aes_utf8.length > 0) {
+ if (aes->aes_set & AES_SET_UTF8) {
/* Try converting UTF8 to WCS. */
aes->aes_wcs = __archive_string_utf8_w(&(aes->aes_utf8));
+ aes->aes_set |= AES_SET_WCS;
return (aes->aes_wcs);
}
return (NULL);
@@ -246,6 +254,11 @@ aes_set_mbs(struct aes *aes, const char *mbs)
static int
aes_copy_mbs(struct aes *aes, const char *mbs)
{
+ if (mbs == NULL) {
+ aes->aes_set = 0;
+ return (0);
+ }
+ aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */
archive_strcpy(&(aes->aes_mbs), mbs);
archive_string_empty(&(aes->aes_utf8));
if (aes->aes_wcs) {
@@ -268,6 +281,11 @@ aes_copy_mbs(struct aes *aes, const char *mbs)
static int
aes_update_utf8(struct aes *aes, const char *utf8)
{
+ if (utf8 == NULL) {
+ aes->aes_set = 0;
+ return (1); /* Succeeded in clearing everything. */
+ }
+
/* Save the UTF8 string. */
archive_strcpy(&(aes->aes_utf8), utf8);
@@ -278,18 +296,24 @@ aes_update_utf8(struct aes *aes, const char *utf8)
aes->aes_wcs = NULL;
}
- /* TODO: We should just do a UTF-8 to MBS conversion here.
- * That would be faster, use less space, and give the same
- * information. */
+ aes->aes_set = AES_SET_UTF8; /* Only UTF8 is set now. */
+
+ /* TODO: We should just do a direct UTF-8 to MBS conversion
+ * here. That would be faster, use less space, and give the
+ * same information. (If a UTF-8 to MBS conversion succeeds,
+ * then UTF-8->WCS and Unicode->MBS conversions will both
+ * succeed.) */
/* Try converting UTF8 to WCS, return false on failure. */
aes->aes_wcs = __archive_string_utf8_w(&(aes->aes_utf8));
if (aes->aes_wcs == NULL)
return (0);
+ aes->aes_set = AES_SET_UTF8 | AES_SET_WCS; /* Both UTF8 and WCS set. */
/* Try converting WCS to MBS, return false on failure. */
if (archive_strappend_w_mbs(&(aes->aes_mbs), aes->aes_wcs) == NULL)
return (0);
+ aes->aes_set = AES_SET_UTF8 | AES_SET_WCS | AES_SET_MBS;
/* All conversions succeeded. */
return (1);
@@ -298,7 +322,7 @@ aes_update_utf8(struct aes *aes, const char *utf8)
static int
aes_copy_wcs(struct aes *aes, const wchar_t *wcs)
{
- return aes_copy_wcs_len(aes, wcs, wcslen(wcs));
+ return aes_copy_wcs_len(aes, wcs, wcs == NULL ? 0 : wcslen(wcs));
}
static int
@@ -306,6 +330,11 @@ aes_copy_wcs_len(struct aes *aes, const wchar_t *wcs, size_t len)
{
wchar_t *w;
+ 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));
if (aes->aes_wcs) {
@@ -623,6 +652,12 @@ archive_entry_size(struct archive_entry *entry)
}
const char *
+archive_entry_sourcepath(struct archive_entry *entry)
+{
+ return (aes_get_mbs(&entry->ae_sourcepath));
+}
+
+const char *
archive_entry_symlink(struct archive_entry *entry)
{
if (!entry->ae_symlinkset)
@@ -922,6 +957,12 @@ archive_entry_set_size(struct archive_entry *entry, int64_t s)
}
void
+archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
+{
+ aes_set_mbs(&entry->ae_sourcepath, path);
+}
+
+void
archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
{
aes_set_mbs(&entry->ae_symlink, linkname);
@@ -1889,13 +1930,13 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
while (*end != '\0' && *end != '\t' &&
*end != ' ' && *end != ',')
end++;
- for (flag = flags; flag->wname != NULL; flag++) {
- if (memcmp(start, flag->wname, end - start) == 0) {
+ for (flag = flags; flag->name != NULL; flag++) {
+ if (memcmp(start, flag->name, end - start) == 0) {
/* Matched "noXXXX", so reverse the sense. */
clear |= flag->set;
set |= flag->clear;
break;
- } else if (memcmp(start, flag->wname + 2, end - start)
+ } else if (memcmp(start, flag->name + 2, end - start)
== 0) {
/* Matched "XXXX", so don't reverse. */
set |= flag->set;
@@ -1904,7 +1945,7 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
}
}
/* Ignore unknown flag names. */
- if (flag->wname == NULL && failed == NULL)
+ if (flag->name == NULL && failed == NULL)
failed = start;
/* Find start of next token. */
diff --git a/archivers/libarchive/files/libarchive/archive_entry.h b/archivers/libarchive/files/libarchive/archive_entry.h
index ba2255e220b..f8601b9ee28 100644
--- a/archivers/libarchive/files/libarchive/archive_entry.h
+++ b/archivers/libarchive/files/libarchive/archive_entry.h
@@ -28,6 +28,14 @@
#ifndef ARCHIVE_ENTRY_H_INCLUDED
#define ARCHIVE_ENTRY_H_INCLUDED
+/*
+ * 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 <time.h>
@@ -37,19 +45,26 @@
#ifdef _WIN32
#define __LA_UID_T unsigned int
#define __LA_GID_T unsigned int
-#define __LA_INO_T unsigned int
#define __LA_DEV_T unsigned int
#define __LA_MODE_T unsigned short
#else
#include <unistd.h>
#define __LA_UID_T uid_t
#define __LA_GID_T gid_t
-#define __LA_INO_T ino_t
#define __LA_DEV_T dev_t
#define __LA_MODE_T mode_t
#endif
/*
+ * XXX Is this defined for all Windows compilers? If so, in what
+ * header? It would be nice to remove the __LA_INO_T indirection and
+ * just use plain ino_t everywhere. Likewise for the other types just
+ * above.
+ */
+#define __LA_INO_T ino_t
+
+
+/*
* 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.
@@ -69,7 +84,7 @@
# endif
# endif
#else
-/* Static libraries and shared libraries on non-Windows. */
+/* Static libraries on all platforms and shared libraries on non-Windows. */
# define __LA_DECL
#endif
@@ -80,7 +95,7 @@ extern "C" {
/*
* Description of an archive entry.
*
- * Basically, a "struct stat" with a few text fields added in.
+ * 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,
@@ -139,40 +154,41 @@ __LA_DECL struct archive_entry *archive_entry_new(void);
* Retrieve fields from an archive_entry.
*/
-__LA_DECL time_t archive_entry_atime(struct archive_entry *);
-__LA_DECL long archive_entry_atime_nsec(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 dev_t archive_entry_dev(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 *,
+__LA_DECL time_t archive_entry_atime(struct archive_entry *);
+__LA_DECL long archive_entry_atime_nsec(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 dev_t archive_entry_dev(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_GID_T archive_entry_gid(struct archive_entry *);
-__LA_DECL const char *archive_entry_gname(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 wchar_t *archive_entry_hardlink_w(struct archive_entry *);
-__LA_DECL __LA_INO_T archive_entry_ino(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 unsigned int archive_entry_nlink(struct archive_entry *);
-__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
-__LA_DECL const wchar_t *archive_entry_pathname_w(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 int64_t archive_entry_size(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 wchar_t *archive_entry_symlink_w(struct archive_entry *);
-__LA_DECL __LA_UID_T archive_entry_uid(struct archive_entry *);
-__LA_DECL const char *archive_entry_uname(struct archive_entry *);
-__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
+__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
+__LA_DECL __LA_GID_T archive_entry_gid(struct archive_entry *);
+__LA_DECL const char *archive_entry_gname(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 wchar_t *archive_entry_hardlink_w(struct archive_entry *);
+__LA_DECL __LA_INO_T archive_entry_ino(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 unsigned int archive_entry_nlink(struct archive_entry *);
+__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_pathname_w(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 int64_t archive_entry_size(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 wchar_t *archive_entry_symlink_w(struct archive_entry *);
+__LA_DECL __LA_UID_T archive_entry_uid(struct archive_entry *);
+__LA_DECL const char *archive_entry_uname(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
/*
* Set fields in an archive_entry.
@@ -220,6 +236,7 @@ __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 *, int64_t);
+__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_symlink(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 *);
diff --git a/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c b/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
index 0df9ff92e68..c0770c239de 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
+++ b/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
@@ -60,8 +60,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_link_resolver.c,v 1.1 2007/
/* 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_OLD_CPIO 1
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 2
+#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
@@ -130,6 +131,9 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
break;
}
break;
+ case ARCHIVE_FORMAT_MTREE:
+ res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
+ break;
case ARCHIVE_FORMAT_TAR:
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
break;
@@ -144,6 +148,9 @@ archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
{
struct links_entry *le;
+ if (res == NULL)
+ return;
+
if (res->buckets != NULL) {
while ((le = next_entry(res)) != NULL)
archive_entry_free(le->entry);
@@ -164,8 +171,10 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
if (*e == NULL) {
le = next_entry(res);
- if (le != NULL)
+ if (le != NULL) {
*e = le->entry;
+ le->entry = NULL;
+ }
return;
}
@@ -178,7 +187,15 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
le = find_entry(res, *e);
if (le != NULL) {
archive_entry_set_size(*e, 0);
- archive_entry_set_hardlink(*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);
@@ -198,12 +215,14 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
le->entry = t;
/* Make the old entry into a hardlink. */
archive_entry_set_size(*e, 0);
- archive_entry_set_hardlink(*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)
+ if (le->links == 0) {
*f = le->entry;
+ le->entry = NULL;
+ }
} else {
/*
* If we haven't seen it, tuck it away
@@ -232,6 +251,7 @@ find_entry(struct archive_entry_linkresolver *res,
/* 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;
}
@@ -248,8 +268,8 @@ find_entry(struct archive_entry_linkresolver *res,
bucket = hash % res->number_buckets;
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
if (le->hash == hash
- && dev == archive_entry_dev(le->entry)
- && ino == archive_entry_ino(le->entry)) {
+ && dev == archive_entry_dev(le->canonical)
+ && ino == archive_entry_ino(le->canonical)) {
/*
* Decrement link count each time and release
* the entry if it hits zero. This saves
@@ -320,7 +340,8 @@ insert_entry(struct archive_entry_linkresolver *res,
le = malloc(sizeof(struct links_entry));
if (le == NULL)
return (NULL);
- le->entry = entry;
+ memset(le, 0, sizeof(*le));
+ 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)
@@ -338,7 +359,6 @@ insert_entry(struct archive_entry_linkresolver *res,
res->buckets[bucket] = le;
le->hash = hash;
le->links = archive_entry_nlink(entry) - 1;
- le->canonical = archive_entry_clone(entry);
return (le);
}
diff --git a/archivers/libarchive/files/libarchive/archive_entry_private.h b/archivers/libarchive/files/libarchive/archive_entry_private.h
index d8dd9b6b70d..f893fb982ae 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_private.h
+++ b/archivers/libarchive/files/libarchive/archive_entry_private.h
@@ -22,7 +22,7 @@
* (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_entry_private.h,v 1.2 2007/12/30 04:58:21 kientzle Exp $
+ * $FreeBSD: src/lib/libarchive/archive_entry_private.h,v 1.3 2008/03/31 06:24:39 kientzle Exp $
*/
#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
@@ -33,13 +33,20 @@
/*
* Handle wide character (i.e., Unicode) and non-wide character
* strings transparently.
- *
*/
struct aes {
struct archive_string aes_mbs;
struct archive_string aes_utf8;
const wchar_t *aes_wcs;
+ /* 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
};
struct ae_acl {
@@ -129,8 +136,6 @@ struct archive_entry {
dev_t aest_rdevminor;
} ae_stat;
-
-
/*
* Use aes here so that we get transparent mbs<->wcs conversions.
*/
@@ -145,15 +150,21 @@ struct archive_entry {
unsigned char ae_hardlinkset;
unsigned char ae_symlinkset;
+ /* Not used within libarchive; useful for some clients. */
+ struct aes ae_sourcepath; /* Path this entry is sourced from. */
+
+ /* ACL support. */
struct ae_acl *acl_head;
struct ae_acl *acl_p;
int acl_state; /* See acl_next for details. */
wchar_t *acl_text_w;
+ /* extattr support. */
struct ae_xattr *xattr_head;
struct ae_xattr *xattr_p;
- char strmode[11];
+ /* Miscellaneous. */
+ char strmode[12];
};
diff --git a/archivers/libarchive/files/libarchive/archive_entry_strmode.c b/archivers/libarchive/files/libarchive/archive_entry_strmode.c
index dc08d9721a6..cfe6ae33baa 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_strmode.c
+++ b/archivers/libarchive/files/libarchive/archive_entry_strmode.c
@@ -24,7 +24,7 @@
*/
#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.2 2008/02/19 05:49:02 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.3 2008/05/23 04:57:28 cperciva Exp $");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.2 2008/02/19
const char *
archive_entry_strmode(struct archive_entry *entry)
{
- static const char *perms = "?rwxrwxrwx ";
static const mode_t permbits[] =
{ 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 };
char *bp = entry->strmode;
@@ -47,7 +46,7 @@ archive_entry_strmode(struct archive_entry *entry)
int i;
/* Fill in a default string, then selectively override. */
- strcpy(bp, perms);
+ strcpy(bp, "?rwxrwxrwx ");
mode = archive_entry_mode(entry);
switch (archive_entry_filetype(entry)) {
diff --git a/archivers/libarchive/files/libarchive/archive_read.3 b/archivers/libarchive/files/libarchive/archive_read.3
index e15c904a712..dbbe1f7f1e6 100644
--- a/archivers/libarchive/files/libarchive/archive_read.3
+++ b/archivers/libarchive/files/libarchive/archive_read.3
@@ -56,6 +56,7 @@
.\" #endif
.Nm archive_read_data_into_fd ,
.Nm archive_read_extract ,
+.Nm archive_read_extract2 ,
.Nm archive_read_extract_set_progress_callback ,
.Nm archive_read_close ,
.Nm archive_read_finish
@@ -145,6 +146,12 @@
.Fa "struct archive_entry *"
.Fa "int flags"
.Fc
+.Ft int
+.Fo archive_read_extract2
+.Fa "struct archive *src"
+.Fa "struct archive_entry *"
+.Fa "struct archive *dest"
+.Fc
.Ft void
.Fo archive_read_extract_set_progress_callback
.Fa "struct archive *"
@@ -314,6 +321,22 @@ The
.Va flags
argument is passed unmodified to
.Xr archive_write_disk_set_options 3 .
+.It Fn archive_read_extract2
+This is another version of
+.Fn archive_read_extract
+that allows you to provide your own restore object.
+In particular, this allows you to override the standard lookup functions
+using
+.Xr archive_write_disk_set_group_lookup 3 ,
+and
+.Xr archive_write_disk_set_user_lookup 3 .
+Note that
+.Fn archive_read_extract2
+does not accept a
+.Va flags
+argument; you should use
+.Fn archive_write_disk_set_options
+to set the restore options yourself.
.It Fn archive_read_extract_set_progress_callback
Sets a pointer to a user-defined callback that can be used
for updating progress displays during extraction.
diff --git a/archivers/libarchive/files/libarchive/archive_read_data_into_fd.c b/archivers/libarchive/files/libarchive/archive_read_data_into_fd.c
index 664cc2c3c24..3aeef3bc2da 100644
--- a/archivers/libarchive/files/libarchive/archive_read_data_into_fd.c
+++ b/archivers/libarchive/files/libarchive/archive_read_data_into_fd.c
@@ -24,7 +24,7 @@
*/
#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.15 2007/04/02 00:21:46 kientzle Exp $");
+__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>
@@ -64,8 +64,12 @@ archive_read_data_into_fd(struct archive *a, int fd)
ARCHIVE_OK) {
const char *p = buff;
if (offset > output_offset) {
- lseek(fd, offset - output_offset, SEEK_CUR);
- output_offset = offset;
+ output_offset = lseek(fd,
+ offset - output_offset, SEEK_CUR);
+ if (output_offset != offset) {
+ archive_set_error(a, errno, "Seek error");
+ return (ARCHIVE_FATAL);
+ }
}
while (size > 0) {
bytes_to_write = size;
@@ -74,7 +78,7 @@ archive_read_data_into_fd(struct archive *a, int fd)
bytes_written = write(fd, p, bytes_to_write);
if (bytes_written < 0) {
archive_set_error(a, errno, "Write error");
- return (-1);
+ return (ARCHIVE_FATAL);
}
output_offset += bytes_written;
total_written += bytes_written;
diff --git a/archivers/libarchive/files/libarchive/archive_read_extract.c b/archivers/libarchive/files/libarchive/archive_read_extract.c
index bb5add7bbdc..ab01f7df3e2 100644
--- a/archivers/libarchive/files/libarchive/archive_read_extract.c
+++ b/archivers/libarchive/files/libarchive/archive_read_extract.c
@@ -82,34 +82,40 @@ get_extract(struct archive_read *a)
int
archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
{
- struct archive_read *a = (struct archive_read *)_a;
struct extract *extract;
- int r, r2;
- extract = get_extract(a);
+ extract = get_extract((struct archive_read *)_a);
if (extract == NULL)
return (ARCHIVE_FATAL);
+ archive_write_disk_set_options(extract->ad, flags);
+ return (archive_read_extract2(_a, entry, extract->ad));
+}
+
+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. */
- extract = a->extract;
- archive_write_disk_set_options(a->extract->ad, flags);
- archive_write_disk_set_skip_file(a->extract->ad,
+ archive_write_disk_set_skip_file(ad,
a->skip_file_dev, a->skip_file_ino);
- r = archive_write_header(a->extract->ad, entry);
+ 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, extract->ad);
+ archive_copy_error(&a->archive, ad);
else
/* Otherwise, pour data into the entry. */
- r = copy_data(_a, a->extract->ad);
- r2 = archive_write_finish_entry(a->extract->ad);
+ 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, extract->ad);
+ archive_copy_error(&a->archive, ad);
/* Use the worst error return. */
if (r2 < r)
r = r2;
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_compression_bzip2.c b/archivers/libarchive/files/libarchive/archive_read_support_compression_bzip2.c
index 372eff09541..e6397df9634 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_compression_bzip2.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_compression_bzip2.c
@@ -116,17 +116,29 @@ bid(const void *buff, size_t len)
if (buffer[3] < '1' || buffer[3] > '9')
return (0);
bits_checked += 5;
+ if (len < 5)
+ return (bits_checked);
- /*
- * Research Question: Can we do any more to verify that this
- * really is BZip2 format?? For 99.9% of the time, the above
- * test is sufficient, but it would be nice to do a more
- * thorough check. It's especially troubling that the BZip2
- * signature begins with all ASCII characters; a tar archive
- * whose first filename begins with 'BZh3' would potentially
- * fool this logic. (It may also be possible to guard against
- * such anomalies in archive_read_support_compression_none.)
- */
+ /* After BZh[1-9], there must be either a data block
+ * which begins with 0x314159265359 or an end-of-data
+ * marker of 0x177245385090. */
+
+ if (buffer[4] == 0x31) {
+ /* Verify the data block signature. */
+ size_t s = len;
+ if (s > 10) s = 10;
+ if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", s - 4) != 0)
+ return (0);
+ bits_checked += 8 * (s - 4);
+ } else if (buffer[4] == 0x17) {
+ /* Verify the end-of-data marker. */
+ size_t s = len;
+ if (s > 10) s = 10;
+ if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", s - 4) != 0)
+ return (0);
+ bits_checked += 8 * (s - 4);
+ } else
+ return (0);
return (bits_checked);
}
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_compression_program.c b/archivers/libarchive/files/libarchive/archive_read_support_compression_program.c
index 58b4bbddf0b..206215c897c 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_compression_program.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_compression_program.c
@@ -26,6 +26,24 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_program.c,v 1.2 2007/07/20 01:28:50 kientzle Exp $");
+
+/* This capability is only available on POSIX systems. */
+#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL)
+
+/*
+ * On non-Posix systems, allow the program to build, but choke if
+ * this function is actually invoked.
+ */
+int
+archive_read_support_compression_program(struct archive *_a, const char *cmd)
+{
+ archive_set_error(_a, -1,
+ "External compression programs not supported on this platform");
+ return (ARCHIVE_FATAL);
+}
+
+#else
+
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
@@ -313,3 +331,5 @@ archive_decompressor_program_finish(struct archive_read *a)
return (ARCHIVE_OK);
}
+
+#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
index f6e4cc7e2ab..15d7e7cfd72 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_ar.c
@@ -350,12 +350,16 @@ archive_read_format_ar_read_header(struct archive_read *a,
/* Parse the size of the name, adjust the file size. */
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
- if ((off_t)number > ar->entry_bytes_remaining) {
+ bsd_name_length = (size_t)number;
+ /* Guard against the filename + trailing NUL
+ * overflowing a size_t and against the filename size
+ * being larger than the entire entry. */
+ if (number > (uint64_t)(bsd_name_length + 1)
+ || (off_t)bsd_name_length > ar->entry_bytes_remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Bad input file size");
return (ARCHIVE_FATAL);
}
- bsd_name_length = (size_t)number;
ar->entry_bytes_remaining -= bsd_name_length;
/* Adjust file size reported to client. */
archive_entry_set_size(entry, ar->entry_bytes_remaining);
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
index d333f0ccb4e..e0825a36e1a 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
@@ -595,8 +595,11 @@ add_entry(struct iso9660 *iso9660, struct file_info *file)
struct file_info **new_pending_files;
int new_size = iso9660->pending_files_allocated * 2;
- if (new_size < 1024)
+ if (iso9660->pending_files_allocated < 1024)
new_size = 1024;
+ /* Overflow might keep us from growing the list. */
+ if (new_size <= iso9660->pending_files_allocated)
+ __archive_errx(1, "Out of memory");
new_pending_files = (struct file_info **)malloc(new_size * sizeof(new_pending_files[0]));
if (new_pending_files == NULL)
__archive_errx(1, "Out of memory");
@@ -908,6 +911,11 @@ fprintf(stderr, " *** Discarding CE data.\n");
file->ce_size = 0;
}
+ /* Don't waste time seeking for zero-length bodies. */
+ if (file->size == 0) {
+ file->offset = iso9660->current_position;
+ }
+
/* If CE exists, find and read it now. */
if (file->ce_offset > 0)
offset = file->ce_offset;
@@ -1041,51 +1049,22 @@ isodate17(const unsigned char *v)
return (time_from_tm(&tm));
}
-/*
- * timegm() converts a struct tm to a time_t, except it isn't standard,
- * so I provide my own function here that (ideally) is just a wrapper
- * for timegm().
- */
static time_t
time_from_tm(struct tm *t)
{
#if HAVE_TIMEGM
+ /* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE_STRUCT_TM_TM_GMTOFF
- /*
- * Unfortunately, timegm() isn't standard. The standard
- * mktime() function is a close match, except that it uses
- * local timezone instead of GMT. You can compensate for
- * this by adding the timezone and DST offsets back in, at
- * the cost of two calls to mktime().
- */
- mktime(t); /* Normalize the time and get the TZ offset. */
- t->tm_sec += t->tm_gmtoff; /* Try to adjust for the timezone and DST.*/
- if (t->tm_isdst)
- t->tm_hour -= 1;
- return (mktime(t)); /* Re-convert. */
-#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV) && defined(HAVE_TZSET)
- /* No timegm() and no tm_gmtoff, let's try forcing mktime() to UTC. */
- time_t ret;
- char *tz;
-
- /* Reset the timezone, remember the old one. */
- tz = getenv("TZ");
- setenv("TZ", "UTC 0", 1);
- tzset();
-
- ret = mktime(t);
-
- /* Restore the previous timezone. */
- if (tz)
- setenv("TZ", tz, 1);
- else
- unsetenv("TZ");
- tzset();
- return ret;
#else
- /* <sigh> We have no choice but to use localtime instead of UTC. */
- return (mktime(t));
+ /* 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
}
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c b/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
index f1980e6bd10..72232ed7e03 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_mtree.c
@@ -1,5 +1,6 @@
/*-
* 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
@@ -24,7 +25,7 @@
*/
#include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.4 2008/03/15 11:02:47 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.5 2008/05/19 18:06:48 cperciva Exp $");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -54,11 +55,29 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.4
#define O_BINARY 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
+
+struct mtree_option {
+ struct mtree_option *next;
+ char *value;
+};
+
struct mtree_entry {
struct mtree_entry *next;
+ struct mtree_option *options;
char *name;
- char *option_start;
- char *option_end;
char full;
char used;
};
@@ -77,18 +96,20 @@ struct mtree {
struct archive_string current_dir;
struct archive_string contents_name;
+ struct archive_entry_linkresolver *resolver;
+
off_t cur_size, cur_offset;
};
static int cleanup(struct archive_read *);
static int mtree_bid(struct archive_read *);
static int parse_file(struct archive_read *, struct archive_entry *,
- struct mtree *, struct mtree_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 *);
+ struct mtree *, struct mtree_entry *, int *);
static int parse_keyword(struct archive_read *, struct mtree *,
- struct archive_entry *, char *, char *);
+ struct archive_entry *, struct mtree_option *, int *);
static int read_data(struct archive_read *a,
const void **buff, size_t *size, off_t *offset);
static ssize_t readline(struct archive_read *, struct mtree *, char **, ssize_t);
@@ -97,6 +118,19 @@ static int read_header(struct archive_read *,
struct archive_entry *);
static int64_t mtree_atol10(char **);
static int64_t mtree_atol8(char **);
+static int64_t mtree_atol(char **);
+
+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);
+ }
+}
int
archive_read_support_format_mtree(struct archive *_a)
@@ -129,21 +163,20 @@ cleanup(struct archive_read *a)
struct mtree_entry *p, *q;
mtree = (struct mtree *)(a->format->data);
+
p = mtree->entries;
while (p != NULL) {
q = p->next;
free(p->name);
- /*
- * Note: option_start, option_end are pointers into
- * the block that p->name points to. So we should
- * not try to free them!
- */
+ 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;
@@ -184,21 +217,205 @@ mtree_bid(struct archive_read *a)
/*
* The extended mtree format permits multiple lines specifying
- * attributes for each file. Practically speaking, that means we have
+ * 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 *option;
+
+ if ((option = malloc(sizeof(*option))) == NULL) {
+ archive_set_error(&a->archive, errno, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ if ((option->value = malloc(len + 1)) == NULL) {
+ free(option);
+ archive_set_error(&a->archive, errno, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ memcpy(option->value, value, len);
+ option->value[len] = '\0';
+ option->next = *global;
+ *global = option;
+ 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 ((next = 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,
+ struct mtree_entry **last_entry)
+{
+ struct mtree_entry *entry;
+ struct mtree_option *iter;
+ const char *next, *eq;
+ size_t len;
+ int r;
+
+ 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;
+
+ len = strcspn(line, " \t\r\n");
+ if ((entry->name = malloc(len + 1)) == NULL) {
+ archive_set_error(&a->archive, errno, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ memcpy(entry->name, line, len);
+ entry->name[len] = '\0';
+ parse_escapes(entry->name, entry);
+
+ line += len;
+ 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);
+ line = next;
+ next = line + strcspn(line, " \t\r\n");
+ eq = strchr(line, '=');
+ if (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;
- struct mtree_entry *mentry;
- struct mtree_entry *last_mentry = NULL;
+ struct mtree_option *global;
+ struct mtree_entry *last_entry;
+ int r;
mtree->archive_format = ARCHIVE_FORMAT_MTREE_V1;
mtree->archive_format_name = "mtree";
- for (;;) {
+ global = NULL;
+ last_entry = NULL;
+ r = ARCHIVE_OK;
+
+ for (counter = 1; ; ++counter) {
len = readline(a, mtree, &p, 256);
if (len == 0) {
mtree->this_entry = mtree->entries;
@@ -216,46 +433,27 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
- mentry = malloc(sizeof(*mentry));
- if (mentry == NULL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory");
- return (ARCHIVE_FATAL);
- }
- memset(mentry, 0, sizeof(*mentry));
- /* Add this entry to list. */
- if (last_mentry == NULL) {
- last_mentry = mtree->entries = mentry;
- } else {
- last_mentry->next = mentry;
- }
- last_mentry = mentry;
+ if (*p != '/') {
+ r = process_add_entry(a, mtree, &global, p,
+ &last_entry);
+ } else if (strncmp(p, "/set", 4) == 0) {
+ if (p[4] != ' ' && p[4] != '\t')
+ break;
+ r = process_global_set(a, &global, p);
+ } else if (strncmp(p, "/unset", 6) == 0) {
+ if (p[6] != ' ' && p[6] != '\t')
+ break;
+ r = process_global_unset(a, &global, p);
+ } else
+ break;
- /* Copy line over onto heap. */
- mentry->name = malloc(len + 1);
- if (mentry->name == NULL) {
- free(mentry);
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory");
- return (ARCHIVE_FATAL);
- }
- strcpy(mentry->name, p);
- mentry->option_end = mentry->name + len;
- /* Find end of name. */
- p = mentry->name;
- while (*p != ' ' && *p != '\n' && *p != '\0')
- ++p;
- *p++ = '\0';
- parse_escapes(mentry->name, mentry);
- /* Find start of options and record it. */
- while (p < mentry->option_end && (*p == ' ' || *p == '\t'))
- ++p;
- mentry->option_start = p;
- /* Null terminate each separate option. */
- while (++p < mentry->option_end)
- if (*p == ' ' || *p == '\t' || *p == '\n')
- *p = '\0';
+ if (r != ARCHIVE_OK)
+ return r;
}
+
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't parse line %ju", counter);
+ return ARCHIVE_FATAL;
}
/*
@@ -267,7 +465,7 @@ read_header(struct archive_read *a, struct archive_entry *entry)
{
struct mtree *mtree;
char *p;
- int r;
+ int r, use_next;
mtree = (struct mtree *)(a->format->data);
@@ -277,6 +475,11 @@ read_header(struct archive_read *a, struct archive_entry *entry)
}
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);
@@ -303,8 +506,10 @@ read_header(struct archive_read *a, struct archive_entry *entry)
}
}
if (!mtree->this_entry->used) {
- r = parse_file(a, entry, mtree, mtree->this_entry);
- return (r);
+ 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;
}
@@ -317,11 +522,13 @@ read_header(struct archive_read *a, struct archive_entry *entry)
*/
static int
parse_file(struct archive_read *a, struct archive_entry *entry,
- struct mtree *mtree, struct mtree_entry *mentry)
+ struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
{
- struct stat st;
+ const char *path;
+ struct stat st_storage, *st;
struct mtree_entry *mp;
- int r = ARCHIVE_OK, r1;
+ struct archive_entry *sparse_entry;
+ int r = ARCHIVE_OK, r1, parsed_kws, mismatched_type;
mentry->used = 1;
@@ -330,7 +537,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_size(entry, 0);
/* Parse options from this line. */
- r = parse_line(a, entry, mtree, mentry);
+ parsed_kws = 0;
+ r = parse_line(a, entry, mtree, mentry, &parsed_kws);
if (mentry->full) {
archive_entry_copy_pathname(entry, mentry->name);
@@ -349,7 +557,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
&& strcmp(mentry->name, mp->name) == 0) {
/* Later lines override earlier ones. */
mp->used = 1;
- r1 = parse_line(a, entry, mtree, mp);
+ r1 = parse_line(a, entry, mtree, mp,
+ &parsed_kws);
if (r1 < r)
r = r1;
}
@@ -381,49 +590,126 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* disk.)
*/
mtree->fd = -1;
- if (archive_strlen(&mtree->contents_name) > 0) {
- mtree->fd = open(mtree->contents_name.s,
+ 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);
- if (mtree->fd < 0) {
+ if (mtree->fd == -1 &&
+ (errno != ENOENT ||
+ archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno,
- "Can't open content=\"%s\"",
- mtree->contents_name.s);
+ "Can't open %s", path);
r = ARCHIVE_WARN;
}
- } else if (archive_entry_filetype(entry) == AE_IFREG) {
- mtree->fd = open(archive_entry_pathname(entry),
- O_RDONLY | O_BINARY);
}
- /*
- * If there is a contents file on disk, use that size;
- * otherwise leave it as-is (it might have been set from
- * the mtree size= keyword).
- */
+ st = &st_storage;
if (mtree->fd >= 0) {
- if (fstat(mtree->fd, &st) != 0) {
+ if (fstat(mtree->fd, st) == -1) {
archive_set_error(&a->archive, errno,
- "could not stat %s",
- archive_entry_pathname(entry));
+ "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;
- } else if ((st.st_mode & S_IFMT) != S_IFREG) {
- archive_set_error(&a->archive, errno,
- "%s is not a regular file",
- archive_entry_pathname(entry));
- r = ARCHIVE_WARN;
+ st = NULL;
+ }
+ } else if (lstat(path, st) == -1) {
+ st = NULL;
+ }
+
+ /*
+ * If there is a contents file on disk, use that size;
+ * otherwise leave it as-is (it might have been set from
+ * the mtree size= keyword).
+ */
+ if (st != NULL) {
+ mismatched_type = 0;
+ if ((st->st_mode & S_IFMT) == S_IFREG &&
+ archive_entry_filetype(entry) != AE_IFREG)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFMT) == S_IFLNK &&
+ archive_entry_filetype(entry) != AE_IFLNK)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
+ archive_entry_filetype(entry) != AE_IFSOCK)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFMT) == S_IFCHR &&
+ archive_entry_filetype(entry) != AE_IFCHR)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFMT) == S_IFBLK &&
+ archive_entry_filetype(entry) != AE_IFBLK)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFMT) == S_IFDIR &&
+ archive_entry_filetype(entry) != AE_IFDIR)
+ mismatched_type = 1;
+ if ((st->st_mode & S_IFMT) == S_IFIFO &&
+ archive_entry_filetype(entry) != AE_IFIFO)
+ mismatched_type = 1;
+
+ if (mismatched_type) {
+ if ((parsed_kws & MTREE_HAS_OPTIONAL) == 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "mtree specification has different type for %s",
+ archive_entry_pathname(entry));
+ r = ARCHIVE_WARN;
+ } else {
+ *use_next = 1;
+ }
/* Don't hold a non-regular file open. */
close(mtree->fd);
mtree->fd = -1;
- } else {
- 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_set_nlink(entry, st.st_nlink);
+ st = NULL;
+ return r;
}
}
+
+ if (st != NULL) {
+ if ((parsed_kws & MTREE_HAS_DEVICE) == 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)
+ archive_entry_set_gid(entry, st->st_gid);
+ if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
+ archive_entry_set_uid(entry, st->st_uid);
+ if ((parsed_kws & MTREE_HAS_MTIME) == 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);
+#else
+ archive_entry_set_mtime(entry, st->st_mtime, 0);
+#endif
+ }
+ if ((parsed_kws & MTREE_HAS_NLINK) == 0)
+ archive_entry_set_nlink(entry, st->st_nlink);
+ if ((parsed_kws & MTREE_HAS_PERM) == 0)
+ archive_entry_set_perm(entry, st->st_mode);
+ if ((parsed_kws & MTREE_HAS_SIZE) == 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;
@@ -435,36 +721,82 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
*/
static int
parse_line(struct archive_read *a, struct archive_entry *entry,
- struct mtree *mtree, struct mtree_entry *mp)
+ struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
{
- char *p, *q;
+ struct mtree_option *iter;
int r = ARCHIVE_OK, r1;
- p = mp->option_start;
- while (p < mp->option_end) {
- q = p + strlen(p);
- r1 = parse_keyword(a, mtree, entry, p, q);
+ for (iter = mp->options; iter != NULL; iter = iter->next) {
+ r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
if (r1 < r)
r = r1;
- p = q + 1;
+ }
+ if ((*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]
+ *
+ * Just use major and minor, no translation etc is done
+ * between formats.
+ */
+static int
+parse_device(struct archive *a, struct archive_entry *entry, char *val)
+{
+ char *comma1, *comma2;
+
+ comma1 = strchr(val, ',');
+ if (comma1 == NULL) {
+ archive_entry_set_dev(entry, mtree_atol10(&val));
+ return (ARCHIVE_OK);
+ }
+ ++comma1;
+ comma2 = strchr(comma1, ',');
+ if (comma1 == NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed device attribute");
+ return (ARCHIVE_WARN);
+ }
+ ++comma2;
+ archive_entry_set_rdevmajor(entry, mtree_atol(&comma1));
+ archive_entry_set_rdevminor(entry, mtree_atol(&comma2));
+ return (ARCHIVE_OK);
+}
+
+/*
* Parse a single keyword and its value.
*/
static int
parse_keyword(struct archive_read *a, struct mtree *mtree,
- struct archive_entry *entry, char *key, char *end)
+ struct archive_entry *entry, struct mtree_option *option, int *parsed_kws)
{
- char *val;
+ char *val, *key;
+
+ key = option->value;
- if (end == key)
- return (ARCHIVE_OK);
if (*key == '\0')
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,
@@ -483,38 +815,93 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_strcpy(&mtree->contents_name, val);
break;
}
+ if (strcmp(key, "cksum") == 0)
+ break;
+ case 'd':
+ if (strcmp(key, "device") == 0) {
+ *parsed_kws |= MTREE_HAS_DEVICE;
+ return parse_device(&a->archive, entry, val);
+ }
+ case 'f':
+ if (strcmp(key, "flags") == 0) {
+ *parsed_kws |= MTREE_HAS_FFLAGS;
+ archive_entry_copy_fflags_text(entry, val);
+ break;
+ }
case 'g':
if (strcmp(key, "gid") == 0) {
+ *parsed_kws |= MTREE_HAS_GID;
archive_entry_set_gid(entry, mtree_atol10(&val));
break;
}
if (strcmp(key, "gname") == 0) {
+ *parsed_kws |= MTREE_HAS_GNAME;
archive_entry_copy_gname(entry, val);
break;
}
case 'l':
if (strcmp(key, "link") == 0) {
- archive_entry_set_link(entry, val);
+ archive_entry_copy_symlink(entry, val);
break;
}
case 'm':
+ if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
+ break;
if (strcmp(key, "mode") == 0) {
- if (val[0] == '0') {
+ if (val[0] >= '0' && val[0] <= '9') {
+ *parsed_kws |= MTREE_HAS_PERM;
archive_entry_set_perm(entry,
mtree_atol8(&val));
- } else
+ } else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Symbolic mode \"%s\" unsupported", val);
+ return ARCHIVE_WARN;
+ }
+ break;
+ }
+ case 'n':
+ if (strcmp(key, "nlink") == 0) {
+ *parsed_kws |= MTREE_HAS_NLINK;
+ archive_entry_set_nlink(entry, mtree_atol10(&val));
break;
}
+ case 'r':
+ if (strcmp(key, "rmd160") == 0 ||
+ strcmp(key, "rmd160digest") == 0)
+ break;
case 's':
+ if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
+ break;
+ if (strcmp(key, "sha256") == 0 ||
+ strcmp(key, "sha256digest") == 0)
+ break;
+ if (strcmp(key, "sha384") == 0 ||
+ strcmp(key, "sha384digest") == 0)
+ break;
+ if (strcmp(key, "sha512") == 0 ||
+ strcmp(key, "sha512digest") == 0)
+ break;
if (strcmp(key, "size") == 0) {
archive_entry_set_size(entry, mtree_atol10(&val));
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.
+ */
+ break;
+ }
+ if (strcmp(key, "time") == 0) {
+ *parsed_kws |= MTREE_HAS_MTIME;
+ archive_entry_set_mtime(entry, mtree_atol10(&val), 0);
+ break;
+ }
if (strcmp(key, "type") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
switch (val[0]) {
case 'b':
if (strcmp(val, "block") == 0) {
@@ -554,16 +941,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_filetype(entry, mtree->filetype);
break;
}
- if (strcmp(key, "time") == 0) {
- archive_entry_set_mtime(entry, mtree_atol10(&val), 0);
- break;
- }
case 'u':
if (strcmp(key, "uid") == 0) {
+ *parsed_kws |= MTREE_HAS_UID;
archive_entry_set_uid(entry, mtree_atol10(&val));
break;
}
if (strcmp(key, "uname") == 0) {
+ *parsed_kws |= MTREE_HAS_UNAME;
archive_entry_copy_uname(entry, val);
break;
}
@@ -596,6 +981,7 @@ read_data(struct archive_read *a, const void **buff, size_t *size, off_t *offset
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
}
+ return (ARCHIVE_FATAL);
}
*buff = mtree->buff;
@@ -642,6 +1028,13 @@ parse_escapes(char *src, struct mtree_entry *mentry)
char *dest = src;
char c;
+ /*
+ * The current directory is somewhat special, it should be archived
+ * only once as it will confuse extraction otherwise.
+ */
+ if (strcmp(src, ".") == 0)
+ mentry->full = 1;
+
while (*src != '\0') {
c = *src++;
if (c == '/' && mentry != NULL)
@@ -724,6 +1117,66 @@ mtree_atol10(char **p)
}
/*
+ * 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_atol16(char **p)
+{
+ int64_t l, limit, last_digit_limit;
+ int base, digit, sign;
+
+ base = 16;
+ limit = INT64_MAX / base;
+ last_digit_limit = INT64_MAX % base;
+
+ if (**p == '-') {
+ sign = -1;
+ ++(*p);
+ } else
+ sign = 1;
+
+ l = 0;
+ if (**p >= '0' && **p <= '9')
+ digit = **p - '0';
+ else if (**p >= 'a' && **p <= 'f')
+ digit = **p - 'a' + 10;
+ else if (**p >= 'A' && **p <= 'F')
+ digit = **p - 'A' + 10;
+ else
+ digit = -1;
+ while (digit >= 0 && digit < base) {
+ if (l > limit || (l == limit && digit > last_digit_limit)) {
+ l = UINT64_MAX; /* Truncate on overflow. */
+ break;
+ }
+ l = (l * base) + digit;
+ if (**p >= '0' && **p <= '9')
+ digit = **p - '0';
+ else if (**p >= 'a' && **p <= 'f')
+ digit = **p - 'a' + 10;
+ else if (**p >= 'A' && **p <= 'F')
+ digit = **p - 'A' + 10;
+ else
+ digit = -1;
+ }
+ return (sign < 0) ? -l : l;
+}
+
+static int64_t
+mtree_atol(char **p)
+{
+ if (**p != '0')
+ return mtree_atol10(p);
+ if ((*p)[1] == 'x' || (*p)[1] == 'X') {
+ *p += 2;
+ return mtree_atol16(p);
+ }
+ return mtree_atol8(p);
+}
+
+/*
* Returns length of line (including trailing newline)
* or negative on error. 'start' argument is updated to
* point to first character of line.
diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
index 147ec0b2795..6d7f048a40d 100644
--- a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
+++ b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c
@@ -2303,7 +2303,7 @@ base64_decode(const char *s, size_t len, size_t *out_len)
/* Allocate enough space to hold the entire output. */
/* Note that we may not use all of this... */
- out = (char *)malloc((len * 3 + 3) / 4);
+ out = (char *)malloc(len - len / 4 + 1);
if (out == NULL) {
*out_len = 0;
return (NULL);
diff --git a/archivers/libarchive/files/libarchive/archive_string.c b/archivers/libarchive/files/libarchive/archive_string.c
index e308c480bba..7c378deead4 100644
--- a/archivers/libarchive/files/libarchive/archive_string.c
+++ b/archivers/libarchive/files/libarchive/archive_string.c
@@ -41,6 +41,14 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_string.c,v 1.11 2007/07/15 19:13:
#include <wchar.h>
#endif
+#ifdef __sgi
+/*
+ * The following prototype is missing on IRXI,
+ * even though the function is implemented in libc.
+ */
+size_t wcrtomb(char *, wchar_t, mbstate_t *);
+#endif
+
#include "archive_private.h"
#include "archive_string.h"
diff --git a/archivers/libarchive/files/libarchive/archive_windows.c b/archivers/libarchive/files/libarchive/archive_windows.c
new file mode 100644
index 00000000000..1f4d273dabb
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_windows.c
@@ -0,0 +1,188 @@
+/*-
+ * 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.
+ */
+
+#ifdef _WIN32
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/utime.h>
+#include <sys/stat.h>
+#include <process.h>
+#include <stdlib.h>
+#include <windows.h>
+#include "archive_platform.h"
+
+/* Make a link to FROM called TO. */
+int link (from, to)
+ const char *from;
+ const char *to;
+{
+ int res;
+
+ if (from == NULL || to == NULL) {
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ if (!_access (from, F_OK))
+ res = CopyFile (from, to, FALSE);
+ else {
+ /* from doesn not exist; try to prepend it with the dirname of to */
+ char *fullfrompath, *slash, *todir;
+ todir = strdup (to);
+ if (!todir)
+ return -1;
+ slash = strrchr(todir, '/');
+ if (slash)
+ *slash = '\0';
+ fullfrompath = malloc (strlen (from) + strlen (todir) + 2);
+ if (!fullfrompath)
+ return -1;
+ strcpy (fullfrompath, todir);
+ strcat (fullfrompath, "/");
+ strcat (fullfrompath, from);
+ if (todir)
+ free (todir);
+ if (_access (fullfrompath, R_OK))
+ return -1;
+ res = CopyFile (fullfrompath, to, FALSE);
+ if (fullfrompath)
+ free (fullfrompath);
+ }
+
+ if (res == 0) {
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 0;
+}
+
+/* Make a symbolic link to FROM called TO. */
+int symlink (from, to)
+ const char *from;
+ const char *to;
+{
+ return link (from, to);
+}
+
+static int get_dev_ino (HANDLE hFile, dev_t *dev, ino_t *ino)
+{
+/* dev_t: short (2 bytes); ino_t: unsigned int (4 bytes) */
+#define LODWORD(l) ((DWORD)((DWORDLONG)(l)))
+#define HIDWORD(l) ((DWORD)(((DWORDLONG)(l)>>32)&0xFFFFFFFF))
+#define MAKEDWORDLONG(a,b) ((DWORDLONG)(((DWORD)(a))|(((DWORDLONG)((DWORD)(b)))<<32)))
+
+#define INOSIZE (8*sizeof(ino_t)) /* 32 */
+//#define DEVSIZE (8*sizeof(dev_t)) /* 16 */
+#define SEQNUMSIZE (16)
+
+ BY_HANDLE_FILE_INFORMATION FileInformation;
+ uint64_t ino64, FileReferenceNumber ;
+ ino_t resino;
+ dev_t resdev;
+ DWORD VolumeSerialNumber;
+
+ *ino = 0;
+ *dev = 0;
+ if (hFile == INVALID_HANDLE_VALUE) /* file cannot be opened */
+ return 0;
+ ZeroMemory (&FileInformation, sizeof(FileInformation));
+ if (!GetFileInformationByHandle (hFile, &FileInformation)) /* cannot obtain FileInformation */
+ return 0;
+ ino64 = (uint64_t) MAKEDWORDLONG (
+ FileInformation.nFileIndexLow, FileInformation.nFileIndexHigh);
+ FileReferenceNumber = ino64 & ((~(0ULL)) >> SEQNUMSIZE); /* remove sequence number */
+ /* transform 64-bits ino into 32-bits by hashing */
+ resino = (ino_t) (
+ ( (LODWORD(FileReferenceNumber)) ^ ((LODWORD(FileReferenceNumber)) >> INOSIZE) )
+// ^
+// ( (HIDWORD(FileReferenceNumber)) ^ ((HIDWORD(FileReferenceNumber)) >> INOSIZE) )
+ );
+ *ino = resino;
+ VolumeSerialNumber = FileInformation.dwVolumeSerialNumber;
+ //resdev = (unsigned short) ( (LOWORD(VolumeSerialNumber)) ^ ((HIWORD(VolumeSerialNumber)) >> DEVSIZE) );
+ resdev = (dev_t) VolumeSerialNumber;
+ *dev = resdev;
+//printf ("get_dev_ino: dev = %d; ino = %u\n", resdev, resino);
+ return 0;
+}
+
+int get_dev_ino_fd (int fd, dev_t *dev, ino_t *ino)
+{
+ HANDLE hFile;
+ hFile = (HANDLE) _get_osfhandle (fd);
+ return get_dev_ino (hFile, dev, ino);
+}
+
+int get_dev_ino_filename (char *path, dev_t *dev, ino_t *ino)
+{
+ HANDLE hFile;
+ int res;
+ if (!path || !*path) /* path = NULL */
+ return 0;
+ if (_access (path, F_OK)) /* path does not exist */
+ return -1;
+/* obtain handle to file "name"; FILE_FLAG_BACKUP_SEMANTICS is used to open directories */
+ hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
+ NULL);
+ res = get_dev_ino (hFile, dev, ino);
+ CloseHandle (hFile);
+ return res;
+}
+
+int fstati64 (int fd, struct _stati64 *st)
+{
+ int res;
+ res = _fstati64 (fd, st);
+ if (res < 0)
+ return -1;
+ if (st->st_ino == 0)
+ res = get_dev_ino_fd (fd, &st->st_dev, &st->st_ino);
+// printf ("fstat: dev = %u; ino = %u\n", st->st_dev, st->st_ino);
+ return res;
+}
+
+#endif /* _WIN32 */
diff --git a/archivers/libarchive/files/libarchive/archive_windows.h b/archivers/libarchive/files/libarchive/archive_windows.h
new file mode 100644
index 00000000000..9bc21e4de8f
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/archive_windows.h
@@ -0,0 +1,152 @@
+/*-
+ * 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$
+ */
+
+#ifndef LIBARCHIVE_NONPOSIX_H_INCLUDED
+#define LIBARCHIVE_NONPOSIX_H_INCLUDED
+
+/* Start of configuration for native Win32 */
+
+#include <errno.h>
+#define set_errno(val) ((errno)=val)
+#include <io.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <process.h>
+#include <direct.h>
+
+#define EFTYPE 7
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+/* TODO: Fix the code, don't suppress the warnings. */
+#pragma warning(disable:4244) /* 'conversion' conversion from 'type1' to 'type2', possible loss of data */
+#pragma warning(disable:4146) /* unary minus operator applied to unsigned type, result still unsigned */
+#pragma warning(disable:4996) /* 'function': was declared deprecated */
+#pragma warning(disable:4267) /* Conversion, possible loss of data */
+
+/* Basic definitions for system and integer types. */
+#ifndef _SSIZE_T_
+# define SSIZE_MAX LONG_MAX
+#define _SSIZE_T_
+#endif /* _SSIZE_T_ */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/* 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)))
+
+#define EFTYPE 7
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif /* STDERR_FILENO */
+
+/* Alias the Windows _function to the POSIX equivalent. */
+#define chdir _chdir
+#define chmod _chmod
+#define close _close
+#define fileno _fileno
+#define fstat _fstat
+#define lseek _lseek
+#define open _open
+#define stat _stat
+#define mkdir(d,m) _mkdir(d)
+#define mktemp _mktemp
+#define read _read
+#define rmdir _rmdir
+#define strdup _strdup
+#define tzset _tzset
+#define umask _umask
+#define write _write
+
+#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 S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define S_IFMT 0170000
+#define S_IFDIR _S_IFDIR
+#define S_IFREG _S_IFREG
+
+#define S_ISDIR(m) (((m) & 0170000) == _S_IFDIR) /* directory */
+#define S_ISCHR(m) (((m) & 0170000) == _S_IFCHR) /* char special */
+#define S_ISREG(m) (((m) & 0170000) == _S_IFREG) /* regular file */
+
+/* Windows doesn't have the following, so they're trivial. */
+#define S_ISBLK(m) (0) /* block special */
+#define S_ISFIFO(m) (0) /* fifo or socket */
+#define S_ISLNK(m) (0) /* Symbolic link */
+#define S_ISSOCK(m) (0) /* Socket */
+
+/* replace stat and seek by their large-file equivalents */
+#undef stat
+#define stat _stati64
+#undef fstat
+#define fstat _fstati64
+
+#undef lseek
+#define lseek _lseeki64
+#define lseek64 _lseeki64
+#define tell _telli64
+#define tell64 _telli64
+
+#ifdef __MINGW32__
+# define fseek fseeko64
+# define fseeko fseeko64
+# define ftell ftello64
+# define ftello ftello64
+# define ftell64 ftello64
+#endif /* __MINGW32__ */
+
+/* End of Win32 definitions. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int link (const char *from, const char *to);
+extern int symlink (const char *from, const char *to);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBARCHIVE_NONPOSIX_H_INCLUDED */
diff --git a/archivers/libarchive/files/libarchive/archive_write.3 b/archivers/libarchive/files/libarchive/archive_write.3
index 253b39e7826..fff84f7cddc 100644
--- a/archivers/libarchive/files/libarchive/archive_write.3
+++ b/archivers/libarchive/files/libarchive/archive_write.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD: src/lib/libarchive/archive_write.3,v 1.23 2008/03/10 14:44:41 jkoshy Exp $
.\"
-.Dd August 19, 2006
+.Dd May 11, 2008
.Dt archive_write 3
.Os
.Sh NAME
@@ -39,6 +39,7 @@
.Nm archive_write_set_bytes_per_block ,
.Nm archive_write_set_bytes_in_last_block ,
.Nm archive_write_set_compression_bzip2 ,
+.Nm archive_write_set_compression_compress ,
.Nm archive_write_set_compression_gzip ,
.Nm archive_write_set_compression_none ,
.Nm archive_write_set_compression_program ,
@@ -66,6 +67,8 @@
.Ft int
.Fn archive_write_set_compression_bzip2 "struct archive *"
.Ft int
+.Fn archive_write_set_compression_compress "struct archive *"
+.Ft int
.Fn archive_write_set_compression_gzip "struct archive *"
.Ft int
.Fn archive_write_set_compression_none "struct archive *"
@@ -197,6 +200,7 @@ the pax extended header for most normal files.
In most cases, this will result in ordinary ustar archives.
.It Xo
.Fn archive_write_set_compression_bzip2 ,
+.Fn archive_write_set_compression_compress ,
.Fn archive_write_set_compression_gzip ,
.Fn archive_write_set_compression_none
.Xc
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk.3 b/archivers/libarchive/files/libarchive/archive_write_disk.3
index 5d836e105e3..f71d7d54854 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk.3
+++ b/archivers/libarchive/files/libarchive/archive_write_disk.3
@@ -170,6 +170,10 @@ Note that paths ending in
.Pa ..
always cause an error, regardless of this flag.
.El
+.It Cm ARCHIVE_EXTRACT_SPARSE
+Scan data for blocks of NUL bytes and try to recreate them with holes.
+This results in sparse files, independent of whether the archive format
+supports or uses them.
.It Xo
.Fn archive_write_disk_set_group_lookup ,
.Fn archive_write_disk_set_user_lookup
diff --git a/archivers/libarchive/files/libarchive/archive_write_disk.c b/archivers/libarchive/files/libarchive/archive_write_disk.c
index 620beac48ed..8010c1330ea 100644
--- a/archivers/libarchive/files/libarchive/archive_write_disk.c
+++ b/archivers/libarchive/files/libarchive/archive_write_disk.c
@@ -187,6 +187,8 @@ struct archive_write_disk {
/* UID/GID to use in restoring this entry. */
uid_t uid;
gid_t gid;
+ /* Last offset written to disk. */
+ off_t last_offset;
};
/*
@@ -242,6 +244,31 @@ static int _archive_write_finish_entry(struct archive *);
static ssize_t _archive_write_data(struct archive *, const void *, size_t);
static ssize_t _archive_write_data_block(struct archive *, const void *, size_t, off_t);
+static int
+_archive_write_disk_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 occured. Do we want to check explicitly for that?
+ */
+ if (lstat(a->name, &a->st) == 0) {
+ a->pst = &a->st;
+ return (ARCHIVE_OK);
+ }
+ archive_set_error(&a->archive, errno, "Couldn't stat file");
+ return (ARCHIVE_WARN);
+}
+
static struct archive_vtable *
archive_write_disk_vtable(void)
{
@@ -294,7 +321,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
archive_clear_error(&a->archive);
if (a->archive.state & ARCHIVE_STATE_DATA) {
r = _archive_write_finish_entry(&a->archive);
- if (r != ARCHIVE_OK)
+ if (r == ARCHIVE_FATAL)
return (r);
}
@@ -308,6 +335,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
}
a->entry = archive_entry_clone(entry);
a->fd = -1;
+ a->last_offset = 0;
a->offset = 0;
a->uid = a->user_uid;
a->mode = archive_entry_mode(a->entry);
@@ -463,6 +491,7 @@ _archive_write_data_block(struct archive *_a,
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
ssize_t bytes_written = 0;
+ ssize_t block_size, bytes_to_write;
int r = ARCHIVE_OK;
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -473,31 +502,53 @@ _archive_write_data_block(struct archive *_a,
}
archive_clear_error(&a->archive);
- /* Seek if necessary to the specified offset. */
- if (offset != a->offset) {
- if (lseek(a->fd, offset, SEEK_SET) < 0) {
- archive_set_error(&a->archive, errno, "Seek failed");
- return (ARCHIVE_WARN);
- }
- a->offset = offset;
+ if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+ block_size = a->pst->st_blksize;
+ } else
+ block_size = -1;
+
+ if ((off_t)(offset + size) > a->filesize) {
+ size = (size_t)(a->filesize - a->offset);
+ archive_set_error(&a->archive, 0,
+ "Write request too large");
+ r = ARCHIVE_WARN;
}
/* Write the data. */
- while (size > 0 && a->offset < a->filesize) {
- if ((off_t)(a->offset + size) > a->filesize) {
- size = (size_t)(a->filesize - a->offset);
- archive_set_error(&a->archive, errno,
- "Write request too large");
- r = ARCHIVE_WARN;
- }
+ while (size > 0) {
+ if (block_size != -1) {
+ const char *buf;
+
+ for (buf = buff; size; ++buf, --size, ++offset) {
+ if (*buf != '\0')
+ break;
+ }
+ if (size == 0)
+ break;
+ bytes_to_write = block_size - offset % block_size;
+ buff = buf;
+ } else
+ bytes_to_write = size;
+ /* Seek if necessary to the specified offset. */
+ if (offset != a->last_offset) {
+ if (lseek(a->fd, offset, SEEK_SET) < 0) {
+ archive_set_error(&a->archive, errno, "Seek failed");
+ return (ARCHIVE_FATAL);
+ }
+ }
bytes_written = write(a->fd, buff, size);
if (bytes_written < 0) {
archive_set_error(&a->archive, errno, "Write failed");
return (ARCHIVE_WARN);
}
+ buff = (const char *)buff + bytes_written;
size -= bytes_written;
- a->offset += bytes_written;
+ offset += bytes_written;
+ a->last_offset = a->offset = offset;
}
+ a->offset = offset;
return (r);
}
@@ -505,7 +556,6 @@ static ssize_t
_archive_write_data(struct archive *_a, const void *buff, size_t size)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
- off_t offset;
int r;
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -513,11 +563,10 @@ _archive_write_data(struct archive *_a, const void *buff, size_t size)
if (a->fd < 0)
return (ARCHIVE_OK);
- offset = a->offset;
r = _archive_write_data_block(_a, buff, size, a->offset);
if (r < ARCHIVE_OK)
return (r);
- return (a->offset - offset);
+ return size;
}
static int
@@ -533,6 +582,34 @@ _archive_write_finish_entry(struct archive *_a)
return (ARCHIVE_OK);
archive_clear_error(&a->archive);
+ if (a->last_offset != a->filesize && a->fd >= 0) {
+ if (ftruncate(a->fd, a->filesize) == -1 &&
+ a->filesize == 0) {
+ archive_set_error(&a->archive, errno,
+ "File size could not be restored");
+ return (ARCHIVE_FAILED);
+ }
+ /*
+ * Explicitly stat the file as some platforms might not
+ * implement the XSI option to extend files via ftruncate.
+ */
+ a->pst = NULL;
+ if ((ret = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
+ return (ret);
+ if (a->st.st_size != a->filesize) {
+ const char nul = '\0';
+ if (lseek(a->fd, a->st.st_size - 1, SEEK_SET) < 0) {
+ archive_set_error(&a->archive, errno, "Seek failed");
+ return (ARCHIVE_FATAL);
+ }
+ if (write(a->fd, &nul, 1) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write to restore size failed");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ }
+
/* Restore metadata. */
/*
@@ -723,11 +800,13 @@ restore_entry(struct archive_write_disk *a)
* object isn't a dir.
*/
if (unlink(a->name) == 0) {
- /* We removed it, we're done. */
+ /* 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,
@@ -768,6 +847,7 @@ restore_entry(struct archive_write_disk *a)
"Can't remove already-existing dir");
return (ARCHIVE_WARN);
}
+ a->pst = NULL;
/* Try again. */
en = create_filesystem_object(a);
} else if (en == EEXIST) {
@@ -807,6 +887,7 @@ restore_entry(struct archive_write_disk *a)
"Can't unlink already-existing object");
return (ARCHIVE_WARN);
}
+ a->pst = NULL;
/* Try again. */
en = create_filesystem_object(a);
} else if (!S_ISDIR(a->mode)) {
@@ -866,8 +947,18 @@ create_filesystem_object(struct archive_write_disk *a)
* 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-authoritive 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) {
+ if (r == 0 && a->filesize == 0) {
+ a->todo = 0;
+ a->deferred = 0;
+ } if (r == 0 && a->filesize > 0) {
a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY);
if (a->fd < 0)
r = errno;
@@ -1203,6 +1294,7 @@ check_symlinks(struct archive_write_disk *a)
pn[0] = c;
return (ARCHIVE_WARN);
}
+ a->pst = NULL;
/*
* Even if we did remove it, a warning
* is in order. The warning is silly,
@@ -1226,6 +1318,7 @@ check_symlinks(struct archive_write_disk *a)
pn[0] = c;
return (ARCHIVE_WARN);
}
+ a->pst = NULL;
} else {
archive_set_error(&a->archive, 0,
"Cannot extract through symlink %s",
@@ -1608,19 +1701,8 @@ set_mode(struct archive_write_disk *a, int mode)
* process, since systems sometimes set GID from
* the enclosing dir or based on ACLs.
*/
- if (a->pst != NULL) {
- /* Already have stat() data available. */
-#ifdef HAVE_FSTAT
- } else if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
- a->pst = &a->st;
-#endif
- } else if (stat(a->name, &a->st) == 0) {
- a->pst = &a->st;
- } else {
- archive_set_error(&a->archive, errno,
- "Couldn't stat file");
- return (ARCHIVE_WARN);
- }
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
if (a->pst->st_gid != a->gid) {
mode &= ~ S_ISGID;
if (a->flags & ARCHIVE_EXTRACT_OWNER) {
@@ -1783,6 +1865,8 @@ 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;
+
(void)mode; /* UNUSED */
if (set == 0 && clear == 0)
return (ARCHIVE_OK);
@@ -1793,15 +1877,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
* about the correct approach if we're overwriting an existing
* file that already has flags on it. XXX
*/
- if (fd >= 0 && fstat(fd, &a->st) == 0)
- a->pst = &a->st;
- else if (lstat(name, &a->st) == 0)
- a->pst = &a->st;
- else {
- archive_set_error(&a->archive, errno,
- "Couldn't stat file");
- return (ARCHIVE_WARN);
- }
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
a->st.st_flags &= ~clear;
a->st.st_flags |= set;
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_compression_program.c b/archivers/libarchive/files/libarchive/archive_write_set_compression_program.c
index fc1481dbcd9..b8b20c86cf9 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_compression_program.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_compression_program.c
@@ -27,6 +27,23 @@
__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_program.c,v 1.1 2007/05/29 01:00:19 kientzle Exp $");
+/* This capability is only available on POSIX systems. */
+#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL)
+
+/*
+ * On non-Posix systems, allow the program to build, but choke if
+ * this function is actually invoked.
+ */
+int
+archive_write_set_compression_program(struct archive *_a, const char *cmd)
+{
+ archive_set_error(_a, -1,
+ "External compression programs not supported on this platform");
+ return (ARCHIVE_FATAL);
+}
+
+#else
+
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
@@ -320,3 +337,5 @@ cleanup:
free(state);
return (ret);
}
+
+#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
index 313d0b390f9..1731844d339 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_ar.c
@@ -142,12 +142,15 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
struct ar_w *ar;
const char *pathname;
const char *filename;
+ int64_t size;
ret = 0;
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.
@@ -285,8 +288,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_WARN);
}
append_fn = 1;
- archive_entry_set_size(entry,
- archive_entry_size(entry) + strlen(filename));
+ size += strlen(filename);
}
}
@@ -322,8 +324,7 @@ stat:
}
size:
- if (format_decimal(archive_entry_size(entry), buff + AR_size_offset,
- AR_size_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);
@@ -333,7 +334,7 @@ size:
if (ret != ARCHIVE_OK)
return (ret);
- ar->entry_bytes_remaining = archive_entry_size(entry);
+ ar->entry_bytes_remaining = size;
ar->entry_padding = ar->entry_bytes_remaining % 2;
if (append_fn > 0) {
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c b/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
index 585989fd79b..89f89bc9f54 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_pax.c
@@ -386,7 +386,7 @@ archive_write_pax_header(struct archive_write *a,
const char *p;
char *t;
const wchar_t *wp;
- const char *suffix_start;
+ const char *suffix;
int need_extension, r, ret;
struct pax *pax;
const char *hdrcharset = NULL;
@@ -508,35 +508,60 @@ archive_write_pax_header(struct archive_write *a,
add_pax_attr_w(&(pax->pax_header), "path", path_w);
archive_entry_set_pathname(entry_main, "@WidePath");
need_extension = 1;
- } else {
- /* We have a narrow path; we first need to decide
- * if we can just put it in the ustar header. */
- suffix_start = path; /* Start with a zero-length prefix. */
- if (strlen(path) > 100) {
- /* Find largest suffix that will fit. */
- suffix_start = strchr(path + strlen(path) - 100 - 1, '/');
+ } else if (has_non_ASCII(path_w)) {
+ /* We have non-ASCII characters. */
+ if (path_w == NULL || hdrcharset != NULL) {
+ /* Can't do UTF-8, so store it raw. */
+ add_pax_attr(&(pax->pax_header), "path", path);
+ } else {
+ /* Store UTF-8 */
+ add_pax_attr_w(&(pax->pax_header),
+ "path", path_w);
}
- /* 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.)
+ archive_entry_set_pathname(entry_main,
+ build_ustar_entry_name(ustar_entry_name,
+ path, strlen(path), 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
+ * write_set_format_ustar.c
*/
- if (has_non_ASCII(path_w) || suffix_start == NULL
- || suffix_start - path > 155) {
- /* Path is either too long or has non-ASCII chars. */
- if (path_w == NULL || hdrcharset != NULL) {
- /* Can't do UTF-8, so store it raw. */
- add_pax_attr(&(pax->pax_header), "path", path);
- } else {
- /* Store UTF-8 */
- add_pax_attr_w(&(pax->pax_header),
- "path", path_w);
+ if (strlen(path) <= 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 + strlen(path) - 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 */
+ {
+ if (path_w == NULL || hdrcharset != NULL) {
+ /* Can't do UTF-8, so store it raw. */
+ add_pax_attr(&(pax->pax_header),
+ "path", path);
+ } else {
+ /* Store UTF-8 */
+ add_pax_attr_w(&(pax->pax_header),
+ "path", path_w);
+ }
+ archive_entry_set_pathname(entry_main,
+ build_ustar_entry_name(ustar_entry_name,
+ path, strlen(path), NULL));
+ need_extension = 1;
}
- archive_entry_set_pathname(entry_main,
- build_ustar_entry_name(ustar_entry_name,
- path, strlen(path), NULL));
- need_extension = 1;
}
}
diff --git a/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c b/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
index c2c0011aee2..970fee8db1b 100644
--- a/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
+++ b/archivers/libarchive/files/libarchive/archive_write_set_format_ustar.c
@@ -195,7 +195,7 @@ static int
archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
{
char buff[512];
- int ret;
+ int ret, ret2;
struct ustar *ustar;
ustar = (struct ustar *)a->format_data;
@@ -206,7 +206,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
!(archive_entry_filetype(entry) == AE_IFREG))
archive_entry_set_size(entry, 0);
- if (AE_IFDIR == archive_entry_mode(entry)) {
+ if (AE_IFDIR == archive_entry_filetype(entry)) {
const char *p;
char *t;
/*
@@ -229,15 +229,17 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
}
ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1);
- if (ret != ARCHIVE_OK)
- return (ret);
- ret = (a->compressor.write)(a, buff, 512);
- if (ret != ARCHIVE_OK)
+ if (ret < ARCHIVE_WARN)
return (ret);
+ ret2 = (a->compressor.write)(a, buff, 512);
+ if (ret2 < ARCHIVE_WARN)
+ 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);
- return (ARCHIVE_OK);
+ return (ret);
}
/*
@@ -282,27 +284,33 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
/* Store in two pieces, splitting at a '/'. */
p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
/*
- * If the separator we found is the first '/', find
- * the next one. (This is a pathological case that
- * occurs for paths of exactly 101 bytes that start with
- * '/'; it occurs because the separating '/' is not
- * stored explicitly and the reconstruction assumes that
- * an empty prefix means there is no '/' separator.)
+ * 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, '/');
- /*
- * If there is no path separator, or the prefix or
- * remaining name are too large, return an error.
- */
+ /* 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
+ * explicity forbid, but it just feels wrong.
+ */
archive_set_error(&a->archive, ENAMETOOLONG,
"Pathname too long");
- ret = ARCHIVE_WARN;
+ 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_WARN;
+ ret = ARCHIVE_FAILED;
} else {
/* Copy prefix and remainder to appropriate places */
memcpy(h + USTAR_prefix_offset, pp, p - pp);
@@ -320,7 +328,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
if (copy_length > USTAR_linkname_size) {
archive_set_error(&a->archive, ENAMETOOLONG,
"Link contents too long");
- ret = ARCHIVE_WARN;
+ ret = ARCHIVE_FAILED;
copy_length = USTAR_linkname_size;
}
memcpy(h + USTAR_linkname_offset, p, copy_length);
@@ -332,7 +340,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
if (copy_length > USTAR_uname_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Username too long");
- ret = ARCHIVE_WARN;
+ ret = ARCHIVE_FAILED;
copy_length = USTAR_uname_size;
}
memcpy(h + USTAR_uname_offset, p, copy_length);
@@ -344,7 +352,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
if (strlen(p) > USTAR_gname_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Group name too long");
- ret = ARCHIVE_WARN;
+ ret = ARCHIVE_FAILED;
copy_length = USTAR_gname_size;
}
memcpy(h + USTAR_gname_offset, p, copy_length);
@@ -352,28 +360,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
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_WARN;
+ 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_WARN;
+ 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_WARN;
+ 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_WARN;
+ 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_WARN;
+ ret = ARCHIVE_FAILED;
}
if (archive_entry_filetype(entry) == AE_IFBLK
@@ -382,14 +390,14 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Major device number too large");
- ret = ARCHIVE_WARN;
+ 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_WARN;
+ ret = ARCHIVE_FAILED;
}
}
@@ -409,7 +417,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"tar format cannot archive this (mode=0%lo)",
(unsigned long)archive_entry_mode(entry));
- ret = ARCHIVE_WARN;
+ ret = ARCHIVE_FAILED;
}
}
diff --git a/archivers/libarchive/files/libarchive/config_freebsd.h b/archivers/libarchive/files/libarchive/config_freebsd.h
index 97127a19be8..3d5e821612f 100644
--- a/archivers/libarchive/files/libarchive/config_freebsd.h
+++ b/archivers/libarchive/files/libarchive/config_freebsd.h
@@ -51,6 +51,7 @@
#define HAVE_FCHFLAGS 1
#define HAVE_FCHMOD 1
#define HAVE_FCHOWN 1
+#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FSEEKO 1
#define HAVE_FSTAT 1
@@ -70,6 +71,7 @@
#define HAVE_MKDIR 1
#define HAVE_MKFIFO 1
#define HAVE_MKNOD 1
+#define HAVE_PIPE 1
#define HAVE_POLL 1
#define HAVE_POLL_H 1
#define HAVE_PWD_H 1
@@ -102,6 +104,7 @@
#define HAVE_UTIME 1
#define HAVE_UTIMES 1
#define HAVE_UTIME_H 1
+#define HAVE_VFORK 1
#define HAVE_WCHAR_H 1
#define HAVE_WCSCPY 1
#define HAVE_WCSLEN 1
diff --git a/archivers/libarchive/files/libarchive/config_windows.h b/archivers/libarchive/files/libarchive/config_windows.h
index 64eb15f3317..0ccb2f1b166 100644
--- a/archivers/libarchive/files/libarchive/config_windows.h
+++ b/archivers/libarchive/files/libarchive/config_windows.h
@@ -1,510 +1,688 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-#ifndef CONFIG_H_INCLUDED
-#define CONFIG_H_INCLUDED
-
-/* Version number of bsdcpio */
-#define BSDCPIO_VERSION_STRING "0.9.9"
-
-/* Version number of bsdtar */
-#define BSDTAR_VERSION_STRING "2.5.0"
-
-/* Define to 1 if you have the `acl_create_entry' function. */
-/* #undef HAVE_ACL_CREATE_ENTRY */
-
-/* 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_perm_np' function. */
-/* #undef HAVE_ACL_GET_PERM_NP */
-
-/* Define to 1 if you have the `acl_init' function. */
-/* #undef HAVE_ACL_INIT */
-
-/* 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_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 */
-
-/* True for systems with POSIX ACL support */
-/* #undef HAVE_ACL_USER */
-
-/* Define to 1 if you have the <attr/xattr.h> header file. */
-/* #undef HAVE_ATTR_XATTR_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 declaration of `INT64_MAX', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_INT64_MAX */
-
-/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_INT64_MIN */
-
-/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_OPTARG */
-
-/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_OPTIND */
-
-/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
- don't. */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-#define HAVE_DECL_SIZE_MAX 1
-#else
-/* #undef HAVE_DECL_SIZE_MAX */
-#endif
-
-/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_STRERROR_R */
-
-/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_UINT32_MAX */
-
-/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_UINT64_MAX */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-/* #undef HAVE_DIRENT_H */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* 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 */
-#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 <ext2fs/ext2_fs.h> header file. */
-/* #undef HAVE_EXT2FS_EXT2_FS_H */
-
-/* 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.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if your system has a working POSIX `fnmatch' function. */
-/* #undef HAVE_FNMATCH */
-
-/* Define to 1 if fnmatch(3) supports the FNM_LEADING_DIR flag */
-/* #undef HAVE_FNM_LEADING_DIR */
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-/* #undef HAVE_FSEEKO */
-
-/* Define to 1 if you have the `fsetxattr' function. */
-/* #undef HAVE_FSETXATTR */
-
-/* Define to 1 if you have the `ftruncate' function. */
-/* #undef HAVE_FTRUNCATE */
-
-/* Define to 1 if you have the `futimes' function. */
-/* #undef HAVE_FUTIMES */
-
-/* Define to 1 if you have the `geteuid' function. */
-/* #undef HAVE_GETEUID */
-
-/* Define to 1 if you have the `getopt_long' function. */
-/* #undef HAVE_GETOPT_LONG */
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the <grp.h> header file. */
-/* #undef HAVE_GRP_H */
-
-/* Define to 1 if the system has the type `intmax_t'. */
-/* #undef HAVE_INTMAX_T */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-/* #undef HAVE_INTTYPES_H */
-
-/* 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 `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 `attr' library (-lattr). */
-/* #undef HAVE_LIBATTR */
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-/* #undef HAVE_LIBBZ2 */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <linux/ext2_fs.h> header file. */
-/* #undef HAVE_LINUX_EXT2_FS_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 `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* 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 `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* 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. */
-/* #undef HAVE_LUTIMES */
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* 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 <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-/* #undef HAVE_NL_LANGINFO */
-
-/* Define to 1 if you have the <paths.h> header file. */
-/* #undef HAVE_PATHS_H */
-
-/* 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 <pwd.sh.h> header file. */
-/* #undef HAVE_PWD_H */
-
-/* Define to 1 if you have the `select' function. */
-/* #undef HAVE_SELECT */
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 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. */
-/* #undef HAVE_STDINT_H */
-
-/* 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 to 1 if you have the `strerror_r' function. */
-/* #undef HAVE_STRERROR_R */
-
-/* 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 `strrchr' function. */
-#define HAVE_STRRCHR 1
-
-/* Define to 1 if `st_mtimespec.tv_nsec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */
-
-/* Define to 1 if `st_mtim.tv_nsec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
-
-/* Define to 1 if `st_rdev' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_RDEV 1
-
-/* Define to 1 if `tm_gmtoff' is member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM_TM_GMTOFF */
-
-/* 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/dir.h> header file, and it defines `DIR'.
- */
-/* #undef HAVE_SYS_DIR_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/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. */
-/* #undef HAVE_SYS_PARAM_H */
-
-/* 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/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_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/time.h> header file. */
-/* #undef HAVE_SYS_TIME_H */
-
-/* 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 <sys/wait.h> that is POSIX.1 compatible. */
-/* #undef HAVE_SYS_WAIT_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 the system has the type `uintmax_t'. */
-/* #undef HAVE_UINTMAX_T */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
-
-/* 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 `utimes' function. */
-/* #undef HAVE_UTIMES */
-
-/* Define to 1 if you have the <utime.h> header file. */
-/* #undef HAVE_UTIME_H */
-
-/* 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 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 `wmemcmp' function. */
-/* #undef HAVE_WMEMCMP */
-
-/* Define to 1 if you have the `wmemcpy' function. */
-/* #undef HAVE_WMEMCPY */
-
-/* Define to 1 if you have the <zlib.h> header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Version number of libarchive as a single integer */
-#define LIBARCHIVE_VERSION_NUMBER "2005000"
-
-/* Version number of libarchive */
-#define LIBARCHIVE_VERSION_STRING "2.5.0b"
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
- slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* 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 1 if your C compiler doesn't accept -c and -o together. */
-/* #undef NO_MINUS_C_MINUS_O */
-
-/* Name of package */
-#define PACKAGE "libarchive"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "kientzle@freebsd.org"
-
-/* 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 2.4.12"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libarchive"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.4.12"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r returns char *. */
-/* #undef STRERROR_R_CHAR_P */
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#define TIME_WITH_SYS_TIME 1
-
-/* Version number of package */
-#define VERSION "2.4.12"
-
-/* 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 uint64_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
- #define below would cause a syntax error. */
-/* #undef _UINT64_T */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#define gid_t int
-
-/* Define to `unsigned long' if <sys/types.h> does not define. */
-#define id_t int
-
-/* 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. */
-#define int64_t long long
-
-/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
- not define. */
-#define intmax_t long long
-
-/* Define to `int' if <sys/types.h> does not define. */
-#define mode_t unsigned short
-
-/* 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 `int' if <sys/types.h> doesn't define. */
-#define uid_t int
-
-/* 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. */
-#define uint64_t unsigned long long
-
-/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
- do not define. */
-#define uintmax_t unsigned long long
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef uintptr_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#define pid_t unsigned int
-
-#define uint32_t unsigned long
-#define uint16_t unsigned short
-#define ssize_t long
-
-#endif /* CONFIG_H_INCLUDED */
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+#ifndef CONFIG_H_INCLUDED
+#define CONFIG_H_INCLUDED
+
+
+///////////////////////////////////////////////////////////////////////////
+// Check for Watcom and Microsoft Visual C compilers (WIN32 only) ///////
+///////////////////////////////////////////////////////////////////////////
+#if defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)
+ #define IS_WIN32 1
+
+ #if defined(__TURBOC__) || defined(__BORLANDC__) /* Borland compilers */
+ #elif defined( __WATCOMC__ ) || defined(__WATCOMCPP__) /* Watcom compilers */
+ #define IS_WATCOM 1
+ /* Define to 1 if __INT64 is defined */
+ #define HAVE___INT64 1
+
+ /* Define to 1 if UID should be unsigned */
+ #define USE_UNSIGNED_UID 1
+
+ /* Define to 1 if UID should be unsigned */
+ #define USE_UNSIGNED_GID 1
+
+ #elif defined(__IBMC__) || defined(__IBMCPP__) /* IBM compilers */
+ #elif defined( __SC__ ) /* Symantec C++ compilers */
+ #elif defined( M_I86 ) && defined( MSDOS ) /* Microsoft DOS/Win 16 compilers */
+ #elif defined( _M_IX86 ) || defined( _68K_ ) /* Microsoft Win32 compilers */
+ #define IS_VISUALC 1
+ /* Define to 1 if __INT64 is defined */
+ #define HAVE___INT64 1
+ #else
+ #endif
+
+#endif
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+/* Define to 1 if you have the `acl_create_entry' function. */
+/* #undef HAVE_ACL_CREATE_ENTRY */
+
+/* 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_perm_np' function. */
+/* #undef HAVE_ACL_GET_PERM_NP */
+
+/* Define to 1 if you have the `acl_init' function. */
+/* #undef HAVE_ACL_INIT */
+
+/* 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_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 */
+
+/* True for systems with POSIX ACL support */
+/* #undef HAVE_ACL_USER */
+
+/* Define to 1 if you have the <attr/xattr.h> header file. */
+/* #undef HAVE_ATTR_XATTR_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 declaration of `INT64_MAX', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_INT64_MAX */
+
+/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_INT64_MIN */
+
+/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
+ */
+/* #undef HAVE_DECL_OPTARG */
+
+/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
+ */
+/* #undef HAVE_DECL_OPTIND */
+
+/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_SIZE_MAX */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#define HAVE_DECL_SIZE_MAX 1
+#endif
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_STRERROR_R */
+
+/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_UINT32_MAX */
+
+/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_UINT64_MAX */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_DIRENT_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* 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 */
+#if ((IS_WATCOM) || (IS_VISUALC))
+#define HAVE_EFTYPE 0
+#else
+#define HAVE_EFTYPE 1
+#endif
+
+/* 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 <ext2fs/ext2_fs.h> header file. */
+/* #undef HAVE_EXT2FS_EXT2_FS_H */
+
+/* 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.h> header file. */
+/* #undef HAVE_FCNTL_H 1 */
+
+/* Define to 1 if you have the fcntl() function. */
+/* #undef HAVE_FCNTL_FN */
+
+/* Define to 1 if your system has a working POSIX `fnmatch' function. */
+/* #undef HAVE_FNMATCH */
+
+/* Define to 1 if fnmatch(3) supports the FNM_LEADING_DIR flag */
+/* #undef HAVE_FNM_LEADING_DIR */
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+/* #undef HAVE_FSEEKO */
+
+/* Define to 1 if you have the `fsetxattr' function. */
+/* #undef HAVE_FSETXATTR */
+
+/* Define to 1 if you have the `ftruncate' function. */
+/* #undef HAVE_FTRUNCATE */
+
+/* Define to 1 if you have the `futimes' function. */
+/* #undef HAVE_FUTIMES */
+
+/* Define to 1 if you have the `geteuid' function. */
+/* #undef HAVE_GETEUID */
+
+/* Define to 1 if you have the `getopt_long' function. */
+/* #undef HAVE_GETOPT_LONG */
+
+/* Define to 1 if you have the `getxattr' function. */
+/* #undef HAVE_GETXATTR */
+
+/* Define to 1 if you have the <grp.h> header file. */
+/* #undef HAVE_GRP_H */
+
+/* Define to 1 if the system has the type `intmax_t'. */
+/* #undef HAVE_INTMAX_T */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* 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 `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 `attr' library (-lattr). */
+/* #undef HAVE_LIBATTR */
+
+/* Define to 1 if you have the `bz2' library (-lbz2). */
+/* #undef HAVE_LIBBZ2 */
+
+/* Define to 1 if you have the `z' library (-lz). */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_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 `listxattr' function. */
+/* #undef HAVE_LISTXATTR */
+
+/* Define to 1 if you have the `llistxattr' function. */
+/* #undef HAVE_LLISTXATTR */
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* 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 `lsetxattr' function. */
+/* #undef HAVE_LSETXATTR */
+
+/* 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. */
+/* #undef HAVE_LUTIMES */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* 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 <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the `nl_langinfo' function. */
+/* #undef HAVE_NL_LANGINFO */
+
+/* Define to 1 if you have the <paths.h> header file. */
+/* #undef HAVE_PATHS_H */
+
+/* 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 <pwd.sh.h> header file. */
+/* #undef HAVE_PWD_H */
+
+/* Define to 1 if you have the `select' function. */
+/* #undef HAVE_SELECT */
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 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. */
+/* #undef HAVE_STDINT_H */
+
+/* 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 to 1 if you have the `strerror_r' function. */
+/* #undef HAVE_STRERROR_R */
+
+/* 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 `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if `st_mtimespec.tv_nsec' is member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC */
+
+/* Define to 1 if `st_mtim.tv_nsec' is member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
+
+/* Define to 1 if `st_rdev' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+
+/* Define to 1 if `tm_gmtoff' is member of `struct tm'. */
+/* #undef HAVE_STRUCT_TM_TM_GMTOFF */
+
+/* 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/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_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/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. */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* 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/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_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/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* 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 <sys/wait.h> that is POSIX.1 compatible. */
+/* #undef HAVE_SYS_WAIT_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 the system has the type `uintmax_t'. */
+/* #undef HAVE_UINTMAX_T */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* 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 `utimes' function. */
+/* #undef HAVE_UTIMES */
+
+/* Define to 1 if you have the <utime.h> header file. */
+/* #undef HAVE_UTIME_H */
+
+/* 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 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 `wmemcmp' function. */
+/* #undef HAVE_WMEMCMP */
+
+/* Define to 1 if you have the `wmemcpy' function. */
+/* #undef HAVE_WMEMCPY */
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#define HAVE_ZLIB_H 1
+
+/* Version number of libarchive as a single integer */
+#define LIBARCHIVE_VERSION_NUMBER "2005000"
+
+/* Version number of libarchive */
+#define LIBARCHIVE_VERSION_STRING "2.5.0b"
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
+
+/* 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 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "libarchive"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "kientzle@freebsd.org"
+
+/* 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 2.4.12"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libarchive"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.4.12"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strerror_r returns char *. */
+/* #undef STRERROR_R_CHAR_P */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "2.4.12"
+
+/* 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 uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT64_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#if (USE_UNSIGNED_GID)
+#define gid_t unsigned int
+#else
+#define gid_t int
+#endif
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#define id_t int
+
+/* 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. */
+#if (HAVE___INT64)
+typedef __int64 int64_t;
+#else
+#define int64_t long long
+#endif
+
+/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
+ not define. */
+#if (HAVE___INT64)
+typedef __int64 intmax_t;
+#else
+#define intmax_t long long
+#endif
+
+/* Define to `int' if <sys/types.h> does not define. */
+#define mode_t unsigned short
+
+/* 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 `int' if <sys/types.h> doesn't define. */
+#if (USE_UNSIGNED_UID)
+#define uid_t unsigned int
+#else
+#define uid_t int
+#endif
+
+/* 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. */
+#if (HAVE___INT64)
+typedef unsigned __int64 uint64_t;
+#else
+#define uint64_t unsigned long long
+#endif
+
+/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
+ do not define. */
+#if (HAVE___INT64)
+typedef unsigned __int64 uintmax_t;
+#else
+#define uintmax_t unsigned long long
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef uintptr_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#define pid_t unsigned int
+
+#define uint32_t unsigned long
+#define uint16_t unsigned short
+#define ssize_t long
+
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+#if (IS_VISUALC)
+ #include <io.h>
+ #include <stdlib.h> //brings in NULL
+ #include <sys/stat.h> //brings in S_IFMT(), etc...
+
+ #define HAVE_UINTPTR 0
+
+ #if !defined(STDIN_FILENO)
+ #define STDIN_FILENO 0
+ #endif
+
+ #if !defined(STDOUT_FILENO)
+ #define STDOUT_FILENO 1
+ #endif
+
+ #if !defined(STDERR_FILENO)
+ #define STDERR_FILENO 2
+ #endif
+
+ /* Define to 1 if ino_t is defined (possibly in sys/types.h) */
+ #define HAVE_INO_T 1
+
+ #define S_IFFIFO _S_IFIFO
+
+ #define S_ISBLK( m ) 0
+ #define S_ISFIFO( m ) (((m) & S_IFMT) == S_IFFIFO)
+ #define S_ISCHR( m ) (((m) & S_IFMT) == S_IFCHR)
+ #define S_ISDIR( m ) (((m) & S_IFMT) == S_IFDIR)
+ #define S_ISREG( m ) (((m) & S_IFMT) == S_IFREG)
+ #define S_ISUID 0004000
+ #define S_ISGID 0002000
+ #define S_ISVTX 0001000
+
+ //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
+
+ #define lstat _stat
+
+ /* 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
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+#if (IS_WATCOM)
+ #include <io.h> //brings in STDERR/OUT/IN_FILENO, dup(), dup2(), close(), write(), etc...
+ #include <process.h> //brings in execlp() and _exit()
+ #include <stdlib.h> //brings in NULL
+ #include <sys/stat.h>
+
+ /* Define to 1 if ino_t is defined (possibly in sys/types.h) */
+ #define HAVE_INO_T 1
+
+ //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
+
+ //Prototypes for functions which we'll define in archive_windows.c
+ extern unsigned int sleep (unsigned int seconds);
+
+ #define lstat _stat
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////
+#if !(HAVE_UINTPTR)
+ typedef unsigned int *uintptr_t;
+ #if defined(HAVE_UINTPTR)
+ #undef HAVE_UINTPTR
+ #endif
+ #define HAVE_UINTPTR 1
+#endif
+
+#if !defined(SSIZE_MAX)
+ //#define _POSIX_SSIZE_MAX 32767
+ #if defined(_POSIX_SSIZE_MAX)
+ #define SSIZE_MAX _POSIX_SSIZE_MAX
+ #else
+ #define SSIZE_MAX ((ssize_t)((size_t)-1 >> 1))
+ #endif
+#endif
+
+#if !(HAVE_FCNTL_FN)
+ #define F_SETFL 4 /* Set file status flags. */
+
+ #if defined(HAVE_FCNTL_FN)
+ #undef HAVE_FCNTL_FN
+ #endif
+ #define HAVE_FCNTL_FN 1
+#endif
+
+ #define _S_IFLNK 0xA000 /* symbolic link */
+ #if !defined(_S_IFMT)
+ #define _S_IFMT S_IFMT
+ #endif
+
+ #define _S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK)
+ #define S_ISLNK(m) _S_ISLNK(m)
+
+
+/* Replacement for major/minor/makedev. */
+#if !(MAJOR_IN_MKDEV) && !(MAJOR_IN_SYSMACROS)
+ #define major(x) ((int)(0x00ff & ((x) >> 8)))
+ #define minor(x) ((int)(0xffff00ff & (x)))
+ #define makedev(maj,min) ((0xff00 & ((maj)<<8))|(0xffff00ff & (min)))
+#endif
+
+#define set_errno(val) ((errno)=val)
+
+
+#endif /* CONFIG_H_INCLUDED */
diff --git a/archivers/libarchive/files/libarchive/filter_fork.c b/archivers/libarchive/files/libarchive/filter_fork.c
index 8cad9e2f098..3c2d829d052 100644
--- a/archivers/libarchive/files/libarchive/filter_fork.c
+++ b/archivers/libarchive/files/libarchive/filter_fork.c
@@ -25,6 +25,9 @@
#include "archive_platform.h"
+/* This capability is only available on POSIX systems. */
+#if defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL)
+
__FBSDID("$FreeBSD: src/lib/libarchive/filter_fork.c,v 1.2 2007/12/30 04:58:22 kientzle Exp $");
#if defined(HAVE_POLL)
@@ -137,3 +140,5 @@ __archive_check_child(int in, int out)
sleep(1);
#endif
}
+
+#endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */
diff --git a/archivers/libarchive/files/libarchive/libarchive-formats.5 b/archivers/libarchive/files/libarchive/libarchive-formats.5
index 0346d8f5aff..f570935c824 100644
--- a/archivers/libarchive/files/libarchive/libarchive-formats.5
+++ b/archivers/libarchive/files/libarchive/libarchive-formats.5
@@ -259,6 +259,14 @@ There are two common variants:
the GNU format derived from SVR4,
and the BSD format, which first appeared in 4.4BSD.
Libarchive provides read and write support for both variants.
+.Ss mtree
+Libarchive can read files in
+.Xr mtree 5
+format. This format is not a true archive format, but rather a description
+of a file hierarchy. When requested, libarchive obtains the contents of
+the files described by the
+.Xr mtree 5
+format from files on disk instead.
.Sh SEE ALSO
.Xr ar 1 ,
.Xr cpio 1 ,
diff --git a/archivers/libarchive/files/libarchive/mtree.5 b/archivers/libarchive/files/libarchive/mtree.5
index 2341626d877..b6637d6f55e 100644
--- a/archivers/libarchive/files/libarchive/mtree.5
+++ b/archivers/libarchive/files/libarchive/mtree.5
@@ -33,12 +33,12 @@
.Os
.Sh NAME
.Nm mtree
-.Nd format of mtree dir heirarchy files
+.Nd format of mtree dir hierarchy files
.Sh DESCRIPTION
The
.Nm
format is a textual format that describes a collection of filesystem objects.
-Such files are typically used to create or verify directory heirarchies.
+Such files are typically used to create or verify directory hierarchies.
.Ss General Format
An
.Nm
@@ -135,8 +135,7 @@ the
.Xr cksum 1
utility.
.It Cm contents
-The full pathname of a file whose contents should be
-compared to the contents of this file.
+The full pathname of a file that holds the contents of this file.
.It Cm flags
The file flags as a symbolic name.
See
@@ -152,7 +151,7 @@ The file group as a symbolic name.
.It Cm ignore
Ignore any file hierarchy below this file.
.It Cm link
-The file the symbolic link is expected to reference.
+The target of the symbolic link when type=link.
.It Cm md5
The MD5 message digest of the file.
.It Cm md5digest
diff --git a/archivers/libarchive/files/libarchive/test/list.h b/archivers/libarchive/files/libarchive/test/list.h
index 94f9fc11a39..278821ad974 100644
--- a/archivers/libarchive/files/libarchive/test/list.h
+++ b/archivers/libarchive/files/libarchive/test/list.h
@@ -31,6 +31,7 @@ DEFINE_TEST(test_read_format_isorr_bz2)
DEFINE_TEST(test_read_format_mtree)
DEFINE_TEST(test_read_format_pax_bz2)
DEFINE_TEST(test_read_format_tar)
+DEFINE_TEST(test_read_format_tar_empty_filename)
DEFINE_TEST(test_read_format_tbz)
DEFINE_TEST(test_read_format_tgz)
DEFINE_TEST(test_read_format_tz)
@@ -41,6 +42,7 @@ DEFINE_TEST(test_read_position)
DEFINE_TEST(test_read_truncated)
DEFINE_TEST(test_tar_filenames)
DEFINE_TEST(test_tar_large)
+DEFINE_TEST(test_ustar_filenames)
DEFINE_TEST(test_write_compress)
DEFINE_TEST(test_write_compress_program)
DEFINE_TEST(test_write_disk)
@@ -55,4 +57,5 @@ DEFINE_TEST(test_write_format_cpio_odc)
DEFINE_TEST(test_write_format_shar_empty)
DEFINE_TEST(test_write_format_tar)
DEFINE_TEST(test_write_format_tar_empty)
+DEFINE_TEST(test_write_format_tar_ustar)
DEFINE_TEST(test_write_open_memory)
diff --git a/archivers/libarchive/files/libarchive/test/main.c b/archivers/libarchive/files/libarchive/test/main.c
index 71493321510..6e6ca6c8da1 100644
--- a/archivers/libarchive/files/libarchive/test/main.c
+++ b/archivers/libarchive/files/libarchive/test/main.c
@@ -63,10 +63,14 @@ extern char *optarg;
extern int optind;
#endif
-/* Default is to crash and try to force a core dump on failure. */
-static int dump_on_failure = 1;
+/* Enable core dump on failure. */
+static int dump_on_failure = 0;
+/* Default is to remove temp dirs for successful tests. */
+static int keep_temp_files = 0;
/* Default is to print some basic information about each test. */
static int quiet_flag = 0;
+/* Default is to summarize repeated failures. */
+static int verbose = 0;
/* Cumulative count of component failures. */
static int failures = 0;
/* Cumulative count of skipped component tests. */
@@ -242,7 +246,7 @@ test_assert(const char *file, int line, int value, const char *condition, void *
return (value);
}
failures ++;
- if (previous_failures(file, line))
+ if (!verbose && previous_failures(file, line))
return (value);
fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
fprintf(stderr, " Condition: %s\n", condition);
@@ -261,7 +265,7 @@ test_assert_equal_int(const char *file, int line,
return (1);
}
failures ++;
- if (previous_failures(file, line))
+ if (!verbose && previous_failures(file, line))
return (0);
fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n",
file, line);
@@ -313,16 +317,16 @@ test_assert_equal_string(const char *file, int line,
return (1);
}
failures ++;
- if (previous_failures(file, line))
+ if (!verbose && previous_failures(file, line))
return (0);
fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n",
file, line);
fprintf(stderr, " %s = ", e1);
strdump(v1);
- fprintf(stderr, "\n");
+ fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : strlen(v1));
fprintf(stderr, " %s = ", e2);
strdump(v2);
- fprintf(stderr, "\n");
+ fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : strlen(v2));
report_failure(extra);
return (0);
}
@@ -371,7 +375,7 @@ test_assert_equal_wstring(const char *file, int line,
return (1);
}
failures ++;
- if (previous_failures(file, line))
+ if (!verbose && previous_failures(file, line))
return (0);
fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n",
file, line);
@@ -441,7 +445,7 @@ test_assert_equal_mem(const char *file, int line,
return (1);
}
failures ++;
- if (previous_failures(file, line))
+ if (!verbose && previous_failures(file, line))
return (0);
fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n",
file, line);
@@ -473,12 +477,13 @@ test_assert_empty_file(const char *f1fmt, ...)
if (stat(f1, &st) != 0) {
fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1);
report_failure(NULL);
+ return (0);
}
if (st.st_size == 0)
return (1);
failures ++;
- if (previous_failures(test_filename, test_line))
+ if (!verbose && previous_failures(test_filename, test_line))
return (0);
fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1);
@@ -525,7 +530,7 @@ test_assert_equal_file(const char *f1, const char *f2pattern, ...)
break;
}
failures ++;
- if (previous_failures(test_filename, test_line))
+ if (!verbose && previous_failures(test_filename, test_line))
return (0);
fprintf(stderr, "%s:%d: Files are not identical\n",
test_filename, test_line);
@@ -696,6 +701,12 @@ static int test_run(int i, const char *tmpdir)
(*tests[i].func)();
/* Summarize the results of this test. */
summarize();
+ /* If there were no failures, we can remove the work dir. */
+ if (failures == failures_before) {
+ if (!keep_temp_files && chdir(tmpdir) == 0) {
+ systemf("rm -rf %s", tests[i].name);
+ }
+ }
/* Return appropriate status. */
return (failures == failures_before ? 0 : 1);
}
@@ -709,8 +720,9 @@ static void usage(const char *program)
printf("Default is to run all tests.\n");
printf("Otherwise, specify the numbers of the tests you wish to run.\n");
printf("Options:\n");
- printf(" -k Keep running after failures.\n");
- printf(" Default: Core dump after any failure.\n");
+ printf(" -d Dump core after any failure, for debugging.\n");
+ printf(" -k Keep all temp files.\n");
+ printf(" Default: temp files for successful tests deleted.\n");
#ifdef PROGRAM
printf(" -p <path> Path to executable to be tested.\n");
printf(" Default: path taken from " ENVBASE " environment variable.\n");
@@ -718,6 +730,7 @@ static void usage(const char *program)
printf(" -q Quiet.\n");
printf(" -r <dir> Path to dir containing reference files.\n");
printf(" Default: Current directory.\n");
+ printf(" -v Verbose.\n");
printf("Available tests:\n");
for (i = 0; i < limit; i++)
printf(" %d: %s\n", i, tests[i].name);
@@ -810,9 +823,9 @@ int main(int argc, char **argv)
testprog = getenv(ENVBASE);
#endif
- /* Allow -k to be controlled through the environment. */
- if (getenv(ENVBASE "_KEEP_GOING") != NULL)
- dump_on_failure = 0;
+ /* Allow -d to be controlled through the environment. */
+ if (getenv(ENVBASE "_DEBUG") != NULL)
+ dump_on_failure = 1;
/* Get the directory holding test files from environment. */
refdir = getenv(ENVBASE "_TEST_FILES");
@@ -820,10 +833,13 @@ int main(int argc, char **argv)
/*
* Parse options.
*/
- while ((opt = getopt(argc, argv, "kp:qr:")) != -1) {
+ while ((opt = getopt(argc, argv, "dkp:qr:v")) != -1) {
switch (opt) {
+ case 'd':
+ dump_on_failure = 1;
+ break;
case 'k':
- dump_on_failure = 0;
+ keep_temp_files = 1;
break;
case 'p':
#ifdef PROGRAM
@@ -838,6 +854,9 @@ int main(int argc, char **argv)
case 'r':
refdir = optarg;
break;
+ case 'v':
+ verbose = 1;
+ break;
case '?':
default:
usage(progname);
@@ -886,6 +905,7 @@ int main(int argc, char **argv)
--p;
*p = '\0';
}
+ systemf("rm %s/refdir", tmpdir);
}
/*
@@ -941,5 +961,9 @@ int main(int argc, char **argv)
free(refdir_alloc);
+ /* If the final tmpdir is empty, we can remove it. */
+ /* This should be the usual case when all tests succeed. */
+ rmdir(tmpdir);
+
return (tests_failed);
}
diff --git a/archivers/libarchive/files/libarchive/test/test_entry.c b/archivers/libarchive/files/libarchive/test/test_entry.c
index 8386d98926e..5ed3278c60b 100644
--- a/archivers/libarchive/files/libarchive/test/test_entry.c
+++ b/archivers/libarchive/files/libarchive/test/test_entry.c
@@ -232,6 +232,11 @@ DEFINE_TEST(test_entry)
assertEqualString(archive_entry_fflags_text(e),
"uappnd,nouchg,nodump,noopaque,uunlnk");
/* TODO: Test archive_entry_copy_fflags_text_w() */
+ /* Test archive_entry_copy_fflags_text() */
+ archive_entry_copy_fflags_text(e, "nouappnd, nouchg, dump,uunlnk");
+ archive_entry_fflags(e, &set, &clear);
+ assertEqualInt(16, set);
+ assertEqualInt(7, clear);
#endif
/* See test_acl_basic.c for tests of ACL set/get consistency. */
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_mtree.c b/archivers/libarchive/files/libarchive/test/test_read_format_mtree.c
index e5165d31fbe..b2fdbb88349 100644
--- a/archivers/libarchive/files/libarchive/test/test_read_format_mtree.c
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_mtree.c
@@ -32,18 +32,18 @@ static unsigned char archive[] = {
"dir type=dir\n"
" file\\040with\\040space type=file uid=18\n"
" ..\n"
- "file\\04with\\040space\n"
+ "file\\04with\\040space type=file\n"
"dir2 type=dir\n"
" dir3a type=dir\n"
- " indir3a\n"
+ " indir3a type=file\n"
"dir2/fullindir2 type=file mode=0777\n"
" ..\n"
- " indir2\n"
+ " indir2 type=file\n"
" dir3b type=dir\n"
- " indir3b\n"
+ " indir3b type=file\n"
" ..\n"
" ..\n"
- "notindir\n"
+ "notindir type=file\n"
"dir2/fullindir2 mode=0644\n"
};
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.c b/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.c
new file mode 100644
index 00000000000..d9ba69bd93c
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.c
@@ -0,0 +1,66 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Tar entries with empty filenames are unusual, but shouldn't crash us.
+ */
+DEFINE_TEST(test_read_format_tar_empty_filename)
+{
+ char name[] = "test_read_format_tar_empty_filename.tar";
+ struct archive_entry *ae;
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ extract_reference_file(name);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
+
+ /* Read first entry. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("", archive_entry_pathname(ae));
+ assertEqualInt(1208628157, archive_entry_mtime(ae));
+ assertEqualInt(1000, archive_entry_uid(ae));
+ assertEqualString("tim", archive_entry_uname(ae));
+ assertEqualInt(0, archive_entry_gid(ae));
+ assertEqualString("wheel", archive_entry_gname(ae));
+ assertEqualInt(040775, archive_entry_mode(ae));
+
+ /* Verify the end-of-archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify that the format detection worked. */
+ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+#if ARCHIVE_API_VERSION > 1
+ assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+#else
+ archive_read_finish(a);
+#endif
+}
diff --git a/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.tar.uu b/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.tar.uu
new file mode 100644
index 00000000000..7a34c82ca6b
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_read_format_tar_empty_filename.tar.uu
@@ -0,0 +1,38 @@
+begin 644 test_compat_tar_1.tar
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````#`P,#<W-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P
+M(#$Q,#`R-#,Q-C<U(#`Q,3`P,0`@-0``````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
+M````````````````````````````````````=VAE96P`````````````````
+M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+&````````
+`
+end
diff --git a/archivers/libarchive/files/libarchive/test/test_tar_filenames.c b/archivers/libarchive/files/libarchive/test/test_tar_filenames.c
index 8b83b527733..9b98448e4a7 100644
--- a/archivers/libarchive/files/libarchive/test/test_tar_filenames.c
+++ b/archivers/libarchive/files/libarchive/test/test_tar_filenames.c
@@ -40,19 +40,22 @@ test_filename(const char *prefix, int dlen, int flen)
struct archive_entry *ae;
struct archive *a;
size_t used;
- size_t prefix_length = 0;
- unsigned i = 0;
+ char *p;
+ int i;
+ p = filename;
if (prefix) {
strcpy(filename, prefix);
- i = prefix_length = strlen(prefix);
+ p += strlen(p);
}
- for (; i < prefix_length + dlen; i++)
- filename[i] = 'a';
- filename[i++] = '/';
- for (; i < prefix_length + dlen + flen + 1; i++)
- filename[i] = 'b';
- filename[i++] = '\0';
+ if (dlen > 0) {
+ for (i = 0; i < dlen; i++)
+ *p++ = 'a';
+ *p++ = '/';
+ }
+ for (i = 0; i < flen; i++)
+ *p++ = 'b';
+ *p = '\0';
strcpy(dirname, filename);
@@ -160,15 +163,22 @@ DEFINE_TEST(test_tar_filenames)
int dlen, flen;
/* Repeat the following for a variety of dir/file lengths. */
- for (dlen = 40; dlen < 60; dlen++) {
- for (flen = 40; flen < 60; flen++) {
+ for (dlen = 45; dlen < 55; dlen++) {
+ for (flen = 45; flen < 55; flen++) {
+ test_filename(NULL, dlen, flen);
+ test_filename("/", dlen, flen);
+ }
+ }
+
+ for (dlen = 0; dlen < 140; dlen += 10) {
+ for (flen = 98; flen < 102; flen++) {
test_filename(NULL, dlen, flen);
test_filename("/", dlen, flen);
}
}
for (dlen = 140; dlen < 160; dlen++) {
- for (flen = 90; flen < 110; flen++) {
+ for (flen = 95; flen < 105; flen++) {
test_filename(NULL, dlen, flen);
test_filename("/", dlen, flen);
}
diff --git a/archivers/libarchive/files/libarchive/test/test_tar_large.c b/archivers/libarchive/files/libarchive/test/test_tar_large.c
index c675ac1ee04..a05b49f6ab5 100644
--- a/archivers/libarchive/files/libarchive/test/test_tar_large.c
+++ b/archivers/libarchive/files/libarchive/test/test_tar_large.c
@@ -242,6 +242,11 @@ DEFINE_TEST(test_tar_large)
archive_entry_copy_pathname(ae, namebuff);
archive_entry_set_mode(ae, S_IFREG | 0755);
filesize = tests[i];
+
+ if (filesize < 0) {
+ skipping("32-bit off_t doesn't permit testing of very large files.");
+ return;
+ }
archive_entry_set_size(ae, filesize);
assertA(0 == archive_write_header(a, ae));
diff --git a/archivers/libarchive/files/libarchive/test/test_ustar_filenames.c b/archivers/libarchive/files/libarchive/test/test_ustar_filenames.c
new file mode 100644
index 00000000000..88b4b2c4ac4
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_ustar_filenames.c
@@ -0,0 +1,183 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Exercise various lengths of filenames in ustar archives.
+ */
+
+static void
+test_filename(const char *prefix, int dlen, int flen)
+{
+ char buff[8192];
+ char filename[400];
+ char dirname[400];
+ struct archive_entry *ae;
+ struct archive *a;
+ size_t used;
+ int separator = 0;
+ int i = 0;
+
+ if (prefix != NULL) {
+ strcpy(filename, prefix);
+ i = strlen(prefix);
+ }
+ if (dlen > 0) {
+ for (; i < dlen; i++)
+ filename[i] = 'a';
+ filename[i++] = '/';
+ separator = 1;
+ }
+ for (; i < dlen + flen + separator; i++)
+ filename[i] = 'b';
+ filename[i++] = '\0';
+
+ strcpy(dirname, filename);
+
+ /* Create a new archive in memory. */
+ assert((a = archive_write_new()) != NULL);
+ assertA(0 == archive_write_set_format_ustar(a));
+ assertA(0 == archive_write_set_compression_none(a));
+ assertA(0 == archive_write_set_bytes_per_block(a,0));
+ assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
+
+ /*
+ * Write a file to it.
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, filename);
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ failure("dlen=%d, flen=%d", dlen, flen);
+ if (flen > 100) {
+ assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
+ } else {
+ assertEqualIntA(a, 0, archive_write_header(a, ae));
+ }
+ archive_entry_free(ae);
+
+ /*
+ * Write a dir to it (without trailing '/').
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, dirname);
+ archive_entry_set_mode(ae, S_IFDIR | 0755);
+ failure("dlen=%d, flen=%d", dlen, flen);
+ if (flen >= 100) {
+ assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
+ } else {
+ assertEqualIntA(a, 0, archive_write_header(a, ae));
+ }
+ archive_entry_free(ae);
+
+ /* Tar adds a '/' to directory names. */
+ strcat(dirname, "/");
+
+ /*
+ * Write a dir to it (with trailing '/').
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, dirname);
+ archive_entry_set_mode(ae, S_IFDIR | 0755);
+ failure("dlen=%d, flen=%d", dlen, flen);
+ if (flen >= 100) {
+ assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
+ } else {
+ assertEqualIntA(a, 0, archive_write_header(a, ae));
+ }
+ archive_entry_free(ae);
+
+ /* Close out the archive. */
+ assertA(0 == archive_write_close(a));
+ assertA(0 == archive_write_finish(a));
+
+ /*
+ * Now, read the data back.
+ */
+ assert((a = archive_read_new()) != NULL);
+ assertA(0 == archive_read_support_format_all(a));
+ assertA(0 == archive_read_support_compression_all(a));
+ assertA(0 == archive_read_open_memory(a, buff, used));
+
+ if (flen <= 100) {
+ /* Read the file and check the filename. */
+ assertA(0 == archive_read_next_header(a, &ae));
+ failure("dlen=%d, flen=%d", dlen, flen);
+ assertEqualString(filename, archive_entry_pathname(ae));
+ assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
+ }
+
+ /*
+ * Read the two dirs and check the names.
+ *
+ * Both dirs should read back with the same name, since
+ * tar should add a trailing '/' to any dir that doesn't
+ * already have one.
+ */
+ if (flen <= 99) {
+ assertA(0 == archive_read_next_header(a, &ae));
+ assert((S_IFDIR | 0755) == archive_entry_mode(ae));
+ failure("dlen=%d, flen=%d", dlen, flen);
+ assertEqualString(dirname, archive_entry_pathname(ae));
+ }
+
+ if (flen <= 99) {
+ assertA(0 == archive_read_next_header(a, &ae));
+ assert((S_IFDIR | 0755) == archive_entry_mode(ae));
+ assertEqualString(dirname, archive_entry_pathname(ae));
+ }
+
+ /* Verify the end of the archive. */
+ failure("This fails if entries were written that should not have been written. dlen=%d, flen=%d", dlen, flen);
+ assertEqualInt(1, archive_read_next_header(a, &ae));
+ assert(0 == archive_read_close(a));
+ assert(0 == archive_read_finish(a));
+}
+
+DEFINE_TEST(test_ustar_filenames)
+{
+ int dlen, flen;
+
+ /* Try a bunch of different file/dir lengths that add up
+ * to just a little less or a little more than 100 bytes.
+ * This exercises the code that splits paths between ustar
+ * filename and prefix fields.
+ */
+ for (dlen = 5; dlen < 70; dlen += 5) {
+ for (flen = 100 - dlen - 5; flen < 100 - dlen + 5; flen++) {
+ test_filename(NULL, dlen, flen);
+ test_filename("/", dlen, flen);
+ }
+ }
+
+ /* Probe the 100-char limit for paths with no '/'. */
+ for (flen = 90; flen < 110; flen++) {
+ test_filename(NULL, 0, flen);
+ test_filename("/", dlen, flen);
+ }
+
+ /* XXXX TODO Probe the 100-char limit with a dir prefix. */
+ /* XXXX TODO Probe the 255-char total limit. */
+}
diff --git a/archivers/libarchive/files/libarchive/test/test_write_disk_hardlink.c b/archivers/libarchive/files/libarchive/test/test_write_disk_hardlink.c
index b21c44b2384..0729c38a114 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_disk_hardlink.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_disk_hardlink.c
@@ -29,6 +29,10 @@ __FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_disk_hardlink.c,v 1.1 200
/*
* Exercise hardlink recreation.
+ *
+ * File permissions are chosen so that the authoritive entry
+ * has the correct permission and the non-authoritive versions
+ * are just writeable files.
*/
DEFINE_TEST(test_write_disk_hardlink)
{
@@ -64,7 +68,7 @@ DEFINE_TEST(test_write_disk_hardlink)
/* Link. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "link1b");
- archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_mode(ae, S_IFREG | 0600);
archive_entry_set_size(ae, 0);
archive_entry_copy_hardlink(ae, "link1a");
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
@@ -80,7 +84,7 @@ DEFINE_TEST(test_write_disk_hardlink)
/* Regular file. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "link2a");
- archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_mode(ae, S_IFREG | 0600);
archive_entry_set_size(ae, sizeof(data));
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
@@ -106,10 +110,14 @@ DEFINE_TEST(test_write_disk_hardlink)
/* Regular file. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "link3a");
- archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_mode(ae, S_IFREG | 0600);
archive_entry_set_size(ae, 0);
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
- assertEqualInt(0, archive_write_data(ad, data, sizeof(data)));
+#if ARCHIVE_VERSION_NUMBER < 3000000
+ assertEqualInt(ARCHIVE_WARN, archive_write_data(ad, data, 1));
+#else
+ assertEqualInt(-1, archive_write_data(ad, data, 1));
+#endif
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_ar.c b/archivers/libarchive/files/libarchive/test/test_write_format_ar.c
index 6c7a4462a90..4bb84a6a615 100644
--- a/archivers/libarchive/files/libarchive/test/test_write_format_ar.c
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_ar.c
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_format_ar.c,v 1.6 2008/03
char buff[4096];
char buff2[64];
-static unsigned char strtab[] = "abcdefghijklmn.o/\nggghhhjjjrrrttt.o/\niiijjjdddsssppp.o/\n";
+static char strtab[] = "abcdefghijklmn.o/\nggghhhjjjrrrttt.o/\niiijjjdddsssppp.o/\n";
DEFINE_TEST(test_write_format_ar)
{
@@ -162,6 +162,7 @@ DEFINE_TEST(test_write_format_ar)
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, 5);
assertA(0 == archive_write_header(a, ae));
+ assertA(5 == archive_entry_size(ae));
assertA(5 == archive_write_data(a, "12345", 7));
archive_entry_free(ae);
diff --git a/archivers/libarchive/files/libarchive/test/test_write_format_tar_ustar.c b/archivers/libarchive/files/libarchive/test/test_write_format_tar_ustar.c
new file mode 100644
index 00000000000..53eb07cf7d9
--- /dev/null
+++ b/archivers/libarchive/files/libarchive/test/test_write_format_tar_ustar.c
@@ -0,0 +1,342 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+static int
+is_null(const char *p, size_t l)
+{
+ while (l > 0) {
+ if (*p != '\0')
+ return (0);
+ --l;
+ ++p;
+ }
+ return (1);
+}
+
+/* Verify the contents, then erase them to NUL bytes. */
+/* Tar requires all "unused" bytes be set to NUL; this allows us
+ * to easily verify that by invoking is_null() over the entire header
+ * after verifying each field. */
+#define myAssertEqualMem(a,b,s) assertEqualMem(a, b, s); memset(a, 0, s)
+
+/*
+ * Detailed verification that 'ustar' archives are written with
+ * the correct format.
+ */
+DEFINE_TEST(test_write_format_tar_ustar)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ char *buff, *e;
+ size_t buffsize = 100000;
+ size_t used;
+ int i;
+ char f99[100];
+ char f100[101];
+ char f256[257];
+
+ for (i = 0; i < 99; ++i)
+ f99[i] = 'a' + i % 26;
+ f99[99] = '\0';
+
+ for (i = 0; i < 100; ++i)
+ f100[i] = 'A' + i % 26;
+ f100[100] = '\0';
+
+ for (i = 0; i < 256; ++i)
+ f256[i] = 'A' + i % 26;
+ f256[155] = '/';
+ f256[256] = '\0';
+
+ buff = malloc(buffsize);
+
+ /* Create a new archive in memory. */
+ assert((a = archive_write_new()) != NULL);
+ assertEqualIntA(a, 0, archive_write_set_format_ustar(a));
+ assertEqualIntA(a, 0, archive_write_set_compression_none(a));
+ assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));
+
+ /*
+ * Add various files to it.
+ * TODO: Extend this to cover more filetypes.
+ */
+
+ /* "file" with 10 bytes of content */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 1, 10);
+ archive_entry_set_pathname(entry, "file");
+ archive_entry_set_mode(entry, S_IFREG | 0664);
+ archive_entry_set_size(entry, 10);
+ archive_entry_set_uid(entry, 80);
+ archive_entry_set_gid(entry, 90);
+ archive_entry_set_dev(entry, 12);
+ archive_entry_set_ino(entry, 89);
+ archive_entry_set_nlink(entry, 2);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));
+
+ /* Hardlink to "file" with 10 bytes of content */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 1, 10);
+ archive_entry_set_pathname(entry, "linkfile");
+ archive_entry_set_mode(entry, S_IFREG | 0664);
+ /* TODO: Put this back and fix the bug. */
+ /* archive_entry_set_size(entry, 10); */
+ archive_entry_set_uid(entry, 80);
+ archive_entry_set_gid(entry, 90);
+ archive_entry_set_dev(entry, 12);
+ archive_entry_set_ino(entry, 89);
+ archive_entry_set_nlink(entry, 2);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ /* Write of data to dir should fail == zero bytes get written. */
+ assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
+
+ /* "dir" */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 2, 20);
+ archive_entry_set_pathname(entry, "dir");
+ archive_entry_set_mode(entry, S_IFDIR | 0775);
+ archive_entry_set_size(entry, 10);
+ archive_entry_set_nlink(entry, 2);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ /* Write of data to dir should fail == zero bytes get written. */
+ assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
+
+ /* "symlink" pointing to "file" */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 3, 30);
+ archive_entry_set_pathname(entry, "symlink");
+ archive_entry_set_mode(entry, S_IFLNK | 0664);
+ archive_entry_set_symlink(entry,"file");
+ archive_entry_set_size(entry, 0);
+ archive_entry_set_uid(entry, 88);
+ archive_entry_set_gid(entry, 98);
+ archive_entry_set_dev(entry, 12);
+ archive_entry_set_ino(entry, 90);
+ archive_entry_set_nlink(entry, 1);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ /* Write of data to symlink should fail == zero bytes get written. */
+ assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
+
+ /* file with 99-char filename. */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 1, 10);
+ archive_entry_set_pathname(entry, f99);
+ archive_entry_set_mode(entry, S_IFREG | 0664);
+ archive_entry_set_size(entry, 0);
+ archive_entry_set_uid(entry, 82);
+ archive_entry_set_gid(entry, 93);
+ archive_entry_set_dev(entry, 102);
+ archive_entry_set_ino(entry, 7);
+ archive_entry_set_nlink(entry, 1);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+
+ /* file with 100-char filename. */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 1, 10);
+ archive_entry_set_pathname(entry, f100);
+ archive_entry_set_mode(entry, S_IFREG | 0664);
+ archive_entry_set_size(entry, 0);
+ archive_entry_set_uid(entry, 82);
+ archive_entry_set_gid(entry, 93);
+ archive_entry_set_dev(entry, 102);
+ archive_entry_set_ino(entry, 7);
+ archive_entry_set_nlink(entry, 1);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+
+ /* file with 256-char filename. */
+ assert((entry = archive_entry_new()) != NULL);
+ archive_entry_set_mtime(entry, 1, 10);
+ archive_entry_set_pathname(entry, f256);
+ archive_entry_set_mode(entry, S_IFREG | 0664);
+ archive_entry_set_size(entry, 0);
+ archive_entry_set_uid(entry, 82);
+ archive_entry_set_gid(entry, 93);
+ archive_entry_set_dev(entry, 102);
+ archive_entry_set_ino(entry, 7);
+ archive_entry_set_nlink(entry, 1);
+ assertEqualIntA(a, 0, archive_write_header(a, entry));
+ archive_entry_free(entry);
+
+ assert(0 == archive_write_finish(a));
+
+ /*
+ * Verify the archive format.
+ */
+ e = buff;
+
+ /* "file" */
+ myAssertEqualMem(e + 0, "file", 5); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000012 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "010034\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "0", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ myAssertEqualMem(e + 512, "1234567890", 10);
+ assert(is_null(e + 512, 512));
+ e += 1024;
+
+ /* hardlink to "file" */
+ myAssertEqualMem(e + 0, "linkfile", 9); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "010707\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "0", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* "dir" */
+ myAssertEqualMem(e + 0, "dir/", 4); /* Filename */
+ myAssertEqualMem(e + 100, "000775 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000000 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000000 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000002 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "007747\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "5", 1); /* typeflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* "symlink" pointing to "file" */
+ myAssertEqualMem(e + 0, "symlink", 8); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000130 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000142 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000003 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "011446\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "2", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "file", 5); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* File with 99-char filename */
+ myAssertEqualMem(e + 0, f99, 100); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "034242\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "0", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* File with 100-char filename */
+ myAssertEqualMem(e + 0, f100, 100); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "026230\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "0", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, "", 1); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* File with 256-char filename */
+ myAssertEqualMem(e + 0, f256 + 156, 100); /* Filename */
+ myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
+ myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
+ myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
+ myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
+ myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
+ myAssertEqualMem(e + 148, "055570\0 ", 8); /* checksum */
+ myAssertEqualMem(e + 156, "0", 1); /* linkflag */
+ myAssertEqualMem(e + 157, "", 1); /* linkname */
+ myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
+ myAssertEqualMem(e + 265, "", 1); /* uname */
+ myAssertEqualMem(e + 297, "", 1); /* gname */
+ myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
+ myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
+ myAssertEqualMem(e + 345, f256, 155); /* prefix */
+ assert(is_null(e + 0, 512));
+ e += 512;
+
+ /* TODO: Verify other types of entries. */
+
+ /* Last entry is end-of-archive marker. */
+ assert(is_null(e, 1024));
+ e += 1024;
+
+ assertEqualInt(used, e - buff);
+
+ free(buff);
+}