From: Peter Avalos Date: Mon, 26 Mar 2007 00:30:55 +0000 (+0000) Subject: GC old libarchive/bsdtar. X-Git-Tag: v2.0.1~3338 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/d66439e83ca8dad14f63f0b3ceb0655d98681346 GC old libarchive/bsdtar. --- diff --git a/contrib/libarchive-1.3.1/COPYING b/contrib/libarchive-1.3.1/COPYING deleted file mode 100644 index 6128d175fd..0000000000 --- a/contrib/libarchive-1.3.1/COPYING +++ /dev/null @@ -1,26 +0,0 @@ -All of the C source code and documentation in this package is subject -to the following: - -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. diff --git a/contrib/libarchive-1.3.1/NEWS b/contrib/libarchive-1.3.1/NEWS deleted file mode 100644 index f770403a4f..0000000000 --- a/contrib/libarchive-1.3.1/NEWS +++ /dev/null @@ -1,73 +0,0 @@ - -Sep 05, 2006: libarchive 1.3.1 released -Sep 5, 2006: Bump version to 1.3 for new I/O wrappers. -Sep 4, 2006: New memory and FILE read/write wrappers. -Sep 4, 2006: libarchive test harness is now minimally functional; - it's located a few minor bugs in error-handling logic - -Aug 19, 2006: libarchive 1.2.57 released - -Aug 19, 2006: libarchive 1.2.56 released -Aug 19, 2006: Documentation updates. - -Aug 19, 2006: libarchive 1.2.55 released - -Aug 17, 2006: libarchive 1.2.54 released -Aug 17, 2006: Outline ABI changes for libarchive 2.0; these - are protected behind #ifdef's until I think I've found everything - that needs to change. -Aug 17, 2006: Fix error-handling in archive_read/write_close() - They weren't returning any errors before. -Aug 17, 2006: Fix recursive-add logic to not trigger if it's not set - Fixes a bug adding files when writing archive to pipe or when - using archive_write_open() directly. -Jul 2006: New "skip" handling improves performance extracting - single files from large uncompressed archives. - -Mar 23, 2006: libarchive 1.2.53 released -Mar 22, 2006: Fix a stupid error in Linux extended-attribute support - -Mar 21, 2006: 1.2.52 released -Mar 21, 2006: Fix -p on platforms that don't have platform-specific - extended attribute code. -Mar 20, 2006: Add NEWS file; fill in some older history from other - files. I'll try to keep this file up-to-date from now on. - -OLDER NEWS SUMMARIES - -Mar 19, 2006: libarchive 1.2.51 released -Mar 18, 2006: Many fixes to extended attribute support, including a redesign - of the storage format to simplify debugging. -Mar 12, 2006: Remove 'tp' support; it was a fun idea, but not worth - spending much time on. -Mar 11, 2006: Incorporated Jaakko Heinonen's still-experimental support - for extended attributes (Currently Linux-only.). -Mar 11, 2006: Reorganized distribution package: There is now one tar.gz - file that builds both libarchive and bsdtar. -Feb 13, 2006: Minor bug fixes: correctly read cpio device entries, write - Pax attribute entry names. -Nov 7, 2005: Experimental 'tp' format support in libarchive. Feedback - appreciated; this is not enabled by archive_read_support_format_all() - yet as I'm not quite content with the format detection heuristics. -Nov 7, 2005: Some more portability improvements thanks to Darin Broady, - minor bugfixes. -Oct 12, 2005: Use GNU libtool to build shared libraries on many systems. -Aug 9, 2005: Correctly detect that MacOS X does not have POSIX ACLs. -Apr 17, 2005: Kees Zeelenberg has ported libarchive and bsdtar to Windows: - http://gnuwin32.sourceforge.net/ -Apr 11, 2005: Extended Zip/Zip64 support thanks to Dan Nelson. -L/-h - fix from Jaakko Heinonen. -Mar 12, 2005: archive_read_extract can now handle very long - pathnames (I've tested with pathnames up to 1MB). -Mar 12, 2005: Marcus Geiger has written an article about libarchive - http://xsnil.antbear.org/2005/02/05/archive-mit-libarchive-verarbeiten/ - including examples of using it from Objective-C. His MoinX - http://moinx.antbear.org/ desktop Wiki uses - libarchive for archiving and restoring Wiki pages. -Jan 22, 2005: Preliminary ZIP extraction support, - new directory-walking code for bsdtar. -Jan 16, 2005: ISO9660 extraction code added; manpage corrections. -May 22, 2004: Many gtar-compatible long options have been added; almost - all FreeBSD ports extract correctly with bsdtar. -May 18, 2004: bsdtar can read Solaris, HP-UX, Unixware, star, gtar, - and pdtar archives. diff --git a/contrib/libarchive-1.3.1/README b/contrib/libarchive-1.3.1/README deleted file mode 100644 index 872649b425..0000000000 --- a/contrib/libarchive-1.3.1/README +++ /dev/null @@ -1,114 +0,0 @@ -README for libarchive bundle. - -This distribution bundle includes the following components: - - * libarchive: a library for reading and writing streaming archives - * tar: the 'bsdtar' program is a full-featured 'tar' - replacement built on libarchive - * minitar: a compact sample demonstrating use of libarchive - -The top-level directory contains the following information files: - * AUTHORS - who wrote all of this - * COPYING - what you can do with this - * ChangeLog - highlights of recent changes - * INSTALL - installation instructions - * README - this file - * configure - configuration script, see INSTALL for details. - -The following files in the top-level directory are used by the -'configure' script: - - * Makefile.am, aclocal.m4, configure.ac - - used to build this distribution, only needed by maintainers - * Makefile.in, config.h.in - - templates used by configure script - * config.aux/* - auxiliary scripts used by build system - -Guide to Documentation installed by this system: - * bsdtar.1 explains the use of the bsdtar program - * libarchive.3 gives an overview of the library as a whole - * archive_read.3 and archive_write.3 provide detailed calling - sequences for the read and write APIs - * archive_entry.3 details the "struct archive_entry" utility class - * libarchive-formats.5 documents the file formats supported by the library - * tar.5 provides some detailed information about a variety of different - "tar" formats. - -You should also read the copious comments in "archive.h" and the source -code for the sample "bsdtar" program for more details. Please let me know -about any errors or omissions you find. - -Currently, the library automatically detects and reads the following: - * gzip compression - * bzip2 compression - * compress/LZW compression - * GNU tar format (including GNU long filenames, long link names, and - sparse files) - * Solaris 9 extended tar format (including ACLs) - * Old V7 tar archives - * POSIX ustar - * POSIX pax interchange format - * POSIX octet-oriented cpio - * SVR4 ASCII cpio - * Binary cpio (big-endian or little-endian) - * ISO9660 CD-ROM images (with optional Rockridge extensions) - * ZIP archives (with uncompressed or "deflate" compressed entries) - * Experimental support for Unix 4th Edition "tp" archives - -The library can write: - * gzip compression - * bzip2 compression - * POSIX ustar - * POSIX pax interchange format - * "restricted" pax format, which will create ustar archives except for - entries that require pax extensions (for long filenames, ACLs, etc). - * POSIX octet-oriented cpio - * shar archives - -Notes about the library architecture: - - * This is a heavily stream-oriented system. There is no direct - support for in-place modification or random access and no intention - of ever adding such support. Adding such support would require - sacrificing a lot of other features, so don't bother asking. - - * The library is designed to be extended with new compression and - archive formats. The only requirement is that the format be - readable or writable as a stream and that each archive entry be - independent. - - * On read, compression and format are always detected automatically. - - * I've attempted to minimize static link pollution. If you don't - explicitly invoke a particular feature (such as support for a - particular compression or format), it won't get pulled in. - In particular, if you don't explicitly enable a particular - compression or decompression support, you won't need to link - against the corresponding compression or decompression libraries. - This also reduces the size of statically-linked binaries in - environments where that matters. - - * On read, the library accepts whatever blocks you hand it. - Your read callback is free to pass the library a byte at a time - or mmap the entire archive and give it to the library at once. - On write, the library always produces correctly-blocked - output. - - * The object-style approach allows you to have multiple archive streams - open at once. bsdtar uses this in its "@archive" extension. - - * The archive itself is read/written using callback functions. - You can read an archive directly from an in-memory buffer or - write it to a socket, if you wish. There are some utility - functions to provide easy-to-use "open file," etc, capabilities. - - * The read/write APIs are designed to allow individual entries - to be read or written to any data source: You can create - a block of data in memory and add it to a tar archive without - first writing a temporary file. You can also read an entry from - an archive and write the data directly to a socket. If you want - to read/write entries to disk, there are convenience functions to - make this especially easy. - - * Note: "pax interchange format" is really an extended tar format, - despite what the name says. diff --git a/contrib/libarchive-1.3.1/README.DELETED b/contrib/libarchive-1.3.1/README.DELETED deleted file mode 100644 index 2bb2de8dbd..0000000000 --- a/contrib/libarchive-1.3.1/README.DELETED +++ /dev/null @@ -1,13 +0,0 @@ -INSTALL -Makefile.am -Makefile.in -aclocal.m4 -config.aux/ -config.h.in -configure -configure.ac -libarchive/test/ -minitar/ -tar/getdate.c -tar/getdate.h -tar/test/ diff --git a/contrib/libarchive-1.3.1/README.DRAGONFLY b/contrib/libarchive-1.3.1/README.DRAGONFLY deleted file mode 100644 index cdb56c3f7c..0000000000 --- a/contrib/libarchive-1.3.1/README.DRAGONFLY +++ /dev/null @@ -1,11 +0,0 @@ -Original source can be downloaded from: -http://people.freebsd.org/~kientzle/libarchive/src/ - -MD5 (libarchive-1.3.1.tar.gz) = c618d26d680ace57fcd5f59cea3151c6 -SHA1 (libarchive-1.3.1.tar.gz) = aed6eda15b012adbb88af0f0d76887920ffe7bbf - -A list of deleted files is in README.DELETED. - -This source is used in: - lib/libarchive - usr.bin/tar diff --git a/contrib/libarchive-1.3.1/libarchive/archive.h.in b/contrib/libarchive-1.3.1/libarchive/archive.h.in deleted file mode 100644 index 081e789bcb..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive.h.in +++ /dev/null @@ -1,402 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/lib/libarchive/archive.h.in,v 1.31 2006/09/05 05:59:45 kientzle Exp $ - */ - -#ifndef ARCHIVE_H_INCLUDED -#define ARCHIVE_H_INCLUDED - -/* - * This header file corresponds to: - * Library version @VERSION@ - * Shared library version @SHLIB_MAJOR@ - */ - -#include /* Linux requires this for off_t */ -@ARCHIVE_H_INCLUDE_INTTYPES_H@ -#include /* For FILE * */ -#include /* For ssize_t and size_t */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * If ARCHIVE_API_VERSION != archive_api_version(), then the library you - * were linked with is using an incompatible API to the one you were - * compiled with. This is almost certainly a fatal problem. - * - * ARCHIVE_API_FEATURE is incremented with each significant feature - * addition, so you can test (at compile or run time) if a particular - * feature is implemented. It's no big deal if ARCHIVE_API_FEATURE != - * archive_api_feature(), as long as both are high enough to include - * the features you're relying on. Specific values of FEATURE are - * documented here: - * - * 1 - Version tests are available. - * 2 - archive_{read,write}_close available separately from _finish. - * 3 - open_memory, open_memory2, open_FILE, open_fd available - */ -#define ARCHIVE_API_VERSION @ARCHIVE_API_MAJOR@ -int archive_api_version(void); -#define ARCHIVE_API_FEATURE @ARCHIVE_API_MINOR@ -int archive_api_feature(void); -/* Textual name/version of the library. */ -#define ARCHIVE_LIBRARY_VERSION "libarchive @VERSION@" -const char * archive_version(void); - -#define ARCHIVE_BYTES_PER_RECORD 512 -#define ARCHIVE_DEFAULT_BYTES_PER_BLOCK 10240 - -/* 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 sucess. */ -#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 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 */ -typedef ssize_t archive_skip_callback(struct archive *, void *_client_data, - size_t request); -/* Returns size actually written, zero on EOF, -1 on error. */ -typedef ssize_t archive_write_callback(struct archive *, void *_client_data, - 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 - -/* - * 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. - */ -#define ARCHIVE_FORMAT_BASE_MASK 0xff0000U -#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 - -/*- - * 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. - */ -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. - */ -int archive_read_support_compression_all(struct archive *); -int archive_read_support_compression_bzip2(struct archive *); -int archive_read_support_compression_compress(struct archive *); -int archive_read_support_compression_gzip(struct archive *); -int archive_read_support_compression_none(struct archive *); - -int archive_read_support_format_all(struct archive *); -int archive_read_support_format_cpio(struct archive *); -int archive_read_support_format_gnutar(struct archive *); -int archive_read_support_format_iso9660(struct archive *); -int archive_read_support_format_tar(struct archive *); -int archive_read_support_format_zip(struct archive *); - - -/* Open the archive using callbacks for archive I/O. */ -int archive_read_open(struct archive *, void *_client_data, - archive_open_callback *, archive_read_callback *, - archive_close_callback *); -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. */ -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(). */ -int archive_read_open_file(struct archive *, - const char *_filename, size_t _block_size); -/* Read an archive that's stored in memory. */ -int archive_read_open_memory(struct archive *, - void * buff, size_t size); -/* A more involved version that is only used for internal testing. */ -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. */ -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. */ -int archive_read_open_FILE(struct archive *, FILE *_file); - -/* Parses and returns next entry header. */ -int archive_read_next_header(struct archive *, - struct archive_entry **); - -/* - * Retrieve the byte offset in UNCOMPRESSED data where last-read - * header started. - */ -int64_t archive_read_header_position(struct archive *); - -/* Read data from the body of an entry. Similar to read(2). */ -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 gaurantee that offsets will - * be strictly increasing and that returned blocks will not overlap. - */ -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 - */ -int archive_read_data_skip(struct archive *); -int archive_read_data_into_buffer(struct archive *, void *buffer, - ssize_t len); -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. */ -/* TODO: The 'Default' comments here are not quite correct; clean this up. */ -#define ARCHIVE_EXTRACT_OWNER (1) /* Default: owner/group not restored */ -#define ARCHIVE_EXTRACT_PERM (2) /* Default: restore perm only for reg file*/ -#define ARCHIVE_EXTRACT_TIME (4) /* Default: mod time not restored */ -#define ARCHIVE_EXTRACT_NO_OVERWRITE (8) /* Default: Replace files on disk */ -#define ARCHIVE_EXTRACT_UNLINK (16) /* Default: don't unlink existing files */ -#define ARCHIVE_EXTRACT_ACL (32) /* Default: don't restore ACLs */ -#define ARCHIVE_EXTRACT_FFLAGS (64) /* Default: don't restore fflags */ -#define ARCHIVE_EXTRACT_XATTR (128) /* Default: don't restore xattrs */ - -int archive_read_extract(struct archive *, struct archive_entry *, - int flags); -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. */ -void archive_read_extract_set_skip_file(struct archive *, - dev_t, ino_t); - -/* Close the file and release most resources. */ -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_API_VERSION > 1 -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 */ -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 - */ -struct archive *archive_write_new(void); -int archive_write_set_bytes_per_block(struct archive *, - int bytes_per_block); -int archive_write_get_bytes_per_block(struct archive *); -/* XXX This is badly misnamed; suggestions appreciated. XXX */ -int archive_write_set_bytes_in_last_block(struct archive *, - int bytes_in_last_block); -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. */ -int archive_write_set_skip_file(struct archive *, dev_t, ino_t); - -int archive_write_set_compression_bzip2(struct archive *); -int archive_write_set_compression_gzip(struct archive *); -int archive_write_set_compression_none(struct archive *); -/* A convenience function to set the format based on the code or name. */ -int archive_write_set_format(struct archive *, int format_code); -int archive_write_set_format_by_name(struct archive *, - const char *name); -/* To minimize link pollution, use one or more of the following. */ -int archive_write_set_format_cpio(struct archive *); -/* TODO: int archive_write_set_format_old_tar(struct archive *); */ -int archive_write_set_format_pax(struct archive *); -int archive_write_set_format_pax_restricted(struct archive *); -int archive_write_set_format_shar(struct archive *); -int archive_write_set_format_shar_dump(struct archive *); -int archive_write_set_format_ustar(struct archive *); -int archive_write_open(struct archive *, void *, - archive_open_callback *, archive_write_callback *, - archive_close_callback *); -int archive_write_open_fd(struct archive *, int _fd); -int archive_write_open_filename(struct archive *, const char *_file); -/* A deprecated synonym for archive_write_open_filename() */ -int archive_write_open_file(struct archive *, const char *_file); -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. */ -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. - */ -int archive_write_header(struct archive *, - struct archive_entry *); -#if ARCHIVE_API_VERSION > 1 -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. */ -int archive_write_data(struct archive *, const void *, size_t); -#endif -int archive_write_close(struct archive *); -#if ARCHIVE_API_VERSION > 1 -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. */ -void archive_write_finish(struct archive *); -#endif - -/* - * Accessor functions to read/set various information in - * the struct archive object: - */ -/* Bytes written after compression or read before decompression. */ -int64_t archive_position_compressed(struct archive *); -/* Bytes written to compressor or read from decompressor. */ -int64_t archive_position_uncompressed(struct archive *); - -const char *archive_compression_name(struct archive *); -int archive_compression(struct archive *); -int archive_errno(struct archive *); -const char *archive_error_string(struct archive *); -const char *archive_format_name(struct archive *); -int archive_format(struct archive *); -void archive_set_error(struct archive *, int _err, const char *fmt, ...); - -#ifdef __cplusplus -} -#endif - -#endif /* !ARCHIVE_H_INCLUDED */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_check_magic.c b/contrib/libarchive-1.3.1/libarchive/archive_check_magic.c deleted file mode 100644 index 63932a0bd3..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_check_magic.c +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_check_magic.c,v 1.5 2004/10/18 04:34:30 kientzle Exp $"); - -#include - -#include -#include -#include - -#include "archive_private.h" - -static void -errmsg(const char *m) -{ - write(STDERR_FILENO, m, strlen(m)); -} - -static void -diediedie(void) -{ - *(char *)0 = 1; /* Deliberately segfault and force a coredump. */ - _exit(1); /* If that didn't work, just exit with an error. */ -} - -static const char * -state_name(unsigned s) -{ - switch (s) { - case ARCHIVE_STATE_NEW: return ("new"); - case ARCHIVE_STATE_HEADER: return ("header"); - case ARCHIVE_STATE_DATA: return ("data"); - case ARCHIVE_STATE_EOF: return ("eof"); - case ARCHIVE_STATE_CLOSED: return ("closed"); - case ARCHIVE_STATE_FATAL: return ("fatal"); - default: return ("??"); - } -} - - -static void -write_all_states(int states) -{ - unsigned lowbit; - - /* A trick for computing the lowest set bit. */ - while ((lowbit = states & (-states)) != 0) { - states &= ~lowbit; /* Clear the low bit. */ - errmsg(state_name(lowbit)); - if (states != 0) - errmsg("/"); - } -} - -/* - * Check magic value and current state; bail if it isn't valid. - * - * This is designed to catch serious programming errors that violate - * the libarchive API. - */ -void -__archive_check_magic(struct archive *a, unsigned magic, unsigned state, - const char *function) -{ - if (a->magic != magic) { - errmsg("INTERNAL ERROR: Function "); - errmsg(function); - errmsg(" invoked with invalid struct archive structure.\n"); - diediedie(); - } - - if (state == ARCHIVE_STATE_ANY) - return; - - if ((a->state & state) == 0) { - errmsg("INTERNAL ERROR: Function '"); - errmsg(function); - errmsg("' invoked with archive structure in state '"); - write_all_states(a->state); - errmsg("', should be in state '"); - write_all_states(state); - errmsg("'\n"); - diediedie(); - } -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_entry.3 b/contrib/libarchive-1.3.1/libarchive/archive_entry.3 deleted file mode 100644 index f5ed30db86..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_entry.3 +++ /dev/null @@ -1,341 +0,0 @@ -.\" Copyright (c) 2003-2004 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 AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.11 2005/11/24 10:06:05 ru Exp $ -.\" -.Dd December 15, 2003 -.Dt archive_entry 3 -.Os -.Sh NAME -.Nm archive_entry_acl_add_entry , -.Nm archive_entry_acl_add_entry_w , -.Nm archive_entry_acl_clear , -.Nm archive_entry_acl_count , -.Nm archive_entry_acl_next , -.Nm archive_entry_acl_next_w , -.Nm archive_entry_acl_reset , -.Nm archive_entry_acl_text_w , -.Nm archive_entry_atime , -.Nm archive_entry_atime_nsec , -.Nm archive_entry_clear , -.Nm archive_entry_clone , -.Nm archive_entry_copy_fflags_text_w , -.Nm archive_entry_copy_gname_w , -.Nm archive_entry_copy_hardlink , -.Nm archive_entry_copy_hardlink_w , -.Nm archive_entry_copy_pathname_w , -.Nm archive_entry_copy_stat , -.Nm archive_entry_copy_symlink_w , -.Nm archive_entry_copy_uname_w , -.Nm archive_entry_dev , -.Nm archive_entry_fflags , -.Nm archive_entry_fflags_text , -.Nm archive_entry_free , -.Nm archive_entry_gid , -.Nm archive_entry_gname , -.Nm archive_entry_hardlink , -.Nm archive_entry_ino , -.Nm archive_entry_mode , -.Nm archive_entry_mtime , -.Nm archive_entry_mtime_nsec , -.Nm archive_entry_new , -.Nm archive_entry_pathname , -.Nm archive_entry_pathname_w , -.Nm archive_entry_rdev , -.Nm archive_entry_rdevmajor , -.Nm archive_entry_rdevminor , -.Nm archive_entry_set_fflags , -.Nm archive_entry_set_gid , -.Nm archive_entry_set_gname , -.Nm archive_entry_set_hardlink , -.Nm archive_entry_set_link , -.Nm archive_entry_set_mode , -.Nm archive_entry_set_mtime , -.Nm archive_entry_set_pathname , -.Nm archive_entry_set_rdevmajor , -.Nm archive_entry_set_rdevminor , -.Nm archive_entry_set_size , -.Nm archive_entry_set_symlink , -.Nm archive_entry_set_uid , -.Nm archive_entry_set_uname , -.Nm archive_entry_size , -.Nm archive_entry_stat , -.Nm archive_entry_symlink , -.Nm archive_entry_uid , -.Nm archive_entry_uname -.Nd functions for manipulating archive entry descriptions -.Sh SYNOPSIS -.In archive_entry.h -.Ft void -.Fn archive_entry_acl_add_entry "struct archive_entry *" "int type" "int permset" "int tag" "int qual" "const char *name" -.Ft void -.Fn archive_entry_acl_add_entry_w "struct archive_entry *" "int type" "int permset" "int tag" "int qual" "const wchar_t *name" -.Ft void -.Fn archive_entry_acl_clear "struct archive_entry *" -.Ft int -.Fn archive_entry_acl_count "struct archive_entry *" "int type" -.Ft int -.Fn archive_entry_acl_next "struct archive_entry *" "int want_type" "int *type" "int *permset" "int *tag" "int *qual" "const char **name" -.Ft int -.Fn archive_entry_acl_next_w "struct archive_entry *" "int want_type" "int *type" "int *permset" "int *tag" "int *qual" "const wchar_t **name" -.Ft int -.Fn archive_entry_acl_reset "struct archive_entry *" "int want_type" -.Ft const wchar_t * -.Fn archive_entry_acl_text_w "struct archive_entry *" "int flags" -.Ft time_t -.Fn archive_entry_atime "struct archive_entry *" -.Ft long -.Fn archive_entry_atime_nsec "struct archive_entry *" -.Ft "struct archive_entry *" -.Fn archive_entry_clear "struct archive_entry *" -.Ft struct archive_entry * -.Fn archive_entry_clone "struct archive_entry *" -.Ft const wchar_t * -.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const wchar_t *" -.Ft void -.Fn archive_entry_copy_gname_w "struct archive_entry *" "const wchar_t *" -.Ft void -.Fn archive_entry_copy_hardlink "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_copy_hardlink_w "struct archive_entry *" "const wchar_t *" -.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 *" -.Ft void -.Fn archive_entry_copy_symlink_w "struct archive_entry *" "const wchar_t *" -.Ft void -.Fn archive_entry_copy_uname_w "struct archive_entry *" "const wchar_t *" -.Ft dev_t -.Fn archive_entry_dev "struct archive_entry *" -.Ft void -.Fn archive_entry_fflags "struct archive_entry *" "unsigned long *set" "unsigned long *clear" -.Ft const char * -.Fn archive_entry_fflags_text "struct archive_entry *" -.Ft void -.Fn archive_entry_free "struct archive_entry *" -.Ft const char * -.Fn archive_entry_gname "struct archive_entry *" -.Ft const char * -.Fn archive_entry_hardlink "struct archive_entry *" -.Ft ino_t -.Fn archive_entry_ino "struct archive_entry *" -.Ft mode_t -.Fn archive_entry_mode "struct archive_entry *" -.Ft time_t -.Fn archive_entry_mtime "struct archive_entry *" -.Ft long -.Fn archive_entry_mtime_nsec "struct archive_entry *" -.Ft struct archive_entry * -.Fn archive_entry_new "void" -.Ft const char * -.Fn archive_entry_pathname "struct archive_entry *" -.Ft const wchar_t * -.Fn archive_entry_pathname_w "struct archive_entry *" -.Ft dev_t -.Fn archive_entry_rdev "struct archive_entry *" -.Ft dev_t -.Fn archive_entry_rdevmajor "struct archive_entry *" -.Ft dev_t -.Fn archive_entry_rdevminor "struct archive_entry *" -.Ft void -.Fn archive_entry_set_fflags "struct archive_entry *" "unsigned long set" "unsigned long clear" -.Ft void -.Fn archive_entry_set_gid "struct archive_entry *" "gid_t" -.Ft void -.Fn archive_entry_set_gname "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_set_hardlink "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_set_link "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_set_mode "struct archive_entry *" "mode_t" -.Ft void -.Fn archive_entry_set_mtime "struct archive_entry *" "time_t" "long nanos" -.Ft void -.Fn archive_entry_set_pathname "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_set_rdevmajor "struct archive_entry *" "dev_t" -.Ft void -.Fn archive_entry_set_rdevminor "struct archive_entry *" "dev_t" -.Ft void -.Fn archive_entry_set_size "struct archive_entry *" "int64_t" -.Ft void -.Fn archive_entry_set_symlink "struct archive_entry *" "const char *" -.Ft void -.Fn archive_entry_set_uid "struct archive_entry *" "uid_t" -.Ft void -.Fn archive_entry_set_uname "struct archive_entry *" "const char *" -.Ft int64_t -.Fn archive_entry_size "struct archive_entry *" -.Ft const struct stat * -.Fn archive_entry_stat "struct archive_entry *" -.Ft const char * -.Fn archive_entry_symlink "struct archive_entry *" -.Ft const char * -.Fn archive_entry_uname "struct archive_entry *" -.Sh DESCRIPTION -These functions create and manipulate data objects that -represent entries within an archive. -You can think of a -.Tn struct archive_entry -as a heavy-duty version of -.Tn struct stat : -it includes everything from -.Tn struct stat -plus associated pathname, textual group and user names, etc. -These objects are used by -.Xr libarchive 3 -to represent the metadata associated with a particular -entry in an archive. -.Ss Create and Destroy -There are functions to allocate, destroy, clear, and copy -.Va archive_entry -objects: -.Bl -tag -compact -width indent -.It Fn archive_entry_clear -Erases the object, resetting all internal fields to the -same state as a newly-created object. -This is provided to allow you to quickly recycle objects -without thrashing the heap. -.It Fn archive_entry_clone -A deep copy operation; all text fields are duplicated. -.It Fn archive_entry_free -Releases the -.Tn struct archive_entry -object. -.It Fn archive_entry_new -Allocate and return a blank -.Tn struct archive_entry -object. -.El -.Ss Set and Get Functions -Most of the functions here set or read entries in an object. -Such functions have one of the following forms: -.Bl -tag -compact -width indent -.It Fn archive_entry_set_XXXX -Stores the provided data in the object. -In particular, for strings, the pointer is stored, -not the referenced string. -.It Fn archive_entry_copy_XXXX -As above, except that the referenced data is copied -into the object. -.It Fn archive_entry_XXXX -Returns the specified data. -In the case of strings, a const-qualified pointer to -the string is returned. -.El -String data can be set or accessed as wide character strings -or normal -.Va char -strings. -The functions that use wide character strings are suffixed with -.Cm _w . -Note that these are different representations of the same data: -For example, if you store a narrow string and read the corresponding -wide string, the object will transparently convert formats -using the current locale. -Similarly, if you store a wide string and then store a -narrow string for the same data, the previously-set wide string will -be discarded in favor of the new data. -.Pp -There are a few set/get functions that merit additional description: -.Bl -tag -compact -width indent -.It Fn archive_entry_set_link -This function sets the symlink field if it is already set. -Otherwise, it sets the hardlink field. -.El -.Ss File Flags -File flags are transparently converted between a bitmap -representation and a textual format. -For example, if you set the bitmap and ask for text, the library -will build a canonical text format. -However, if you set a text format and request a text format, -you will get back the same text, even if it is ill-formed. -If you need to canonicalize a textual flags string, you should first set the -text form, then request the bitmap form, then use that to set the bitmap form. -Setting the bitmap format will clear the internal text representation -and force it to be reconstructed when you next request the text form. -.Pp -The bitmap format consists of two integers, one containing bits -that should be set, the other specifying bits that should be -cleared. -Bits not mentioned in either bitmap will be ignored. -Usually, the bitmap of bits to be cleared will be set to zero. -In unusual circumstances, you can force a fully-specified set -of file flags by setting the bitmap of flags to clear to the complement -of the bitmap of flags to set. -(This differs from -.Xr fflagstostr 3 , -which only includes names for set bits.) -Converting a bitmap to a textual string is a platform-specific -operation; bits that are not meaningful on the current platform -will be ignored. -.Pp -The canonical text format is a comma-separated list of flag names. -The -.Fn archive_entry_copy_fflags_text_w -function parses 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 -recognized, or NULL if every name was recognized. -Note that every name--including names that follow an unrecognized name--will -be evaluated, and the bitmaps will be set to reflect every name that is -recognized. -(In particular, this differs from -.Xr strtofflags 3 , -which stops parsing at the first unrecognized name.) -.Ss ACL Handling -XXX This needs serious help. -XXX -.Pp -An -.Dq Access Control List -(ACL) is a list of permissions that grant access to particular users or -groups beyond what would normally be provided by standard POSIX mode bits. -The ACL handling here addresses some deficiencies in the POSIX.1e draft 17 ACL -specification. -In particular, POSIX.1e draft 17 specifies several different formats, but -none of those formats include both textual user/group names and numeric -UIDs/GIDs. -.Pp -XXX explain ACL stuff XXX -.\" .Sh EXAMPLE -.\" .Sh RETURN VALUES -.\" .Sh ERRORS -.Sh SEE ALSO -.Xr archive 3 -.Sh HISTORY -The -.Nm libarchive -library first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm libarchive -library was written by -.An Tim Kientzle Aq kientzle@acm.org . -.\" .Sh BUGS diff --git a/contrib/libarchive-1.3.1/libarchive/archive_entry.c b/contrib/libarchive-1.3.1/libarchive/archive_entry.c deleted file mode 100644 index 2d9f4a3b22..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_entry.c +++ /dev/null @@ -1,1742 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.35 2006/05/01 00:55:44 kientzle Exp $"); - -#include -#include -#ifdef MAJOR_IN_MKDEV -#include -#else -#ifdef MAJOR_IN_SYSMACROS -#include -#endif -#endif -#ifdef HAVE_EXT2FS_EXT2_FS_H -#include /* for Linux file flags */ -#endif -#include -#include -#include -#include -#include - -/* Obtain suitable wide-character manipulation functions. */ -#ifdef HAVE_WCHAR_H -#include -#else -static size_t wcslen(const wchar_t *s) -{ - const wchar_t *p = s; - while (*p != L'\0') - ++p; - return p - s; -} -static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) -{ - wchar_t *dest = s1; - while ((*s1 = *s2) != L'\0') - ++s1, ++s2; - return dest; -} -#define wmemcpy(a,b,i) (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t)) -/* Good enough for simple equality testing, but not for sorting. */ -#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) -#endif - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -#undef max -#define max(a, b) ((a)>(b)?(a):(b)) - -/* - * Handle wide character (i.e., Unicode) and non-wide character - * strings transparently. - * - */ - -struct aes { - const char *aes_mbs; - char *aes_mbs_alloc; - const wchar_t *aes_wcs; - wchar_t *aes_wcs_alloc; -}; - -struct ae_acl { - struct ae_acl *next; - int type; /* E.g., access or default */ - int tag; /* E.g., user/group/other/mask */ - int permset; /* r/w/x bits */ - int id; /* uid/gid for user/group */ - struct aes name; /* uname/gname */ -}; - -struct ae_xattr { - struct ae_xattr *next; - - char *name; - void *value; - size_t size; -}; - -static void aes_clean(struct aes *); -static void aes_copy(struct aes *dest, struct aes *src); -static const char * aes_get_mbs(struct aes *); -static const wchar_t * aes_get_wcs(struct aes *); -static void aes_set_mbs(struct aes *, const char *mbs); -static void aes_copy_mbs(struct aes *, const char *mbs); -/* static void aes_set_wcs(struct aes *, const wchar_t *wcs); */ -static void aes_copy_wcs(struct aes *, const wchar_t *wcs); - -static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear); -static const wchar_t *ae_wcstofflags(const wchar_t *stringp, - unsigned long *setp, unsigned long *clrp); -static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id); -static void append_id_w(wchar_t **wp, int id); - -static int acl_special(struct archive_entry *entry, - int type, int permset, int tag); -static struct ae_acl *acl_new_entry(struct archive_entry *entry, - int type, int permset, int tag, int id); -static void next_field_w(const wchar_t **wp, const wchar_t **start, - const wchar_t **end, wchar_t *sep); -static int prefix_w(const wchar_t *start, const wchar_t *end, - const wchar_t *test); - - -/* - * Description of an archive entry. - * - * Basically, this is a "struct stat" with a few text fields added in. - * - * TODO: Add "comment", "charset", and possibly other entries - * that are supported by "pax interchange" format. However, GNU, ustar, - * cpio, and other variants don't support these features, so they're not an - * excruciatingly high priority right now. - * - * TODO: "pax interchange" format allows essentially arbitrary - * key/value attributes to be attached to any entry. Supporting - * such extensions may make this library useful for special - * applications (e.g., a package manager could attach special - * package-management attributes to each entry). There are tricky - * API issues involved, so this is not going to happen until - * there's a real demand for it. - * - * TODO: Design a good API for handling sparse files. - */ -struct archive_entry { - /* - * Note that ae_stat.st_mode & S_IFMT can be 0! - * - * This occurs when the actual file type of the object is not - * in the archive. For example, 'tar' archives store - * hardlinks without marking the type of the underlying - * object. - */ - struct stat ae_stat; - - /* - * Use aes here so that we get transparent mbs<->wcs conversions. - */ - struct aes ae_fflags_text; /* Text fflags per fflagstostr(3) */ - unsigned long ae_fflags_set; /* Bitmap fflags */ - unsigned long ae_fflags_clear; - struct aes ae_gname; /* Name of owning group */ - struct aes ae_hardlink; /* Name of target for hardlink */ - struct aes ae_pathname; /* Name of entry */ - struct aes ae_symlink; /* symlink contents */ - struct aes ae_uname; /* Name of owner */ - - struct ae_acl *acl_head; - struct ae_acl *acl_p; - int acl_state; /* See acl_next for details. */ - wchar_t *acl_text_w; - - struct ae_xattr *xattr_head; - struct ae_xattr *xattr_p; -}; - -static void -aes_clean(struct aes *aes) -{ - if (aes->aes_mbs_alloc) { - free(aes->aes_mbs_alloc); - aes->aes_mbs_alloc = NULL; - } - if (aes->aes_wcs_alloc) { - free(aes->aes_wcs_alloc); - aes->aes_wcs_alloc = NULL; - } - memset(aes, 0, sizeof(*aes)); -} - -static void -aes_copy(struct aes *dest, struct aes *src) -{ - *dest = *src; - if (src->aes_mbs != NULL) { - dest->aes_mbs_alloc = strdup(src->aes_mbs); - dest->aes_mbs = dest->aes_mbs_alloc; - if (dest->aes_mbs == NULL) - __archive_errx(1, "No memory for aes_copy()"); - } - - if (src->aes_wcs != NULL) { - dest->aes_wcs_alloc = malloc((wcslen(src->aes_wcs) + 1) - * sizeof(wchar_t)); - dest->aes_wcs = dest->aes_wcs_alloc; - if (dest->aes_wcs == NULL) - __archive_errx(1, "No memory for aes_copy()"); - wcscpy(dest->aes_wcs_alloc, src->aes_wcs); - } -} - -static const char * -aes_get_mbs(struct aes *aes) -{ - if (aes->aes_mbs == NULL && aes->aes_wcs == NULL) - return NULL; - if (aes->aes_mbs == NULL && aes->aes_wcs != NULL) { - /* - * XXX Need to estimate the number of byte in the - * multi-byte form. Assume that, on average, wcs - * chars encode to no more than 3 bytes. There must - * be a better way... XXX - */ - int mbs_length = wcslen(aes->aes_wcs) * 3 + 64; - aes->aes_mbs_alloc = malloc(mbs_length); - aes->aes_mbs = aes->aes_mbs_alloc; - if (aes->aes_mbs == NULL) - __archive_errx(1, "No memory for aes_get_mbs()"); - wcstombs(aes->aes_mbs_alloc, aes->aes_wcs, mbs_length - 1); - aes->aes_mbs_alloc[mbs_length - 1] = 0; - } - return (aes->aes_mbs); -} - -static const wchar_t * -aes_get_wcs(struct aes *aes) -{ - if (aes->aes_wcs == NULL && aes->aes_mbs == NULL) - return NULL; - if (aes->aes_wcs == NULL && aes->aes_mbs != NULL) { - /* - * No single byte will be more than one wide character, - * so this length estimate will always be big enough. - */ - int wcs_length = strlen(aes->aes_mbs); - aes->aes_wcs_alloc - = malloc((wcs_length + 1) * sizeof(wchar_t)); - aes->aes_wcs = aes->aes_wcs_alloc; - if (aes->aes_wcs == NULL) - __archive_errx(1, "No memory for aes_get_wcs()"); - mbstowcs(aes->aes_wcs_alloc, aes->aes_mbs, wcs_length); - aes->aes_wcs_alloc[wcs_length] = 0; - } - return (aes->aes_wcs); -} - -static void -aes_set_mbs(struct aes *aes, const char *mbs) -{ - if (aes->aes_mbs_alloc) { - free(aes->aes_mbs_alloc); - aes->aes_mbs_alloc = NULL; - } - if (aes->aes_wcs_alloc) { - free(aes->aes_wcs_alloc); - aes->aes_wcs_alloc = NULL; - } - aes->aes_mbs = mbs; - aes->aes_wcs = NULL; -} - -static void -aes_copy_mbs(struct aes *aes, const char *mbs) -{ - if (aes->aes_mbs_alloc) { - free(aes->aes_mbs_alloc); - aes->aes_mbs_alloc = NULL; - } - if (aes->aes_wcs_alloc) { - free(aes->aes_wcs_alloc); - aes->aes_wcs_alloc = NULL; - } - aes->aes_mbs_alloc = malloc((strlen(mbs) + 1) * sizeof(char)); - if (aes->aes_mbs_alloc == NULL) - __archive_errx(1, "No memory for aes_copy_mbs()"); - strcpy(aes->aes_mbs_alloc, mbs); - aes->aes_mbs = aes->aes_mbs_alloc; - aes->aes_wcs = NULL; -} - -#if 0 -static void -aes_set_wcs(struct aes *aes, const wchar_t *wcs) -{ - if (aes->aes_mbs_alloc) { - free(aes->aes_mbs_alloc); - aes->aes_mbs_alloc = NULL; - } - if (aes->aes_wcs_alloc) { - free(aes->aes_wcs_alloc); - aes->aes_wcs_alloc = NULL; - } - aes->aes_mbs = NULL; - aes->aes_wcs = wcs; -} -#endif - -static void -aes_copy_wcs(struct aes *aes, const wchar_t *wcs) -{ - if (aes->aes_mbs_alloc) { - free(aes->aes_mbs_alloc); - aes->aes_mbs_alloc = NULL; - } - if (aes->aes_wcs_alloc) { - free(aes->aes_wcs_alloc); - aes->aes_wcs_alloc = NULL; - } - aes->aes_mbs = NULL; - aes->aes_wcs_alloc = malloc((wcslen(wcs) + 1) * sizeof(wchar_t)); - if (aes->aes_wcs_alloc == NULL) - __archive_errx(1, "No memory for aes_copy_wcs()"); - wcscpy(aes->aes_wcs_alloc, wcs); - aes->aes_wcs = aes->aes_wcs_alloc; -} - -struct archive_entry * -archive_entry_clear(struct archive_entry *entry) -{ - aes_clean(&entry->ae_fflags_text); - aes_clean(&entry->ae_gname); - aes_clean(&entry->ae_hardlink); - aes_clean(&entry->ae_pathname); - aes_clean(&entry->ae_symlink); - aes_clean(&entry->ae_uname); - archive_entry_acl_clear(entry); - archive_entry_xattr_clear(entry); - memset(entry, 0, sizeof(*entry)); - return entry; -} - -struct archive_entry * -archive_entry_clone(struct archive_entry *entry) -{ - struct archive_entry *entry2; - - /* Allocate new structure and copy over all of the fields. */ - entry2 = malloc(sizeof(*entry2)); - if (entry2 == NULL) - return (NULL); - memset(entry2, 0, sizeof(*entry2)); - entry2->ae_stat = entry->ae_stat; - entry2->ae_fflags_set = entry->ae_fflags_set; - entry2->ae_fflags_clear = entry->ae_fflags_clear; - - aes_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text); - aes_copy(&entry2->ae_gname, &entry->ae_gname); - aes_copy(&entry2->ae_hardlink, &entry->ae_hardlink); - aes_copy(&entry2->ae_pathname, &entry->ae_pathname); - aes_copy(&entry2->ae_symlink, &entry->ae_symlink); - aes_copy(&entry2->ae_uname, &entry->ae_uname); - - /* XXX TODO: Copy ACL data over as well. XXX */ - /* XXX TODO: Copy xattr data over as well. XXX */ - return (entry2); -} - -void -archive_entry_free(struct archive_entry *entry) -{ - archive_entry_clear(entry); - free(entry); -} - -struct archive_entry * -archive_entry_new(void) -{ - struct archive_entry *entry; - - entry = malloc(sizeof(*entry)); - if (entry == NULL) - return (NULL); - memset(entry, 0, sizeof(*entry)); - return (entry); -} - -/* - * Functions for reading fields from an archive_entry. - */ - -time_t -archive_entry_atime(struct archive_entry *entry) -{ - return (entry->ae_stat.st_atime); -} - -long -archive_entry_atime_nsec(struct archive_entry *entry) -{ - (void)entry; /* entry can be unused here. */ - return (ARCHIVE_STAT_ATIME_NANOS(&entry->ae_stat)); -} - -time_t -archive_entry_ctime(struct archive_entry *entry) -{ - return (entry->ae_stat.st_ctime); -} - -long -archive_entry_ctime_nsec(struct archive_entry *entry) -{ - (void)entry; /* entry can be unused here. */ - return (ARCHIVE_STAT_CTIME_NANOS(&entry->ae_stat)); -} - -dev_t -archive_entry_dev(struct archive_entry *entry) -{ - return (entry->ae_stat.st_dev); -} - -void -archive_entry_fflags(struct archive_entry *entry, - unsigned long *set, unsigned long *clear) -{ - *set = entry->ae_fflags_set; - *clear = entry->ae_fflags_clear; -} - -/* - * Note: if text was provided, this just returns that text. If you - * really need the text to be rebuilt in a canonical form, set the - * text, ask for the bitmaps, then set the bitmaps. (Setting the - * bitmaps clears any stored text.) This design is deliberate: if - * we're editing archives, we don't want to discard flags just because - * they aren't supported on the current system. The bitmap<->text - * conversions are platform-specific (see below). - */ -const char * -archive_entry_fflags_text(struct archive_entry *entry) -{ - const char *f; - char *p; - - f = aes_get_mbs(&entry->ae_fflags_text); - if (f != NULL) - return (f); - - if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) - return (NULL); - - p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); - if (p == NULL) - return (NULL); - - aes_copy_mbs(&entry->ae_fflags_text, p); - free(p); - f = aes_get_mbs(&entry->ae_fflags_text); - return (f); -} - -gid_t -archive_entry_gid(struct archive_entry *entry) -{ - return (entry->ae_stat.st_gid); -} - -const char * -archive_entry_gname(struct archive_entry *entry) -{ - return (aes_get_mbs(&entry->ae_gname)); -} - -const wchar_t * -archive_entry_gname_w(struct archive_entry *entry) -{ - return (aes_get_wcs(&entry->ae_gname)); -} - -const char * -archive_entry_hardlink(struct archive_entry *entry) -{ - return (aes_get_mbs(&entry->ae_hardlink)); -} - -const wchar_t * -archive_entry_hardlink_w(struct archive_entry *entry) -{ - return (aes_get_wcs(&entry->ae_hardlink)); -} - -ino_t -archive_entry_ino(struct archive_entry *entry) -{ - return (entry->ae_stat.st_ino); -} - -mode_t -archive_entry_mode(struct archive_entry *entry) -{ - return (entry->ae_stat.st_mode); -} - -time_t -archive_entry_mtime(struct archive_entry *entry) -{ - return (entry->ae_stat.st_mtime); -} - -long -archive_entry_mtime_nsec(struct archive_entry *entry) -{ - (void)entry; /* entry can be unused here. */ - return (ARCHIVE_STAT_MTIME_NANOS(&entry->ae_stat)); -} - -const char * -archive_entry_pathname(struct archive_entry *entry) -{ - return (aes_get_mbs(&entry->ae_pathname)); -} - -const wchar_t * -archive_entry_pathname_w(struct archive_entry *entry) -{ - return (aes_get_wcs(&entry->ae_pathname)); -} - -dev_t -archive_entry_rdev(struct archive_entry *entry) -{ - return (entry->ae_stat.st_rdev); -} - -dev_t -archive_entry_rdevmajor(struct archive_entry *entry) -{ - return (major(entry->ae_stat.st_rdev)); -} - -dev_t -archive_entry_rdevminor(struct archive_entry *entry) -{ - return (minor(entry->ae_stat.st_rdev)); -} - -int64_t -archive_entry_size(struct archive_entry *entry) -{ - return (entry->ae_stat.st_size); -} - -const struct stat * -archive_entry_stat(struct archive_entry *entry) -{ - return (&entry->ae_stat); -} - -const char * -archive_entry_symlink(struct archive_entry *entry) -{ - return (aes_get_mbs(&entry->ae_symlink)); -} - -const wchar_t * -archive_entry_symlink_w(struct archive_entry *entry) -{ - return (aes_get_wcs(&entry->ae_symlink)); -} - -uid_t -archive_entry_uid(struct archive_entry *entry) -{ - return (entry->ae_stat.st_uid); -} - -const char * -archive_entry_uname(struct archive_entry *entry) -{ - return (aes_get_mbs(&entry->ae_uname)); -} - -const wchar_t * -archive_entry_uname_w(struct archive_entry *entry) -{ - return (aes_get_wcs(&entry->ae_uname)); -} - -/* - * Functions to set archive_entry properties. - */ - -/* - * Note "copy" not "set" here. The "set" functions that accept a pointer - * only store the pointer; they don't copy the underlying object. - */ -void -archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st) -{ - entry->ae_stat = *st; -} - -void -archive_entry_set_fflags(struct archive_entry *entry, - unsigned long set, unsigned long clear) -{ - aes_clean(&entry->ae_fflags_text); - entry->ae_fflags_set = set; - entry->ae_fflags_clear = clear; -} - -const wchar_t * -archive_entry_copy_fflags_text_w(struct archive_entry *entry, - const wchar_t *flags) -{ - aes_copy_wcs(&entry->ae_fflags_text, flags); - return (ae_wcstofflags(flags, - &entry->ae_fflags_set, &entry->ae_fflags_clear)); -} - -void -archive_entry_set_gid(struct archive_entry *entry, gid_t g) -{ - entry->ae_stat.st_gid = g; -} - -void -archive_entry_set_gname(struct archive_entry *entry, const char *name) -{ - aes_set_mbs(&entry->ae_gname, name); -} - -void -archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) -{ - aes_copy_wcs(&entry->ae_gname, name); -} - -void -archive_entry_set_hardlink(struct archive_entry *entry, const char *target) -{ - aes_set_mbs(&entry->ae_hardlink, target); -} - -void -archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) -{ - aes_copy_mbs(&entry->ae_hardlink, target); -} - -void -archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) -{ - aes_copy_wcs(&entry->ae_hardlink, target); -} - -void -archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) -{ - entry->ae_stat.st_atime = t; - ARCHIVE_STAT_SET_ATIME_NANOS(&entry->ae_stat, ns); -} - -void -archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) -{ - entry->ae_stat.st_ctime = t; - ARCHIVE_STAT_SET_CTIME_NANOS(&entry->ae_stat, ns); -} - -/* Set symlink if symlink is already set, else set hardlink. */ -void -archive_entry_set_link(struct archive_entry *entry, const char *target) -{ - if (entry->ae_symlink.aes_mbs != NULL || - entry->ae_symlink.aes_wcs != NULL) - aes_set_mbs(&entry->ae_symlink, target); - else - aes_set_mbs(&entry->ae_hardlink, target); -} - -void -archive_entry_set_mode(struct archive_entry *entry, mode_t m) -{ - entry->ae_stat.st_mode = m; -} - -void -archive_entry_set_mtime(struct archive_entry *entry, time_t m, long ns) -{ - entry->ae_stat.st_mtime = m; - ARCHIVE_STAT_SET_MTIME_NANOS(&entry->ae_stat, ns); -} - -void -archive_entry_set_pathname(struct archive_entry *entry, const char *name) -{ - aes_set_mbs(&entry->ae_pathname, name); -} - -void -archive_entry_copy_pathname(struct archive_entry *entry, const char *name) -{ - aes_copy_mbs(&entry->ae_pathname, name); -} - -void -archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) -{ - aes_copy_wcs(&entry->ae_pathname, name); -} - -void -archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) -{ - dev_t d; - - d = entry->ae_stat.st_rdev; - entry->ae_stat.st_rdev = makedev(major(m), minor(d)); -} - -void -archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) -{ - dev_t d; - - d = entry->ae_stat.st_rdev; - entry->ae_stat.st_rdev = makedev(major(d), minor(m)); -} - -void -archive_entry_set_size(struct archive_entry *entry, int64_t s) -{ - entry->ae_stat.st_size = s; -} - -void -archive_entry_set_symlink(struct archive_entry *entry, const char *linkname) -{ - aes_set_mbs(&entry->ae_symlink, linkname); -} - -void -archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) -{ - aes_copy_wcs(&entry->ae_symlink, linkname); -} - -void -archive_entry_set_uid(struct archive_entry *entry, uid_t u) -{ - entry->ae_stat.st_uid = u; -} - -void -archive_entry_set_uname(struct archive_entry *entry, const char *name) -{ - aes_set_mbs(&entry->ae_uname, name); -} - -void -archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) -{ - aes_copy_wcs(&entry->ae_uname, name); -} - -/* - * ACL management. The following would, of course, be a lot simpler - * if: 1) the last draft of POSIX.1e were a really thorough and - * complete standard that addressed the needs of ACL archiving and 2) - * everyone followed it faithfully. Alas, neither is true, so the - * following is a lot more complex than might seem necessary to the - * uninitiated. - */ - -void -archive_entry_acl_clear(struct archive_entry *entry) -{ - struct ae_acl *ap; - - while (entry->acl_head != NULL) { - ap = entry->acl_head->next; - aes_clean(&entry->acl_head->name); - free(entry->acl_head); - entry->acl_head = ap; - } - if (entry->acl_text_w != NULL) { - free(entry->acl_text_w); - entry->acl_text_w = NULL; - } - entry->acl_p = NULL; - entry->acl_state = 0; /* Not counting. */ -} - -/* - * Add a single ACL entry to the internal list of ACL data. - */ -void -archive_entry_acl_add_entry(struct archive_entry *entry, - int type, int permset, int tag, int id, const char *name) -{ - struct ae_acl *ap; - - if (acl_special(entry, type, permset, tag) == 0) - return; - ap = acl_new_entry(entry, type, permset, tag, id); - if (ap == NULL) { - /* XXX Error XXX */ - return; - } - if (name != NULL && *name != '\0') - aes_copy_mbs(&ap->name, name); - else - aes_clean(&ap->name); -} - -/* - * As above, but with a wide-character name. - */ -void -archive_entry_acl_add_entry_w(struct archive_entry *entry, - int type, int permset, int tag, int id, const wchar_t *name) -{ - struct ae_acl *ap; - - if (acl_special(entry, type, permset, tag) == 0) - return; - ap = acl_new_entry(entry, type, permset, tag, id); - if (ap == NULL) { - /* XXX Error XXX */ - return; - } - if (name != NULL && *name != L'\0') - aes_copy_wcs(&ap->name, name); - else - aes_clean(&ap->name); -} - -/* - * If this ACL entry is part of the standard POSIX permissions set, - * store the permissions in the stat structure and return zero. - */ -static int -acl_special(struct archive_entry *entry, int type, int permset, int tag) -{ - if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { - switch (tag) { - case ARCHIVE_ENTRY_ACL_USER_OBJ: - entry->ae_stat.st_mode &= ~0700; - entry->ae_stat.st_mode |= (permset & 7) << 6; - return (0); - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - entry->ae_stat.st_mode &= ~0070; - entry->ae_stat.st_mode |= (permset & 7) << 3; - return (0); - case ARCHIVE_ENTRY_ACL_OTHER: - entry->ae_stat.st_mode &= ~0007; - entry->ae_stat.st_mode |= permset & 7; - return (0); - } - } - return (1); -} - -/* - * Allocate and populate a new ACL entry with everything but the - * name. - */ -static struct ae_acl * -acl_new_entry(struct archive_entry *entry, - int type, int permset, int tag, int id) -{ - struct ae_acl *ap; - - if (type != ARCHIVE_ENTRY_ACL_TYPE_ACCESS && - type != ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) - return (NULL); - if (entry->acl_text_w != NULL) { - free(entry->acl_text_w); - entry->acl_text_w = NULL; - } - - /* XXX TODO: More sanity-checks on the arguments XXX */ - - /* If there's a matching entry already in the list, overwrite it. */ - for (ap = entry->acl_head; ap != NULL; ap = ap->next) { - if (ap->type == type && ap->tag == tag && ap->id == id) { - ap->permset = permset; - return (ap); - } - } - - /* Add a new entry to the list. */ - ap = malloc(sizeof(*ap)); - if (ap == NULL) - return (NULL); - memset(ap, 0, sizeof(*ap)); - ap->next = entry->acl_head; - entry->acl_head = ap; - ap->type = type; - ap->tag = tag; - ap->id = id; - ap->permset = permset; - return (ap); -} - -/* - * Return a count of entries matching "want_type". - */ -int -archive_entry_acl_count(struct archive_entry *entry, int want_type) -{ - int count; - struct ae_acl *ap; - - count = 0; - ap = entry->acl_head; - while (ap != NULL) { - if ((ap->type & want_type) != 0) - count++; - ap = ap->next; - } - - if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) - count += 3; - return (count); -} - -/* - * Prepare for reading entries from the ACL data. Returns a count - * of entries matching "want_type", or zero if there are no - * non-extended ACL entries of that type. - */ -int -archive_entry_acl_reset(struct archive_entry *entry, int want_type) -{ - int count, cutoff; - - count = archive_entry_acl_count(entry, want_type); - - /* - * If the only entries are the three standard ones, - * then don't return any ACL data. (In this case, - * client can just use chmod(2) to set permissions.) - */ - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) - cutoff = 3; - else - cutoff = 0; - - if (count > cutoff) - entry->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ; - else - entry->acl_state = 0; - entry->acl_p = entry->acl_head; - return (count); -} - -/* - * Return the next ACL entry in the list. Fake entries for the - * standard permissions and include them in the returned list. - */ - -int -archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, - int *permset, int *tag, int *id, const char **name) -{ - *name = NULL; - *id = -1; - - /* - * The acl_state is either zero (no entries available), -1 - * (reading from list), or an entry type (retrieve that type - * from ae_stat.st_mode). - */ - if (entry->acl_state == 0) - return (ARCHIVE_WARN); - - /* The first three access entries are special. */ - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - switch (entry->acl_state) { - case ARCHIVE_ENTRY_ACL_USER_OBJ: - *permset = (entry->ae_stat.st_mode >> 6) & 7; - *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - *tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - entry->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - return (ARCHIVE_OK); - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - *permset = (entry->ae_stat.st_mode >> 3) & 7; - *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - *tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - entry->acl_state = ARCHIVE_ENTRY_ACL_OTHER; - return (ARCHIVE_OK); - case ARCHIVE_ENTRY_ACL_OTHER: - *permset = entry->ae_stat.st_mode & 7; - *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - *tag = ARCHIVE_ENTRY_ACL_OTHER; - entry->acl_state = -1; - entry->acl_p = entry->acl_head; - return (ARCHIVE_OK); - default: - break; - } - } - - while (entry->acl_p != NULL && (entry->acl_p->type & want_type) == 0) - entry->acl_p = entry->acl_p->next; - if (entry->acl_p == NULL) { - entry->acl_state = 0; - return (ARCHIVE_WARN); - } - *type = entry->acl_p->type; - *permset = entry->acl_p->permset; - *tag = entry->acl_p->tag; - *id = entry->acl_p->id; - *name = aes_get_mbs(&entry->acl_p->name); - entry->acl_p = entry->acl_p->next; - return (ARCHIVE_OK); -} - -/* - * Generate a text version of the ACL. The flags parameter controls - * the style of the generated ACL. - */ -const wchar_t * -archive_entry_acl_text_w(struct archive_entry *entry, int flags) -{ - int count; - int length; - const wchar_t *wname; - const wchar_t *prefix; - wchar_t separator; - struct ae_acl *ap; - int id; - wchar_t *wp; - - if (entry->acl_text_w != NULL) { - free (entry->acl_text_w); - entry->acl_text_w = NULL; - } - - separator = L','; - count = 0; - length = 0; - ap = entry->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - length += 1; /* colon */ - wname = aes_get_wcs(&ap->name); - if (wname != NULL) - length += wcslen(wname); - length ++; /* colon */ - length += 3; /* rwx */ - length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ - } - ap = ap->next; - } - - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } - - if (count == 0) - return (NULL); - - /* Now, allocate the string and actually populate it. */ - wp = entry->acl_text_w = malloc(length * sizeof(wchar_t)); - if (wp == NULL) - __archive_errx(1, "No memory to generate the text version of the ACL"); - count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, - entry->ae_stat.st_mode & 0700, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, - entry->ae_stat.st_mode & 0070, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, - entry->ae_stat.st_mode & 0007, -1); - count += 3; - - ap = entry->acl_head; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - wname = aes_get_wcs(&ap->name); - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, NULL, ap->tag, wname, - ap->permset, id); - count++; - } - ap = ap->next; - } - } - - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) - prefix = L"default:"; - else - prefix = NULL; - ap = entry->acl_head; - count = 0; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - wname = aes_get_wcs(&ap->name); - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, prefix, ap->tag, - wname, ap->permset, id); - count ++; - } - ap = ap->next; - } - } - - return (entry->acl_text_w); -} - -static void -append_id_w(wchar_t **wp, int id) -{ - if (id > 9) - append_id_w(wp, id / 10); - *(*wp)++ = L"0123456789"[id % 10]; -} - -static void -append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id) -{ - if (prefix != NULL) { - wcscpy(*wp, prefix); - *wp += wcslen(*wp); - } - switch (tag) { - case ARCHIVE_ENTRY_ACL_USER_OBJ: - wname = NULL; - id = -1; - /* FALL THROUGH */ - case ARCHIVE_ENTRY_ACL_USER: - wcscpy(*wp, L"user"); - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - wname = NULL; - id = -1; - /* FALL THROUGH */ - case ARCHIVE_ENTRY_ACL_GROUP: - wcscpy(*wp, L"group"); - break; - case ARCHIVE_ENTRY_ACL_MASK: - wcscpy(*wp, L"mask"); - wname = NULL; - id = -1; - break; - case ARCHIVE_ENTRY_ACL_OTHER: - wcscpy(*wp, L"other"); - wname = NULL; - id = -1; - break; - } - *wp += wcslen(*wp); - *(*wp)++ = L':'; - if (wname != NULL) { - wcscpy(*wp, wname); - *wp += wcslen(*wp); - } - *(*wp)++ = L':'; - *(*wp)++ = (perm & 0444) ? L'r' : L'-'; - *(*wp)++ = (perm & 0222) ? L'w' : L'-'; - *(*wp)++ = (perm & 0111) ? L'x' : L'-'; - if (id != -1) { - *(*wp)++ = L':'; - append_id_w(wp, id); - } - **wp = L'\0'; -} - -/* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". - */ -int -__archive_entry_acl_parse_w(struct archive_entry *entry, - const wchar_t *text, int default_type) -{ - int type, tag, permset, id; - const wchar_t *start, *end; - const wchar_t *name_start, *name_end; - wchar_t sep; - wchar_t *namebuff; - int namebuff_length; - - name_start = name_end = NULL; - namebuff = NULL; - namebuff_length = 0; - - while (text != NULL && *text != L'\0') { - next_field_w(&text, &start, &end, &sep); - if (sep != L':') - goto fail; - - /* - * Solaris extension: "defaultuser::rwx" is the - * default ACL corresponding to "user::rwx", etc. - */ - if (end-start > 7 && wmemcmp(start, L"default", 7) == 0) { - type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - start += 7; - } else - type = default_type; - - if (prefix_w(start, end, L"user")) { - next_field_w(&text, &start, &end, &sep); - if (sep != L':') - goto fail; - if (end > start) { - tag = ARCHIVE_ENTRY_ACL_USER; - name_start = start; - name_end = end; - } else - tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix_w(start, end, L"group")) { - next_field_w(&text, &start, &end, &sep); - if (sep != L':') - goto fail; - if (end > start) { - tag = ARCHIVE_ENTRY_ACL_GROUP; - name_start = start; - name_end = end; - } else - tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix_w(start, end, L"other")) { - next_field_w(&text, &start, &end, &sep); - if (sep != L':') - goto fail; - if (end > start) - goto fail; - tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix_w(start, end, L"mask")) { - next_field_w(&text, &start, &end, &sep); - if (sep != L':') - goto fail; - if (end > start) - goto fail; - tag = ARCHIVE_ENTRY_ACL_MASK; - } else - goto fail; - - next_field_w(&text, &start, &end, &sep); - permset = 0; - while (start < end) { - switch (*start++) { - case 'r': case 'R': - permset |= ARCHIVE_ENTRY_ACL_READ; - break; - case 'w': case 'W': - permset |= ARCHIVE_ENTRY_ACL_WRITE; - break; - case 'x': case 'X': - permset |= ARCHIVE_ENTRY_ACL_EXECUTE; - break; - case '-': - break; - default: - goto fail; - } - } - - /* - * Support star-compatible numeric UID/GID extension. - * This extension adds a ":" followed by the numeric - * ID so that "group:groupname:rwx", for example, - * becomes "group:groupname:rwx:999", where 999 is the - * numeric GID. This extension makes it possible, for - * example, to correctly restore ACLs on a system that - * might have a damaged passwd file or be disconnected - * from a central NIS server. This extension is compatible - * with POSIX.1e draft 17. - */ - if (sep == L':' && (tag == ARCHIVE_ENTRY_ACL_USER || - tag == ARCHIVE_ENTRY_ACL_GROUP)) { - next_field_w(&text, &start, &end, &sep); - - id = 0; - while (start < end && *start >= '0' && *start <= '9') { - if (id > (INT_MAX / 10)) - id = INT_MAX; - else { - id *= 10; - id += *start - '0'; - start++; - } - } - } else - id = -1; /* No id specified. */ - - /* Skip any additional entries. */ - while (sep == L':') { - next_field_w(&text, &start, &end, &sep); - } - - /* Add entry to the internal list. */ - if (name_end == name_start) { - archive_entry_acl_add_entry_w(entry, type, permset, - tag, id, NULL); - } else { - if (namebuff_length <= name_end - name_start) { - if (namebuff != NULL) - free(namebuff); - namebuff_length = name_end - name_start + 256; - namebuff = - malloc(namebuff_length * sizeof(wchar_t)); - if (namebuff == NULL) - goto fail; - } - wmemcpy(namebuff, name_start, name_end - name_start); - namebuff[name_end - name_start] = L'\0'; - archive_entry_acl_add_entry_w(entry, type, - permset, tag, id, namebuff); - } - } - if (namebuff != NULL) - free(namebuff); - return (ARCHIVE_OK); - -fail: - if (namebuff != NULL) - free(namebuff); - return (ARCHIVE_WARN); -} - -/* - * extended attribute handling - */ - -void -archive_entry_xattr_clear(struct archive_entry *entry) -{ - struct ae_xattr *xp; - - while (entry->xattr_head != NULL) { - xp = entry->xattr_head->next; - free(entry->xattr_head->name); - free(entry->xattr_head->value); - free(entry->xattr_head); - entry->xattr_head = xp; - } - - entry->xattr_head = NULL; -} - -void -archive_entry_xattr_add_entry(struct archive_entry *entry, - const char *name, const void *value, size_t size) -{ - struct ae_xattr *xp; - - for (xp = entry->xattr_head; xp != NULL; xp = xp->next) - ; - - if ((xp = malloc(sizeof(struct ae_xattr))) == NULL) - /* XXX Error XXX */ - return; - - xp->name = strdup(name); - if ((xp -> value = malloc(size)) != NULL) { - memcpy(xp -> value, value, size); - xp -> size = size; - } else - xp -> size = 0; - - xp->next = entry->xattr_head; - entry->xattr_head = xp; -} - - -/* - * returns number of the extended attribute entries - */ -int -archive_entry_xattr_count(struct archive_entry *entry) -{ - struct ae_xattr *xp; - int count = 0; - - for (xp = entry->xattr_head; xp != NULL; xp = xp->next) - count++; - - return count; -} - -int -archive_entry_xattr_reset(struct archive_entry * entry) -{ - entry->xattr_p = entry->xattr_head; - - return archive_entry_xattr_count(entry); -} - -int -archive_entry_xattr_next(struct archive_entry * entry, - const char **name, const void **value, size_t *size) -{ - if (entry->xattr_p) { - *name = entry->xattr_p->name; - *value = entry->xattr_p->value; - *size = entry->xattr_p->size; - - entry->xattr_p = entry->xattr_p->next; - - return (ARCHIVE_OK); - } else { - *name = NULL; - *name = NULL; - *size = (size_t)0; - return (ARCHIVE_WARN); - } -} - -/* - * end of xattr handling - */ - -/* - * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated - * to point to just after the separator. *start points to the first - * character of the matched text and *end just after the last - * character of the matched identifier. In particular *end - *start - * is the length of the field body, not including leading or trailing - * whitespace. - */ -static void -next_field_w(const wchar_t **wp, const wchar_t **start, - const wchar_t **end, wchar_t *sep) -{ - /* Skip leading whitespace to find start of field. */ - while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') { - (*wp)++; - } - *start = *wp; - - /* Scan for the separator. */ - while (**wp != L'\0' && **wp != L',' && **wp != L':' && - **wp != L'\n') { - (*wp)++; - } - *sep = **wp; - - /* Trim trailing whitespace to locate end of field. */ - *end = *wp - 1; - while (**end == L' ' || **end == L'\t' || **end == L'\n') { - (*end)--; - } - (*end)++; - - /* Adjust scanner location. */ - if (**wp != L'\0') - (*wp)++; -} - -static int -prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test) -{ - if (start == end) - return (0); - - if (*start++ != *test++) - return (0); - - while (start < end && *start++ == *test++) - ; - - if (start < end) - return (0); - - return (1); -} - - -/* - * Following code is modified from UC Berkeley sources, and - * is subject to the following copyright notice. - */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -static struct flag { - const char *name; - const wchar_t *wname; - unsigned long set; - unsigned long clear; -} flags[] = { - /* Preferred (shorter) names per flag first, all prefixed by "no" */ -#ifdef SF_APPEND - { "nosappnd", L"nosappnd", SF_APPEND, 0 }, - { "nosappend", L"nosappend", SF_APPEND, 0 }, -#endif -#ifdef EXT2_APPEND_FL /* 'a' */ - { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 }, - { "nosappend", L"nosappend", EXT2_APPEND_FL, 0 }, -#endif -#ifdef SF_ARCHIVED - { "noarch", L"noarch", SF_ARCHIVED, 0 }, - { "noarchived", L"noarchived", SF_ARCHIVED, 0 }, -#endif -#ifdef SF_IMMUTABLE - { "noschg", L"noschg", SF_IMMUTABLE, 0 }, - { "noschange", L"noschange", SF_IMMUTABLE, 0 }, - { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 }, -#endif -#ifdef EXT2_IMMUTABLE_FL /* 'i' */ - { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 }, - { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 }, - { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 }, -#endif -#ifdef SF_NOUNLINK - { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0 }, - { "nosunlink", L"nosunlink", SF_NOUNLINK, 0 }, -#endif -#ifdef SF_SNAPSHOT - { "nosnapshot", L"nosnapshot", SF_SNAPSHOT, 0 }, -#endif -#ifdef UF_APPEND - { "nouappnd", L"nouappnd", UF_APPEND, 0 }, - { "nouappend", L"nouappend", UF_APPEND, 0 }, -#endif -#ifdef UF_IMMUTABLE - { "nouchg", L"nouchg", UF_IMMUTABLE, 0 }, - { "nouchange", L"nouchange", UF_IMMUTABLE, 0 }, - { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0 }, -#endif -#ifdef UF_NODUMP - { "nodump", L"nodump", 0, UF_NODUMP}, -#endif -#ifdef EXT2_NODUMP_FL /* 'd' */ - { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, -#endif -#ifdef UF_OPAQUE - { "noopaque", L"noopaque", UF_OPAQUE, 0 }, -#endif -#ifdef UF_NOUNLINK - { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 }, - { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 }, -#endif -#ifdef EXT2_COMPR_FL /* 'c' */ - { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 }, -#endif - -#ifdef EXT2_NOATIME_FL /* 'A' */ - { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, -#endif - { NULL, NULL, 0, 0 } -}; - -/* - * fflagstostr -- - * Convert file flags to a comma-separated string. If no flags - * are set, return the empty string. - */ -char * -ae_fflagstostr(unsigned long bitset, unsigned long bitclear) -{ - char *string, *dp; - const char *sp; - unsigned long bits; - struct flag *flag; - int length; - - bits = bitset | bitclear; - length = 0; - for (flag = flags; flag->name != NULL; flag++) - if (bits & (flag->set | flag->clear)) { - length += strlen(flag->name) + 1; - bits &= ~(flag->set | flag->clear); - } - - if (length == 0) - return (NULL); - string = malloc(length); - if (string == NULL) - return (NULL); - - dp = string; - for (flag = flags; flag->name != NULL; flag++) { - if (bitset & flag->set || bitclear & flag->clear) { - sp = flag->name + 2; - } else if (bitset & flag->clear || bitclear & flag->set) { - sp = flag->name; - } else - continue; - bitset &= ~(flag->set | flag->clear); - bitclear &= ~(flag->set | flag->clear); - if (dp > string) - *dp++ = ','; - while ((*dp++ = *sp++) != '\0') - ; - dp--; - } - - *dp = '\0'; - return (string); -} - -/* - * wcstofflags -- - * Take string of arguments and return file flags. This - * version works a little differently than strtofflags(3). - * In particular, it always tests every token, skipping any - * unrecognized tokens. It returns a pointer to the first - * unrecognized token, or NULL if every token was recognized. - * This version is also const-correct and does not modify the - * provided string. - */ -const wchar_t * -ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) -{ - const wchar_t *start, *end; - struct flag *flag; - unsigned long set, clear; - const wchar_t *failed; - - set = clear = 0; - start = s; - failed = NULL; - /* Find start of first token. */ - while (*start == L'\t' || *start == L' ' || *start == L',') - start++; - while (*start != L'\0') { - /* Locate end of token. */ - end = start; - while (*end != L'\0' && *end != L'\t' && - *end != L' ' && *end != L',') - end++; - for (flag = flags; flag->wname != NULL; flag++) { - if (wmemcmp(start, flag->wname, end - start) == 0) { - /* Matched "noXXXX", so reverse the sense. */ - clear |= flag->set; - set |= flag->clear; - break; - } else if (wmemcmp(start, flag->wname + 2, end - start) - == 0) { - /* Matched "XXXX", so don't reverse. */ - set |= flag->set; - clear |= flag->clear; - break; - } - } - /* Ignore unknown flag names. */ - if (flag->wname == NULL && failed == NULL) - failed = start; - - /* Find start of next token. */ - start = end; - while (*start == L'\t' || *start == L' ' || *start == L',') - start++; - - } - - if (setp) - *setp = set; - if (clrp) - *clrp = clear; - - /* Return location of first failure. */ - return (failed); -} - - -#ifdef TEST -#include -int -main(int argc, char **argv) -{ - struct archive_entry *entry = archive_entry_new(); - unsigned long set, clear; - const wchar_t *remainder; - - remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); - archive_entry_fflags(entry, &set, &clear); - - wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); - - wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); - return (0); -} -#endif diff --git a/contrib/libarchive-1.3.1/libarchive/archive_entry.h b/contrib/libarchive-1.3.1/libarchive/archive_entry.h deleted file mode 100644 index 6bf89574c6..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_entry.h +++ /dev/null @@ -1,251 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/lib/libarchive/archive_entry.h,v 1.19 2006/03/21 16:55:46 kientzle Exp $ - */ - -#ifndef ARCHIVE_ENTRY_H_INCLUDED -#define ARCHIVE_ENTRY_H_INCLUDED - -#include /* for wchar_t */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Description of an archive entry. - * - * Basically, a "struct stat" with a few text fields added in. - * - * TODO: Add "comment", "charset", and possibly other entries that are - * supported by "pax interchange" format. However, GNU, ustar, cpio, - * and other variants don't support these features, so they're not an - * excruciatingly high priority right now. - * - * TODO: "pax interchange" format allows essentially arbitrary - * key/value attributes to be attached to any entry. Supporting - * such extensions may make this library useful for special - * applications (e.g., a package manager could attach special - * package-management attributes to each entry). - */ -struct archive_entry; - -/* - * Basic object manipulation - */ - -struct archive_entry *archive_entry_clear(struct archive_entry *); -/* The 'clone' function does a deep copy; all of the strings are copied too. */ -struct archive_entry *archive_entry_clone(struct archive_entry *); -void archive_entry_free(struct archive_entry *); -struct archive_entry *archive_entry_new(void); - -/* - * Retrieve fields from an archive_entry. - */ - -time_t archive_entry_atime(struct archive_entry *); -long archive_entry_atime_nsec(struct archive_entry *); -time_t archive_entry_ctime(struct archive_entry *); -long archive_entry_ctime_nsec(struct archive_entry *); -dev_t archive_entry_dev(struct archive_entry *); -void archive_entry_fflags(struct archive_entry *, - unsigned long *set, unsigned long *clear); -const char *archive_entry_fflags_text(struct archive_entry *); -gid_t archive_entry_gid(struct archive_entry *); -const char *archive_entry_gname(struct archive_entry *); -const wchar_t *archive_entry_gname_w(struct archive_entry *); -const char *archive_entry_hardlink(struct archive_entry *); -const wchar_t *archive_entry_hardlink_w(struct archive_entry *); -ino_t archive_entry_ino(struct archive_entry *); -mode_t archive_entry_mode(struct archive_entry *); -time_t archive_entry_mtime(struct archive_entry *); -long archive_entry_mtime_nsec(struct archive_entry *); -const char *archive_entry_pathname(struct archive_entry *); -const wchar_t *archive_entry_pathname_w(struct archive_entry *); -dev_t archive_entry_rdev(struct archive_entry *); -dev_t archive_entry_rdevmajor(struct archive_entry *); -dev_t archive_entry_rdevminor(struct archive_entry *); -int64_t archive_entry_size(struct archive_entry *); -const struct stat *archive_entry_stat(struct archive_entry *); -const char *archive_entry_symlink(struct archive_entry *); -const wchar_t *archive_entry_symlink_w(struct archive_entry *); -uid_t archive_entry_uid(struct archive_entry *); -const char *archive_entry_uname(struct archive_entry *); -const wchar_t *archive_entry_uname_w(struct archive_entry *); - -/* - * Set fields in an archive_entry. - * - * Note that string 'set' functions do not copy the string, only the pointer. - * In contrast, 'copy' functions do copy the object pointed to. - */ - -void archive_entry_copy_stat(struct archive_entry *, const struct stat *); -void archive_entry_set_atime(struct archive_entry *, time_t, long); -void archive_entry_set_ctime(struct archive_entry *, time_t, long); -void archive_entry_set_fflags(struct archive_entry *, - unsigned long set, unsigned long clear); -/* Returns pointer to start of first invalid token, or NULL if none. */ -/* Note that all recognized tokens are processed, regardless. */ -const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, - const wchar_t *); -void archive_entry_set_gid(struct archive_entry *, gid_t); -void archive_entry_set_gname(struct archive_entry *, const char *); -void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_hardlink(struct archive_entry *, const char *); -void archive_entry_copy_hardlink(struct archive_entry *, const char *); -void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_link(struct archive_entry *, const char *); -void archive_entry_set_mode(struct archive_entry *, mode_t); -void archive_entry_set_mtime(struct archive_entry *, time_t, long); -void archive_entry_set_pathname(struct archive_entry *, const char *); -void archive_entry_copy_pathname(struct archive_entry *, const char *); -void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); -void archive_entry_set_rdevminor(struct archive_entry *, dev_t); -void archive_entry_set_size(struct archive_entry *, int64_t); -void archive_entry_set_symlink(struct archive_entry *, const char *); -void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_uid(struct archive_entry *, uid_t); -void archive_entry_set_uname(struct archive_entry *, const char *); -void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); - -/* - * ACL routines. This used to simply store and return text-format ACL - * strings, but that proved insufficient for a number of reasons: - * = clients need control over uname/uid and gname/gid mappings - * = there are many different ACL text formats - * = would like to be able to read/convert archives containing ACLs - * on platforms that lack ACL libraries - */ - -/* - * Permission bits mimic POSIX.1e. Note that I've not followed POSIX.1e's - * "permset"/"perm" abstract type nonsense. A permset is just a simple - * bitmap, following long-standing Unix tradition. - */ -#define ARCHIVE_ENTRY_ACL_EXECUTE 1 -#define ARCHIVE_ENTRY_ACL_WRITE 2 -#define ARCHIVE_ENTRY_ACL_READ 4 - -/* We need to be able to specify either or both of these. */ -#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 -#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 - -/* Tag values mimic POSIX.1e */ -#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ -#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ -#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ -#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ -#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access. */ -#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public. */ - -/* - * Set the ACL by clearing it and adding entries one at a time. - * Unlike the POSIX.1e ACL routines, you must specify the type - * (access/default) for each entry. Internally, the ACL data is just - * a soup of entries. API calls here allow you to retrieve just the - * entries of interest. This design (which goes against the spirit of - * POSIX.1e) is useful for handling archive formats that combine - * default and access information in a single ACL list. - */ -void archive_entry_acl_clear(struct archive_entry *); -void archive_entry_acl_add_entry(struct archive_entry *, - int type, int permset, int tag, int qual, const char *name); -void archive_entry_acl_add_entry_w(struct archive_entry *, - int type, int permset, int tag, int qual, const wchar_t *name); - -/* - * To retrieve the ACL, first "reset", then repeatedly ask for the - * "next" entry. The want_type parameter allows you to request only - * access entries or only default entries. - */ -int archive_entry_acl_reset(struct archive_entry *, int want_type); -int archive_entry_acl_next(struct archive_entry *, int want_type, - int *type, int *permset, int *tag, int *qual, const char **name); -int archive_entry_acl_next_w(struct archive_entry *, int want_type, - int *type, int *permset, int *tag, int *qual, - const wchar_t **name); - -/* - * Construct a text-format ACL. The flags argument is a bitmask that - * can include any of the following: - * - * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include access entries. - * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include default entries. - * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in - * each ACL entry. (As used by 'star'.) - * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each - * default ACL entry. - */ -#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 -#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 -const wchar_t *archive_entry_acl_text_w(struct archive_entry *, int flags); - -/* Return a count of entries matching 'want_type' */ -int archive_entry_acl_count(struct archive_entry *, int want_type); - -/* - * Private ACL parser. This is private because it handles some - * very weird formats that clients should not be messing with. - * Clients should only deal with their platform-native formats. - * Because of the need to support many formats cleanly, new arguments - * are likely to get added on a regular basis. Clients who try to use - * this interface are likely to be surprised when it changes. - * - * You were warned! - */ -int __archive_entry_acl_parse_w(struct archive_entry *, - const wchar_t *, int type); - - -#ifdef __cplusplus -} -#endif - -/* - * extended attributes - */ - -void archive_entry_xattr_clear(struct archive_entry *); -void archive_entry_xattr_add_entry(struct archive_entry *, - const char *name, const void *value, size_t size); - -/* - * To retrieve the xattr list, first "reset", then repeatedly ask for the - * "next" entry. - */ - -int archive_entry_xattr_count(struct archive_entry *); -int archive_entry_xattr_reset(struct archive_entry *); -int archive_entry_xattr_next(struct archive_entry *, - const char **name, const void **value, size_t *); - - -#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_platform.h b/contrib/libarchive-1.3.1/libarchive/archive_platform.h deleted file mode 100644 index 8f860582c0..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_platform.h +++ /dev/null @@ -1,193 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/lib/libarchive/archive_platform.h,v 1.20 2006/03/08 01:56:06 kientzle Exp $ - */ - -/* - * This header is the first thing included in any of the libarchive - * source files. As far as possible, platform-specific issues should - * be dealt with here and not within individual source files. I'm - * actively trying to minimize #if blocks within the main source, - * since they obfuscate the code. - */ - -#ifndef ARCHIVE_PLATFORM_H_INCLUDED -#define ARCHIVE_PLATFORM_H_INCLUDED - -#if HAVE_CONFIG_H -#include "../config.h" -#else - -/* A default configuration for FreeBSD, used if there is no config.h. */ -#ifdef __FreeBSD__ -#if __FreeBSD__ > 4 -#define HAVE_ACL_CREATE_ENTRY 1 -#define HAVE_ACL_INIT 1 -#define HAVE_ACL_SET_FD 1 -#define HAVE_ACL_SET_FD_NP 1 -#define HAVE_ACL_SET_FILE 1 -#define HAVE_ACL_USER 1 -#endif -#define HAVE_BZLIB_H 1 -#define HAVE_CHFLAGS 1 -#define HAVE_DECL_STRERROR_R 1 -#define HAVE_EFTYPE 1 -#define HAVE_EILSEQ 1 -#define HAVE_ERRNO_H 1 -#define HAVE_FCHDIR 1 -#define HAVE_FCHFLAGS 1 -#define HAVE_FCHMOD 1 -#define HAVE_FCHOWN 1 -#define HAVE_FCNTL_H 1 -#define HAVE_FUTIMES 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_LCHFLAGS 1 -#define HAVE_LCHMOD 1 -#define HAVE_LCHOWN 1 -#define HAVE_LIMITS_H 1 -#define HAVE_LUTIMES 1 -#define HAVE_MALLOC 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMORY_H 1 -#define HAVE_MEMSET 1 -#define HAVE_MKDIR 1 -#define HAVE_MKFIFO 1 -#define HAVE_PATHS_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRCHR 1 -#define HAVE_STRDUP 1 -#define HAVE_STRERROR 1 -#define HAVE_STRERROR_R 1 -#define HAVE_STRINGS_H 1 -#define HAVE_STRING_H 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_STAT_ST_RDEV 1 -#define HAVE_SYS_ACL_H 1 -#define HAVE_SYS_IOCTL_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_SYS_WAIT_H 1 -#define HAVE_TIMEGM 1 -#define HAVE_UNISTD_H 1 -#define HAVE_WCHAR_H 1 -#define HAVE_ZLIB_H 1 -#define STDC_HEADERS 1 -#define TIME_WITH_SYS_TIME 1 -#else /* !__FreeBSD__ */ -/* Warn if the library hasn't been (automatically or manually) configured. */ -#error Oops: No config.h and no built-in configuration in archive_platform.h. -#endif /* !__FreeBSD__ */ - -#endif /* !HAVE_CONFIG_H */ - -/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ -#ifdef __FreeBSD__ -#include /* For __FBSDID */ -#else -#define __FBSDID(a) /* null */ -#endif - -#if HAVE_INTTYPES_H -#include -#endif - -/* FreeBSD 4 and earlier lack intmax_t/uintmax_t */ -#if defined(__FreeBSD__) && __FreeBSD__ < 5 -#define intmax_t int64_t -#define uintmax_t uint64_t -#endif - -/* - * If this platform has , acl_create(), acl_init(), - * acl_set_file(), and ACL_USER, we assume it has the rest of the - * POSIX.1e draft functions used in archive_read_extract.c. - */ -#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER -#define HAVE_POSIX_ACL 1 -#endif - -/* - * If we can't restore metadata using a file descriptor, then - * for compatibility's sake, close files before trying to restore metadata. - */ -#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN) -#define CAN_RESTORE_METADATA_FD -#endif - -/* Set up defaults for internal error codes. */ -#ifndef ARCHIVE_ERRNO_FILE_FORMAT -#if HAVE_EFTYPE -#define ARCHIVE_ERRNO_FILE_FORMAT EFTYPE -#else -#if HAVE_EILSEQ -#define ARCHIVE_ERRNO_FILE_FORMAT EILSEQ -#else -#define ARCHIVE_ERRNO_FILE_FORMAT EINVAL -#endif -#endif -#endif - -#ifndef ARCHIVE_ERRNO_PROGRAMMER -#define ARCHIVE_ERRNO_PROGRAMMER EINVAL -#endif - -#ifndef ARCHIVE_ERRNO_MISC -#define ARCHIVE_ERRNO_MISC (-1) -#endif - -/* Select the best way to set/get hi-res timestamps. */ -#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC -/* FreeBSD uses "timespec" members. */ -#define ARCHIVE_STAT_ATIME_NANOS(st) (st)->st_atimespec.tv_nsec -#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctimespec.tv_nsec -#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtimespec.tv_nsec -#define ARCHIVE_STAT_SET_ATIME_NANOS(st, n) (st)->st_atimespec.tv_nsec = (n) -#define ARCHIVE_STAT_SET_CTIME_NANOS(st, n) (st)->st_ctimespec.tv_nsec = (n) -#define ARCHIVE_STAT_SET_MTIME_NANOS(st, n) (st)->st_mtimespec.tv_nsec = (n) -#else -#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC -/* Linux uses "tim" members. */ -#define ARCHIVE_STAT_ATIME_NANOS(pstat) (pstat)->st_atim.tv_nsec -#define ARCHIVE_STAT_CTIME_NANOS(pstat) (pstat)->st_ctim.tv_nsec -#define ARCHIVE_STAT_MTIME_NANOS(pstat) (pstat)->st_mtim.tv_nsec -#define ARCHIVE_STAT_SET_ATIME_NANOS(st, n) (st)->st_atim.tv_nsec = (n) -#define ARCHIVE_STAT_SET_CTIME_NANOS(st, n) (st)->st_ctim.tv_nsec = (n) -#define ARCHIVE_STAT_SET_MTIME_NANOS(st, n) (st)->st_mtim.tv_nsec = (n) -#else -/* If we can't find a better way, just use stubs. */ -#define ARCHIVE_STAT_ATIME_NANOS(pstat) 0 -#define ARCHIVE_STAT_CTIME_NANOS(pstat) 0 -#define ARCHIVE_STAT_MTIME_NANOS(pstat) 0 -#define ARCHIVE_STAT_SET_ATIME_NANOS(st, n) -#define ARCHIVE_STAT_SET_CTIME_NANOS(st, n) -#define ARCHIVE_STAT_SET_MTIME_NANOS(st, n) -#endif -#endif - -#endif /* !ARCHIVE_H_INCLUDED */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_private.h b/contrib/libarchive-1.3.1/libarchive/archive_private.h deleted file mode 100644 index e4c5c4fdf4..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_private.h +++ /dev/null @@ -1,246 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/lib/libarchive/archive_private.h,v 1.23 2006/09/05 05:59:45 kientzle Exp $ - */ - -#ifndef ARCHIVE_PRIVATE_H_INCLUDED -#define ARCHIVE_PRIVATE_H_INCLUDED - -#include "archive.h" -#include "archive_string.h" - -#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU) -#define ARCHIVE_READ_MAGIC (0xdeb0c5U) - -struct archive { - /* - * The magic/state values are used to sanity-check the - * client's usage. If an API function is called at a - * rediculous time, or the client passes us an invalid - * pointer, these values allow me to catch that. - */ - unsigned magic; - unsigned state; - - struct archive_entry *entry; - uid_t user_uid; /* UID of current user. */ - - /* Dev/ino of the archive being read/written. */ - dev_t skip_file_dev; - ino_t skip_file_ino; - - /* Utility: Pointer to a block of nulls. */ - const unsigned char *nulls; - size_t null_length; - - /* - * Used by archive_read_data() to track blocks and copy - * data to client buffers, filling gaps with zero bytes. - */ - const char *read_data_block; - off_t read_data_offset; - off_t read_data_output_offset; - size_t read_data_remaining; - - /* Callbacks to open/read/write/close archive stream. */ - archive_open_callback *client_opener; - archive_read_callback *client_reader; - archive_skip_callback *client_skipper; - archive_write_callback *client_writer; - archive_close_callback *client_closer; - void *client_data; - - /* - * Blocking information. Note that bytes_in_last_block is - * misleadingly named; I should find a better name. These - * control the final output from all compressors, including - * compression_none. - */ - int bytes_per_block; - int bytes_in_last_block; - - /* - * These control whether data within a gzip/bzip2 compressed - * stream gets padded or not. If pad_uncompressed is set, - * the data will be padded to a full block before being - * compressed. The pad_uncompressed_byte determines the value - * that will be used for padding. Note that these have no - * effect on compression "none." - */ - int pad_uncompressed; - int pad_uncompressed_byte; /* TODO: Support this. */ - - /* Position in UNCOMPRESSED data stream. */ - off_t file_position; - /* Position in COMPRESSED data stream. */ - off_t raw_position; - /* File offset of beginning of most recently-read header. */ - off_t header_position; - - /* - * Detection functions for decompression: bid functions are - * given a block of data from the beginning of the stream and - * can bid on whether or not they support the data stream. - * General guideline: bid the number of bits that you actually - * test, e.g., 16 if you test a 2-byte magic value. The - * highest bidder will have their init function invoked, which - * can set up pointers to specific handlers. - * - * On write, the client just invokes an archive_write_set function - * which sets up the data here directly. - */ - int compression_code; /* Currently active compression. */ - const char *compression_name; - struct { - int (*bid)(const void *buff, size_t); - int (*init)(struct archive *, const void *buff, size_t); - } decompressors[4]; - /* Read/write data stream (with compression). */ - void *compression_data; /* Data for (de)compressor. */ - int (*compression_init)(struct archive *); /* Initialize. */ - int (*compression_finish)(struct archive *); - int (*compression_write)(struct archive *, const void *, size_t); - /* - * Read uses a peek/consume I/O model: the decompression code - * returns a pointer to the requested block and advances the - * file position only when requested by a consume call. This - * reduces copying and also simplifies look-ahead for format - * detection. - */ - ssize_t (*compression_read_ahead)(struct archive *, - const void **, size_t request); - ssize_t (*compression_read_consume)(struct archive *, size_t); - ssize_t (*compression_skip)(struct archive *, size_t); - - /* - * Format detection is mostly the same as compression - * detection, with two significant differences: The bidders - * use the read_ahead calls above to examine the stream rather - * than having the supervisor hand them a block of data to - * examine, and the auction is repeated for every header. - * Winning bidders should set the archive_format and - * archive_format_name appropriately. Bid routines should - * check archive_format and decline to bid if the format of - * the last header was incompatible. - * - * Again, write support is considerably simpler because there's - * no need for an auction. - */ - int archive_format; - const char *archive_format_name; - - struct archive_format_descriptor { - int (*bid)(struct archive *); - int (*read_header)(struct archive *, struct archive_entry *); - int (*read_data)(struct archive *, const void **, size_t *, off_t *); - int (*read_data_skip)(struct archive *); - int (*cleanup)(struct archive *); - void *format_data; /* Format-specific data for readers. */ - } formats[8]; - struct archive_format_descriptor *format; /* Active format. */ - - /* - * Storage for format-specific data. Note that there can be - * multiple format readers active at one time, so we need to - * allow for multiple format readers to have their data - * available. The pformat_data slot here is the solution: on - * read, it is gauranteed to always point to a void* variable - * that the format can use. - */ - void **pformat_data; /* Pointer to current format_data. */ - void *format_data; /* Used by writers. */ - - /* - * Pointers to format-specific functions for writing. They're - * initialized by archive_write_set_format_XXX() calls. - */ - int (*format_init)(struct archive *); /* Only used on write. */ - int (*format_finish)(struct archive *); - int (*format_finish_entry)(struct archive *); - int (*format_write_header)(struct archive *, - struct archive_entry *); - ssize_t (*format_write_data)(struct archive *, - const void *buff, size_t); - - /* - * Various information needed by archive_extract. - */ - struct extract *extract; - void (*extract_progress)(void *); - void *extract_progress_user_data; - int (*cleanup_archive_extract)(struct archive *); - - int archive_error_number; - const char *error; - struct archive_string error_string; -}; - - -#define ARCHIVE_STATE_ANY 0xFFFFU -#define ARCHIVE_STATE_NEW 1U -#define ARCHIVE_STATE_HEADER 2U -#define ARCHIVE_STATE_DATA 4U -#define ARCHIVE_STATE_EOF 8U -#define ARCHIVE_STATE_CLOSED 0x10U -#define ARCHIVE_STATE_FATAL 0x8000U - -/* Check magic value and state; exit if it isn't valid. */ -void __archive_check_magic(struct archive *, unsigned magic, - unsigned state, const char *func); - - -int __archive_read_register_format(struct archive *a, - void *format_data, - int (*bid)(struct archive *), - int (*read_header)(struct archive *, struct archive_entry *), - int (*read_data)(struct archive *, const void **, size_t *, off_t *), - int (*read_data_skip)(struct archive *), - int (*cleanup)(struct archive *)); - -int __archive_read_register_compression(struct archive *a, - int (*bid)(const void *, size_t), - int (*init)(struct archive *, const void *, size_t)); - -void __archive_errx(int retvalue, const char *msg); - -#define err_combine(a,b) ((a) < (b) ? (a) : (b)) - - -/* - * Utility function to format a USTAR header into a buffer. If - * "strict" is set, this tries to create the absolutely most portable - * version of a ustar header. If "strict" is set to 0, then it will - * relax certain requirements. - * - * Generally, format-specific declarations don't belong in this - * header; this is a rare example of a function that is shared by - * two very similar formats (ustar and pax). - */ -int -__archive_write_format_header_ustar(struct archive *, char buff[512], - struct archive_entry *, int tartype, int strict); - -#endif diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read.3 b/contrib/libarchive-1.3.1/libarchive/archive_read.3 deleted file mode 100644 index b210206fe0..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read.3 +++ /dev/null @@ -1,550 +0,0 @@ -.\" 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/archive_read.3,v 1.24 2006/09/05 05:59:45 kientzle Exp $ -.\" -.Dd August 19, 2006 -.Dt archive_read 3 -.Os -.Sh NAME -.Nm archive_read_new , -.Nm archive_read_set_bytes_per_block , -.Nm archive_read_support_compression_all , -.Nm archive_read_support_compression_bzip2 , -.Nm archive_read_support_compression_compress , -.Nm archive_read_support_compression_gzip , -.Nm archive_read_support_compression_none , -.Nm archive_read_support_format_all , -.Nm archive_read_support_format_cpio , -.Nm archive_read_support_format_iso9660 , -.Nm archive_read_support_format_tar , -.Nm archive_read_support_format_zip , -.Nm archive_read_open , -.Nm archive_read_open2 , -.Nm archive_read_open_fd , -.Nm archive_read_open_FILE , -.Nm archive_read_open_filename , -.Nm archive_read_open_memory , -.Nm archive_read_next_header , -.Nm archive_read_data , -.Nm archive_read_data_block , -.Nm archive_read_data_skip , -.Nm archive_read_data_into_buffer , -.Nm archive_read_data_into_fd , -.Nm archive_read_extract , -.Nm archive_read_extract_set_progress_callback , -.Nm archive_read_close , -.Nm archive_read_finish -.Nd functions for reading streaming archives -.Sh SYNOPSIS -.In archive.h -.Ft struct archive * -.Fn archive_read_new "void" -.Ft int -.Fn archive_read_set_bytes_per_block "struct archive *" "int" -.Ft int -.Fn archive_read_support_compression_all "struct archive *" -.Ft int -.Fn archive_read_support_compression_bzip2 "struct archive *" -.Ft int -.Fn archive_read_support_compression_compress "struct archive *" -.Ft int -.Fn archive_read_support_compression_gzip "struct archive *" -.Ft int -.Fn archive_read_support_compression_none "struct archive *" -.Ft int -.Fn archive_read_support_format_all "struct archive *" -.Ft int -.Fn archive_read_support_format_cpio "struct archive *" -.Ft int -.Fn archive_read_support_format_iso9660 "struct archive *" -.Ft int -.Fn archive_read_support_format_tar "struct archive *" -.Ft int -.Fn archive_read_support_format_zip "struct archive *" -.Ft int -.Fn archive_read_open "struct archive *" "void *client_data" "archive_open_callback *" "archive_read_callback *" "archive_close_callback *" -.Ft int -.Fn archive_read_open2 "struct archive *" "void *client_data" "archive_open_callback *" "archive_read_callback *" "archive_skip_callback *" "archive_close_callback *" -.Ft int -.Fn archive_read_open_FILE "struct archive *" "FILE *file" -.Ft int -.Fn archive_read_open_fd "struct archive *" "int fd" "size_t block_size" -.Ft int -.Fn archive_read_open_filename "struct archive *" "const char *filename" "size_t block_size" -.Ft int -.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size" -.Ft int -.Fn archive_read_next_header "struct archive *" "struct archive_entry **" -.Ft ssize_t -.Fn archive_read_data "struct archive *" "void *buff" "size_t len" -.Ft int -.Fn archive_read_data_block "struct archive *" "const void **buff" "size_t *len" "off_t *offset" -.Ft int -.Fn archive_read_data_skip "struct archive *" -.Ft int -.Fn archive_read_data_into_buffer "struct archive *" "void *" "ssize_t len" -.Ft int -.Fn archive_read_data_into_fd "struct archive *" "int fd" -.Ft int -.Fn archive_read_extract "struct archive *" "struct archive_entry *" "int flags" -.Ft void -.Fn archive_read_extract_set_progress_callback "struct archive *" "void (*func)(void *)" "void *user_data" -.Ft int -.Fn archive_read_close "struct archive *" -.Ft int -.Fn archive_read_finish "struct archive *" -.Sh DESCRIPTION -These functions provide a complete API for reading streaming archives. -The general process is to first create the -.Tn struct archive -object, set options, initialize the reader, iterate over the archive -headers and associated data, then close the archive and release all -resources. -The following summary describes the functions in approximately the -order they would be used: -.Bl -tag -compact -width indent -.It Fn archive_read_new -Allocates and initializes a -.Tn struct archive -object suitable for reading from an archive. -.It Fn archive_read_set_bytes_per_block -Sets the block size used for reading the archive data. -This controls the size that will be used when invoking the read -callback function. -The default is 20 records or 10240 bytes for tar formats. -.It Fn archive_read_support_compression_all , Fn archive_read_support_compression_bzip2 , Fn archive_read_support_compression_compress , Fn archive_read_support_compression_gzip , Fn archive_read_support_compression_none -Enables auto-detection code and decompression support for the -specified compression. -Note that -.Dq none -is always enabled by default. -For convenience, -.Fn archive_read_support_compression_all -enables all available decompression code. -.It Fn archive_read_support_format_all , Fn archive_read_support_format_cpio , Fn archive_read_support_format_iso9660 , Fn archive_read_support_format_tar, Fn archive_read_support_format_zip -Enables support---including auto-detection code---for the -specified archive format. -For example, -.Fn archive_read_support_format_tar -enables support for a variety of standard tar formats, old-style tar, -ustar, pax interchange format, and many common variants. -For convenience, -.Fn archive_read_support_format_all -enables support for all available formats. -Note that there is no default. -.It Fn archive_read_open -The same as -.Fn archive_read_open2 , -except that the skip callback is assumed to be -.Dv NULL . -.It Fn archive_read_open2 -Freeze the settings, open the archive, and prepare for reading entries. -This is the most generic version of this call, which accepts -four callback functions. -Most clients will want to use -.Fn archive_read_open_filename , -.Fn archive_read_open_FILE , -.Fn archive_read_open_fd , -or -.Fn archive_read_open_memory -instead. -The library invokes the client-provided functions to obtain -raw bytes from the archive. -.It Fn archive_read_open_FILE -Like -.Fn archive_read_open , -except that it accepts a -.Ft "FILE *" -pointer. -This function should not be used with tape drives or other devices -that require strict I/O blocking. -.It Fn archive_read_open_fd -Like -.Fn archive_read_open , -except that it accepts a file descriptor and block size rather than -a set of function pointers. -Note that the file descriptor will not be automatically closed at -end-of-archive. -This function is safe for use with tape drives or other blocked devices. -.It Fn archive_read_open_file -A deprecated synonym for -.Fn archive_read_open_filename . -.It Fn archive_read_open_filename -Like -.Fn archive_read_open , -except that it accepts a simple filename and a block size. -A NULL filename represents standard input. -This function is safe for use with tape drives or other blocked devices. -.It Fn archive_read_open_memory -Like -.Fn archive_read_open , -except that it accepts a pointer and size of a block of -memory containing the archive data. -.It Fn archive_read_next_header -Read the header for the next entry and return a pointer to -a -.Tn struct archive_entry . -.It Fn archive_read_data -Read data associated with the header just read. -Internally, this is a convenience function that calls -.Fn archive_read_data_block -and fills any gaps with nulls so that callers see a single -continuous stream of data. -.It Fn archive_read_data_block -Return the next available block of data for this entry. -Unlike -.Fn archive_read_data , -the -.Fn archive_read_data_block -function avoids copying data and allows you to correctly handle -sparse files, as supported by some archive formats. -The library guarantees that offsets will increase and that blocks -will not overlap. -Note that the blocks returned from this function can be much larger -than the block size read from disk, due to compression -and internal buffer optimizations. -.It Fn archive_read_data_skip -A convenience function that repeatedly calls -.Fn archive_read_data_block -to skip all of the data for this archive entry. -.It Fn archive_read_data_into_buffer -A convenience function that repeatedly calls -.Fn archive_read_data_block -to copy the entire entry into the client-supplied buffer. -Note that the client is responsible for sizing the buffer appropriately. -.It Fn archive_read_data_into_fd -A convenience function that repeatedly calls -.Fn archive_read_data_block -to copy the entire entry to the provided file descriptor. -.It Fn archive_read_extract_set_skip_file -This function records the device and inode numbers -of a file that should not be restored. -This is a convenience that prevents -.Fn archive_read_extract -from restoring a file over the archive itself. -.It Fn archive_read_extract -A convenience function that recreates the specified object on -disk and reads the entry data into that object. -The filename, permissions, and other critical information -are taken from the provided -.Va archive_entry -object. -The -.Va flags -argument modifies how the object is recreated. -It consists of a bitwise OR of one or more of the following values: -.Bl -tag -compact -width "indent" -.It Cm ARCHIVE_EXTRACT_OWNER -The user and group IDs should be set on the restored file. -By default, the user and group IDs are not restored. -.It Cm ARCHIVE_EXTRACT_PERM -The permissions (mode bits) should be restored for all objects. -By default, permissions are only restored for regular files. -.It Cm ARCHIVE_EXTRACT_TIME -The timestamps (mtime, ctime, and atime) should be restored. -By default, they are ignored. -Note that restoring of atime is not currently supported. -.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE -Existing files on disk will not be overwritten. -By default, existing regular files are truncated and overwritten; -existing directories will have their permissions updated; -other pre-existing objects are unlinked and recreated from scratch. -.It Cm ARCHIVE_EXTRACT_UNLINK -Existing files on disk will be unlinked and recreated from scratch. -By default, existing files are truncated and rewritten, but -the file is not recreated. -In particular, the default behavior does not break existing hard links. -.It Cm ARCHIVE_EXTRACT_ACL -Attempt to restore ACLs. -By default, extended ACLs are ignored. -.It Cm ARCHIVE_EXTRACT_FFLAGS -Attempt to restore extended file flags. -By default, file flags are ignored. -.El -Note that not all attributes are set immediately; -some attributes are cached in memory and written to disk only -when the archive is closed. -(For example, read-only directories are initially created -writable so that files within those directories can be -restored. -The final permissions are set when the archive is closed.) -.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. -The progress function will be invoked during the extraction of large -regular files. -The progress function will be invoked with the pointer provided to this call. -Generally, the data pointed to should include a reference to the archive -object and the archive_entry object so that various statistics -can be retrieved for the progress display. -.It Fn archive_read_close -Complete the archive and invoke the close callback. -.It Fn archive_read_finish -Invokes -.Fn archive_read_close -if it was not invoked manually, then release all resources. -Note: In libarchive 1.x, this function was declared to return -.Ft void , -which made it impossible to detect certain errors when -.Fn archive_read_close -was invoked implicitly from this function. -The declaration is corrected beginning with libarchive 2.0. -.El -.Pp -Note that the library determines most of the relevant information about -the archive by inspection. -In particular, it automatically detects -.Xr gzip 1 -or -.Xr bzip2 1 -compression and transparently performs the appropriate decompression. -It also automatically detects the archive format. -.Pp -A complete description of the -.Tn struct archive -and -.Tn struct archive_entry -objects can be found in the overview manual page for -.Xr libarchive 3 . -.Sh CLIENT CALLBACKS -The callback functions must match the following prototypes: -.Bl -item -offset indent -.It -.Ft typedef ssize_t -.Fn archive_read_callback "struct archive *" "void *client_data" "const void **buffer" -.It -.Ft typedef int -.Fn archive_skip_callback "struct archive *" "void *client_data" "size_t request" -.It -.Ft typedef int -.Fn archive_open_callback "struct archive *" "void *client_data" -.It -.Ft typedef int -.Fn archive_close_callback "struct archive *" "void *client_data" -.El -.Pp -The open callback is invoked by -.Fn archive_open . -It should return -.Cm ARCHIVE_OK -if the underlying file or data source is successfully -opened. -If the open fails, it should call -.Fn archive_set_error -to register an error code and message and return -.Cm ARCHIVE_FATAL . -.Pp -The read callback is invoked whenever the library -requires raw bytes from the archive. -The read callback should read data into a buffer, -set the -.Li const void **buffer -argument to point to the available data, and -return a count of the number of bytes available. -The library will invoke the read callback again -only after it has consumed this data. -The library imposes no constraints on the size -of the data blocks returned. -On end-of-file, the read callback should -return zero. -On error, the read callback should invoke -.Fn archive_set_error -to register an error code and message and -return -1. -.Pp -The skip callback is invoked when the -library wants to ignore a block of data. -The return value is the number of bytes actually -skipped, which may differ from the request. -If the callback cannot skip data, it should return -zero. -If the skip callback is not provided (the -function pointer is -.Dv NULL ), -the library will invoke the read function -instead and simply discard the result. -A skip callback can provide significant -performance gains when reading uncompressed -archives from slow disk drives or other media -that can skip quickly. -.Pp -The close callback is invoked by archive_close when -the archive processing is complete. -The callback should return -.Cm ARCHIVE_OK -on success. -On failure, the callback should invoke -.Fn archive_set_error -to register an error code and message and -return -.Cm ARCHIVE_FATAL. -.Sh EXAMPLE -The following illustrates basic usage of the library. -In this example, -the callback functions are simply wrappers around the standard -.Xr open 2 , -.Xr read 2 , -and -.Xr close 2 -system calls. -.Bd -literal -offset indent -void -list_archive(const char *name) -{ - struct mydata *mydata; - struct archive *a; - struct archive_entry *entry; - - mydata = malloc(sizeof(struct mydata)); - a = archive_read_new(); - mydata->name = name; - archive_read_support_compression_all(a); - archive_read_support_format_all(a); - archive_read_open(a, mydata, myopen, myread, myclose); - while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - printf("%s\\n",archive_entry_pathname(entry)); - archive_read_data_skip(a); - } - archive_read_finish(a); - free(mydata); -} - -ssize_t -myread(struct archive *a, void *client_data, const void **buff) -{ - struct mydata *mydata = client_data; - - *buff = mydata->buff; - return (read(mydata->fd, mydata->buff, 10240)); -} - -int -myopen(struct archive *a, void *client_data) -{ - struct mydata *mydata = client_data; - - mydata->fd = open(mydata->name, O_RDONLY); - return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL); -} - -int -myclose(struct archive *a, void *client_data) -{ - struct mydata *mydata = client_data; - - if (mydata->fd > 0) - close(mydata->fd); - return (ARCHIVE_OK); -} -.Ed -.Sh RETURN VALUES -Most functions return zero on success, non-zero on error. -The possible return codes include: -.Cm ARCHIVE_OK -(the operation succeeded), -.Cm ARCHIVE_WARN -(the operation succeeded but a non-critical error was encountered), -.Cm ARCHIVE_EOF -(end-of-archive was encountered), -.Cm ARCHIVE_RETRY -(the operation failed but can be retried), -and -.Cm ARCHIVE_FATAL -(there was a fatal error; the archive should be closed immediately). -Detailed error codes and textual descriptions are available from the -.Fn archive_errno -and -.Fn archive_error_string -functions. -.Pp -.Fn archive_read_new -returns a pointer to a freshly allocated -.Tn struct archive -object. -It returns -.Dv NULL -on error. -.Pp -.Fn archive_read_data -returns a count of bytes actually read or zero at the end of the entry. -On error, a value of -.Cm ARCHIVE_FATAL , -.Cm ARCHIVE_WARN , -or -.Cm ARCHIVE_RETRY -is returned and an error code and textual description can be retrieved from the -.Fn archive_errno -and -.Fn archive_error_string -functions. -.Pp -The library expects the client callbacks to behave similarly. -If there is an error, you can use -.Fn archive_set_error -to set an appropriate error code and description, -then return one of the non-zero values above. -(Note that the value eventually returned to the client may -not be the same; many errors that are not critical at the level -of basic I/O can prevent the archive from being properly read, -thus most I/O errors eventually cause -.Cm ARCHIVE_FATAL -to be returned.) -.\" .Sh ERRORS -.Sh SEE ALSO -.Xr tar 1 , -.Xr archive 3 , -.Xr archive_util 3 , -.Xr tar 5 -.Sh HISTORY -The -.Nm libarchive -library first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm libarchive -library was written by -.An Tim Kientzle Aq kientzle@acm.org . -.Sh BUGS -Directories are actually extracted in two distinct phases. -Directories are created during -.Fn archive_read_extract , -but final permissions are not set until -.Fn archive_read_close . -This separation is necessary to correctly handle borderline -cases such as a non-writable directory containing -files, but can cause unexpected results. -In particular, directory permissions are not fully -restored until the archive is closed. -If you use -.Xr chdir 2 -to change the current directory between calls to -.Fn archive_read_extract -or before calling -.Fn archive_read_close , -you may confuse the permission-setting logic with -the result that directory permissions are restored -incorrectly. diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read.c b/contrib/libarchive-1.3.1/libarchive/archive_read.c deleted file mode 100644 index 78475ad8cd..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read.c +++ /dev/null @@ -1,628 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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. - */ - -/* - * This file contains the "essential" portions of the read API, that - * is, stuff that will probably always be used by any client that - * actually needs to read an archive. Optional pieces have been, as - * far as possible, separated out into separate files to avoid - * needlessly bloating statically-linked clients. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read.c,v 1.22 2006/09/05 05:59:45 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -static int choose_decompressor(struct archive *, const void*, size_t); -static int choose_format(struct archive *); - -/* - * Allocate, initialize and return a struct archive object. - */ -struct archive * -archive_read_new(void) -{ - struct archive *a; - unsigned char *nulls; - - a = malloc(sizeof(*a)); - if (a == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate archive object"); - return (NULL); - } - memset(a, 0, sizeof(*a)); - - a->user_uid = geteuid(); - a->magic = ARCHIVE_READ_MAGIC; - a->bytes_per_block = ARCHIVE_DEFAULT_BYTES_PER_BLOCK; - - a->null_length = 1024; - nulls = malloc(a->null_length); - if (nulls == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate archive object 'nulls' element"); - free(a); - return (NULL); - } - memset(nulls, 0, a->null_length); - a->nulls = nulls; - - a->state = ARCHIVE_STATE_NEW; - a->entry = archive_entry_new(); - - /* We always support uncompressed archives. */ - archive_read_support_compression_none((struct archive*)a); - - return (a); -} - -/* - * Record the do-not-extract-to file. This belongs in archive_read_extract.c. - */ -void -archive_read_extract_set_skip_file(struct archive *a, dev_t d, ino_t i) -{ - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file"); - a->skip_file_dev = d; - a->skip_file_ino = i; -} - - -/* - * Open the archive - */ -int -archive_read_open(struct archive *a, void *client_data, - archive_open_callback *client_opener, archive_read_callback *client_reader, - archive_close_callback *client_closer) -{ - /* Old archive_read_open() is just a thin shell around - * archive_read_open2. */ - return archive_read_open2(a, client_data, client_opener, - client_reader, NULL, client_closer); -} - -int -archive_read_open2(struct archive *a, void *client_data, - archive_open_callback *client_opener, - archive_read_callback *client_reader, - archive_skip_callback *client_skipper, - archive_close_callback *client_closer) -{ - const void *buffer; - ssize_t bytes_read; - int high_bidder; - int e; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); - - if (client_reader == NULL) - __archive_errx(1, - "No reader function provided to archive_read_open"); - - /* - * Set these NULL initially. If the open or initial read fails, - * we'll leave them NULL to indicate that the file is invalid. - * (In particular, this helps ensure that the closer doesn't - * get called more than once.) - */ - a->client_opener = NULL; - a->client_reader = NULL; - a->client_skipper = NULL; - a->client_closer = NULL; - a->client_data = NULL; - - /* Open data source. */ - if (client_opener != NULL) { - e =(client_opener)(a, client_data); - if (e != 0) { - /* If the open failed, call the closer to clean up. */ - if (client_closer) - (client_closer)(a, client_data); - return (e); - } - } - - /* Read first block now for format detection. */ - bytes_read = (client_reader)(a, client_data, &buffer); - - if (bytes_read < 0) { - /* If the first read fails, close before returning error. */ - if (client_closer) - (client_closer)(a, client_data); - /* client_reader should have already set error information. */ - return (ARCHIVE_FATAL); - } - - /* An empty archive is a serious error. */ - if (bytes_read == 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Empty input file"); - /* Close the empty file. */ - if (client_closer) - (client_closer)(a, client_data); - return (ARCHIVE_FATAL); - } - - /* Now that the client callbacks have worked, remember them. */ - a->client_opener = client_opener; /* Do we need to remember this? */ - a->client_reader = client_reader; - a->client_skipper = client_skipper; - a->client_closer = client_closer; - a->client_data = client_data; - - /* Select a decompression routine. */ - high_bidder = choose_decompressor(a, buffer, bytes_read); - if (high_bidder < 0) - return (ARCHIVE_FATAL); - - /* Initialize decompression routine with the first block of data. */ - e = (a->decompressors[high_bidder].init)(a, buffer, bytes_read); - - if (e == ARCHIVE_OK) - a->state = ARCHIVE_STATE_HEADER; - - return (e); -} - -/* - * Allow each registered decompression routine to bid on whether it - * wants to handle this stream. Return index of winning bidder. - */ -static int -choose_decompressor(struct archive *a, const void *buffer, size_t bytes_read) -{ - int decompression_slots, i, bid, best_bid, best_bid_slot; - - decompression_slots = sizeof(a->decompressors) / - sizeof(a->decompressors[0]); - - best_bid = -1; - best_bid_slot = -1; - - for (i = 0; i < decompression_slots; i++) { - if (a->decompressors[i].bid) { - bid = (a->decompressors[i].bid)(buffer, bytes_read); - if ((bid > best_bid) || (best_bid_slot < 0)) { - best_bid = bid; - best_bid_slot = i; - } - } - } - - /* - * There were no bidders; this is a serious programmer error - * and demands a quick and definitive abort. - */ - if (best_bid_slot < 0) - __archive_errx(1, "No decompressors were registered; you " - "must call at least one " - "archive_read_support_compression_XXX function in order " - "to successfully read an archive."); - - /* - * There were bidders, but no non-zero bids; this means we can't - * support this stream. - */ - if (best_bid < 1) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Unrecognized archive format"); - return (ARCHIVE_FATAL); - } - - return (best_bid_slot); -} - -/* - * Read header of next entry. - */ -int -archive_read_next_header(struct archive *a, struct archive_entry **entryp) -{ - struct archive_entry *entry; - int slot, ret; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, - ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, "archive_read_next_header"); - - *entryp = NULL; - entry = a->entry; - archive_entry_clear(entry); - archive_string_empty(&a->error_string); - - /* - * If client didn't consume entire data, skip any remainder - * (This is especially important for GNU incremental directories.) - */ - if (a->state == ARCHIVE_STATE_DATA) { - ret = archive_read_data_skip(a); - if (ret == ARCHIVE_EOF) { - archive_set_error(a, EIO, "Premature end-of-file."); - a->state = ARCHIVE_STATE_FATAL; - return (ARCHIVE_FATAL); - } - if (ret != ARCHIVE_OK) - return (ret); - } - - /* Record start-of-header. */ - a->header_position = a->file_position; - - slot = choose_format(a); - if (slot < 0) { - a->state = ARCHIVE_STATE_FATAL; - return (ARCHIVE_FATAL); - } - a->format = &(a->formats[slot]); - a->pformat_data = &(a->format->format_data); - ret = (a->format->read_header)(a, entry); - - /* - * EOF and FATAL are persistent at this layer. By - * modifying the state, we gaurantee that future calls to - * read a header or read data will fail. - */ - switch (ret) { - case ARCHIVE_EOF: - a->state = ARCHIVE_STATE_EOF; - break; - case ARCHIVE_OK: - a->state = ARCHIVE_STATE_DATA; - break; - case ARCHIVE_WARN: - a->state = ARCHIVE_STATE_DATA; - break; - case ARCHIVE_RETRY: - break; - case ARCHIVE_FATAL: - a->state = ARCHIVE_STATE_FATAL; - break; - } - - *entryp = entry; - a->read_data_output_offset = 0; - a->read_data_remaining = 0; - return (ret); -} - -/* - * Allow each registered format to bid on whether it wants to handle - * the next entry. Return index of winning bidder. - */ -static int -choose_format(struct archive *a) -{ - int slots; - int i; - int bid, best_bid; - int best_bid_slot; - - slots = sizeof(a->formats) / sizeof(a->formats[0]); - best_bid = -1; - best_bid_slot = -1; - - /* Set up a->format and a->pformat_data for convenience of bidders. */ - a->format = &(a->formats[0]); - for (i = 0; i < slots; i++, a->format++) { - if (a->format->bid) { - a->pformat_data = &(a->format->format_data); - bid = (a->format->bid)(a); - if (bid == ARCHIVE_FATAL) - return (ARCHIVE_FATAL); - if ((bid > best_bid) || (best_bid_slot < 0)) { - best_bid = bid; - best_bid_slot = i; - } - } - } - - /* - * There were no bidders; this is a serious programmer error - * and demands a quick and definitive abort. - */ - if (best_bid_slot < 0) - __archive_errx(1, "No formats were registered; you must " - "invoke at least one archive_read_support_format_XXX " - "function in order to successfully read an archive."); - - /* - * There were bidders, but no non-zero bids; this means we - * can't support this stream. - */ - if (best_bid < 1) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Unrecognized archive format"); - return (ARCHIVE_FATAL); - } - - return (best_bid_slot); -} - -/* - * Return the file offset (within the uncompressed data stream) where - * the last header started. - */ -int64_t -archive_read_header_position(struct archive *a) -{ - return (a->header_position); -} - -/* - * Read data from an archive entry, using a read(2)-style interface. - * This is a convenience routine that just calls - * archive_read_data_block and copies the results into the client - * buffer, filling any gaps with zero bytes. Clients using this - * API can be completely ignorant of sparse-file issues; sparse files - * will simply be padded with nulls. - * - * DO NOT intermingle calls to this function and archive_read_data_block - * to read a single entry body. - */ -ssize_t -archive_read_data(struct archive *a, void *buff, size_t s) -{ - char *dest; - size_t bytes_read; - size_t len; - int r; - - bytes_read = 0; - dest = buff; - - while (s > 0) { - if (a->read_data_remaining <= 0) { - r = archive_read_data_block(a, - (const void **)&a->read_data_block, - &a->read_data_remaining, - &a->read_data_offset); - if (r == ARCHIVE_EOF) - return (bytes_read); - /* - * Error codes are all negative, so the status - * return here cannot be confused with a valid - * byte count. (ARCHIVE_OK is zero.) - */ - if (r < ARCHIVE_OK) - return (r); - } - - if (a->read_data_offset < a->read_data_output_offset) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Encountered out-of-order sparse blocks"); - return (ARCHIVE_RETRY); - } else { - len = a->read_data_remaining; - if (len > s) - len = s; - memcpy(dest, a->read_data_block, len); - s -= len; - a->read_data_block += len; - a->read_data_remaining -= len; - a->read_data_output_offset += len; - a->read_data_offset += len; - dest += len; - bytes_read += len; - } - } - return (bytes_read); -} - -/* - * Skip over all remaining data in this entry. - */ -int -archive_read_data_skip(struct archive *a) -{ - int r; - const void *buff; - size_t size; - off_t offset; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_skip"); - - if (a->format->read_data_skip != NULL) - r = (a->format->read_data_skip)(a); - else { - while ((r = archive_read_data_block(a, &buff, &size, &offset)) - == ARCHIVE_OK) - ; - } - - if (r == ARCHIVE_EOF) - r = ARCHIVE_OK; - - a->state = ARCHIVE_STATE_HEADER; - return (r); -} - -/* - * Read the next block of entry data from the archive. - * This is a zero-copy interface; the client receives a pointer, - * size, and file offset of the next available block of data. - * - * Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if - * the end of entry is encountered. - */ -int -archive_read_data_block(struct archive *a, - const void **buff, size_t *size, off_t *offset) -{ - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_block"); - - if (a->format->read_data == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "Internal error: " - "No format_read_data_block function registered"); - return (ARCHIVE_FATAL); - } - - return (a->format->read_data)(a, buff, size, offset); -} - -/* - * Close the file and release most resources. - * - * Be careful: client might just call read_new and then read_finish. - * Don't assume we actually read anything or performed any non-trivial - * initialization. - */ -int -archive_read_close(struct archive *a) -{ - int r = ARCHIVE_OK, r1 = ARCHIVE_OK; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_close"); - a->state = ARCHIVE_STATE_CLOSED; - - /* Call cleanup functions registered by optional components. */ - if (a->cleanup_archive_extract != NULL) - r = (a->cleanup_archive_extract)(a); - - /* TODO: Finish the format processing. */ - - /* Close the input machinery. */ - if (a->compression_finish != NULL) { - r1 = (a->compression_finish)(a); - if (r1 < r) - r = r1; - } - - return (r); -} - -/* - * Release memory and other resources. - */ -#if ARCHIVE_API_VERSION > 1 -int -#else -/* Temporarily allow library to compile with either 1.x or 2.0 API. */ -void -#endif -archive_read_finish(struct archive *a) -{ - int i; - int slots; - int r = ARCHIVE_OK; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_finish"); - if (a->state != ARCHIVE_STATE_CLOSED) - r = archive_read_close(a); - - /* Cleanup format-specific data. */ - slots = sizeof(a->formats) / sizeof(a->formats[0]); - for (i = 0; i < slots; i++) { - a->pformat_data = &(a->formats[i].format_data); - if (a->formats[i].cleanup) - (a->formats[i].cleanup)(a); - } - - /* Casting a pointer to int allows us to remove 'const.' */ - free((void *)(uintptr_t)(const void *)a->nulls); - archive_string_free(&a->error_string); - if (a->entry) - archive_entry_free(a->entry); - a->magic = 0; - free(a); -#if ARCHIVE_API_VERSION > 1 - return (r); -#endif -} - -/* - * Used internally by read format handlers to register their bid and - * initialization functions. - */ -int -__archive_read_register_format(struct archive *a, - void *format_data, - int (*bid)(struct archive *), - int (*read_header)(struct archive *, struct archive_entry *), - int (*read_data)(struct archive *, const void **, size_t *, off_t *), - int (*read_data_skip)(struct archive *), - int (*cleanup)(struct archive *)) -{ - int i, number_slots; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "__archive_read_register_format"); - - number_slots = sizeof(a->formats) / sizeof(a->formats[0]); - - for (i = 0; i < number_slots; i++) { - if (a->formats[i].bid == bid) - return (ARCHIVE_WARN); /* We've already installed */ - if (a->formats[i].bid == NULL) { - a->formats[i].bid = bid; - a->formats[i].read_header = read_header; - a->formats[i].read_data = read_data; - a->formats[i].read_data_skip = read_data_skip; - a->formats[i].cleanup = cleanup; - a->formats[i].format_data = format_data; - return (ARCHIVE_OK); - } - } - - __archive_errx(1, "Not enough slots for format registration"); - return (ARCHIVE_FATAL); /* Never actually called. */ -} - -/* - * Used internally by decompression routines to register their bid and - * initialization functions. - */ -int -__archive_read_register_compression(struct archive *a, - int (*bid)(const void *, size_t), - int (*init)(struct archive *, const void *, size_t)) -{ - int i, number_slots; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "__archive_read_register_compression"); - - number_slots = sizeof(a->decompressors) / sizeof(a->decompressors[0]); - - for (i = 0; i < number_slots; i++) { - if (a->decompressors[i].bid == bid) - return (ARCHIVE_OK); /* We've already installed */ - if (a->decompressors[i].bid == NULL) { - a->decompressors[i].bid = bid; - a->decompressors[i].init = init; - return (ARCHIVE_OK); - } - } - - __archive_errx(1, "Not enough slots for compression registration"); - return (ARCHIVE_FATAL); /* Never actually executed. */ -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_buffer.c b/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_buffer.c deleted file mode 100644 index 48d12ff101..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_buffer.c +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_buffer.c,v 1.4 2004/06/27 01:15:31 kientzle Exp $"); - -#include - -#include "archive.h" - -int -archive_read_data_into_buffer(struct archive *a, void *d, ssize_t len) -{ - char *dest; - ssize_t bytes_read, total_bytes; - - dest = d; - total_bytes = 0; - bytes_read = archive_read_data(a, dest, len); - while (bytes_read > 0) { - total_bytes += bytes_read; - bytes_read = archive_read_data(a, dest + total_bytes, - len - total_bytes); - } - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_fd.c b/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_fd.c deleted file mode 100644 index 98a90216ba..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_data_into_fd.c +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.10 2005/09/24 21:15:00 kientzle Exp $"); - -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -/* Maximum amount of data to write at one time. */ -#define MAX_WRITE (1024 * 1024) - -/* - * This implementation minimizes copying of data and is sparse-file aware. - */ -int -archive_read_data_into_fd(struct archive *a, int fd) -{ - int r; - const void *buff; - size_t size; - ssize_t bytes_to_write, bytes_written, total_written; - off_t offset; - off_t output_offset; - - __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_into_fd"); - - total_written = 0; - output_offset = 0; - - while ((r = archive_read_data_block(a, &buff, &size, &offset)) == - ARCHIVE_OK) { - if (offset > output_offset) { - lseek(fd, offset - output_offset, SEEK_CUR); - output_offset = offset; - } - while (size > 0) { - bytes_to_write = size; - if (bytes_to_write > MAX_WRITE) - bytes_to_write = MAX_WRITE; - bytes_written = write(fd, buff, bytes_to_write); - if (bytes_written < 0) { - archive_set_error(a, errno, "Write error"); - return (-1); - } - output_offset += bytes_written; - total_written += bytes_written; - size -= bytes_written; - if (a->extract_progress != NULL) - (*a->extract_progress)(a->extract_progress_user_data); - } - } - - if (r != ARCHIVE_EOF) - return (r); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_extract.c b/contrib/libarchive-1.3.1/libarchive/archive_read_extract.c deleted file mode 100644 index 8f398bd662..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_extract.c +++ /dev/null @@ -1,1605 +0,0 @@ -/*- - * Copyright (c) 2003-2005 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.47 2006/09/05 05:59:45 kientzle Exp $"); - -#include -#ifdef HAVE_SYS_ACL_H -#include -#endif -#ifdef HAVE_ATTR_XATTR_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#include -#include - -#ifdef HAVE_EXT2FS_EXT2_FS_H -#include /* for Linux file flags */ -#endif -#include -#include -#include -#ifdef HAVE_LINUX_EXT2_FS_H -#include /* for Linux file flags */ -#endif -#include -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_string.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct fixup_entry { - struct fixup_entry *next; - mode_t mode; - int64_t mtime; - int64_t atime; - unsigned long mtime_nanos; - unsigned long atime_nanos; - unsigned long fflags_set; - int fixup; /* bitmask of what needs fixing */ - char *name; -}; - -#define FIXUP_MODE 1 -#define FIXUP_TIMES 2 -#define FIXUP_FFLAGS 4 - -struct bucket { - char *name; - int hash; - id_t id; -}; - -struct extract { - mode_t umask; - mode_t default_dir_mode; - struct archive_string create_parent_dir; - struct fixup_entry *fixup_list; - struct fixup_entry *current_fixup; - - struct bucket ucache[127]; - struct bucket gcache[127]; - - /* - * Cached stat data from disk for the current entry. - * If this is valid, pst points to st. Otherwise, - * pst is null. - */ - struct stat st; - struct stat *pst; -}; - -/* Default mode for dirs created automatically (will be modified by umask). */ -#define DEFAULT_DIR_MODE 0777 -/* - * Mode to use for newly-created dirs during extraction; the correct - * mode will be set at the end of the extraction. - */ -#define SECURE_DIR_MODE 0700 - -static int archive_extract_cleanup(struct archive *); -static int extract_block_device(struct archive *, - struct archive_entry *, int); -static int extract_char_device(struct archive *, - struct archive_entry *, int); -static int extract_device(struct archive *, - struct archive_entry *, int flags, mode_t mode); -static int extract_dir(struct archive *, struct archive_entry *, int); -static int extract_fifo(struct archive *, struct archive_entry *, int); -static int extract_file(struct archive *, struct archive_entry *, int); -static int extract_hard_link(struct archive *, struct archive_entry *, int); -static int extract_symlink(struct archive *, struct archive_entry *, int); -static unsigned int hash(const char *); -static gid_t lookup_gid(struct archive *, const char *uname, gid_t); -static uid_t lookup_uid(struct archive *, const char *uname, uid_t); -static int create_dir(struct archive *, const char *, int flags); -static int create_dir_mutable(struct archive *, char *, int flags); -static int create_dir_recursive(struct archive *, char *, int flags); -static int create_parent_dir(struct archive *, const char *, int flags); -static int create_parent_dir_mutable(struct archive *, char *, int flags); -static int restore_metadata(struct archive *, int fd, - struct archive_entry *, int flags); -#ifdef HAVE_POSIX_ACL -static int set_acl(struct archive *, int fd, struct archive_entry *, - acl_type_t, int archive_entry_acl_type, const char *tn); -#endif -static int set_acls(struct archive *, int fd, struct archive_entry *); -static int set_xattrs(struct archive *, int fd, struct archive_entry *); -static int set_fflags(struct archive *, int fd, const char *name, mode_t, - unsigned long fflags_set, unsigned long fflags_clear); -static int set_ownership(struct archive *, int fd, struct archive_entry *, - int flags); -static int set_perm(struct archive *, int fd, struct archive_entry *, - int mode, int flags); -static int set_time(struct archive *, int fd, struct archive_entry *, int); -static struct fixup_entry *sort_dir_list(struct fixup_entry *p); - - -/* - * Extract this entry to disk. - * - * TODO: Validate hardlinks. According to the standards, we're - * supposed to check each extracted hardlink and squawk if it refers - * to a file that we didn't restore. I'm not entirely convinced this - * is a good idea, but more importantly: Is there any way to validate - * hardlinks without keeping a complete list of filenames from the - * entire archive?? Ugh. - * - */ -int -archive_read_extract(struct archive *a, struct archive_entry *entry, int flags) -{ - mode_t mode; - struct extract *extract; - int ret; - int restore_pwd; - char *original_filename; - - if (a->extract == NULL) { - a->extract = malloc(sizeof(*a->extract)); - if (a->extract == NULL) { - archive_set_error(a, ENOMEM, "Can't extract"); - return (ARCHIVE_FATAL); - } - a->cleanup_archive_extract = archive_extract_cleanup; - memset(a->extract, 0, sizeof(*a->extract)); - } - extract = a->extract; - umask(extract->umask = umask(0)); /* Read the current umask. */ - extract->default_dir_mode = DEFAULT_DIR_MODE & ~extract->umask; - extract->pst = NULL; - extract->current_fixup = NULL; - restore_pwd = -1; - original_filename = NULL; - - /* The following is not possible without fchdir. */ -#ifdef HAVE_FCHDIR - /* - * If pathname is longer than PATH_MAX, record starting directory - * and chdir to a suitable intermediate dir. - */ - if (strlen(archive_entry_pathname(entry)) > PATH_MAX) { - char *intdir, *tail; - - restore_pwd = open(".", O_RDONLY); - if (restore_pwd < 0) { - archive_set_error(a, errno, - "Unable to restore long pathname"); - return (ARCHIVE_WARN); - } - - /* - * Yes, the copy here is necessary because we edit - * the pathname in-place to create intermediate dirnames. - */ - original_filename = strdup(archive_entry_pathname(entry)); - - /* - * "intdir" points to the initial dir section we're going - * to remove, "tail" points to the remainder of the path. - */ - intdir = tail = original_filename; - while (strlen(tail) > PATH_MAX) { - intdir = tail; - - /* Locate a dir prefix shorter than PATH_MAX. */ - tail = intdir + PATH_MAX - 8; - while (tail > intdir && *tail != '/') - tail--; - if (tail <= intdir) { - archive_set_error(a, EPERM, - "Path element too long"); - ret = ARCHIVE_WARN; - goto cleanup; - } - - /* Create intdir and chdir to it. */ - *tail = '\0'; /* Terminate dir portion */ - ret = create_dir(a, intdir, flags); - if (ret == ARCHIVE_OK && chdir(intdir) != 0) { - archive_set_error(a, errno, "Couldn't chdir"); - ret = ARCHIVE_WARN; - } - *tail = '/'; /* Restore the / we removed. */ - if (ret != ARCHIVE_OK) - goto cleanup; - tail++; - } - archive_entry_set_pathname(entry, tail); - } -#endif - - if (stat(archive_entry_pathname(entry), &extract->st) == 0) - extract->pst = &extract->st; - - if (extract->pst != NULL && - extract->pst->st_dev == a->skip_file_dev && - extract->pst->st_ino == a->skip_file_ino) { - archive_set_error(a, 0, "Refusing to overwrite archive"); - ret = ARCHIVE_WARN; - } else if (archive_entry_hardlink(entry) != NULL) - ret = extract_hard_link(a, entry, flags); - else { - mode = archive_entry_mode(entry); - switch (mode & S_IFMT) { - default: - /* Fall through, as required by POSIX. */ - case S_IFREG: - ret = extract_file(a, entry, flags); - break; - case S_IFLNK: /* Symlink */ - ret = extract_symlink(a, entry, flags); - break; - case S_IFCHR: - ret = extract_char_device(a, entry, flags); - break; - case S_IFBLK: - ret = extract_block_device(a, entry, flags); - break; - case S_IFDIR: - ret = extract_dir(a, entry, flags); - break; - case S_IFIFO: - ret = extract_fifo(a, entry, flags); - break; - } - } - - -cleanup: -#ifdef HAVE_FCHDIR - /* If we changed directory above, restore it here. */ - if (restore_pwd >= 0 && original_filename != NULL) { - fchdir(restore_pwd); - close(restore_pwd); - archive_entry_copy_pathname(entry, original_filename); - free(original_filename); - } -#endif - - return (ret); -} - -/* - * Cleanup function for archive_extract. Mostly, this involves processing - * the fixup list, which is used to address a number of problems: - * * Dir permissions might prevent us from restoring a file in that - * dir, so we restore the dir 0700 first, then correct the - * mode at the end. - * * Similarly, the act of restoring a file touches the directory - * and changes the timestamp on the dir, so we have to touch-up dir - * timestamps at the end as well. - * * Some file flags can interfere with the restore by, for example, - * preventing the creation of hardlinks to those files. - * - * Note that tar/cpio do not require that archives be in a particular - * order; there is no way to know when the last file has been restored - * within a directory, so there's no way to optimize the memory usage - * here by fixing up the directory any earlier than the - * end-of-archive. - * - * XXX TODO: Directory ACLs should be restored here, for the same - * reason we set directory perms here. XXX - * - * Registering this function (rather than calling it explicitly by - * name from archive_read_finish) reduces static link pollution, since - * applications that don't use this API won't get this file linked in. - */ -static int -archive_extract_cleanup(struct archive *a) -{ - struct fixup_entry *next, *p; - struct extract *extract; - - /* Sort dir list so directories are fixed up in depth-first order. */ - extract = a->extract; - p = sort_dir_list(extract->fixup_list); - - while (p != NULL) { - extract->pst = NULL; /* Mark stat cache as out-of-date. */ - if (p->fixup & FIXUP_TIMES) { - struct timeval times[2]; - times[1].tv_sec = p->mtime; - times[1].tv_usec = p->mtime_nanos / 1000; - times[0].tv_sec = p->atime; - times[0].tv_usec = p->atime_nanos / 1000; - utimes(p->name, times); - } - if (p->fixup & FIXUP_MODE) - chmod(p->name, p->mode); - - if (p->fixup & FIXUP_FFLAGS) - set_fflags(a, -1, p->name, p->mode, p->fflags_set, 0); - - next = p->next; - free(p->name); - free(p); - p = next; - } - extract->fixup_list = NULL; - archive_string_free(&extract->create_parent_dir); - free(a->extract); - a->extract = NULL; - return (ARCHIVE_OK); -} - -/* - * Simple O(n log n) merge sort to order the fixup list. In - * particular, we want to restore dir timestamps depth-first. - */ -static struct fixup_entry * -sort_dir_list(struct fixup_entry *p) -{ - struct fixup_entry *a, *b, *t; - - if (p == NULL) - return (NULL); - /* A one-item list is already sorted. */ - if (p->next == NULL) - return (p); - - /* Step 1: split the list. */ - t = p; - a = p->next->next; - while (a != NULL) { - /* Step a twice, t once. */ - a = a->next; - if (a != NULL) - a = a->next; - t = t->next; - } - /* Now, t is at the mid-point, so break the list here. */ - b = t->next; - t->next = NULL; - a = p; - - /* Step 2: Recursively sort the two sub-lists. */ - a = sort_dir_list(a); - b = sort_dir_list(b); - - /* Step 3: Merge the returned lists. */ - /* Pick the first element for the merged list. */ - if (strcmp(a->name, b->name) > 0) { - t = p = a; - a = a->next; - } else { - t = p = b; - b = b->next; - } - - /* Always put the later element on the list first. */ - while (a != NULL && b != NULL) { - if (strcmp(a->name, b->name) > 0) { - t->next = a; - a = a->next; - } else { - t->next = b; - b = b->next; - } - t = t->next; - } - - /* Only one list is non-empty, so just splice it on. */ - if (a != NULL) - t->next = a; - if (b != NULL) - t->next = b; - - return (p); -} - -/* - * Returns a new, initialized fixup entry. - * - * TODO: Reduce the memory requirements for this list by using a tree - * structure rather than a simple list of names. - */ -static struct fixup_entry * -new_fixup(struct archive *a, const char *pathname) -{ - struct extract *extract; - struct fixup_entry *fe; - - extract = a->extract; - fe = malloc(sizeof(struct fixup_entry)); - if (fe == NULL) - return (NULL); - fe->next = extract->fixup_list; - extract->fixup_list = fe; - fe->fixup = 0; - fe->name = strdup(pathname); - return (fe); -} - -/* - * Returns a fixup structure for the current entry. - */ -static struct fixup_entry * -current_fixup(struct archive *a, const char *pathname) -{ - struct extract *extract; - - extract = a->extract; - if (extract->current_fixup == NULL) - extract->current_fixup = new_fixup(a, pathname); - return (extract->current_fixup); -} - -static int -extract_file(struct archive *a, struct archive_entry *entry, int flags) -{ - struct extract *extract; - const char *name; - mode_t mode; - int fd, r, r2; - - extract = a->extract; - name = archive_entry_pathname(entry); - mode = archive_entry_mode(entry) & 0777; - r = ARCHIVE_OK; - - /* - * If we're not supposed to overwrite pre-existing files, - * use O_EXCL. Otherwise, use O_TRUNC. - */ - if (flags & (ARCHIVE_EXTRACT_UNLINK | ARCHIVE_EXTRACT_NO_OVERWRITE)) - fd = open(name, O_WRONLY | O_CREAT | O_EXCL, mode); - else - fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode); - - /* Try removing a pre-existing file. */ - if (fd < 0 && !(flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { - unlink(name); - fd = open(name, O_WRONLY | O_CREAT | O_EXCL, mode); - } - - /* Might be a non-existent parent dir; try fixing that. */ - if (fd < 0) { - create_parent_dir(a, name, flags); - fd = open(name, O_WRONLY | O_CREAT | O_EXCL, mode); - } - if (fd < 0) { - archive_set_error(a, errno, "Can't open '%s'", name); - return (ARCHIVE_WARN); - } - r = archive_read_data_into_fd(a, fd); - extract->pst = NULL; /* Cached stat data no longer valid. */ - r2 = restore_metadata(a, fd, entry, flags); - close(fd); - return (err_combine(r, r2)); -} - -static int -extract_dir(struct archive *a, struct archive_entry *entry, int flags) -{ - struct extract *extract; - struct fixup_entry *fe; - char *path, *p; - - extract = a->extract; - extract->pst = NULL; /* Invalidate cached stat data. */ - - /* Copy path to mutable storage. */ - archive_strcpy(&(extract->create_parent_dir), - archive_entry_pathname(entry)); - path = extract->create_parent_dir.s; - - if (*path == '\0') { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid empty pathname"); - return (ARCHIVE_WARN); - } - - /* Deal with any troublesome trailing path elements. */ - /* TODO: Someday, generalize this to remove '//' or '/./' from - * the middle of paths. But, it should not compress '..' from - * the middle of paths. It's a feature that restoring - * "a/../b" creates both 'a' and 'b' directories. */ - for (;;) { - /* Locate last element. */ - p = strrchr(path, '/'); - if (p != NULL) - p++; - else - p = path; - /* Trim trailing '/' unless that's the entire path. */ - if (p[0] == '\0' && p - 1 > path) { - p[-1] = '\0'; - continue; - } - /* Trim trailing '.' unless that's the entire path. */ - if (p > path && p[0] == '.' && p[1] == '\0') { - p[0] = '\0'; - continue; - } - /* Just exit on trailing '..'. */ - if (p[0] == '.' && p[1] == '.' && p[2] == '\0') { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Can't restore directory '..'"); - return (ARCHIVE_WARN); - } - break; - } - - if (mkdir(path, SECURE_DIR_MODE) == 0) - goto success; - - if (extract->pst == NULL && stat(path, &extract->st) == 0) - extract->pst = &extract->st; - - if (extract->pst != NULL) { - extract->pst = &extract->st; - /* If dir already exists, don't reset permissions. */ - if (S_ISDIR(extract->pst->st_mode)) - return (ARCHIVE_OK); - /* It exists but isn't a dir. */ - if ((flags & ARCHIVE_EXTRACT_UNLINK)) - unlink(path); - } else { - /* Doesn't already exist; try building the parent path. */ - if (create_parent_dir_mutable(a, path, flags) != ARCHIVE_OK) - return (ARCHIVE_WARN); - } - - /* One final attempt to create the dir. */ - if (mkdir(path, SECURE_DIR_MODE) != 0) { - archive_set_error(a, errno, "Can't create directory"); - return (ARCHIVE_WARN); - } - -success: - /* Add this dir to the fixup list. */ - fe = current_fixup(a, path); - fe->fixup |= FIXUP_MODE; - fe->mode = archive_entry_mode(entry); - if ((flags & ARCHIVE_EXTRACT_PERM) == 0) - fe->mode &= ~extract->umask; - if (flags & ARCHIVE_EXTRACT_TIME) { - fe->fixup |= FIXUP_TIMES; - fe->mtime = archive_entry_mtime(entry); - fe->mtime_nanos = archive_entry_mtime_nsec(entry); - fe->atime = archive_entry_atime(entry); - fe->atime_nanos = archive_entry_atime_nsec(entry); - } - /* For now, set the mode to SECURE_DIR_MODE. */ - archive_entry_set_mode(entry, SECURE_DIR_MODE); - return (restore_metadata(a, -1, entry, flags)); -} - - -/* - * Create the parent of the specified path. Copy the provided - * path into mutable storage first. - */ -static int -create_parent_dir(struct archive *a, const char *path, int flags) -{ - int r; - - /* Copy path to mutable storage. */ - archive_strcpy(&(a->extract->create_parent_dir), path); - r = create_parent_dir_mutable(a, a->extract->create_parent_dir.s, flags); - return (r); -} - -/* - * Like create_parent_dir, but creates the dir actually requested, not - * the parent. - */ -static int -create_dir(struct archive *a, const char *path, int flags) -{ - int r; - /* Copy path to mutable storage. */ - archive_strcpy(&(a->extract->create_parent_dir), path); - r = create_dir_mutable(a, a->extract->create_parent_dir.s, flags); - return (r); -} - -/* - * Create the parent directory of the specified path, assuming path - * is already in mutable storage. - */ -static int -create_parent_dir_mutable(struct archive *a, char *path, int flags) -{ - char *slash; - int r; - - /* Remove tail element to obtain parent name. */ - slash = strrchr(path, '/'); - if (slash == NULL) - return (ARCHIVE_OK); - *slash = '\0'; - r = create_dir_mutable(a, path, flags); - *slash = '/'; - return (r); -} - -/* - * Create the specified dir, assuming path is already in - * mutable storage. - */ -static int -create_dir_mutable(struct archive *a, char *path, int flags) -{ - mode_t old_umask; - int r; - - old_umask = umask(~SECURE_DIR_MODE); - r = create_dir_recursive(a, path, flags); - umask(old_umask); - return (r); -} - -/* - * Create the specified dir, recursing to create parents as necessary. - * - * Returns ARCHIVE_OK if the path exists when we're done here. - * Otherwise, returns ARCHIVE_WARN. - */ -static int -create_dir_recursive(struct archive *a, char *path, int flags) -{ - struct stat st; - struct extract *extract; - struct fixup_entry *le; - char *slash, *base; - int r; - - extract = a->extract; - r = ARCHIVE_OK; - - /* Check for special names and just skip them. */ - slash = strrchr(path, '/'); - base = strrchr(path, '/'); - if (slash == NULL) - base = path; - else - base = slash + 1; - - if (base[0] == '\0' || - (base[0] == '.' && base[1] == '\0') || - (base[0] == '.' && base[1] == '.' && base[2] == '\0')) { - /* Don't bother trying to create null path, '.', or '..'. */ - if (slash != NULL) { - *slash = '\0'; - r = create_dir_recursive(a, path, flags); - *slash = '/'; - return (r); - } - return (ARCHIVE_OK); - } - - /* - * Yes, this should be stat() and not lstat(). Using lstat() - * here loses the ability to extract through symlinks. Also note - * that this should not use the extract->st cache. - */ - if (stat(path, &st) == 0) { - if (S_ISDIR(st.st_mode)) - return (ARCHIVE_OK); - if ((flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { - archive_set_error(a, EEXIST, - "Can't create directory '%s'", path); - return (ARCHIVE_WARN); - } - if (unlink(path) != 0) { - archive_set_error(a, errno, - "Can't create directory '%s': " - "Conflicting file cannot be removed"); - return (ARCHIVE_WARN); - } - } else if (errno != ENOENT && errno != ENOTDIR) { - /* Stat failed? */ - archive_set_error(a, errno, "Can't test directory '%s'", path); - return (ARCHIVE_WARN); - } else if (slash != NULL) { - *slash = '\0'; - r = create_dir_recursive(a, path, flags); - *slash = '/'; - if (r != ARCHIVE_OK) - return (r); - } - - if (mkdir(path, SECURE_DIR_MODE) == 0) { - le = new_fixup(a, path); - le->fixup |= FIXUP_MODE; - le->mode = extract->default_dir_mode; - return (ARCHIVE_OK); - } - - /* - * Without the following check, a/b/../b/c/d fails at the - * second visit to 'b', so 'd' can't be created. Note that we - * don't add it to the fixup list here, as it's already been - * added. - */ - if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) - return (ARCHIVE_OK); - - archive_set_error(a, errno, "Failed to create dir '%s'", path); - return (ARCHIVE_WARN); -} - -static int -extract_hard_link(struct archive *a, struct archive_entry *entry, int flags) -{ - struct extract *extract; - int r; - const char *pathname; - const char *linkname; - - extract = a->extract; - pathname = archive_entry_pathname(entry); - linkname = archive_entry_hardlink(entry); - - /* Just remove any pre-existing file with this name. */ - if (!(flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) - unlink(pathname); - - r = link(linkname, pathname); - extract->pst = NULL; /* Invalidate cached stat data. */ - - if (r != 0) { - /* Might be a non-existent parent dir; try fixing that. */ - create_parent_dir(a, pathname, flags); - r = link(linkname, pathname); - } - - if (r != 0) { - /* XXX Better error message here XXX */ - archive_set_error(a, errno, - "Can't restore hardlink to '%s'", linkname); - return (ARCHIVE_WARN); - } - - /* Set ownership, time, permission information. */ - r = restore_metadata(a, -1, entry, flags); - return (r); -} - -static int -extract_symlink(struct archive *a, struct archive_entry *entry, int flags) -{ - struct extract *extract; - int r; - const char *pathname; - const char *linkname; - - extract = a->extract; - pathname = archive_entry_pathname(entry); - linkname = archive_entry_symlink(entry); - - /* Just remove any pre-existing file with this name. */ - if (!(flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) - unlink(pathname); - - r = symlink(linkname, pathname); - extract->pst = NULL; /* Invalidate cached stat data. */ - - if (r != 0) { - /* Might be a non-existent parent dir; try fixing that. */ - create_parent_dir(a, pathname, flags); - r = symlink(linkname, pathname); - } - - if (r != 0) { - /* XXX Better error message here XXX */ - archive_set_error(a, errno, - "Can't restore symlink to '%s'", linkname); - return (ARCHIVE_WARN); - } - - r = restore_metadata(a, -1, entry, flags); - return (r); -} - -static int -extract_device(struct archive *a, struct archive_entry *entry, - int flags, mode_t mode) -{ - struct extract *extract; - int r; - - extract = a->extract; - /* Just remove any pre-existing file with this name. */ - if (!(flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) - unlink(archive_entry_pathname(entry)); - - r = mknod(archive_entry_pathname(entry), mode, - archive_entry_rdev(entry)); - extract->pst = NULL; /* Invalidate cached stat data. */ - - /* Might be a non-existent parent dir; try fixing that. */ - if (r != 0 && errno == ENOENT) { - create_parent_dir(a, archive_entry_pathname(entry), flags); - r = mknod(archive_entry_pathname(entry), mode, - archive_entry_rdev(entry)); - } - - if (r != 0) { - archive_set_error(a, errno, "Can't restore device node"); - return (ARCHIVE_WARN); - } - - r = restore_metadata(a, -1, entry, flags); - return (r); -} - -static int -extract_char_device(struct archive *a, struct archive_entry *entry, int flags) -{ - mode_t mode; - - mode = (archive_entry_mode(entry) & ~S_IFMT) | S_IFCHR; - return (extract_device(a, entry, flags, mode)); -} - -static int -extract_block_device(struct archive *a, struct archive_entry *entry, int flags) -{ - mode_t mode; - - mode = (archive_entry_mode(entry) & ~S_IFMT) | S_IFBLK; - return (extract_device(a, entry, flags, mode)); -} - -static int -extract_fifo(struct archive *a, struct archive_entry *entry, int flags) -{ - struct extract *extract; - int r; - - extract = a->extract; - /* Just remove any pre-existing file with this name. */ - if (!(flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) - unlink(archive_entry_pathname(entry)); - - r = mkfifo(archive_entry_pathname(entry), - archive_entry_mode(entry)); - extract->pst = NULL; /* Invalidate cached stat data. */ - - /* Might be a non-existent parent dir; try fixing that. */ - if (r != 0 && errno == ENOENT) { - create_parent_dir(a, archive_entry_pathname(entry), flags); - r = mkfifo(archive_entry_pathname(entry), - archive_entry_mode(entry)); - } - - if (r != 0) { - archive_set_error(a, errno, "Can't restore fifo"); - return (ARCHIVE_WARN); - } - - r = restore_metadata(a, -1, entry, flags); - return (r); -} - -static int -restore_metadata(struct archive *a, int fd, struct archive_entry *entry, int flags) -{ - int r, r2; - - r = set_ownership(a, fd, entry, flags); - r2 = set_time(a, fd, entry, flags); - r = err_combine(r, r2); - r2 = set_perm(a, fd, entry, archive_entry_mode(entry), flags); - return (err_combine(r, r2)); -} - -static int -set_ownership(struct archive *a, int fd, - struct archive_entry *entry, int flags) -{ - uid_t uid; - gid_t gid; - - /* Not changed. */ - if ((flags & ARCHIVE_EXTRACT_OWNER) == 0) - return (ARCHIVE_OK); - - uid = lookup_uid(a, archive_entry_uname(entry), - archive_entry_uid(entry)); - gid = lookup_gid(a, archive_entry_gname(entry), - archive_entry_gid(entry)); - - /* If we know we can't change it, don't bother trying. */ - if (a->user_uid != 0 && a->user_uid != uid) - return (ARCHIVE_OK); - -#ifdef HAVE_FCHOWN - if (fd >= 0 && fchown(fd, uid, gid) == 0) - return (ARCHIVE_OK); -#endif - -#ifdef HAVE_LCHOWN - if (lchown(archive_entry_pathname(entry), uid, gid)) -#else - if (!S_ISLNK(archive_entry_mode(entry)) - && chown(archive_entry_pathname(entry), uid, gid) != 0) -#endif - { - archive_set_error(a, errno, - "Can't set user=%d/group=%d for %s", uid, gid, - archive_entry_pathname(entry)); - return (ARCHIVE_WARN); - } - return (ARCHIVE_OK); -} - -static int -set_time(struct archive *a, int fd, struct archive_entry *entry, int flags) -{ - const struct stat *st; - struct timeval times[2]; - - (void)a; /* UNUSED */ - st = archive_entry_stat(entry); - - if ((flags & ARCHIVE_EXTRACT_TIME) == 0) - return (ARCHIVE_OK); - /* It's a waste of time to mess with dir timestamps here. */ - if (S_ISDIR(archive_entry_mode(entry))) - return (ARCHIVE_OK); - - times[1].tv_sec = st->st_mtime; - times[1].tv_usec = ARCHIVE_STAT_MTIME_NANOS(st) / 1000; - - times[0].tv_sec = st->st_atime; - times[0].tv_usec = ARCHIVE_STAT_ATIME_NANOS(st) / 1000; - -#ifdef HAVE_FUTIMES - if (fd >= 0 && futimes(fd, times) == 0) - return (ARCHIVE_OK); -#endif - -#ifdef HAVE_LUTIMES - if (lutimes(archive_entry_pathname(entry), times) != 0) { -#else - if ((archive_entry_mode(entry) & S_IFMT) != S_IFLNK && - utimes(archive_entry_pathname(entry), times) != 0) { -#endif - archive_set_error(a, errno, "Can't update time for %s", - archive_entry_pathname(entry)); - return (ARCHIVE_WARN); - } - - /* - * Note: POSIX does not provide a portable way to restore ctime. - * (Apart from resetting the system clock, which is distasteful.) - * So, any restoration of ctime will necessarily be OS-specific. - */ - - /* XXX TODO: Can FreeBSD restore ctime? XXX */ - - return (ARCHIVE_OK); -} - -static int -set_perm(struct archive *a, int fd, struct archive_entry *entry, - int mode, int flags) -{ - struct extract *extract; - struct fixup_entry *le; - const char *name; - unsigned long set, clear; - int r; - int critical_flags; - - extract = a->extract; - - /* Obey umask unless ARCHIVE_EXTRACT_PERM. */ - if ((flags & ARCHIVE_EXTRACT_PERM) == 0) - mode &= ~extract->umask; /* Enforce umask. */ - name = archive_entry_pathname(entry); - - if (mode & (S_ISUID | S_ISGID)) { - if (extract->pst != NULL) { - /* Already have stat() data available. */ -#ifdef HAVE_FSTAT - } else if (fd >= 0 && fstat(fd, &extract->st) == 0) { - extract->pst = &extract->st; -#endif - } else if (stat(name, &extract->st) == 0) { - extract->pst = &extract->st; - } else { - archive_set_error(a, errno, - "Couldn't stat file"); - return (ARCHIVE_WARN); - } - - /* - * TODO: Use the uid/gid looked up in set_ownership - * above rather than the uid/gid stored in the entry. - */ - if (extract->pst->st_uid != archive_entry_uid(entry)) - mode &= ~ S_ISUID; - if (extract->pst->st_gid != archive_entry_gid(entry)) - mode &= ~ S_ISGID; - } - - /* - * Ensure we change permissions on the object we extracted, - * and not any incidental symlink that might have gotten in - * the way. - */ - if (!S_ISLNK(archive_entry_mode(entry))) { -#ifdef HAVE_FCHMOD - if (fd >= 0) { - if (fchmod(fd, mode) != 0) { - archive_set_error(a, errno, - "Can't set permissions"); - return (ARCHIVE_WARN); - } - } else -#endif - if (chmod(name, mode) != 0) { - archive_set_error(a, errno, "Can't set permissions"); - return (ARCHIVE_WARN); - } -#ifdef HAVE_LCHMOD - } else { - /* - * If lchmod() isn't supported, it's no big deal. - * Permissions on symlinks are actually ignored on - * most platforms. - */ - if (lchmod(name, mode) != 0) { - archive_set_error(a, errno, "Can't set permissions"); - return (ARCHIVE_WARN); - } -#endif - } - - if (flags & ARCHIVE_EXTRACT_ACL) { - r = set_acls(a, fd, entry); - if (r != ARCHIVE_OK) - return (r); - } - - if (flags & ARCHIVE_EXTRACT_XATTR) { - r = set_xattrs(a, fd, entry); - if (r != ARCHIVE_OK) - return (r); - } - - /* - * Make 'critical_flags' hold all file flags that can't be - * immediately restored. For example, on BSD systems, - * SF_IMMUTABLE prevents hardlinks from being created, so - * should not be set until after any hardlinks are created. To - * preserve some semblance of portability, this uses #ifdef - * extensively. Ugly, but it works. - * - * Yes, Virginia, this does create a security race. It's mitigated - * somewhat by the practice of creating dirs 0700 until the extract - * is done, but it would be nice if we could do more than that. - * People restoring critical file systems should be wary of - * other programs that might try to muck with files as they're - * being restored. - */ - /* Hopefully, the compiler will optimize this mess into a constant. */ - critical_flags = 0; -#ifdef SF_IMMUTABLE - critical_flags |= SF_IMMUTABLE; -#endif -#ifdef UF_IMMUTABLE - critical_flags |= UF_IMMUTABLE; -#endif -#ifdef SF_APPEND - critical_flags |= SF_APPEND; -#endif -#ifdef UF_APPEND - critical_flags |= UF_APPEND; -#endif -#ifdef EXT2_APPEND_FL - critical_flags |= EXT2_APPEND_FL; -#endif -#ifdef EXT2_IMMUTABLE_FL - critical_flags |= EXT2_IMMUTABLE_FL; -#endif - - if (flags & ARCHIVE_EXTRACT_FFLAGS) { - archive_entry_fflags(entry, &set, &clear); - - /* - * The first test encourages the compiler to eliminate - * all of this if it's not necessary. - */ - if ((critical_flags != 0) && (set & critical_flags)) { - le = current_fixup(a, archive_entry_pathname(entry)); - le->fixup |= FIXUP_FFLAGS; - le->fflags_set = set; - /* Store the mode if it's not already there. */ - if ((le->fixup & FIXUP_MODE) == 0) - le->mode = mode; - } else { - r = set_fflags(a, fd, archive_entry_pathname(entry), - mode, set, clear); - if (r != ARCHIVE_OK) - return (r); - } - } - return (ARCHIVE_OK); -} - - -#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && !defined(__linux) -static int -set_fflags(struct archive *a, int fd, const char *name, mode_t mode, - unsigned long set, unsigned long clear) -{ - struct extract *extract; - - extract = a->extract; - if (set == 0 && clear == 0) - return (ARCHIVE_OK); - - (void)mode; /* UNUSED */ - /* - * XXX Is the stat here really necessary? Or can I just use - * the 'set' flags directly? In particular, I'm not sure - * about the correct approach if we're overwriting an existing - * file that already has flags on it. XXX - */ - if (extract->pst != NULL) { - /* Already have stat() data available. */ - } else if (fd >= 0 && fstat(fd, &extract->st) == 0) - extract->pst = &extract->st; - else if (stat(name, &extract->st) == 0) - extract->pst = &extract->st; - else { - archive_set_error(a, errno, - "Couldn't stat file"); - return (ARCHIVE_WARN); - } - - extract->st.st_flags &= ~clear; - extract->st.st_flags |= set; -#ifdef HAVE_FCHFLAGS - /* If platform has fchflags() and we were given an fd, use it. */ - if (fd >= 0 && fchflags(fd, extract->st.st_flags) == 0) - return (ARCHIVE_OK); -#endif - /* - * If we can't use the fd to set the flags, we'll use the - * pathname to set flags. We prefer lchflags() but will use - * chflags() if we must. - */ -#ifdef HAVE_LCHFLAGS - if (lchflags(name, extract->st.st_flags) == 0) - return (ARCHIVE_OK); -#elif defined(HAVE_CHFLAGS) - if (chflags(name, extract->st.st_flags) == 0) - return (ARCHIVE_OK); -#endif - archive_set_error(a, errno, - "Failed to set file flags"); - return (ARCHIVE_WARN); -} - -#elif defined(__linux) && defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) - -/* - * Linux has flags too, but uses ioctl() to access them instead of - * having a separate chflags() system call. - */ -static int -set_fflags(struct archive *a, int fd, const char *name, mode_t mode, - unsigned long set, unsigned long clear) -{ - struct extract *extract; - int ret; - int myfd = fd; - unsigned long newflags, oldflags; - unsigned long sf_mask = 0; - - extract = a->extract; - if (set == 0 && clear == 0) - return (ARCHIVE_OK); - /* Only regular files and dirs can have flags. */ - if (!S_ISREG(mode) && !S_ISDIR(mode)) - return (ARCHIVE_OK); - - /* If we weren't given an fd, open it ourselves. */ - if (myfd < 0) - myfd = open(name, O_RDONLY|O_NONBLOCK); - if (myfd < 0) - return (ARCHIVE_OK); - - /* - * Linux has no define for the flags that are only settable by - * the root user. This code may seem a little complex, but - * there seem to be some Linux systems that lack these - * defines. (?) The code below degrades reasonably gracefully - * if sf_mask is incomplete. - */ -#ifdef EXT2_IMMUTABLE_FL - sf_mask |= EXT2_IMMUTABLE_FL; -#endif -#ifdef EXT2_APPEND_FL - sf_mask |= EXT2_APPEND_FL; -#endif - /* - * XXX As above, this would be way simpler if we didn't have - * to read the current flags from disk. XXX - */ - ret = ARCHIVE_OK; - /* Try setting the flags as given. */ - if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) { - newflags = (oldflags & ~clear) | set; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) - goto cleanup; - if (errno != EPERM) - goto fail; - } - /* If we couldn't set all the flags, try again with a subset. */ - if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) { - newflags &= ~sf_mask; - oldflags &= sf_mask; - newflags |= oldflags; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) - goto cleanup; - } - /* We couldn't set the flags, so report the failure. */ -fail: - archive_set_error(a, errno, - "Failed to set file flags"); - ret = ARCHIVE_WARN; -cleanup: - if (fd < 0) - close(myfd); - return (ret); -} - -#else /* Not HAVE_CHFLAGS && Not __linux */ - -/* - * Of course, some systems have neither BSD chflags() nor Linux' flags - * support through ioctl(). - */ -static int -set_fflags(struct archive *a, int fd, const char *name, mode_t mode, - unsigned long set, unsigned long clear) -{ - (void)a; - (void)fd; - (void)name; - (void)mode; - (void)set; - (void)clear; - return (ARCHIVE_OK); -} - -#endif /* __linux */ - -#ifndef HAVE_POSIX_ACL -/* Default empty function body to satisfy mainline code. */ -static int -set_acls(struct archive *a, int fd, struct archive_entry *entry) -{ - (void)a; - (void)fd; - (void)entry; - - return (ARCHIVE_OK); -} - -#else - -/* - * XXX TODO: What about ACL types other than ACCESS and DEFAULT? - */ -static int -set_acls(struct archive *a, int fd, struct archive_entry *entry) -{ - int ret; - - ret = set_acl(a, fd, entry, ACL_TYPE_ACCESS, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); - if (ret != ARCHIVE_OK) - return (ret); - ret = set_acl(a, fd, entry, ACL_TYPE_DEFAULT, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); - return (ret); -} - - -static int -set_acl(struct archive *a, int fd, struct archive_entry *entry, - acl_type_t acl_type, int ae_requested_type, const char *typename) -{ - acl_t acl; - acl_entry_t acl_entry; - acl_permset_t acl_permset; - int ret; - int ae_type, ae_permset, ae_tag, ae_id; - uid_t ae_uid; - gid_t ae_gid; - const char *ae_name; - int entries; - const char *name; - - ret = ARCHIVE_OK; - entries = archive_entry_acl_reset(entry, ae_requested_type); - if (entries == 0) - return (ARCHIVE_OK); - acl = acl_init(entries); - while (archive_entry_acl_next(entry, ae_requested_type, &ae_type, - &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { - acl_create_entry(&acl, &acl_entry); - - switch (ae_tag) { - case ARCHIVE_ENTRY_ACL_USER: - acl_set_tag_type(acl_entry, ACL_USER); - ae_uid = lookup_uid(a, ae_name, ae_id); - acl_set_qualifier(acl_entry, &ae_uid); - break; - case ARCHIVE_ENTRY_ACL_GROUP: - acl_set_tag_type(acl_entry, ACL_GROUP); - ae_gid = lookup_gid(a, ae_name, ae_id); - acl_set_qualifier(acl_entry, &ae_gid); - break; - case ARCHIVE_ENTRY_ACL_USER_OBJ: - acl_set_tag_type(acl_entry, ACL_USER_OBJ); - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); - break; - case ARCHIVE_ENTRY_ACL_MASK: - acl_set_tag_type(acl_entry, ACL_MASK); - break; - case ARCHIVE_ENTRY_ACL_OTHER: - acl_set_tag_type(acl_entry, ACL_OTHER); - break; - default: - /* XXX */ - break; - } - - acl_get_permset(acl_entry, &acl_permset); - acl_clear_perms(acl_permset); - if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE) - acl_add_perm(acl_permset, ACL_EXECUTE); - if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE) - acl_add_perm(acl_permset, ACL_WRITE); - if (ae_permset & ARCHIVE_ENTRY_ACL_READ) - acl_add_perm(acl_permset, ACL_READ); - } - - name = archive_entry_pathname(entry); - - /* Try restoring the ACL through 'fd' if we can. */ -#if HAVE_ACL_SET_FD - if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) - ret = ARCHIVE_OK; - else -#else -#if HAVE_ACL_SET_FD_NP - if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) - ret = ARCHIVE_OK; - else -#endif -#endif - if (acl_set_file(name, acl_type, acl) != 0) { - archive_set_error(a, errno, "Failed to set %s acl", typename); - ret = ARCHIVE_WARN; - } - acl_free(acl); - return (ret); -} -#endif - -#if HAVE_LSETXATTR -/* - * Restore extended attributes - Linux implementation - */ -static int -set_xattrs(struct archive *a, int fd, struct archive_entry *entry) -{ - static int warning_done = 0; - int ret = ARCHIVE_OK; - int i = archive_entry_xattr_reset(entry); - - while (i--) { - const char *name; - const void *value; - size_t size; - archive_entry_xattr_next(entry, &name, &value, &size); - if (name != NULL && - strncmp(name, "xfsroot.", 8) != 0 && - strncmp(name, "system.", 7) != 0) { - int e; -#if HAVE_FSETXATTR - if (fd >= 0) - e = fsetxattr(fd, name, value, size, 0); - else -#endif - { - e = lsetxattr(archive_entry_pathname(entry), - name, value, size, 0); - } - if (e == -1) { - if (errno == ENOTSUP) { - if (!warning_done) { - warning_done = 1; - archive_set_error(a, errno, - "Cannot restore extended " - "attributes on this file " - "system"); - } - } else - archive_set_error(a, errno, - "Failed to set extended attribute"); - ret = ARCHIVE_WARN; - } - } else { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Invalid extended attribute encountered"); - ret = ARCHIVE_WARN; - } - } - return (ret); -} -#else -/* - * Restore extended attributes - stub implementation for unsupported systems - */ -static int -set_xattrs(struct archive *a, int fd, struct archive_entry *entry) -{ - static int warning_done = 0; - (void)a; /* UNUSED */ - (void)fd; /* UNUSED */ - - /* If there aren't any extended attributes, then it's okay not - * to extract them, otherwise, issue a single warning. */ - if (archive_entry_xattr_count(entry) != 0 && !warning_done) { - warning_done = 1; - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Cannot restore extended attributes on this system"); - return (ARCHIVE_WARN); - } - /* Warning was already emitted; suppress further warnings. */ - return (ARCHIVE_OK); -} -#endif - -/* - * The following routines do some basic caching of uname/gname - * lookups. All such lookups go through these routines, including ACL - * conversions. Even a small cache here provides an enormous speedup, - * especially on systems using NIS, LDAP, or a similar networked - * directory system. - * - * TODO: Provide an API for clients to override these routines. - */ -static gid_t -lookup_gid(struct archive *a, const char *gname, gid_t gid) -{ - struct group *grent; - struct extract *extract; - int h; - struct bucket *b; - int cache_size; - - extract = a->extract; - cache_size = sizeof(extract->gcache) / sizeof(extract->gcache[0]); - - /* If no gname, just use the gid provided. */ - if (gname == NULL || *gname == '\0') - return (gid); - - /* Try to find gname in the cache. */ - h = hash(gname); - b = &extract->gcache[h % cache_size ]; - if (b->name != NULL && b->hash == h && strcmp(gname, b->name) == 0) - return ((gid_t)b->id); - - /* Free the cache slot for a new entry. */ - if (b->name != NULL) - free(b->name); - b->name = strdup(gname); - /* Note: If strdup fails, that's okay; we just won't cache. */ - b->hash = h; - grent = getgrnam(gname); - if (grent != NULL) - gid = grent->gr_gid; - b->id = gid; - - return (gid); -} - -static uid_t -lookup_uid(struct archive *a, const char *uname, uid_t uid) -{ - struct passwd *pwent; - struct extract *extract; - int h; - struct bucket *b; - int cache_size; - - extract = a->extract; - cache_size = sizeof(extract->ucache) / sizeof(extract->ucache[0]); - - /* If no uname, just use the uid provided. */ - if (uname == NULL || *uname == '\0') - return (uid); - - /* Try to find uname in the cache. */ - h = hash(uname); - b = &extract->ucache[h % cache_size ]; - if (b->name != NULL && b->hash == h && strcmp(uname, b->name) == 0) - return ((uid_t)b->id); - - /* Free the cache slot for a new entry. */ - if (b->name != NULL) - free(b->name); - b->name = strdup(uname); - /* Note: If strdup fails, that's okay; we just won't cache. */ - b->hash = h; - pwent = getpwnam(uname); - if (pwent != NULL) - uid = pwent->pw_uid; - b->id = uid; - - return (uid); -} - -static unsigned int -hash(const char *p) -{ - /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm, - as used by ELF for hashing function names. */ - unsigned g, h = 0; - while (*p != '\0') { - h = ( h << 4 ) + *p++; - if (( g = h & 0xF0000000 )) { - h ^= g >> 24; - h &= 0x0FFFFFFF; - } - } - return h; -} - -void -archive_read_extract_set_progress_callback(struct archive *a, - void (*progress_func)(void *), void *user_data) -{ - a->extract_progress = progress_func; - a->extract_progress_user_data = user_data; -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_open_fd.c b/contrib/libarchive-1.3.1/libarchive/archive_read_open_fd.c deleted file mode 100644 index 95e7b87e02..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_open_fd.c +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_fd.c,v 1.6 2006/07/30 00:29:00 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" - -struct read_fd_data { - int fd; - size_t block_size; - void *buffer; -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_read(struct archive *, void *, const void **buff); -static ssize_t file_skip(struct archive *, void *, size_t request); - -int -archive_read_open_fd(struct archive *a, int fd, size_t block_size) -{ - struct read_fd_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->block_size = block_size; - mine->buffer = malloc(mine->block_size); - if (mine->buffer == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - free(mine); - return (ARCHIVE_FATAL); - } - mine->fd = fd; - return (archive_read_open2(a, mine, file_open, file_read, file_skip, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - struct read_fd_data *mine = client_data; - struct stat st; - - if (fstat(mine->fd, &st) != 0) { - archive_set_error(a, errno, "Can't stat fd %d", mine->fd); - return (ARCHIVE_FATAL); - } - - if (S_ISREG(st.st_mode)) - archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); - - return (ARCHIVE_OK); -} - -static ssize_t -file_read(struct archive *a, void *client_data, const void **buff) -{ - struct read_fd_data *mine = client_data; - ssize_t bytes_read; - - *buff = mine->buffer; - bytes_read = read(mine->fd, mine->buffer, mine->block_size); - if (bytes_read < 0) { - archive_set_error(a, errno, "Error reading fd %d", mine->fd); - } - return (bytes_read); -} - -static ssize_t -file_skip(struct archive *a, void *client_data, size_t request) -{ - struct read_fd_data *mine = client_data; - off_t old_offset, new_offset; - - /* Reduce request to the next smallest multiple of block_size */ - request = (request / mine->block_size) * mine->block_size; - /* - * Hurray for lazy evaluation: if the first lseek fails, the second - * one will not be executed. - */ - if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) < 0) || - ((new_offset = lseek(mine->fd, request, SEEK_CUR)) < 0)) - { - if (errno == ESPIPE) - { - /* - * Failure to lseek() can be caused by the file - * descriptor pointing to a pipe, socket or FIFO. - * Return 0 here, so the compression layer will use - * read()s instead to advance the file descriptor. - * It's slower of course, but works as well. - */ - return (0); - } - /* - * There's been an error other than ESPIPE. This is most - * likely caused by a programmer error (too large request) - * or a corrupted archive file. - */ - archive_set_error(a, errno, "Error seeking"); - return (-1); - } - return (new_offset - old_offset); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct read_fd_data *mine = client_data; - - (void)a; /* UNUSED */ - if (mine->buffer != NULL) - free(mine->buffer); - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_open_file.c b/contrib/libarchive-1.3.1/libarchive/archive_read_open_file.c deleted file mode 100644 index 18979402ab..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_open_file.c +++ /dev/null @@ -1,137 +0,0 @@ -/*- - * 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. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_file.c,v 1.11 2006/09/05 05:59:46 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" - -struct read_FILE_data { - FILE *f; - size_t block_size; - void *buffer; -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_read(struct archive *, void *, const void **buff); -static ssize_t file_skip(struct archive *, void *, size_t request); - -int -archive_read_open_FILE(struct archive *a, FILE *f) -{ - struct read_FILE_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->block_size = 128 * 1024; - mine->buffer = malloc(mine->block_size); - if (mine->buffer == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - free(mine); - return (ARCHIVE_FATAL); - } - mine->f = f; - return (archive_read_open2(a, mine, file_open, file_read, - file_skip, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - struct read_FILE_data *mine = client_data; - struct stat st; - - /* - * If we can't fstat() the file, it may just be that - * it's not a file. (FILE * objects can wrap many kinds - * of I/O streams.) - */ - if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) - archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); - - return (ARCHIVE_OK); -} - -static ssize_t -file_read(struct archive *a, void *client_data, const void **buff) -{ - struct read_FILE_data *mine = client_data; - ssize_t bytes_read; - - *buff = mine->buffer; - bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f); - if (bytes_read < 0) { - archive_set_error(a, errno, "Error reading file"); - } - return (bytes_read); -} - -static ssize_t -file_skip(struct archive *a, void *client_data, size_t request) -{ - struct read_FILE_data *mine = client_data; - off_t old_offset, new_offset; - - /* Reduce request to the next smallest multiple of block_size */ - request = (request / mine->block_size) * mine->block_size; - /* - * Note: the 'fd' and 'filename' versions round the request - * down to a multiple of the block size to ensure proper - * operation on block-oriented media such as tapes. But stdio - * doesn't work with such media (it doesn't ensure blocking), - * so we don't need to bother. - */ - old_offset = ftello(mine->f); - fseeko(mine->f, request, SEEK_CUR); - new_offset = ftello(mine->f); - if (old_offset < 0 || new_offset < 0) { - archive_set_error(a, errno, "Error skipping forward"); - return (ARCHIVE_FATAL); - } - return (new_offset - old_offset); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct read_FILE_data *mine = client_data; - - (void)a; /* UNUSED */ - if (mine->buffer != NULL) - free(mine->buffer); - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_open_filename.c b/contrib/libarchive-1.3.1/libarchive/archive_read_open_filename.c deleted file mode 100644 index 20509ae5f7..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_open_filename.c +++ /dev/null @@ -1,221 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include "archive.h" - -struct read_file_data { - int fd; - size_t block_size; - void *buffer; - mode_t st_mode; /* Mode bits for opened file. */ - char filename[1]; /* Must be last! */ -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_read(struct archive *, void *, const void **buff); -static ssize_t file_skip(struct archive *, void *, size_t request); - -int -archive_read_open_file(struct archive *a, const char *filename, - size_t block_size) -{ - return (archive_read_open_filename(a, filename, block_size)); -} - -int -archive_read_open_filename(struct archive *a, const char *filename, - size_t block_size) -{ - struct read_file_data *mine; - - if (filename == NULL || filename[0] == '\0') { - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->filename[0] = '\0'; - } else { - mine = malloc(sizeof(*mine) + strlen(filename)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - strcpy(mine->filename, filename); - } - mine->block_size = block_size; - mine->buffer = NULL; - mine->fd = -1; - return (archive_read_open2(a, mine, file_open, file_read, file_skip, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - struct read_file_data *mine = client_data; - struct stat st; - - mine->buffer = malloc(mine->block_size); - if (mine->buffer == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - if (mine->filename[0] != '\0') - mine->fd = open(mine->filename, O_RDONLY); - else - mine->fd = 0; /* Fake "open" for stdin. */ - if (mine->fd < 0) { - archive_set_error(a, errno, "Failed to open '%s'", - mine->filename); - return (ARCHIVE_FATAL); - } - if (fstat(mine->fd, &st) == 0) { - if (S_ISREG(st.st_mode)) { - /* Set dev/ino of archive file so extract - won't overwrite. */ - archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); - } - /* Remember mode so close can decide whether to flush. */ - mine->st_mode = st.st_mode; - } else { - if (mine->filename[0] == '\0') - archive_set_error(a, errno, "Can't stat stdin"); - else - archive_set_error(a, errno, "Can't stat '%s'", - mine->filename); - return (ARCHIVE_FATAL); - } - return (0); -} - -static ssize_t -file_read(struct archive *a, void *client_data, const void **buff) -{ - struct read_file_data *mine = client_data; - ssize_t bytes_read; - - *buff = mine->buffer; - bytes_read = read(mine->fd, mine->buffer, mine->block_size); - if (bytes_read < 0) { - if (mine->filename[0] == '\0') - archive_set_error(a, errno, "Error reading stdin"); - else - archive_set_error(a, errno, "Error reading '%s'", - mine->filename); - } - return (bytes_read); -} - -static ssize_t -file_skip(struct archive *a, void *client_data, size_t request) -{ - struct read_file_data *mine = client_data; - off_t old_offset, new_offset; - - /* Reduce request to the next smallest multiple of block_size */ - request = (request / mine->block_size) * mine->block_size; - /* - * Hurray for lazy evaluation: if the first lseek fails, the second - * one will not be executed. - */ - if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) < 0) || - ((new_offset = lseek(mine->fd, request, SEEK_CUR)) < 0)) - { - if (errno == ESPIPE) - { - /* - * Failure to lseek() can be caused by the file - * descriptor pointing to a pipe, socket or FIFO. - * Return 0 here, so the compression layer will use - * read()s instead to advance the file descriptor. - * It's slower of course, but works as well. - */ - return (0); - } - /* - * There's been an error other than ESPIPE. This is most - * likely caused by a programmer error (too large request) - * or a corrupted archive file. - */ - if (mine->filename[0] == '\0') - /* - * Should never get here, since lseek() on stdin ought - * to return an ESPIPE error. - */ - archive_set_error(a, errno, "Error seeking in stdin"); - else - archive_set_error(a, errno, "Error seeking in '%s'", - mine->filename); - return (-1); - } - return (new_offset - old_offset); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct read_file_data *mine = client_data; - - (void)a; /* UNUSED */ - - /* - * Sometimes, we should flush the input before closing. - * Regular files: faster to just close without flush. - * Devices: must not flush (user might need to - * read the "next" item on a non-rewind device). - * Pipes and sockets: must flush (otherwise, the - * program feeding the pipe or socket may complain). - * Here, I flush everything except for regular files and - * device nodes. - */ - if (!S_ISREG(mine->st_mode) - && !S_ISCHR(mine->st_mode) - && !S_ISBLK(mine->st_mode)) { - ssize_t bytesRead; - do { - bytesRead = read(mine->fd, mine->buffer, - mine->block_size); - } while (bytesRead > 0); - } - /* If a named file was opened, then it needs to be closed. */ - if (mine->filename[0] != '\0') - close(mine->fd); - if (mine->buffer != NULL) - free(mine->buffer); - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_open_memory.c b/contrib/libarchive-1.3.1/libarchive/archive_read_open_memory.c deleted file mode 100644 index 3f2b5c9574..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_open_memory.c +++ /dev/null @@ -1,147 +0,0 @@ -/*- - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_fd.c,v 1.5 2006/01/17 04:49:04 kientzle Exp $"); - -#include -#include -#include - -#include "archive.h" - -/* - * Glue to read an archive from a block of memory. - * - * This is mostly a huge help in building test harnesses; - * test programs can build archives in memory and read them - * back again without having to mess with files on disk. - */ - -struct read_memory_data { - unsigned char *buffer; - unsigned char *end; - ssize_t read_size; -}; - -static int memory_read_close(struct archive *, void *); -static int memory_read_open(struct archive *, void *); -static ssize_t memory_read_skip(struct archive *, void *, size_t request); -static ssize_t memory_read(struct archive *, void *, const void **buff); - -int -archive_read_open_memory(struct archive *a, void *buff, size_t size) -{ - return archive_read_open_memory2(a, buff, size, size); -} - -/* - * Don't use this in production code; the archive_read_open_memory() - * version is the one you really want. This is just here so that - * test harnesses can exercise block operations inside the library. - */ -int -archive_read_open_memory2(struct archive *a, void *buff, - size_t size, size_t read_size) -{ - struct read_memory_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - memset(mine, 0, sizeof(*mine)); - mine->buffer = buff; - mine->end = mine->buffer + size; - mine->read_size = read_size; - return (archive_read_open2(a, mine, memory_read_open, - memory_read, memory_read_skip, memory_read_close)); -} - -/* - * There's nothing to open. - */ -static int -memory_read_open(struct archive *a, void *client_data) -{ - (void)a; /* UNUSED */ - (void)client_data; /* UNUSED */ - return (ARCHIVE_OK); -} - -/* - * This is scary simple: Just advance a pointer. Limiting - * to read_size is not technically necessary, but it exercises - * more of the internal logic when used with a small block size - * in a test harness. Production use should not specify a block - * size; then this is much faster. - */ -static ssize_t -memory_read(struct archive *a, void *client_data, const void **buff) -{ - struct read_memory_data *mine = client_data; - ssize_t size; - - (void)a; /* UNUSED */ - *buff = mine->buffer; - size = mine->end - mine->buffer; - if (size > mine->read_size) - size = mine->read_size; - mine->buffer += size; - return (size); -} - -/* - * Advancing is just as simple. Again, this is doing more than - * necessary in order to better exercise internal code when used - * as a test harness. - */ -static ssize_t -memory_read_skip(struct archive *a, void *client_data, size_t skip) -{ - struct read_memory_data *mine = client_data; - - (void)a; /* UNUSED */ - if (mine->buffer + skip > mine->end) - skip = mine->end - mine->buffer; - /* Round down to block size. */ - skip /= mine->read_size; - skip *= mine->read_size; - mine->buffer += skip; - return (skip); -} - -/* - * Close is just cleaning up our one small bit of data. - */ -static int -memory_read_close(struct archive *a, void *client_data) -{ - struct read_memory_data *mine = client_data; - (void)a; /* UNUSED */ - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_all.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_all.c deleted file mode 100644 index b9c458483a..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_all.c +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_all.c,v 1.5 2004/07/30 04:14:47 kientzle Exp $"); - -#include "archive.h" - -int -archive_read_support_compression_all(struct archive *a) -{ -#if HAVE_BZLIB_H - archive_read_support_compression_bzip2(a); -#endif - /* The decompress code doesn't use an outside library. */ - archive_read_support_compression_compress(a); -#if HAVE_ZLIB_H - archive_read_support_compression_gzip(a); -#endif - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_bzip2.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_bzip2.c deleted file mode 100644 index 9704d1e051..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_bzip2.c +++ /dev/null @@ -1,394 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" - -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.9 2006/07/30 00:29:00 kientzle Exp $"); - -#include -#include -#include -#include -#include -#ifdef HAVE_BZLIB_H -#include -#endif - -#include "archive.h" -#include "archive_private.h" - -#if HAVE_BZLIB_H -struct private_data { - bz_stream stream; - char *uncompressed_buffer; - size_t uncompressed_buffer_size; - char *read_next; - int64_t total_out; -}; - -static int finish(struct archive *); -static ssize_t read_ahead(struct archive *, const void **, size_t); -static ssize_t read_consume(struct archive *, size_t); -static int drive_decompressor(struct archive *a, struct private_data *); -#endif - -/* These two functions are defined even if we lack bzlib. See below. */ -static int bid(const void *, size_t); -static int init(struct archive *, const void *, size_t); - -int -archive_read_support_compression_bzip2(struct archive *a) -{ - return (__archive_read_register_compression(a, bid, init)); -} - -/* - * Test whether we can handle this data. - * - * This logic returns zero if any part of the signature fails. It - * also tries to Do The Right Thing if a very short buffer prevents us - * from verifying as much as we would like. - */ -static int -bid(const void *buff, size_t len) -{ - const unsigned char *buffer; - int bits_checked; - - if (len < 1) - return (0); - - buffer = buff; - bits_checked = 0; - if (buffer[0] != 'B') /* Verify first ID byte. */ - return (0); - bits_checked += 8; - if (len < 2) - return (bits_checked); - - if (buffer[1] != 'Z') /* Verify second ID byte. */ - return (0); - bits_checked += 8; - if (len < 3) - return (bits_checked); - - if (buffer[2] != 'h') /* Verify third ID byte. */ - return (0); - bits_checked += 8; - if (len < 4) - return (bits_checked); - - if (buffer[3] < '1' || buffer[3] > '9') - return (0); - bits_checked += 5; - - /* - * 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 gaurd against - * such anomalies in archive_read_support_compression_none.) - */ - - return (bits_checked); -} - -#ifndef HAVE_BZLIB_H - -/* - * If we don't have bzlib on this system, we can't actually do the - * decompression. We can, however, still detect bzip2-compressed - * archives and emit a useful message. - */ -static int -init(struct archive *a, const void *buff, size_t n) -{ - (void)a; /* UNUSED */ - (void)buff; /* UNUSED */ - (void)n; /* UNUSED */ - - archive_set_error(a, -1, - "This version of libarchive was compiled without bzip2 support"); - return (ARCHIVE_FATAL); -} - - -#else - -/* - * Setup the callbacks. - */ -static int -init(struct archive *a, const void *buff, size_t n) -{ - struct private_data *state; - int ret; - - a->compression_code = ARCHIVE_COMPRESSION_BZIP2; - a->compression_name = "bzip2"; - - state = malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for %s decompression", - a->compression_name); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->uncompressed_buffer_size = 64 * 1024; - state->uncompressed_buffer = malloc(state->uncompressed_buffer_size); - state->stream.next_out = state->uncompressed_buffer; - state->read_next = state->uncompressed_buffer; - state->stream.avail_out = state->uncompressed_buffer_size; - - if (state->uncompressed_buffer == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate %s decompression buffers", - a->compression_name); - free(state); - return (ARCHIVE_FATAL); - } - - /* - * A bug in bzlib.h: stream.next_in should be marked 'const' - * but isn't (the library never alters data through the - * next_in pointer, only reads it). The result: this ugly - * cast to remove 'const'. - */ - state->stream.next_in = (void *)(uintptr_t)(const void *)buff; - state->stream.avail_in = n; - - a->compression_read_ahead = read_ahead; - a->compression_read_consume = read_consume; - a->compression_skip = NULL; /* not supported */ - a->compression_finish = finish; - - /* Initialize compression library. */ - ret = BZ2_bzDecompressInit(&(state->stream), - 0 /* library verbosity */, - 0 /* don't use slow low-mem algorithm */); - - /* If init fails, try using low-memory algorithm instead. */ - if (ret == BZ_MEM_ERROR) { - ret = BZ2_bzDecompressInit(&(state->stream), - 0 /* library verbosity */, - 1 /* do use slow low-mem algorithm */); - } - - if (ret == BZ_OK) { - a->compression_data = state; - return (ARCHIVE_OK); - } - - /* Library setup failed: Clean up. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing %s library", a->compression_name); - free(state->uncompressed_buffer); - free(state); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case BZ_PARAM_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid setup parameter"); - break; - case BZ_MEM_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "out of memory"); - break; - case BZ_CONFIG_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "mis-compiled library"); - break; - } - - return (ARCHIVE_FATAL); -} - -/* - * Return a block of data from the decompression buffer. Decompress more - * as necessary. - */ -static ssize_t -read_ahead(struct archive *a, const void **p, size_t min) -{ - struct private_data *state; - int read_avail, was_avail, ret; - - state = a->compression_data; - was_avail = -1; - if (!a->client_reader) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No read callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - read_avail = state->stream.next_out - state->read_next; - - if (read_avail + state->stream.avail_out < min) { - memmove(state->uncompressed_buffer, state->read_next, - read_avail); - state->read_next = state->uncompressed_buffer; - state->stream.next_out = state->read_next + read_avail; - state->stream.avail_out - = state->uncompressed_buffer_size - read_avail; - } - - while (was_avail < read_avail && /* Made some progress. */ - read_avail < (int)min && /* Haven't satisfied min. */ - read_avail < (int)state->uncompressed_buffer_size) { /* !full */ - if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK) - return (ret); - was_avail = read_avail; - read_avail = state->stream.next_out - state->read_next; - } - - *p = state->read_next; - return (read_avail); -} - -/* - * Mark a previously-returned block of data as read. - */ -static ssize_t -read_consume(struct archive *a, size_t n) -{ - struct private_data *state; - - state = a->compression_data; - a->file_position += n; - state->read_next += n; - if (state->read_next > state->stream.next_out) - __archive_errx(1, "Request to consume too many " - "bytes from bzip2 decompressor"); - return (n); -} - -/* - * Clean up the decompressor. - */ -static int -finish(struct archive *a) -{ - struct private_data *state; - int ret; - - state = a->compression_data; - ret = ARCHIVE_OK; - switch (BZ2_bzDecompressEnd(&(state->stream))) { - case BZ_OK: - break; - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", a->compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->uncompressed_buffer); - free(state); - - a->compression_data = NULL; - if (a->client_closer != NULL) - (a->client_closer)(a, a->client_data); - - return (ret); -} - -/* - * Utility function to pull data through decompressor, reading input - * blocks as necessary. - */ -static int -drive_decompressor(struct archive *a, struct private_data *state) -{ - ssize_t ret; - int decompressed, total_decompressed; - char *output; - - total_decompressed = 0; - for (;;) { - if (state->stream.avail_in == 0) { - ret = (a->client_reader)(a, a->client_data, - (const void **)&state->stream.next_in); - if (ret < 0) { - /* - * TODO: Find a better way to handle - * this read failure. - */ - goto fatal; - } - if (ret == 0 && total_decompressed == 0) { - archive_set_error(a, EIO, - "Premature end of %s compressed data", - a->compression_name); - return (ARCHIVE_FATAL); - } - a->raw_position += ret; - state->stream.avail_in = ret; - } - - { - output = state->stream.next_out; - - /* Decompress some data. */ - ret = BZ2_bzDecompress(&(state->stream)); - decompressed = state->stream.next_out - output; - - /* Accumulate the total bytes of output. */ - state->total_out += decompressed; - total_decompressed += decompressed; - - switch (ret) { - case BZ_OK: /* Decompressor made some progress. */ - if (decompressed > 0) - return (ARCHIVE_OK); - break; - case BZ_STREAM_END: /* Found end of stream. */ - return (ARCHIVE_OK); - default: - /* Any other return value is an error. */ - goto fatal; - } - } - } - return (ARCHIVE_OK); - - /* Return a fatal error. */ -fatal: - archive_set_error(a, ARCHIVE_ERRNO_MISC, "%s decompression failed", - a->compression_name); - return (ARCHIVE_FATAL); -} - -#endif /* HAVE_BZLIB_H */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_compress.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_compress.c deleted file mode 100644 index 80e4dc8c62..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_compress.c +++ /dev/null @@ -1,483 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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. - */ - -/* - * This code borrows heavily from "compress" source code, which is - * protected by the following copyright. (Clause 3 dropped by request - * of the Regents.) - */ - -/*- - * Copyright (c) 1985, 1986, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Diomidis Spinellis and James A. Woods, derived from original - * work by Spencer Thomas and Joseph Orost. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_compress.c,v 1.5 2006/07/30 00:29:00 kientzle Exp $"); - -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -/* - * Because LZW decompression is pretty simple, I've just implemented - * the whole decompressor here (cribbing from "compress" source code, - * of course), rather than relying on an external library. I have - * made an effort to clarify and simplify the algorithm, so the - * names and structure here don't exactly match those used by compress. - */ - -struct private_data { - /* Input variables. */ - const unsigned char *next_in; - size_t avail_in; - int bit_buffer; - int bits_avail; - size_t bytes_in_section; - - /* Output variables. */ - size_t uncompressed_buffer_size; - void *uncompressed_buffer; - unsigned char *read_next; /* Data for client. */ - unsigned char *next_out; /* Where to write new data. */ - size_t avail_out; /* Space at end of buffer. */ - - /* Decompression status variables. */ - int use_reset_code; - int end_of_stream; /* EOF status. */ - int maxcode; /* Largest code. */ - int maxcode_bits; /* Length of largest code. */ - int section_end_code; /* When to increase bits. */ - int bits; /* Current code length. */ - int oldcode; /* Previous code. */ - int finbyte; /* Last byte of prev code. */ - - /* Dictionary. */ - int free_ent; /* Next dictionary entry. */ - unsigned char suffix[65536]; - uint16_t prefix[65536]; - - /* - * Scratch area for expanding dictionary entries. Note: - * "worst" case here comes from compressing /dev/zero: the - * last code in the dictionary will code a sequence of - * 65536-256 zero bytes. Thus, we need stack space to expand - * a 65280-byte dictionary entry. (Of course, 32640:1 - * compression could also be considered the "best" case. ;-) - */ - unsigned char *stackp; - unsigned char stack[65300]; -}; - -static int bid(const void *, size_t); -static int finish(struct archive *); -static int init(struct archive *, const void *, size_t); -static ssize_t read_ahead(struct archive *, const void **, size_t); -static ssize_t read_consume(struct archive *, size_t); -static int getbits(struct archive *, struct private_data *, int n); -static int next_code(struct archive *a, struct private_data *state); - -int -archive_read_support_compression_compress(struct archive *a) -{ - return (__archive_read_register_compression(a, bid, init)); -} - -/* - * Test whether we can handle this data. - * - * This logic returns zero if any part of the signature fails. It - * also tries to Do The Right Thing if a very short buffer prevents us - * from verifying as much as we would like. - */ -static int -bid(const void *buff, size_t len) -{ - const unsigned char *buffer; - int bits_checked; - - if (len < 1) - return (0); - - buffer = buff; - bits_checked = 0; - if (buffer[0] != 037) /* Verify first ID byte. */ - return (0); - bits_checked += 8; - if (len < 2) - return (bits_checked); - - if (buffer[1] != 0235) /* Verify second ID byte. */ - return (0); - bits_checked += 8; - if (len < 3) - return (bits_checked); - - /* - * TODO: Verify more. - */ - - return (bits_checked); -} - -/* - * Setup the callbacks. - */ -static int -init(struct archive *a, const void *buff, size_t n) -{ - struct private_data *state; - int code; - - a->compression_code = ARCHIVE_COMPRESSION_COMPRESS; - a->compression_name = "compress (.Z)"; - - a->compression_read_ahead = read_ahead; - a->compression_read_consume = read_consume; - a->compression_skip = NULL; /* not supported */ - a->compression_finish = finish; - - state = malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for %s decompression", - a->compression_name); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - a->compression_data = state; - - state->uncompressed_buffer_size = 64 * 1024; - state->uncompressed_buffer = malloc(state->uncompressed_buffer_size); - - if (state->uncompressed_buffer == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate %s decompression buffers", - a->compression_name); - goto fatal; - } - - state->next_in = buff; - state->avail_in = n; - state->read_next = state->next_out = state->uncompressed_buffer; - state->avail_out = state->uncompressed_buffer_size; - - code = getbits(a, state, 8); - if (code != 037) /* This should be impossible. */ - goto fatal; - - code = getbits(a, state, 8); - if (code != 0235) { - /* This can happen if the library is receiving 1-byte - * blocks and gzip and compress are both enabled. - * You can't distinguish gzip and compress only from - * the first byte. */ - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Compress signature did not match."); - goto fatal; - } - - code = getbits(a, state, 8); - state->maxcode_bits = code & 0x1f; - state->maxcode = (1 << state->maxcode_bits); - state->use_reset_code = code & 0x80; - - /* Initialize decompressor. */ - state->free_ent = 256; - state->stackp = state->stack; - if (state->use_reset_code) - state->free_ent++; - state->bits = 9; - state->section_end_code = (1<bits) - 1; - state->oldcode = -1; - for (code = 255; code >= 0; code--) { - state->prefix[code] = 0; - state->suffix[code] = code; - } - next_code(a, state); - return (ARCHIVE_OK); - -fatal: - finish(a); - return (ARCHIVE_FATAL); -} - -/* - * Return a block of data from the decompression buffer. Decompress more - * as necessary. - */ -static ssize_t -read_ahead(struct archive *a, const void **p, size_t min) -{ - struct private_data *state; - int read_avail, was_avail, ret; - - state = a->compression_data; - was_avail = -1; - if (!a->client_reader) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No read callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - read_avail = state->next_out - state->read_next; - - if (read_avail < (int)min && state->end_of_stream) { - if (state->end_of_stream == ARCHIVE_EOF) - return (0); - else - return (-1); - } - - if (read_avail < (int)min) { - memmove(state->uncompressed_buffer, state->read_next, - read_avail); - state->read_next = state->uncompressed_buffer; - state->next_out = state->read_next + read_avail; - state->avail_out - = state->uncompressed_buffer_size - read_avail; - - while (read_avail < (int)state->uncompressed_buffer_size - && !state->end_of_stream) { - if (state->stackp > state->stack) { - *state->next_out++ = *--state->stackp; - state->avail_out--; - read_avail++; - } else { - ret = next_code(a, state); - if (ret == ARCHIVE_EOF) - state->end_of_stream = ret; - else if (ret != ARCHIVE_OK) - return (ret); - } - } - } - - *p = state->read_next; - return (read_avail); -} - -/* - * Mark a previously-returned block of data as read. - */ -static ssize_t -read_consume(struct archive *a, size_t n) -{ - struct private_data *state; - - state = a->compression_data; - a->file_position += n; - state->read_next += n; - if (state->read_next > state->next_out) - __archive_errx(1, "Request to consume too many " - "bytes from compress decompressor"); - return (n); -} - -/* - * Clean up the decompressor. - */ -static int -finish(struct archive *a) -{ - struct private_data *state; - int ret = ARCHIVE_OK; - - state = a->compression_data; - - if (state != NULL) { - if (state->uncompressed_buffer != NULL) - free(state->uncompressed_buffer); - free(state); - } - - a->compression_data = NULL; - if (a->client_closer != NULL) - ret = (a->client_closer)(a, a->client_data); - - return (ret); -} - -/* - * Process the next code and fill the stack with the expansion - * of the code. Returns ARCHIVE_FATAL if there is a fatal I/O or - * format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise. - */ -static int -next_code(struct archive *a, struct private_data *state) -{ - int code, newcode; - - static int debug_buff[1024]; - static unsigned debug_index; - - code = newcode = getbits(a, state, state->bits); - if (code < 0) - return (code); - - debug_buff[debug_index++] = code; - if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0])) - debug_index = 0; - - /* If it's a reset code, reset the dictionary. */ - if ((code == 256) && state->use_reset_code) { - /* - * The original 'compress' implementation blocked its - * I/O in a manner that resulted in junk bytes being - * inserted after every reset. The next section skips - * this junk. (Yes, the number of *bytes* to skip is - * a function of the current *bit* length.) - */ - int skip_bytes = state->bits - - (state->bytes_in_section % state->bits); - skip_bytes %= state->bits; - state->bits_avail = 0; /* Discard rest of this byte. */ - while (skip_bytes-- > 0) { - code = getbits(a, state, 8); - if (code < 0) - return (code); - } - /* Now, actually do the reset. */ - state->bytes_in_section = 0; - state->bits = 9; - state->section_end_code = (1 << state->bits) - 1; - state->free_ent = 257; - state->oldcode = -1; - return (next_code(a, state)); - } - - if (code > state->free_ent) { - /* An invalid code is a fatal error. */ - archive_set_error(a, -1, "Invalid compressed data: code %d is larger than max code %d (input address %X)", code, state->free_ent, state->next_in); - return (ARCHIVE_FATAL); - } - - /* Special case for KwKwK string. */ - if (code >= state->free_ent) { - *state->stackp++ = state->finbyte; - code = state->oldcode; - } - - /* Generate output characters in reverse order. */ - while (code >= 256) { - *state->stackp++ = state->suffix[code]; - code = state->prefix[code]; - } - *state->stackp++ = state->finbyte = code; - - /* Generate the new entry. */ - code = state->free_ent; - if (code < state->maxcode && state->oldcode >= 0) { - state->prefix[code] = state->oldcode; - state->suffix[code] = state->finbyte; - ++state->free_ent; - } - if (state->free_ent > state->section_end_code) { - state->bits++; - state->bytes_in_section = 0; - if (state->bits == state->maxcode_bits) - state->section_end_code = state->maxcode; - else - state->section_end_code = (1 << state->bits) - 1; - } - - /* Remember previous code. */ - state->oldcode = newcode; - return (ARCHIVE_OK); -} - -/* - * Return next 'n' bits from stream. - * - * -1 indicates end of available data. - */ -static int -getbits(struct archive *a, struct private_data *state, int n) -{ - int code, ret; - static const int mask[] = { - 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, - 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff - }; - - - while (state->bits_avail < n) { - if (state->avail_in <= 0) { - ret = (a->client_reader)(a, a->client_data, - (const void **)&state->next_in); - if (ret < 0) - return (ARCHIVE_FATAL); - if (ret == 0) - return (ARCHIVE_EOF); - a->raw_position += ret; - state->avail_in = ret; - } - state->bit_buffer |= *state->next_in++ << state->bits_avail; - state->avail_in--; - state->bits_avail += 8; - state->bytes_in_section++; - } - - code = state->bit_buffer; - state->bit_buffer >>= n; - state->bits_avail -= n; - - return (code & mask[n]); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_gzip.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_gzip.c deleted file mode 100644 index 95d0894b17..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_gzip.c +++ /dev/null @@ -1,532 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" - -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_gzip.c,v 1.10 2006/07/30 00:29:01 kientzle Exp $"); - - -#include -#include -#include -#include -#ifdef HAVE_ZLIB_H -#include -#endif - -#include "archive.h" -#include "archive_private.h" - -#ifdef HAVE_ZLIB_H -struct private_data { - z_stream stream; - unsigned char *uncompressed_buffer; - size_t uncompressed_buffer_size; - unsigned char *read_next; - int64_t total_out; - unsigned long crc; - char header_done; -}; - -static int finish(struct archive *); -static ssize_t read_ahead(struct archive *, const void **, size_t); -static ssize_t read_consume(struct archive *, size_t); -static int drive_decompressor(struct archive *a, struct private_data *); -#endif - -/* These two functions are defined even if we lack zlib. See below. */ -static int bid(const void *, size_t); -static int init(struct archive *, const void *, size_t); - -int -archive_read_support_compression_gzip(struct archive *a) -{ - return (__archive_read_register_compression(a, bid, init)); -} - -/* - * Test whether we can handle this data. - * - * This logic returns zero if any part of the signature fails. It - * also tries to Do The Right Thing if a very short buffer prevents us - * from verifying as much as we would like. - */ -static int -bid(const void *buff, size_t len) -{ - const unsigned char *buffer; - int bits_checked; - - if (len < 1) - return (0); - - buffer = buff; - bits_checked = 0; - if (buffer[0] != 037) /* Verify first ID byte. */ - return (0); - bits_checked += 8; - if (len < 2) - return (bits_checked); - - if (buffer[1] != 0213) /* Verify second ID byte. */ - return (0); - bits_checked += 8; - if (len < 3) - return (bits_checked); - - if (buffer[2] != 8) /* Compression must be 'deflate'. */ - return (0); - bits_checked += 8; - if (len < 4) - return (bits_checked); - - if ((buffer[3] & 0xE0)!= 0) /* No reserved flags set. */ - return (0); - bits_checked += 3; - if (len < 5) - return (bits_checked); - - /* - * TODO: Verify more; in particular, gzip has an optional - * header CRC, which would give us 16 more verified bits. We - * may also be able to verify certain constraints on other - * fields. - */ - - return (bits_checked); -} - - -#ifndef HAVE_ZLIB_H - -/* - * If we don't have zlib on this system, we can't actually do the - * decompression. We can, however, still detect gzip-compressed - * archives and emit a useful message. - */ -static int -init(struct archive *a, const void *buff, size_t n) -{ - (void)a; /* UNUSED */ - (void)buff; /* UNUSED */ - (void)n; /* UNUSED */ - - archive_set_error(a, -1, - "This version of libarchive was compiled without gzip support"); - return (ARCHIVE_FATAL); -} - - -#else - -/* - * Setup the callbacks. - */ -static int -init(struct archive *a, const void *buff, size_t n) -{ - struct private_data *state; - int ret; - - a->compression_code = ARCHIVE_COMPRESSION_GZIP; - a->compression_name = "gzip"; - - state = malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for %s decompression", - a->compression_name); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->crc = crc32(0L, NULL, 0); - state->header_done = 0; /* We've not yet begun to parse header... */ - - state->uncompressed_buffer_size = 64 * 1024; - state->uncompressed_buffer = malloc(state->uncompressed_buffer_size); - state->stream.next_out = state->uncompressed_buffer; - state->read_next = state->uncompressed_buffer; - state->stream.avail_out = state->uncompressed_buffer_size; - - if (state->uncompressed_buffer == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate %s decompression buffers", - a->compression_name); - free(state); - return (ARCHIVE_FATAL); - } - - /* - * A bug in zlib.h: stream.next_in should be marked 'const' - * but isn't (the library never alters data through the - * next_in pointer, only reads it). The result: this ugly - * cast to remove 'const'. - */ - state->stream.next_in = (void *)(uintptr_t)(const void *)buff; - state->stream.avail_in = n; - - a->compression_read_ahead = read_ahead; - a->compression_read_consume = read_consume; - a->compression_skip = NULL; /* not supported */ - a->compression_finish = finish; - - /* - * TODO: Do I need to parse the gzip header before calling - * inflateInit2()? In particular, one of the header bytes - * marks "best compression" or "fastest", which may be - * appropriate for setting the second parameter here. - * However, I think the only penalty for not setting it - * correctly is wasted memory. If this is necessary, it - * should probably go into drive_decompressor() below. - */ - - /* Initialize compression library. */ - ret = inflateInit2(&(state->stream), - -15 /* Don't check for zlib header */); - if (ret == Z_OK) { - a->compression_data = state; - return (ARCHIVE_OK); - } - - /* Library setup failed: Clean up. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing %s library", a->compression_name); - free(state->uncompressed_buffer); - free(state); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case Z_STREAM_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid setup parameter"); - break; - case Z_MEM_ERROR: - archive_set_error(a, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - case Z_VERSION_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid library version"); - break; - } - - return (ARCHIVE_FATAL); -} - -/* - * Return a block of data from the decompression buffer. Decompress more - * as necessary. - */ -static ssize_t -read_ahead(struct archive *a, const void **p, size_t min) -{ - struct private_data *state; - int read_avail, was_avail, ret; - - state = a->compression_data; - was_avail = -1; - if (!a->client_reader) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No read callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - read_avail = state->stream.next_out - state->read_next; - - if (read_avail + state->stream.avail_out < min) { - memmove(state->uncompressed_buffer, state->read_next, - read_avail); - state->read_next = state->uncompressed_buffer; - state->stream.next_out = state->read_next + read_avail; - state->stream.avail_out - = state->uncompressed_buffer_size - read_avail; - } - - while (was_avail < read_avail && /* Made some progress. */ - read_avail < (int)min && /* Haven't satisfied min. */ - read_avail < (int)state->uncompressed_buffer_size) { /* !full */ - if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK) - return (ret); - was_avail = read_avail; - read_avail = state->stream.next_out - state->read_next; - } - - *p = state->read_next; - return (read_avail); -} - -/* - * Mark a previously-returned block of data as read. - */ -static ssize_t -read_consume(struct archive *a, size_t n) -{ - struct private_data *state; - - state = a->compression_data; - a->file_position += n; - state->read_next += n; - if (state->read_next > state->stream.next_out) - __archive_errx(1, "Request to consume too many " - "bytes from gzip decompressor"); - return (n); -} - -/* - * Clean up the decompressor. - */ -static int -finish(struct archive *a) -{ - struct private_data *state; - int ret; - - state = a->compression_data; - ret = ARCHIVE_OK; - switch (inflateEnd(&(state->stream))) { - case Z_OK: - break; - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", a->compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->uncompressed_buffer); - free(state); - - a->compression_data = NULL; - if (a->client_closer != NULL) - (a->client_closer)(a, a->client_data); - - return (ret); -} - -/* - * Utility function to pull data through decompressor, reading input - * blocks as necessary. - */ -static int -drive_decompressor(struct archive *a, struct private_data *state) -{ - ssize_t ret; - int decompressed, total_decompressed; - int count, flags, header_state; - unsigned char *output; - unsigned char b; - - flags = 0; - count = 0; - header_state = 0; - total_decompressed = 0; - for (;;) { - if (state->stream.avail_in == 0) { - ret = (a->client_reader)(a, a->client_data, - (const void **)&state->stream.next_in); - if (ret < 0) { - /* - * TODO: Find a better way to handle - * this read failure. - */ - goto fatal; - } - if (ret == 0 && total_decompressed == 0) { - archive_set_error(a, EIO, - "Premature end of %s compressed data", - a->compression_name); - return (ARCHIVE_FATAL); - } - a->raw_position += ret; - state->stream.avail_in = ret; - } - - if (!state->header_done) { - /* - * If still parsing the header, interpret the - * next byte. - */ - b = *(state->stream.next_in++); - state->stream.avail_in--; - - /* - * Yes, this is somewhat crude, but it works, - * GZip format isn't likely to change anytime - * in the near future, and header parsing is - * certainly not a performance issue, so - * there's little point in making this more - * elegant. Of course, if you see an easy way - * to make this more elegant, please let me - * know.. ;-) - */ - switch (header_state) { - case 0: /* First byte of signature. */ - if (b != 037) - goto fatal; - header_state = 1; - break; - case 1: /* Second byte of signature. */ - if (b != 0213) - goto fatal; - header_state = 2; - break; - case 2: /* Compression type must be 8. */ - if (b != 8) - goto fatal; - header_state = 3; - break; - case 3: /* GZip flags. */ - flags = b; - header_state = 4; - break; - case 4: case 5: case 6: case 7: /* Mod time. */ - header_state++; - break; - case 8: /* Deflate flags. */ - header_state = 9; - break; - case 9: /* OS. */ - header_state = 10; - break; - case 10: /* Optional Extra: First byte of Length. */ - if ((flags & 4)) { - count = 255 & (int)b; - header_state = 11; - break; - } - /* - * Fall through if there is no - * Optional Extra field. - */ - case 11: /* Optional Extra: Second byte of Length. */ - if ((flags & 4)) { - count = (0xff00 & ((int)b << 8)) | count; - header_state = 12; - break; - } - /* - * Fall through if there is no - * Optional Extra field. - */ - case 12: /* Optional Extra Field: counted length. */ - if ((flags & 4)) { - --count; - if (count == 0) header_state = 13; - else header_state = 12; - break; - } - /* - * Fall through if there is no - * Optional Extra field. - */ - case 13: /* Optional Original Filename. */ - if ((flags & 8)) { - if (b == 0) header_state = 14; - else header_state = 13; - break; - } - /* - * Fall through if no Optional - * Original Filename. - */ - case 14: /* Optional Comment. */ - if ((flags & 16)) { - if (b == 0) header_state = 15; - else header_state = 14; - break; - } - /* Fall through if no Optional Comment. */ - case 15: /* Optional Header CRC: First byte. */ - if ((flags & 2)) { - header_state = 16; - break; - } - /* Fall through if no Optional Header CRC. */ - case 16: /* Optional Header CRC: Second byte. */ - if ((flags & 2)) { - header_state = 17; - break; - } - /* Fall through if no Optional Header CRC. */ - case 17: /* First byte of compressed data. */ - state->header_done = 1; /* done with header */ - state->stream.avail_in++; - state->stream.next_in--; - } - - /* - * TODO: Consider moving the inflateInit2 call - * here so it can include the compression type - * from the header? - */ - } else { - output = state->stream.next_out; - - /* Decompress some data. */ - ret = inflate(&(state->stream), 0); - decompressed = state->stream.next_out - output; - - /* Accumulate the CRC of the uncompressed data. */ - state->crc = crc32(state->crc, output, decompressed); - - /* Accumulate the total bytes of output. */ - state->total_out += decompressed; - total_decompressed += decompressed; - - switch (ret) { - case Z_OK: /* Decompressor made some progress. */ - if (decompressed > 0) - return (ARCHIVE_OK); - break; - case Z_STREAM_END: /* Found end of stream. */ - /* - * TODO: Verify gzip trailer - * (uncompressed length and CRC). - */ - return (ARCHIVE_OK); - default: - /* Any other return value is an error. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "gzip decompression failed (%s)", - state->stream.msg); - goto fatal; - } - } - } - return (ARCHIVE_OK); - - /* Return a fatal error. */ -fatal: - archive_set_error(a, ARCHIVE_ERRNO_MISC, "%s decompression failed", - a->compression_name); - return (ARCHIVE_FATAL); -} - -#endif /* HAVE_ZLIB_H */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_none.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_none.c deleted file mode 100644 index 9af7853d8f..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_compression_none.c +++ /dev/null @@ -1,339 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_none.c,v 1.8 2006/08/29 04:59:25 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -struct archive_decompress_none { - char *buffer; - size_t buffer_size; - char *next; /* Current read location. */ - size_t avail; /* Bytes in my buffer. */ - const char *client_buff; /* Client buffer information. */ - size_t client_total; - const char *client_next; - size_t client_avail; - char end_of_file; - char fatal; -}; - -/* - * Size of internal buffer used for combining short reads. This is - * also an upper limit on the size of a read request. Recall, - * however, that we can (and will!) return blocks of data larger than - * this. The read semantics are: you ask for a minimum, I give you a - * pointer to my best-effort match and tell you how much data is - * there. It could be less than you asked for, it could be much more. - * For example, a client might use mmap() to "read" the entire file as - * a single block. In that case, I will return that entire block to - * my clients. - */ -#define BUFFER_SIZE 65536 - -#define minimum(a, b) (a < b ? a : b) - -static int archive_decompressor_none_bid(const void *, size_t); -static int archive_decompressor_none_finish(struct archive *); -static int archive_decompressor_none_init(struct archive *, - const void *, size_t); -static ssize_t archive_decompressor_none_read_ahead(struct archive *, - const void **, size_t); -static ssize_t archive_decompressor_none_read_consume(struct archive *, - size_t); -static ssize_t archive_decompressor_none_skip(struct archive *, size_t); - -int -archive_read_support_compression_none(struct archive *a) -{ - return (__archive_read_register_compression(a, - archive_decompressor_none_bid, - archive_decompressor_none_init)); -} - -/* - * Try to detect an "uncompressed" archive. - */ -static int -archive_decompressor_none_bid(const void *buff, size_t len) -{ - (void)buff; - (void)len; - - return (1); /* Default: We'll take it if noone else does. */ -} - -static int -archive_decompressor_none_init(struct archive *a, const void *buff, size_t n) -{ - struct archive_decompress_none *state; - - a->compression_code = ARCHIVE_COMPRESSION_NONE; - a->compression_name = "none"; - - state = (struct archive_decompress_none *)malloc(sizeof(*state)); - if (!state) { - archive_set_error(a, ENOMEM, "Can't allocate input data"); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->buffer_size = BUFFER_SIZE; - state->buffer = malloc(state->buffer_size); - state->next = state->buffer; - if (state->buffer == NULL) { - free(state); - archive_set_error(a, ENOMEM, "Can't allocate input buffer"); - return (ARCHIVE_FATAL); - } - - /* Save reference to first block of data. */ - state->client_buff = buff; - state->client_total = n; - state->client_next = state->client_buff; - state->client_avail = state->client_total; - - a->compression_data = state; - a->compression_read_ahead = archive_decompressor_none_read_ahead; - a->compression_read_consume = archive_decompressor_none_read_consume; - a->compression_skip = archive_decompressor_none_skip; - a->compression_finish = archive_decompressor_none_finish; - - return (ARCHIVE_OK); -} - -/* - * We just pass through pointers to the client buffer if we can. - * If the client buffer is short, then we copy stuff to our internal - * buffer to combine reads. - */ -static ssize_t -archive_decompressor_none_read_ahead(struct archive *a, const void **buff, - size_t min) -{ - struct archive_decompress_none *state; - ssize_t bytes_read; - - state = a->compression_data; - if (state->fatal) - return (-1); - - /* - * Don't make special efforts to handle requests larger than - * the copy buffer. - */ - if (min > state->buffer_size) - min = state->buffer_size; - - /* - * Try to satisfy the request directly from the client - * buffer. We can do this if all of the data in the copy - * buffer was copied from the current client buffer. This - * also covers the case where the copy buffer is empty and - * the client buffer has all the data we need. - */ - if (state->client_total >= state->client_avail + state->avail - && state->client_avail + state->avail >= min) { - state->client_avail += state->avail; - state->client_next -= state->avail; - state->avail = 0; - state->next = state->buffer; - *buff = state->client_next; - return (state->client_avail); - } - - /* - * If we can't use client buffer, we'll have to use copy buffer. - */ - - /* Move data forward in copy buffer if necessary. */ - if (state->next > state->buffer && - state->next + min > state->buffer + state->buffer_size) { - if (state->avail > 0) - memmove(state->buffer, state->next, state->avail); - state->next = state->buffer; - } - - /* Collect data in copy buffer to fulfill request. */ - while (state->avail < min) { - /* Copy data from client buffer to our copy buffer. */ - if (state->client_avail > 0) { - /* First estimate: copy to fill rest of buffer. */ - size_t tocopy = (state->buffer + state->buffer_size) - - (state->next + state->avail); - /* Don't copy more than is available. */ - if (tocopy > state->client_avail) - tocopy = state->client_avail; - memcpy(state->next + state->avail, state->client_next, - tocopy); - state->client_next += tocopy; - state->client_avail -= tocopy; - state->avail += tocopy; - } else { - /* There is no more client data: fetch more. */ - /* - * It seems to me that const void ** and const - * char ** should be compatible, but they - * aren't, hence the cast. - */ - bytes_read = (a->client_reader)(a, a->client_data, - (const void **)&state->client_buff); - if (bytes_read < 0) { /* Read error. */ - state->client_total = state->client_avail = 0; - state->client_next = state->client_buff = NULL; - state->fatal = 1; - return (-1); - } - if (bytes_read == 0) { /* End-of-file. */ - state->client_total = state->client_avail = 0; - state->client_next = state->client_buff = NULL; - state->end_of_file = 1; - break; - } - a->raw_position += bytes_read; - state->client_total = bytes_read; - state->client_avail = state->client_total; - state->client_next = state->client_buff; - } - } - - *buff = state->next; - return (state->avail); -} - -/* - * Mark the appropriate data as used. Note that the request here will - * often be much smaller than the size of the previous read_ahead - * request. - */ -static ssize_t -archive_decompressor_none_read_consume(struct archive *a, size_t request) -{ - struct archive_decompress_none *state; - - state = a->compression_data; - if (state->avail > 0) { - /* Read came from copy buffer. */ - state->next += request; - state->avail -= request; - } else { - /* Read came from client buffer. */ - state->client_next += request; - state->client_avail -= request; - } - a->file_position += request; - return (request); -} - -/* - * Skip at most request bytes. Skipped data is marked as consumed. - */ -static ssize_t -archive_decompressor_none_skip(struct archive *a, size_t request) -{ - struct archive_decompress_none *state; - ssize_t bytes_skipped, total_bytes_skipped = 0; - size_t min; - - state = a->compression_data; - if (state->fatal) - return (-1); - /* - * If there is data in the buffers already, use that first. - */ - if (state->avail > 0) { - min = minimum(request, state->avail); - bytes_skipped = archive_decompressor_none_read_consume(a, min); - request -= bytes_skipped; - total_bytes_skipped += bytes_skipped; - } - if (state->client_avail > 0) { - min = minimum(request, state->client_avail); - bytes_skipped = archive_decompressor_none_read_consume(a, min); - request -= bytes_skipped; - total_bytes_skipped += bytes_skipped; - } - if (request == 0) - return (total_bytes_skipped); - /* - * If no client_skipper is provided, just read the old way. It is very - * likely that after skipping, the request has not yet been fully - * satisfied (and is still > 0). In that case, read as well. - */ - if (a->client_skipper != NULL) { - bytes_skipped = (a->client_skipper)(a, a->client_data, - request); - if (bytes_skipped < 0) { /* error */ - state->client_total = state->client_avail = 0; - state->client_next = state->client_buff = NULL; - state->fatal = 1; - return (bytes_skipped); - } - total_bytes_skipped += bytes_skipped; - a->file_position += bytes_skipped; - request -= bytes_skipped; - state->client_next = state->client_buff; - a->raw_position += bytes_skipped; - state->client_avail = state->client_total = 0; - } - while (request > 0) { - const void* dummy_buffer; - ssize_t bytes_read; - bytes_read = archive_decompressor_none_read_ahead(a, - &dummy_buffer, request); - if (bytes_read < 0) - return (bytes_read); - assert(bytes_read >= 0); /* precondition for cast below */ - min = minimum((size_t)bytes_read, request); - bytes_read = archive_decompressor_none_read_consume(a, min); - total_bytes_skipped += bytes_read; - request -= bytes_read; - } - assert(request == 0); - return (total_bytes_skipped); -} - -static int -archive_decompressor_none_finish(struct archive *a) -{ - struct archive_decompress_none *state; - - state = a->compression_data; - free(state->buffer); - free(state); - a->compression_data = NULL; - if (a->client_closer != NULL) - return ((a->client_closer)(a, a->client_data)); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_all.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_all.c deleted file mode 100644 index 3f09482449..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_all.c +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_all.c,v 1.6 2005/01/25 06:07:28 kientzle Exp $"); - -#include "archive.h" - -int -archive_read_support_format_all(struct archive *a) -{ - archive_read_support_format_cpio(a); - archive_read_support_format_iso9660(a); - archive_read_support_format_tar(a); - archive_read_support_format_zip(a); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_cpio.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_cpio.c deleted file mode 100644 index 87e2d0ee99..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_cpio.c +++ /dev/null @@ -1,613 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_cpio.c,v 1.18 2006/07/30 18:33:20 kientzle Exp $"); - -#include -#ifdef MAJOR_IN_MKDEV -#include -#endif - -#include -/* #include */ /* See archive_platform.h */ -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct cpio_bin_header { - unsigned char c_magic[2]; - unsigned char c_dev[2]; - unsigned char c_ino[2]; - unsigned char c_mode[2]; - unsigned char c_uid[2]; - unsigned char c_gid[2]; - unsigned char c_nlink[2]; - unsigned char c_rdev[2]; - unsigned char c_mtime[4]; - unsigned char c_namesize[2]; - unsigned char c_filesize[4]; -}; - -struct cpio_odc_header { - char c_magic[6]; - char c_dev[6]; - char c_ino[6]; - char c_mode[6]; - char c_uid[6]; - char c_gid[6]; - char c_nlink[6]; - char c_rdev[6]; - char c_mtime[11]; - char c_namesize[6]; - char c_filesize[11]; -}; - -struct cpio_newc_header { - char c_magic[6]; - char c_ino[8]; - char c_mode[8]; - char c_uid[8]; - char c_gid[8]; - char c_nlink[8]; - char c_mtime[8]; - char c_filesize[8]; - char c_devmajor[8]; - char c_devminor[8]; - char c_rdevmajor[8]; - char c_rdevminor[8]; - char c_namesize[8]; - char c_crc[8]; -}; - -struct links_entry { - struct links_entry *next; - struct links_entry *previous; - int links; - dev_t dev; - ino_t ino; - char *name; -}; - -#define CPIO_MAGIC 0x13141516 -struct cpio { - int magic; - int (*read_header)(struct archive *, struct cpio *, - struct stat *, size_t *, size_t *); - struct links_entry *links_head; - struct archive_string entry_name; - struct archive_string entry_linkname; - off_t entry_bytes_remaining; - off_t entry_offset; - off_t entry_padding; -}; - -static int64_t atol16(const char *, unsigned); -static int64_t atol8(const char *, unsigned); -static int archive_read_format_cpio_bid(struct archive *); -static int archive_read_format_cpio_cleanup(struct archive *); -static int archive_read_format_cpio_read_data(struct archive *, - const void **, size_t *, off_t *); -static int archive_read_format_cpio_read_header(struct archive *, - struct archive_entry *); -static int be4(const unsigned char *); -static int header_bin_be(struct archive *, struct cpio *, struct stat *, - size_t *, size_t *); -static int header_bin_le(struct archive *, struct cpio *, struct stat *, - size_t *, size_t *); -static int header_newc(struct archive *, struct cpio *, struct stat *, - size_t *, size_t *); -static int header_odc(struct archive *, struct cpio *, struct stat *, - size_t *, size_t *); -static int le4(const unsigned char *); -static void record_hardlink(struct cpio *cpio, struct archive_entry *entry, - const struct stat *st); - -int -archive_read_support_format_cpio(struct archive *a) -{ - struct cpio *cpio; - int r; - - cpio = malloc(sizeof(*cpio)); - if (cpio == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate cpio data"); - return (ARCHIVE_FATAL); - } - memset(cpio, 0, sizeof(*cpio)); - cpio->magic = CPIO_MAGIC; - - r = __archive_read_register_format(a, - cpio, - archive_read_format_cpio_bid, - archive_read_format_cpio_read_header, - archive_read_format_cpio_read_data, - NULL, - archive_read_format_cpio_cleanup); - - if (r != ARCHIVE_OK) - free(cpio); - return (ARCHIVE_OK); -} - - -static int -archive_read_format_cpio_bid(struct archive *a) -{ - int bid, bytes_read; - const void *h; - const unsigned char *p; - struct cpio *cpio; - - cpio = *(a->pformat_data); - bid = 0; - bytes_read = (a->compression_read_ahead)(a, &h, 6); - /* Convert error code into error return. */ - if (bytes_read < 0) - return ((int)bytes_read); - if (bytes_read < 6) - return (-1); - - p = h; - if (memcmp(p, "070707", 6) == 0) { - /* ASCII cpio archive (odc, POSIX.1) */ - cpio->read_header = header_odc; - bid += 48; - /* - * XXX TODO: More verification; Could check that only octal - * digits appear in appropriate header locations. XXX - */ - } else if (memcmp(p, "070701", 6) == 0) { - /* ASCII cpio archive (SVR4 without CRC) */ - cpio->read_header = header_newc; - bid += 48; - /* - * XXX TODO: More verification; Could check that only hex - * digits appear in appropriate header locations. XXX - */ - } else if (memcmp(p, "070702", 6) == 0) { - /* ASCII cpio archive (SVR4 with CRC) */ - /* XXX TODO: Flag that we should check the CRC. XXX */ - cpio->read_header = header_newc; - bid += 48; - /* - * XXX TODO: More verification; Could check that only hex - * digits appear in appropriate header locations. XXX - */ - } else if (p[0] * 256 + p[1] == 070707) { - /* big-endian binary cpio archives */ - cpio->read_header = header_bin_be; - bid += 16; - /* Is more verification possible here? */ - } else if (p[0] + p[1] * 256 == 070707) { - /* little-endian binary cpio archives */ - cpio->read_header = header_bin_le; - bid += 16; - /* Is more verification possible here? */ - } else - return (ARCHIVE_WARN); - - return (bid); -} - -static int -archive_read_format_cpio_read_header(struct archive *a, - struct archive_entry *entry) -{ - struct stat st; - struct cpio *cpio; - size_t bytes; - const void *h; - size_t namelength; - size_t name_pad; - int r; - - memset(&st, 0, sizeof(st)); - - cpio = *(a->pformat_data); - r = (cpio->read_header(a, cpio, &st, &namelength, &name_pad)); - - if (r != ARCHIVE_OK) - return (r); - - /* Assign all of the 'stat' fields at once. */ - archive_entry_copy_stat(entry, &st); - - /* Read name from buffer. */ - bytes = (a->compression_read_ahead)(a, &h, namelength + name_pad); - if (bytes < namelength + name_pad) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, namelength + name_pad); - archive_strncpy(&cpio->entry_name, h, namelength); - archive_entry_set_pathname(entry, cpio->entry_name.s); - cpio->entry_offset = 0; - - /* If this is a symlink, read the link contents. */ - if (S_ISLNK(st.st_mode)) { - bytes = (a->compression_read_ahead)(a, &h, - cpio->entry_bytes_remaining); - if ((off_t)bytes < cpio->entry_bytes_remaining) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, cpio->entry_bytes_remaining); - archive_strncpy(&cpio->entry_linkname, h, - cpio->entry_bytes_remaining); - archive_entry_set_symlink(entry, cpio->entry_linkname.s); - cpio->entry_bytes_remaining = 0; - } - - /* Compare name to "TRAILER!!!" to test for end-of-archive. */ - if (namelength == 11 && strcmp(h, "TRAILER!!!") == 0) { - /* TODO: Store file location of start of block. */ - archive_set_error(a, 0, NULL); - return (ARCHIVE_EOF); - } - - /* Detect and record hardlinks to previously-extracted entries. */ - record_hardlink(cpio, entry, &st); - - return (ARCHIVE_OK); -} - -static int -archive_read_format_cpio_read_data(struct archive *a, - const void **buff, size_t *size, off_t *offset) -{ - ssize_t bytes_read; - struct cpio *cpio; - - cpio = *(a->pformat_data); - if (cpio->entry_bytes_remaining > 0) { - bytes_read = (a->compression_read_ahead)(a, buff, 1); - if (bytes_read <= 0) - return (ARCHIVE_FATAL); - if (bytes_read > cpio->entry_bytes_remaining) - bytes_read = cpio->entry_bytes_remaining; - *size = bytes_read; - *offset = cpio->entry_offset; - cpio->entry_offset += bytes_read; - cpio->entry_bytes_remaining -= bytes_read; - (a->compression_read_consume)(a, bytes_read); - return (ARCHIVE_OK); - } else { - while (cpio->entry_padding > 0) { - bytes_read = (a->compression_read_ahead)(a, buff, 1); - if (bytes_read <= 0) - return (ARCHIVE_FATAL); - if (bytes_read > cpio->entry_padding) - bytes_read = cpio->entry_padding; - (a->compression_read_consume)(a, bytes_read); - cpio->entry_padding -= bytes_read; - } - *buff = NULL; - *size = 0; - *offset = cpio->entry_offset; - return (ARCHIVE_EOF); - } -} - -static int -header_newc(struct archive *a, struct cpio *cpio, struct stat *st, - size_t *namelength, size_t *name_pad) -{ - const void *h; - const struct cpio_newc_header *header; - size_t bytes; - - /* Read fixed-size portion of header. */ - bytes = (a->compression_read_ahead)(a, &h, sizeof(struct cpio_newc_header)); - if (bytes < sizeof(struct cpio_newc_header)) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, sizeof(struct cpio_newc_header)); - - /* Parse out hex fields into struct stat. */ - header = h; - - if (memcmp(header->c_magic, "070701", 6) == 0) { - a->archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; - a->archive_format_name = "ASCII cpio (SVR4 with no CRC)"; - } else if (memcmp(header->c_magic, "070702", 6) == 0) { - a->archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC; - a->archive_format_name = "ASCII cpio (SVR4 with CRC)"; - } else { - /* TODO: Abort here? */ - } - - st->st_dev = makedev( - atol16(header->c_devmajor, sizeof(header->c_devmajor)), - atol16(header->c_devminor, sizeof(header->c_devminor))); - st->st_ino = atol16(header->c_ino, sizeof(header->c_ino)); - st->st_mode = atol16(header->c_mode, sizeof(header->c_mode)); - st->st_uid = atol16(header->c_uid, sizeof(header->c_uid)); - st->st_gid = atol16(header->c_gid, sizeof(header->c_gid)); - st->st_nlink = atol16(header->c_nlink, sizeof(header->c_nlink)); - st->st_rdev = makedev( - atol16(header->c_rdevmajor, sizeof(header->c_rdevmajor)), - atol16(header->c_rdevminor, sizeof(header->c_rdevminor))); - st->st_mtime = atol16(header->c_mtime, sizeof(header->c_mtime)); - *namelength = atol16(header->c_namesize, sizeof(header->c_namesize)); - /* Pad name to 2 more than a multiple of 4. */ - *name_pad = (2 - *namelength) & 3; - - /* - * Note: entry_bytes_remaining is at least 64 bits and - * therefore gauranteed to be big enough for a 33-bit file - * size. struct stat.st_size may only be 32 bits, so - * assigning there first could lose information. - */ - cpio->entry_bytes_remaining = - atol16(header->c_filesize, sizeof(header->c_filesize)); - st->st_size = cpio->entry_bytes_remaining; - /* Pad file contents to a multiple of 4. */ - cpio->entry_padding = 3 & -cpio->entry_bytes_remaining; - return (ARCHIVE_OK); -} - -static int -header_odc(struct archive *a, struct cpio *cpio, struct stat *st, - size_t *namelength, size_t *name_pad) -{ - const void *h; - const struct cpio_odc_header *header; - size_t bytes; - - a->archive_format = ARCHIVE_FORMAT_CPIO_POSIX; - a->archive_format_name = "POSIX octet-oriented cpio"; - - /* Read fixed-size portion of header. */ - bytes = (a->compression_read_ahead)(a, &h, sizeof(struct cpio_odc_header)); - if (bytes < sizeof(struct cpio_odc_header)) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, sizeof(struct cpio_odc_header)); - - /* Parse out octal fields into struct stat. */ - header = h; - - st->st_dev = atol8(header->c_dev, sizeof(header->c_dev)); - st->st_ino = atol8(header->c_ino, sizeof(header->c_ino)); - st->st_mode = atol8(header->c_mode, sizeof(header->c_mode)); - st->st_uid = atol8(header->c_uid, sizeof(header->c_uid)); - st->st_gid = atol8(header->c_gid, sizeof(header->c_gid)); - st->st_nlink = atol8(header->c_nlink, sizeof(header->c_nlink)); - st->st_rdev = atol8(header->c_rdev, sizeof(header->c_rdev)); - st->st_mtime = atol8(header->c_mtime, sizeof(header->c_mtime)); - *namelength = atol8(header->c_namesize, sizeof(header->c_namesize)); - *name_pad = 0; /* No padding of filename. */ - - /* - * Note: entry_bytes_remaining is at least 64 bits and - * therefore gauranteed to be big enough for a 33-bit file - * size. struct stat.st_size may only be 32 bits, so - * assigning there first could lose information. - */ - cpio->entry_bytes_remaining = - atol8(header->c_filesize, sizeof(header->c_filesize)); - st->st_size = cpio->entry_bytes_remaining; - cpio->entry_padding = 0; - return (ARCHIVE_OK); -} - -static int -header_bin_le(struct archive *a, struct cpio *cpio, struct stat *st, - size_t *namelength, size_t *name_pad) -{ - const void *h; - const struct cpio_bin_header *header; - size_t bytes; - - a->archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE; - a->archive_format_name = "cpio (little-endian binary)"; - - /* Read fixed-size portion of header. */ - bytes = (a->compression_read_ahead)(a, &h, sizeof(struct cpio_bin_header)); - if (bytes < sizeof(struct cpio_bin_header)) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, sizeof(struct cpio_bin_header)); - - /* Parse out binary fields into struct stat. */ - header = h; - - st->st_dev = header->c_dev[0] + header->c_dev[1] * 256; - st->st_ino = header->c_ino[0] + header->c_ino[1] * 256; - st->st_mode = header->c_mode[0] + header->c_mode[1] * 256; - st->st_uid = header->c_uid[0] + header->c_uid[1] * 256; - st->st_gid = header->c_gid[0] + header->c_gid[1] * 256; - st->st_nlink = header->c_nlink[0] + header->c_nlink[1] * 256; - st->st_rdev = header->c_rdev[0] + header->c_rdev[1] * 256; - st->st_mtime = le4(header->c_mtime); - *namelength = header->c_namesize[0] + header->c_namesize[1] * 256; - *name_pad = *namelength & 1; /* Pad to even. */ - - cpio->entry_bytes_remaining = le4(header->c_filesize); - st->st_size = cpio->entry_bytes_remaining; - cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ - return (ARCHIVE_OK); -} - -static int -header_bin_be(struct archive *a, struct cpio *cpio, struct stat *st, - size_t *namelength, size_t *name_pad) -{ - const void *h; - const struct cpio_bin_header *header; - size_t bytes; - - a->archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE; - a->archive_format_name = "cpio (big-endian binary)"; - - /* Read fixed-size portion of header. */ - bytes = (a->compression_read_ahead)(a, &h, - sizeof(struct cpio_bin_header)); - if (bytes < sizeof(struct cpio_bin_header)) - return (ARCHIVE_FATAL); - (a->compression_read_consume)(a, sizeof(struct cpio_bin_header)); - - /* Parse out binary fields into struct stat. */ - header = h; - st->st_dev = header->c_dev[0] * 256 + header->c_dev[1]; - st->st_ino = header->c_ino[0] * 256 + header->c_ino[1]; - st->st_mode = header->c_mode[0] * 256 + header->c_mode[1]; - st->st_uid = header->c_uid[0] * 256 + header->c_uid[1]; - st->st_gid = header->c_gid[0] * 256 + header->c_gid[1]; - st->st_nlink = header->c_nlink[0] * 256 + header->c_nlink[1]; - st->st_rdev = header->c_rdev[0] * 256 + header->c_rdev[1]; - st->st_mtime = be4(header->c_mtime); - *namelength = header->c_namesize[0] * 256 + header->c_namesize[1]; - *name_pad = *namelength & 1; /* Pad to even. */ - - cpio->entry_bytes_remaining = be4(header->c_filesize); - st->st_size = cpio->entry_bytes_remaining; - cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ - return (ARCHIVE_OK); -} - -static int -archive_read_format_cpio_cleanup(struct archive *a) -{ - struct cpio *cpio; - - cpio = *(a->pformat_data); - /* Free inode->name map */ - while (cpio->links_head != NULL) { - struct links_entry *lp = cpio->links_head->next; - - if (cpio->links_head->name) - free(cpio->links_head->name); - free(cpio->links_head); - cpio->links_head = lp; - } - - free(cpio); - *(a->pformat_data) = NULL; - return (ARCHIVE_OK); -} - -static int -le4(const unsigned char *p) -{ - return ((p[0]<<16) + (p[1]<<24) + (p[2]<<0) + (p[3]<<8)); -} - - -static int -be4(const unsigned char *p) -{ - return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24)); -} - -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ -static int64_t -atol8(const char *p, unsigned char_cnt) -{ - int64_t l; - int digit; - - l = 0; - while (char_cnt-- > 0) { - if (*p >= '0' && *p <= '7') - digit = *p - '0'; - else - return (l); - p++; - l <<= 3; - l |= digit; - } - return (l); -} - -static int64_t -atol16(const char *p, unsigned char_cnt) -{ - int64_t l; - int digit; - - l = 0; - while (char_cnt-- > 0) { - if (*p >= 'a' && *p <= 'f') - digit = *p - 'a' + 10; - else if (*p >= 'A' && *p <= 'F') - digit = *p - 'A' + 10; - else if (*p >= '0' && *p <= '9') - digit = *p - '0'; - else - return (l); - p++; - l <<= 4; - l |= digit; - } - return (l); -} - -static void -record_hardlink(struct cpio *cpio, struct archive_entry *entry, - const struct stat *st) -{ - struct links_entry *le; - - /* - * First look in the list of multiply-linked files. If we've - * already dumped it, convert this entry to a hard link entry. - */ - for (le = cpio->links_head; le; le = le->next) { - if (le->dev == st->st_dev && le->ino == st->st_ino) { - archive_entry_set_hardlink(entry, le->name); - - if (--le->links <= 0) { - if (le->previous != NULL) - le->previous->next = le->next; - if (le->next != NULL) - le->next->previous = le->previous; - if (cpio->links_head == le) - cpio->links_head = le->next; - free(le); - } - - return; - } - } - - le = malloc(sizeof(struct links_entry)); - if (le == NULL) - __archive_errx(1, "Out of memory adding file to list"); - if (cpio->links_head != NULL) - cpio->links_head->previous = le; - le->next = cpio->links_head; - le->previous = NULL; - cpio->links_head = le; - le->dev = st->st_dev; - le->ino = st->st_ino; - le->links = st->st_nlink - 1; - le->name = strdup(archive_entry_pathname(entry)); - if (le->name == NULL) - __archive_errx(1, "Out of memory adding file to list"); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_iso9660.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_iso9660.c deleted file mode 100644 index 3eb1ef001b..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_iso9660.c +++ /dev/null @@ -1,1061 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1.13 2006/03/21 16:55:46 kientzle Exp $"); - -#include - -#include -/* #include */ /* See archive_platform.h */ -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" -#include "archive_string.h" - -/* - * An overview of ISO 9660 format: - * - * Each disk is laid out as follows: - * * 32k reserved for private use - * * Volume descriptor table. Each volume descriptor - * is 2k and specifies basic format information. - * The "Primary Volume Descriptor" (PVD) is defined by the - * standard and should always be present; other volume - * descriptors include various vendor-specific extensions. - * * Files and directories. Each file/dir is specified by - * an "extent" (starting sector and length in bytes). - * Dirs are just files with directory records packed one - * after another. The PVD contains a single dir entry - * specifying the location of the root directory. Everything - * else follows from there. - * - * This module works by first reading the volume descriptors, then - * building a list of directory entries, sorted by starting - * sector. At each step, I look for the earliest dir entry that - * hasn't yet been read, seek forward to that location and read - * that entry. If it's a dir, I slurp in the new dir entries and - * add them to the heap; if it's a regular file, I return the - * corresponding archive_entry and wait for the client to request - * the file body. This strategy allows us to read most compliant - * CDs with a single pass through the data, as required by libarchive. - */ - -/* Structure of on-disk PVD. */ -struct iso9660_primary_volume_descriptor { - unsigned char type[1]; - char id[5]; - unsigned char version[1]; - char reserved1[1]; - char system_id[32]; - char volume_id[32]; - char reserved2[8]; - char volume_space_size[8]; - char reserved3[32]; - char volume_set_size[4]; - char volume_sequence_number[4]; - char logical_block_size[4]; - char path_table_size[8]; - char type_1_path_table[4]; - char opt_type_1_path_table[4]; - char type_m_path_table[4]; - char opt_type_m_path_table[4]; - char root_directory_record[34]; - char volume_set_id[128]; - char publisher_id[128]; - char preparer_id[128]; - char application_id[128]; - char copyright_file_id[37]; - char abstract_file_id[37]; - char bibliographic_file_id[37]; - char creation_date[17]; - char modification_date[17]; - char expiration_date[17]; - char effective_date[17]; - char file_structure_version[1]; - char reserved4[1]; - char application_data[512]; -}; - -/* Structure of an on-disk directory record. */ -struct iso9660_directory_record { - unsigned char length[1]; - unsigned char ext_attr_length[1]; - unsigned char extent[8]; - unsigned char size[8]; - char date[7]; - unsigned char flags[1]; - unsigned char file_unit_size[1]; - unsigned char interleave[1]; - unsigned char volume_sequence_number[4]; - unsigned char name_len[1]; - char name[1]; -}; - -/* - * Our private data. - */ - -/* In-memory storage for a directory record. */ -struct file_info { - struct file_info *parent; - int refcount; - uint64_t offset; /* Offset on disk. */ - uint64_t size; /* File size in bytes. */ - uint64_t ce_offset; /* Offset of CE */ - uint64_t ce_size; /* Size of CE */ - time_t mtime; /* File last modified time. */ - time_t atime; /* File last accessed time. */ - time_t ctime; /* File creation time. */ - mode_t mode; - uid_t uid; - gid_t gid; - ino_t inode; - int nlinks; - char *name; /* Null-terminated filename. */ - struct archive_string symlink; -}; - - -struct iso9660 { - int magic; -#define ISO9660_MAGIC 0x96609660 - int bid; /* If non-zero, return this as our bid. */ - struct archive_string pathname; - char seenRockridge; /* Set true if RR extensions are used. */ - unsigned char suspOffset; - - uint64_t previous_offset; - uint64_t previous_size; - struct archive_string previous_pathname; - - /* TODO: Make this a heap for fast inserts and deletions. */ - struct file_info **pending_files; - int pending_files_allocated; - int pending_files_used; - - uint64_t current_position; - ssize_t logical_block_size; - - off_t entry_sparse_offset; - ssize_t entry_bytes_remaining; -}; - -static void add_entry(struct iso9660 *iso9660, struct file_info *file); -static int archive_read_format_iso9660_bid(struct archive *); -static int archive_read_format_iso9660_cleanup(struct archive *); -static int archive_read_format_iso9660_read_data(struct archive *, - const void **, size_t *, off_t *); -static int archive_read_format_iso9660_read_header(struct archive *, - struct archive_entry *); -static const char *build_pathname(struct archive_string *, struct file_info *); -static void dump_isodirrec(FILE *, const struct iso9660_directory_record *); -static time_t time_from_tm(struct tm *); -static time_t isodate17(const void *); -static time_t isodate7(const void *); -static int isPVD(struct iso9660 *, const char *); -static struct file_info *next_entry(struct iso9660 *); -static int next_entry_seek(struct archive *a, struct iso9660 *iso9660, - struct file_info **pfile); -static struct file_info * - parse_file_info(struct iso9660 *iso9660, - struct file_info *parent, - const struct iso9660_directory_record *isodirrec); -static void parse_rockridge(struct iso9660 *iso9660, - struct file_info *file, const unsigned char *start, - const unsigned char *end); -static void release_file(struct iso9660 *, struct file_info *); -static int toi(const void *p, int n); - -int -archive_read_support_format_iso9660(struct archive *a) -{ - struct iso9660 *iso9660; - int r; - - iso9660 = malloc(sizeof(*iso9660)); - if (iso9660 == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate iso9660 data"); - return (ARCHIVE_FATAL); - } - memset(iso9660, 0, sizeof(*iso9660)); - iso9660->magic = ISO9660_MAGIC; - iso9660->bid = -1; /* We haven't yet bid. */ - - r = __archive_read_register_format(a, - iso9660, - archive_read_format_iso9660_bid, - archive_read_format_iso9660_read_header, - archive_read_format_iso9660_read_data, - NULL, - archive_read_format_iso9660_cleanup); - - if (r != ARCHIVE_OK) { - free(iso9660); - return (r); - } - return (ARCHIVE_OK); -} - - -static int -archive_read_format_iso9660_bid(struct archive *a) -{ - struct iso9660 *iso9660; - ssize_t bytes_read; - const void *h; - const char *p; - - iso9660 = *(a->pformat_data); - - if (iso9660->bid >= 0) - return (iso9660->bid); - - /* - * Skip the first 32k (reserved area) and get the first - * 8 sectors of the volume descriptor table. Of course, - * if the I/O layer gives us more, we'll take it. - */ - bytes_read = (a->compression_read_ahead)(a, &h, 32768 + 8*2048); - if (bytes_read < 32768 + 8*2048) - return (iso9660->bid = -1); - p = (const char *)h; - - /* Skip the reserved area. */ - bytes_read -= 32768; - p += 32768; - - /* Check each volume descriptor to locate the PVD. */ - for (; bytes_read > 2048; bytes_read -= 2048, p += 2048) { - iso9660->bid = isPVD(iso9660, p); - if (iso9660->bid > 0) - return (iso9660->bid); - if (*p == '\xff') /* End-of-volume-descriptor marker. */ - break; - } - - /* We didn't find a valid PVD; return a bid of zero. */ - iso9660->bid = 0; - return (iso9660->bid); -} - -static int -isPVD(struct iso9660 *iso9660, const char *h) -{ - const struct iso9660_primary_volume_descriptor *voldesc; - struct file_info *file; - - if (h[0] != 1) - return (0); - if (memcmp(h+1, "CD001", 5) != 0) - return (0); - - - voldesc = (const struct iso9660_primary_volume_descriptor *)h; - iso9660->logical_block_size = toi(&voldesc->logical_block_size, 2); - - /* Store the root directory in the pending list. */ - file = parse_file_info(iso9660, NULL, - (struct iso9660_directory_record *)&voldesc->root_directory_record); - add_entry(iso9660, file); - return (48); -} - -static int -archive_read_format_iso9660_read_header(struct archive *a, - struct archive_entry *entry) -{ - struct stat st; - struct iso9660 *iso9660; - struct file_info *file; - ssize_t bytes_read; - int r; - - iso9660 = *(a->pformat_data); - - if (!a->archive_format) { - a->archive_format = ARCHIVE_FORMAT_ISO9660; - a->archive_format_name = "ISO9660"; - } - - /* Get the next entry that appears after the current offset. */ - r = next_entry_seek(a, iso9660, &file); - if (r != ARCHIVE_OK) - return (r); - - iso9660->entry_bytes_remaining = file->size; - iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */ - - /* Set up the entry structure with information about this entry. */ - memset(&st, 0, sizeof(st)); - st.st_mode = file->mode; - st.st_uid = file->uid; - st.st_gid = file->gid; - st.st_nlink = file->nlinks; - st.st_ino = file->inode; - st.st_mtime = file->mtime; - st.st_ctime = file->ctime; - st.st_atime = file->atime; - st.st_size = iso9660->entry_bytes_remaining; - archive_entry_copy_stat(entry, &st); - archive_string_empty(&iso9660->pathname); - archive_entry_set_pathname(entry, - build_pathname(&iso9660->pathname, file)); - if (file->symlink.s != NULL) - archive_entry_set_symlink(entry, file->symlink.s); - - /* If this entry points to the same data as the previous - * entry, convert this into a hardlink to that entry. - * But don't bother for zero-length files. */ - if (file->offset == iso9660->previous_offset - && file->size == iso9660->previous_size - && file->size > 0) { - archive_entry_set_hardlink(entry, - iso9660->previous_pathname.s); - iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; - release_file(iso9660, file); - return (ARCHIVE_OK); - } - - /* If the offset is before our current position, we can't - * seek backwards to extract it, so issue a warning. */ - if (file->offset < iso9660->current_position) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Ignoring out-of-order file"); - iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; - release_file(iso9660, file); - return (ARCHIVE_WARN); - } - - iso9660->previous_size = file->size; - iso9660->previous_offset = file->offset; - archive_strcpy(&iso9660->previous_pathname, iso9660->pathname.s); - - /* If this is a directory, read in all of the entries right now. */ - if (S_ISDIR(st.st_mode)) { - while (iso9660->entry_bytes_remaining > 0) { - const void *block; - const unsigned char *p; - ssize_t step = iso9660->logical_block_size; - if (step > iso9660->entry_bytes_remaining) - step = iso9660->entry_bytes_remaining; - bytes_read = (a->compression_read_ahead)(a, &block, step); - if (bytes_read < step) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Failed to read full block when scanning ISO9660 directory list"); - release_file(iso9660, file); - return (ARCHIVE_FATAL); - } - if (bytes_read > step) - bytes_read = step; - (a->compression_read_consume)(a, bytes_read); - iso9660->current_position += bytes_read; - iso9660->entry_bytes_remaining -= bytes_read; - for (p = block; - *p != 0 && p < (const unsigned char *)block + bytes_read; - p += *p) { - const struct iso9660_directory_record *dr - = (const struct iso9660_directory_record *)p; - struct file_info *child; - - /* Skip '.' entry. */ - if (dr->name_len[0] == 1 - && dr->name[0] == '\0') - continue; - /* Skip '..' entry. */ - if (dr->name_len[0] == 1 - && dr->name[0] == '\001') - continue; - child = parse_file_info(iso9660, file, dr); - add_entry(iso9660, child); - if (iso9660->seenRockridge) { - a->archive_format = - ARCHIVE_FORMAT_ISO9660_ROCKRIDGE; - a->archive_format_name = - "ISO9660 with Rockridge extensions"; - } - } - } - } - - release_file(iso9660, file); - return (ARCHIVE_OK); -} - -static int -archive_read_format_iso9660_read_data(struct archive *a, - const void **buff, size_t *size, off_t *offset) -{ - ssize_t bytes_read; - struct iso9660 *iso9660; - - iso9660 = *(a->pformat_data); - if (iso9660->entry_bytes_remaining <= 0) { - *buff = NULL; - *size = 0; - *offset = iso9660->entry_sparse_offset; - return (ARCHIVE_EOF); - } - - bytes_read = (a->compression_read_ahead)(a, buff, 1); - if (bytes_read == 0) - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Truncated input file"); - if (bytes_read <= 0) - return (ARCHIVE_FATAL); - if (bytes_read > iso9660->entry_bytes_remaining) - bytes_read = iso9660->entry_bytes_remaining; - *size = bytes_read; - *offset = iso9660->entry_sparse_offset; - iso9660->entry_sparse_offset += bytes_read; - iso9660->entry_bytes_remaining -= bytes_read; - iso9660->current_position += bytes_read; - (a->compression_read_consume)(a, bytes_read); - return (ARCHIVE_OK); -} - -static int -archive_read_format_iso9660_cleanup(struct archive *a) -{ - struct iso9660 *iso9660; - struct file_info *file; - - iso9660 = *(a->pformat_data); - while ((file = next_entry(iso9660)) != NULL) - release_file(iso9660, file); - archive_string_free(&iso9660->pathname); - archive_string_free(&iso9660->previous_pathname); - free(iso9660); - *(a->pformat_data) = NULL; - return (ARCHIVE_OK); -} - -/* - * This routine parses a single ISO directory record, makes sense - * of any extensions, and stores the result in memory. - */ -static struct file_info * -parse_file_info(struct iso9660 *iso9660, struct file_info *parent, - const struct iso9660_directory_record *isodirrec) -{ - struct file_info *file; - - /* TODO: Sanity check that name_len doesn't exceed length, etc. */ - - /* Create a new file entry and copy data from the ISO dir record. */ - file = malloc(sizeof(*file)); - if (file == NULL) - return (NULL); - memset(file, 0, sizeof(*file)); - file->parent = parent; - if (parent != NULL) - parent->refcount++; - file->offset = toi(isodirrec->extent, 4) - * iso9660->logical_block_size; - file->size = toi(isodirrec->size, 4); - file->mtime = isodate7(isodirrec->date); - file->ctime = file->atime = file->mtime; - file->name = malloc(isodirrec->name_len[0] + 1); - if (file->name == NULL) { - free(file); - return (NULL); - } - memcpy(file->name, isodirrec->name, isodirrec->name_len[0]); - file->name[(int)isodirrec->name_len[0]] = '\0'; - if (isodirrec->flags[0] & 0x02) - file->mode = S_IFDIR | 0700; - else - file->mode = S_IFREG | 0400; - - /* Rockridge extensions overwrite information from above. */ - { - const unsigned char *rr_start, *rr_end; - rr_end = (const unsigned char *)isodirrec - + isodirrec->length[0]; - rr_start = (const unsigned char *)isodirrec->name - + isodirrec->name_len[0]; - if ((isodirrec->name_len[0] & 1) == 0) - rr_start++; - rr_start += iso9660->suspOffset; - parse_rockridge(iso9660, file, rr_start, rr_end); - } - - /* DEBUGGING: Warn about attributes I don't yet fully support. */ - if ((isodirrec->flags[0] & ~0x02) != 0) { - fprintf(stderr, "\n ** Unrecognized flag: "); - dump_isodirrec(stderr, isodirrec); - fprintf(stderr, "\n"); - } else if (toi(isodirrec->volume_sequence_number, 2) != 1) { - fprintf(stderr, "\n ** Unrecognized sequence number: "); - dump_isodirrec(stderr, isodirrec); - fprintf(stderr, "\n"); - } else if (isodirrec->file_unit_size[0] != 0) { - fprintf(stderr, "\n ** Unexpected file unit size: "); - dump_isodirrec(stderr, isodirrec); - fprintf(stderr, "\n"); - } else if (isodirrec->interleave[0] != 0) { - fprintf(stderr, "\n ** Unexpected interleave: "); - dump_isodirrec(stderr, isodirrec); - fprintf(stderr, "\n"); - } else if (isodirrec->ext_attr_length[0] != 0) { - fprintf(stderr, "\n ** Unexpected extended attribute length: "); - dump_isodirrec(stderr, isodirrec); - fprintf(stderr, "\n"); - } - - return (file); -} - -static void -add_entry(struct iso9660 *iso9660, struct file_info *file) -{ - /* Expand our pending files list as necessary. */ - if (iso9660->pending_files_used >= iso9660->pending_files_allocated) { - struct file_info **new_pending_files; - int new_size = iso9660->pending_files_allocated * 2; - - if (new_size < 1024) - new_size = 1024; - new_pending_files = malloc(new_size * sizeof(new_pending_files[0])); - if (new_pending_files == NULL) - __archive_errx(1, "Out of memory"); - memcpy(new_pending_files, iso9660->pending_files, - iso9660->pending_files_allocated * sizeof(new_pending_files[0])); - if (iso9660->pending_files != NULL) - free(iso9660->pending_files); - iso9660->pending_files = new_pending_files; - iso9660->pending_files_allocated = new_size; - } - - iso9660->pending_files[iso9660->pending_files_used++] = file; -} - -static void -parse_rockridge(struct iso9660 *iso9660, struct file_info *file, - const unsigned char *p, const unsigned char *end) -{ - (void)iso9660; /* UNUSED */ - - while (p + 4 < end /* Enough space for another entry. */ - && p[0] >= 'A' && p[0] <= 'Z' /* Sanity-check 1st char of name. */ - && p[1] >= 'A' && p[1] <= 'Z' /* Sanity-check 2nd char of name. */ - && p + p[2] <= end) { /* Sanity-check length. */ - const unsigned char *data = p + 4; - int data_length = p[2] - 4; - int version = p[3]; - - /* - * Yes, each 'if' here does test p[0] again. - * Otherwise, the fall-through handling to catch - * unsupported extensions doesn't work. - */ - switch(p[0]) { - case 'C': - if (p[0] == 'C' && p[1] == 'E' && version == 1) { - /* - * CE extension comprises: - * 8 byte sector containing extension - * 8 byte offset w/in above sector - * 8 byte length of continuation - */ - file->ce_offset = toi(data, 4) - * iso9660->logical_block_size - + toi(data + 8, 4); - file->ce_size = toi(data + 16, 4); - break; - } - /* FALLTHROUGH */ - case 'N': - if (p[0] == 'N' && p[1] == 'M' && version == 1 - && *data == 0) { - /* NM extension with flag byte == 0 */ - /* - * NM extension comprises: - * one byte flag - * rest is long name - */ - /* TODO: Obey flags. */ - char *old_name = file->name; - - data++; /* Skip flag byte. */ - data_length--; - file->name = malloc(data_length + 1); - if (file->name != NULL) { - free(old_name); - memcpy(file->name, data, data_length); - file->name[data_length] = '\0'; - } else - file->name = old_name; - break; - } - /* FALLTHROUGH */ - case 'P': - if (p[0] == 'P' && p[1] == 'D' && version == 1) { - /* - * PD extension is padding; - * contents are always ignored. - */ - break; - } - if (p[0] == 'P' && p[1] == 'X' && version == 1) { - /* - * PX extension comprises: - * 8 bytes for mode, - * 8 bytes for nlinks, - * 8 bytes for uid, - * 8 bytes for gid, - * 8 bytes for inode. - */ - if (data_length == 32) { - file->mode = toi(data, 4); - file->nlinks = toi(data + 8, 4); - file->uid = toi(data + 16, 4); - file->gid = toi(data + 24, 4); - file->inode = toi(data + 32, 4); - } - break; - } - /* FALLTHROUGH */ - case 'R': - if (p[0] == 'R' && p[1] == 'R' && version == 1) { - iso9660->seenRockridge = 1; - /* - * RR extension comprises: - * one byte flag value - */ - /* TODO: Handle RR extension. */ - break; - } - /* FALLTHROUGH */ - case 'S': - if (p[0] == 'S' && p[1] == 'L' && version == 1 - && *data == 0) { - int cont = 1; - /* SL extension with flags == 0 */ - /* TODO: handle non-zero flag values. */ - data++; /* Skip flag byte. */ - data_length--; - while (data_length > 0) { - unsigned char flag = *data++; - unsigned char nlen = *data++; - data_length -= 2; - - if (cont == 0) - archive_strcat(&file->symlink, "/"); - cont = 0; - - switch(flag) { - case 0x01: /* Continue */ - archive_strncat(&file->symlink, - (const char *)data, nlen); - cont = 1; - break; - case 0x02: /* Current */ - archive_strcat(&file->symlink, "."); - break; - case 0x04: /* Parent */ - archive_strcat(&file->symlink, ".."); - break; - case 0x08: /* Root */ - case 0x10: /* Volume root */ - archive_string_empty(&file->symlink); - break; - case 0x20: /* Hostname */ - archive_strcat(&file->symlink, "hostname"); - break; - case 0: - archive_strncat(&file->symlink, - (const char *)data, nlen); - break; - default: - /* TODO: issue a warning ? */ - break; - } - data += nlen; - data_length -= nlen; - } - break; - } - if (p[0] == 'S' && p[1] == 'P' - && version == 1 && data_length == 7 - && data[0] == (unsigned char)'\xbe' - && data[1] == (unsigned char)'\xef') { - /* - * SP extension stores the suspOffset - * (Number of bytes to skip between - * filename and SUSP records.) - * It is mandatory by the SUSP standard - * (IEEE 1281). - * - * It allows SUSP to coexist with - * non-SUSP uses of the System - * Use Area by placing non-SUSP data - * before SUSP data. - * - * TODO: Add a check for 'SP' in - * first directory entry, disable all SUSP - * processing if not found. - */ - iso9660->suspOffset = data[2]; - break; - } - if (p[0] == 'S' && p[1] == 'T' - && data_length == 0 && version == 1) { - /* - * ST extension marks end of this - * block of SUSP entries. - * - * It allows SUSP to coexist with - * non-SUSP uses of the System - * Use Area by placing non-SUSP data - * after SUSP data. - */ - return; - } - case 'T': - if (p[0] == 'T' && p[1] == 'F' && version == 1) { - char flag = data[0]; - /* - * TF extension comprises: - * one byte flag - * create time (optional) - * modify time (optional) - * access time (optional) - * attribute time (optional) - * Time format and presence of fields - * is controlled by flag bits. - */ - data++; - if (flag & 0x80) { - /* Use 17-byte time format. */ - if (flag & 1) /* Create time. */ - data += 17; - if (flag & 2) { /* Modify time. */ - file->mtime = isodate17(data); - data += 17; - } - if (flag & 4) { /* Access time. */ - file->atime = isodate17(data); - data += 17; - } - if (flag & 8) { /* Attribute time. */ - file->ctime = isodate17(data); - data += 17; - } - } else { - /* Use 7-byte time format. */ - if (flag & 1) /* Create time. */ - data += 7; - if (flag & 2) { /* Modify time. */ - file->mtime = isodate7(data); - data += 7; - } - if (flag & 4) { /* Access time. */ - file->atime = isodate7(data); - data += 7; - } - if (flag & 8) { /* Attribute time. */ - file->ctime = isodate7(data); - data += 7; - } - } - break; - } - /* FALLTHROUGH */ - default: - /* The FALLTHROUGHs above leave us here for - * any unsupported extension. */ - { - const unsigned char *t; - fprintf(stderr, "\nUnsupported RRIP extension for %s\n", file->name); - fprintf(stderr, " %c%c(%d):", p[0], p[1], data_length); - for (t = data; t < data + data_length && t < data + 16; t++) - fprintf(stderr, " %02x", *t); - fprintf(stderr, "\n"); - } - } - - - - p += p[2]; - } -} - -static void -release_file(struct iso9660 *iso9660, struct file_info *file) -{ - struct file_info *parent; - - if (file->refcount == 0) { - parent = file->parent; - if (file->name) - free(file->name); - archive_string_free(&file->symlink); - free(file); - if (parent != NULL) { - parent->refcount--; - release_file(iso9660, parent); - } - } -} - -static int -next_entry_seek(struct archive *a, struct iso9660 *iso9660, - struct file_info **pfile) -{ - struct file_info *file; - uint64_t offset; - - *pfile = NULL; - for (;;) { - *pfile = file = next_entry(iso9660); - if (file == NULL) - return (ARCHIVE_EOF); - - /* CE area precedes actual file data? Ignore it. */ - if (file->ce_offset > file->offset) { -fprintf(stderr, " *** Discarding CE data.\n"); - file->ce_offset = 0; - file->ce_size = 0; - } - - /* If CE exists, find and read it now. */ - if (file->ce_offset > 0) - offset = file->ce_offset; - else - offset = file->offset; - - /* Seek forward to the start of the entry. */ - while (iso9660->current_position < offset) { - ssize_t step = offset - iso9660->current_position; - ssize_t bytes_read; - const void *buff; - - if (step > iso9660->logical_block_size) - step = iso9660->logical_block_size; - bytes_read = (a->compression_read_ahead)(a, &buff, step); - if (bytes_read <= 0) { - release_file(iso9660, file); - return (ARCHIVE_FATAL); - } - if (bytes_read > step) - bytes_read = step; - iso9660->current_position += bytes_read; - (a->compression_read_consume)(a, bytes_read); - } - - /* We found body of file; handle it now. */ - if (offset == file->offset) - return (ARCHIVE_OK); - - /* Found CE? Process it and push the file back onto list. */ - if (offset == file->ce_offset) { - const void *p; - ssize_t size = file->ce_size; - ssize_t bytes_read; - const unsigned char *rr_start; - - file->ce_offset = 0; - file->ce_size = 0; - bytes_read = (a->compression_read_ahead)(a, &p, size); - if (bytes_read > size) - bytes_read = size; - rr_start = (const unsigned char *)p; - parse_rockridge(iso9660, file, rr_start, - rr_start + bytes_read); - (a->compression_read_consume)(a, bytes_read); - iso9660->current_position += bytes_read; - add_entry(iso9660, file); - } - } -} - -static struct file_info * -next_entry(struct iso9660 *iso9660) -{ - int least_index; - uint64_t least_end_offset; - int i; - struct file_info *r; - - if (iso9660->pending_files_used < 1) - return (NULL); - - /* Assume the first file in the list is the earliest on disk. */ - least_index = 0; - least_end_offset = iso9660->pending_files[0]->offset - + iso9660->pending_files[0]->size; - - /* Now, try to find an earlier one. */ - for (i = 0; i < iso9660->pending_files_used; i++) { - /* Use the position of the file *end* as our comparison. */ - uint64_t end_offset = iso9660->pending_files[i]->offset - + iso9660->pending_files[i]->size; - if (iso9660->pending_files[i]->ce_offset > 0 - && iso9660->pending_files[i]->ce_offset < iso9660->pending_files[i]->offset) - end_offset = iso9660->pending_files[i]->ce_offset - + iso9660->pending_files[i]->ce_size; - if (least_end_offset > end_offset) { - least_index = i; - least_end_offset = end_offset; - } - } - r = iso9660->pending_files[least_index]; - iso9660->pending_files[least_index] - = iso9660->pending_files[--iso9660->pending_files_used]; - return (r); -} - -static int -toi(const void *p, int n) -{ - const unsigned char *v = (const unsigned char *)p; - if (n > 1) - return v[0] + 256 * toi(v + 1, n - 1); - if (n == 1) - return v[0]; - return (0); -} - -static time_t -isodate7(const void *p) -{ - struct tm tm; - const unsigned char *v = (const unsigned char *)p; - int offset; - memset(&tm, 0, sizeof(tm)); - tm.tm_year = v[0]; - tm.tm_mon = v[1] - 1; - tm.tm_mday = v[2]; - tm.tm_hour = v[3]; - tm.tm_min = v[4]; - tm.tm_sec = v[5]; - /* v[6] is the timezone offset, in 1/4-hour increments. */ - offset = ((const signed char *)p)[6]; - if (offset > -48 && offset < 52) { - tm.tm_hour -= offset / 4; - tm.tm_min -= (offset % 4) * 15; - } - return (time_from_tm(&tm)); -} - -static time_t -isodate17(const void *p) -{ - struct tm tm; - const unsigned char *v = (const unsigned char *)p; - int offset; - memset(&tm, 0, sizeof(tm)); - tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100 - + (v[2] - '0') * 10 + (v[3] - '0') - - 1900; - tm.tm_mon = (v[4] - '0') * 10 + (v[5] - '0'); - tm.tm_mday = (v[6] - '0') * 10 + (v[7] - '0'); - tm.tm_hour = (v[8] - '0') * 10 + (v[9] - '0'); - tm.tm_min = (v[10] - '0') * 10 + (v[11] - '0'); - tm.tm_sec = (v[12] - '0') * 10 + (v[13] - '0'); - /* v[16] is the timezone offset, in 1/4-hour increments. */ - offset = ((const signed char *)p)[16]; - if (offset > -48 && offset < 52) { - tm.tm_hour -= offset / 4; - tm.tm_min -= (offset % 4) * 15; - } - 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 - return (timegm(t)); -#else - /* - * Unfortunately, timegm() isn't standard. The standard - * mktime() function is a close match, except that it uses - * local timezone instead of GMT. Close enough for now. - * Note that it is not possible to emulate timegm() using - * standard interfaces: - * * ANSI C90 does not even guarantee that time_t is - * an arithmetic type, so time adjustments can only be - * done by manipulating struct tm elements. You cannot - * portably calculate time_t values. - * * POSIX does promise that time_t is an arithmetic type - * measured in seconds, so you can do time_t calculations - * while remaining POSIX-compliant. - * * Neither ANSI nor POSIX provides an easy way to measure - * the timezone offset, so you can't adjust mktime() to - * work like timegm(). - * * POSIX does not promise that the epoch begins in 1970, - * so you can't write a portable timegm() function from - * scratch. - */ - time_t result = mktime(t); - /* TODO: Find a way to improve this approximation to timegm(). */ - return result; -#endif -} - -static const char * -build_pathname(struct archive_string *as, struct file_info *file) -{ - if (file->parent != NULL && file->parent->name[0] != '\0') { - build_pathname(as, file->parent); - archive_strcat(as, "/"); - } - if (file->name[0] == '\0') - archive_strcat(as, "."); - else - archive_strcat(as, file->name); - return (as->s); -} - -static void -dump_isodirrec(FILE *out, const struct iso9660_directory_record *isodirrec) -{ - fprintf(out, " l %d,", isodirrec->length[0]); - fprintf(out, " a %d,", isodirrec->ext_attr_length[0]); - fprintf(out, " ext 0x%x,", toi(isodirrec->extent, 4)); - fprintf(out, " s %d,", toi(isodirrec->size, 4)); - fprintf(out, " f 0x%02x,", isodirrec->flags[0]); - fprintf(out, " u %d,", isodirrec->file_unit_size[0]); - fprintf(out, " ilv %d,", isodirrec->interleave[0]); - fprintf(out, " seq %d,", toi(isodirrec->volume_sequence_number,2)); - fprintf(out, " nl %d:", isodirrec->name_len[0]); - fprintf(out, " `%.*s'", isodirrec->name_len[0], isodirrec->name); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_tar.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_tar.c deleted file mode 100644 index 151c492df2..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_tar.c +++ /dev/null @@ -1,1943 +0,0 @@ -/*- - * 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. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.43 2006/09/05 05:59:46 kientzle Exp $"); - -#include -#ifdef MAJOR_IN_MKDEV -#include -#else -#ifdef MAJOR_IN_SYSMACROS -#include -#endif -#endif -#include -#include -/* #include */ /* See archive_platform.h */ -#include -#include -#include - -/* Obtain suitable wide-character manipulation functions. */ -#ifdef HAVE_WCHAR_H -#include -#else -/* Good enough for equality testing, which is all we need. */ -static int wcscmp(const wchar_t *s1, const wchar_t *s2) -{ - int diff = *s1 - *s2; - while (*s1 && diff == 0) - diff = (int)*++s1 - (int)*++s2; - return diff; -} -/* Good enough for equality testing, which is all we need. */ -static int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) -{ - int diff = *s1 - *s2; - while (*s1 && diff == 0 && n-- > 0) - diff = (int)*++s1 - (int)*++s2; - return diff; -} -static size_t wcslen(const wchar_t *s) -{ - const wchar_t *p = s; - while (*p) - p++; - return p - s; -} -#endif - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -/* - * Layout of POSIX 'ustar' tar header. - */ -struct archive_entry_header_ustar { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char checksum[8]; - char typeflag[1]; - char linkname[100]; /* "old format" header ends here */ - char magic[6]; /* For POSIX: "ustar\0" */ - char version[2]; /* For POSIX: "00" */ - char uname[32]; - char gname[32]; - char rdevmajor[8]; - char rdevminor[8]; - char prefix[155]; -}; - -/* - * Structure of GNU tar header - */ -struct gnu_sparse { - char offset[12]; - char numbytes[12]; -}; - -struct archive_entry_header_gnutar { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char checksum[8]; - char typeflag[1]; - char linkname[100]; - char magic[8]; /* "ustar \0" (note blank/blank/null at end) */ - char uname[32]; - char gname[32]; - char rdevmajor[8]; - char rdevminor[8]; - char atime[12]; - char ctime[12]; - char offset[12]; - char longnames[4]; - char unused[1]; - struct gnu_sparse sparse[4]; - char isextended[1]; - char realsize[12]; - /* - * GNU doesn't use POSIX 'prefix' field; they use the 'L' (longname) - * entry instead. - */ -}; - -/* - * Data specific to this format. - */ -struct sparse_block { - struct sparse_block *next; - off_t offset; - off_t remaining; -}; - -struct tar { - struct archive_string acl_text; - struct archive_string entry_name; - struct archive_string entry_linkname; - struct archive_string entry_uname; - struct archive_string entry_gname; - struct archive_string longlink; - struct archive_string longname; - struct archive_string pax_header; - struct archive_string pax_global; - wchar_t *pax_entry; - size_t pax_entry_length; - int header_recursion_depth; - off_t entry_bytes_remaining; - off_t entry_offset; - off_t entry_padding; - struct sparse_block *sparse_list; -}; - -static size_t UTF8_mbrtowc(wchar_t *pwc, const char *s, size_t n); -static int archive_block_is_null(const unsigned char *p); -static char *base64_decode(const wchar_t *, size_t, size_t *); -static int gnu_read_sparse_data(struct archive *, struct tar *, - const struct archive_entry_header_gnutar *header); -static void gnu_parse_sparse_data(struct archive *, struct tar *, - const struct gnu_sparse *sparse, int length); -static int header_Solaris_ACL(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *); -static int header_common(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *); -static int header_old_tar(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *); -static int header_pax_extensions(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *); -static int header_pax_global(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int header_longlink(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int header_longname(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int header_volume(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int header_ustar(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int header_gnutar(struct archive *, struct tar *, - struct archive_entry *, struct stat *, const void *h); -static int archive_read_format_tar_bid(struct archive *); -static int archive_read_format_tar_cleanup(struct archive *); -static int archive_read_format_tar_read_data(struct archive *a, - const void **buff, size_t *size, off_t *offset); -static int archive_read_format_tar_skip(struct archive *a); -static int archive_read_format_tar_read_header(struct archive *, - struct archive_entry *); -static int checksum(struct archive *, const void *); -static int pax_attribute(struct archive_entry *, struct stat *, - wchar_t *key, wchar_t *value); -static int pax_header(struct archive *, struct tar *, - struct archive_entry *, struct stat *, char *attr); -static void pax_time(const wchar_t *, int64_t *sec, long *nanos); -static int read_body_to_string(struct archive *, struct tar *, - struct archive_string *, const void *h); -static int64_t tar_atol(const char *, unsigned); -static int64_t tar_atol10(const wchar_t *, unsigned); -static int64_t tar_atol256(const char *, unsigned); -static int64_t tar_atol8(const char *, unsigned); -static int tar_read_header(struct archive *, struct tar *, - struct archive_entry *, struct stat *); -static int tohex(int c); -static char *url_decode(const char *); -static int utf8_decode(wchar_t *, const char *, size_t length); -static char *wide_to_narrow(const wchar_t *wval); - -/* - * ANSI C99 defines constants for these, but not everyone supports - * those constants, so I define a couple of static variables here and - * compute the values. These calculations should be portable to any - * 2s-complement architecture. - */ -#ifdef UINT64_MAX -static const uint64_t max_uint64 = UINT64_MAX; -#else -static const uint64_t max_uint64 = ~(uint64_t)0; -#endif -#ifdef INT64_MAX -static const int64_t max_int64 = INT64_MAX; -#else -static const int64_t max_int64 = (int64_t)((~(uint64_t)0) >> 1); -#endif -#ifdef INT64_MIN -static const int64_t min_int64 = INT64_MIN; -#else -static const int64_t min_int64 = (int64_t)(~((~(uint64_t)0) >> 1)); -#endif - -int -archive_read_support_format_gnutar(struct archive *a) -{ - return (archive_read_support_format_tar(a)); -} - - -int -archive_read_support_format_tar(struct archive *a) -{ - struct tar *tar; - int r; - - tar = malloc(sizeof(*tar)); - if (tar == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate tar data"); - return (ARCHIVE_FATAL); - } - memset(tar, 0, sizeof(*tar)); - - r = __archive_read_register_format(a, tar, - archive_read_format_tar_bid, - archive_read_format_tar_read_header, - archive_read_format_tar_read_data, - archive_read_format_tar_skip, - archive_read_format_tar_cleanup); - - if (r != ARCHIVE_OK) - free(tar); - return (ARCHIVE_OK); -} - -static int -archive_read_format_tar_cleanup(struct archive *a) -{ - struct tar *tar; - - tar = *(a->pformat_data); - archive_string_free(&tar->acl_text); - archive_string_free(&tar->entry_name); - archive_string_free(&tar->entry_linkname); - archive_string_free(&tar->entry_uname); - archive_string_free(&tar->entry_gname); - archive_string_free(&tar->pax_global); - archive_string_free(&tar->pax_header); - if (tar->pax_entry != NULL) - free(tar->pax_entry); - free(tar); - *(a->pformat_data) = NULL; - return (ARCHIVE_OK); -} - - -static int -archive_read_format_tar_bid(struct archive *a) -{ - int bid; - ssize_t bytes_read; - const void *h; - const struct archive_entry_header_ustar *header; - - /* - * If we're already reading a non-tar file, don't - * bother to bid. - */ - if (a->archive_format != 0 && - (a->archive_format & ARCHIVE_FORMAT_BASE_MASK) != - ARCHIVE_FORMAT_TAR) - return (0); - bid = 0; - - /* - * If we're already reading a tar format, start the bid at 1 as - * a failsafe. - */ - if ((a->archive_format & ARCHIVE_FORMAT_BASE_MASK) == - ARCHIVE_FORMAT_TAR) - bid++; - - /* Now let's look at the actual header and see if it matches. */ - if (a->compression_read_ahead != NULL) - bytes_read = (a->compression_read_ahead)(a, &h, 512); - else - bytes_read = 0; /* Empty file. */ - if (bytes_read < 0) - return (ARCHIVE_FATAL); - if (bytes_read == 0 && bid > 0) { - /* An archive without a proper end-of-archive marker. */ - /* Hold our nose and bid 1 anyway. */ - return (1); - } - if (bytes_read < 512) { - /* If it's a new archive, then just return a zero bid. */ - if (bid == 0) - return (0); - /* - * If we already know this is a tar archive, - * then we have a problem. - */ - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated tar archive"); - return (ARCHIVE_FATAL); - } - - /* If it's an end-of-archive mark, we can handle it. */ - if ((*(const char *)h) == 0 && archive_block_is_null(h)) { - /* If it's a known tar file, end-of-archive is definite. */ - if ((a->archive_format & ARCHIVE_FORMAT_BASE_MASK) == - ARCHIVE_FORMAT_TAR) - return (512); - /* Empty archive? */ - return (1); - } - - /* If it's not an end-of-archive mark, it must have a valid checksum.*/ - if (!checksum(a, h)) - return (0); - bid += 48; /* Checksum is usually 6 octal digits. */ - - header = h; - - /* Recognize POSIX formats. */ - if ((memcmp(header->magic, "ustar\0", 6) == 0) - &&(memcmp(header->version, "00", 2)==0)) - bid += 56; - - /* Recognize GNU tar format. */ - if ((memcmp(header->magic, "ustar ", 6) == 0) - &&(memcmp(header->version, " \0", 2)==0)) - bid += 56; - - /* Type flag must be null, digit or A-Z, a-z. */ - if (header->typeflag[0] != 0 && - !( header->typeflag[0] >= '0' && header->typeflag[0] <= '9') && - !( header->typeflag[0] >= 'A' && header->typeflag[0] <= 'Z') && - !( header->typeflag[0] >= 'a' && header->typeflag[0] <= 'z') ) - return (0); - bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */ - - /* Sanity check: Look at first byte of mode field. */ - switch (255 & (unsigned)header->mode[0]) { - case 0: case 255: - /* Base-256 value: No further verification possible! */ - break; - case ' ': /* Not recommended, but not illegal, either. */ - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - /* Octal Value. */ - /* TODO: Check format of remainder of this field. */ - break; - default: - /* Not a valid mode; bail out here. */ - return (0); - } - /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */ - - return (bid); -} - -/* - * The function invoked by archive_read_header(). This - * just sets up a few things and then calls the internal - * tar_read_header() function below. - */ -static int -archive_read_format_tar_read_header(struct archive *a, - struct archive_entry *entry) -{ - /* - * When converting tar archives to cpio archives, it is - * essential that each distinct file have a distinct inode - * number. To simplify this, we keep a static count here to - * assign fake dev/inode numbers to each tar entry. Note that - * pax format archives may overwrite this with something more - * useful. - * - * Ideally, we would track every file read from the archive so - * that we could assign the same dev/ino pair to hardlinks, - * but the memory required to store a complete lookup table is - * probably not worthwhile just to support the relatively - * obscure tar->cpio conversion case. - */ - static int default_inode; - static int default_dev; - struct stat st; - struct tar *tar; - const char *p; - int r; - size_t l; - - memset(&st, 0, sizeof(st)); - /* Assign default device/inode values. */ - st.st_dev = 1 + default_dev; /* Don't use zero. */ - st.st_ino = ++default_inode; /* Don't use zero. */ - /* Limit generated st_ino number to 16 bits. */ - if (default_inode >= 0xffff) { - ++default_dev; - default_inode = 0; - } - - tar = *(a->pformat_data); - tar->entry_offset = 0; - - r = tar_read_header(a, tar, entry, &st); - - if (r == ARCHIVE_OK) { - /* - * "Regular" entry with trailing '/' is really - * directory: This is needed for certain old tar - * variants and even for some broken newer ones. - */ - p = archive_entry_pathname(entry); - l = strlen(p); - if (S_ISREG(st.st_mode) && p[l-1] == '/') { - st.st_mode &= ~S_IFMT; - st.st_mode |= S_IFDIR; - } - - /* Copy the final stat data into the entry. */ - archive_entry_copy_stat(entry, &st); - } - return (r); -} - -static int -archive_read_format_tar_read_data(struct archive *a, - const void **buff, size_t *size, off_t *offset) -{ - ssize_t bytes_read; - struct tar *tar; - struct sparse_block *p; - - tar = *(a->pformat_data); - if (tar->sparse_list != NULL) { - /* Remove exhausted entries from sparse list. */ - while (tar->sparse_list != NULL && - tar->sparse_list->remaining == 0) { - p = tar->sparse_list; - tar->sparse_list = p->next; - free(p); - } - if (tar->sparse_list == NULL) { - /* We exhausted the entire sparse list. */ - tar->entry_bytes_remaining = 0; - } - } - - if (tar->entry_bytes_remaining > 0) { - bytes_read = (a->compression_read_ahead)(a, buff, 1); - if (bytes_read <= 0) - return (ARCHIVE_FATAL); - if (bytes_read > tar->entry_bytes_remaining) - bytes_read = tar->entry_bytes_remaining; - if (tar->sparse_list != NULL) { - /* Don't read more than is available in the - * current sparse block. */ - if (tar->sparse_list->remaining < bytes_read) - bytes_read = tar->sparse_list->remaining; - tar->entry_offset = tar->sparse_list->offset; - tar->sparse_list->remaining -= bytes_read; - tar->sparse_list->offset += bytes_read; - } - *size = bytes_read; - *offset = tar->entry_offset; - tar->entry_offset += bytes_read; - tar->entry_bytes_remaining -= bytes_read; - (a->compression_read_consume)(a, bytes_read); - return (ARCHIVE_OK); - } else { - while (tar->entry_padding > 0) { - bytes_read = (a->compression_read_ahead)(a, buff, 1); - if (bytes_read <= 0) - return (ARCHIVE_FATAL); - if (bytes_read > tar->entry_padding) - bytes_read = tar->entry_padding; - (a->compression_read_consume)(a, bytes_read); - tar->entry_padding -= bytes_read; - } - *buff = NULL; - *size = 0; - *offset = tar->entry_offset; - return (ARCHIVE_EOF); - } -} - -static int -archive_read_format_tar_skip(struct archive *a) -{ - ssize_t bytes_skipped; - struct tar* tar; - struct sparse_block *p; - int r = ARCHIVE_OK; - const void *b; /* dummy variables */ - size_t s; - off_t o; - - - tar = *(a->pformat_data); - if (a->compression_skip == NULL) { - while (r == ARCHIVE_OK) - r = archive_read_format_tar_read_data(a, &b, &s, &o); - return (r); - } - bytes_skipped = (a->compression_skip)(a, tar->entry_bytes_remaining); - if (bytes_skipped < 0) - return (ARCHIVE_FATAL); - /* same code as above in _tar_read_data() */ - tar->entry_bytes_remaining -= bytes_skipped; - while (tar->sparse_list != NULL && - tar->sparse_list->remaining == 0) { - p = tar->sparse_list; - tar->sparse_list = p->next; - free(p); - if (tar->sparse_list != NULL) - tar->entry_offset = tar->sparse_list->offset; - } - if (tar->sparse_list != NULL) { - if (tar->sparse_list->remaining < bytes_skipped) - bytes_skipped = tar->sparse_list->remaining; - tar->sparse_list->remaining -= bytes_skipped; - } - tar->entry_offset += bytes_skipped; - tar->entry_bytes_remaining -= bytes_skipped; - /* Reuse padding code above. */ - while (r == ARCHIVE_OK) - r = archive_read_format_tar_read_data(a, &b, &s, &o); - return (r); -} - -/* - * This function recursively interprets all of the headers associated - * with a single entry. - */ -static int -tar_read_header(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st) -{ - ssize_t bytes; - int err; - const void *h; - const struct archive_entry_header_ustar *header; - - /* Read 512-byte header record */ - bytes = (a->compression_read_ahead)(a, &h, 512); - if (bytes < 512) { - /* - * If we're here, it's becase the _bid function accepted - * this file. So just call a short read end-of-archive - * and be done with it. - */ - return (ARCHIVE_EOF); - } - (a->compression_read_consume)(a, 512); - - /* Check for end-of-archive mark. */ - if (((*(const char *)h)==0) && archive_block_is_null(h)) { - /* Try to consume a second all-null record, as well. */ - bytes = (a->compression_read_ahead)(a, &h, 512); - if (bytes > 0) - (a->compression_read_consume)(a, bytes); - archive_set_error(a, 0, NULL); - return (ARCHIVE_EOF); - } - - /* - * Note: If the checksum fails and we return ARCHIVE_RETRY, - * then the client is likely to just retry. This is a very - * crude way to search for the next valid header! - * - * TODO: Improve this by implementing a real header scan. - */ - if (!checksum(a, h)) { - archive_set_error(a, EINVAL, "Damaged tar archive"); - return (ARCHIVE_RETRY); /* Retryable: Invalid header */ - } - - if (++tar->header_recursion_depth > 32) { - archive_set_error(a, EINVAL, "Too many special headers"); - return (ARCHIVE_WARN); - } - - /* Determine the format variant. */ - header = h; - switch(header->typeflag[0]) { - case 'A': /* Solaris tar ACL */ - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; - a->archive_format_name = "Solaris tar"; - err = header_Solaris_ACL(a, tar, entry, st, h); - break; - case 'g': /* POSIX-standard 'g' header. */ - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; - a->archive_format_name = "POSIX pax interchange format"; - err = header_pax_global(a, tar, entry, st, h); - break; - case 'K': /* Long link name (GNU tar, others) */ - err = header_longlink(a, tar, entry, st, h); - break; - case 'L': /* Long filename (GNU tar, others) */ - err = header_longname(a, tar, entry, st, h); - break; - case 'V': /* GNU volume header */ - err = header_volume(a, tar, entry, st, h); - break; - case 'X': /* Used by SUN tar; same as 'x'. */ - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; - a->archive_format_name = - "POSIX pax interchange format (Sun variant)"; - err = header_pax_extensions(a, tar, entry, st, h); - break; - case 'x': /* POSIX-standard 'x' header. */ - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; - a->archive_format_name = "POSIX pax interchange format"; - err = header_pax_extensions(a, tar, entry, st, h); - break; - default: - if (memcmp(header->magic, "ustar \0", 8) == 0) { - a->archive_format = ARCHIVE_FORMAT_TAR_GNUTAR; - a->archive_format_name = "GNU tar format"; - err = header_gnutar(a, tar, entry, st, h); - } else if (memcmp(header->magic, "ustar", 5) == 0) { - if (a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) { - a->archive_format = ARCHIVE_FORMAT_TAR_USTAR; - a->archive_format_name = "POSIX ustar format"; - } - err = header_ustar(a, tar, entry, st, h); - } else { - a->archive_format = ARCHIVE_FORMAT_TAR; - a->archive_format_name = "tar (non-POSIX)"; - err = header_old_tar(a, tar, entry, st, h); - } - } - --tar->header_recursion_depth; - return (err); -} - -/* - * Return true if block checksum is correct. - */ -static int -checksum(struct archive *a, const void *h) -{ - const unsigned char *bytes; - const struct archive_entry_header_ustar *header; - int check, i, sum; - - (void)a; /* UNUSED */ - bytes = h; - header = h; - - /* - * Test the checksum. Note that POSIX specifies _unsigned_ - * bytes for this calculation. - */ - sum = tar_atol(header->checksum, sizeof(header->checksum)); - check = 0; - for (i = 0; i < 148; i++) - check += (unsigned char)bytes[i]; - for (; i < 156; i++) - check += 32; - for (; i < 512; i++) - check += (unsigned char)bytes[i]; - if (sum == check) - return (1); - - /* - * Repeat test with _signed_ bytes, just in case this archive - * was created by an old BSD, Solaris, or HP-UX tar with a - * broken checksum calculation. - */ - check = 0; - for (i = 0; i < 148; i++) - check += (signed char)bytes[i]; - for (; i < 156; i++) - check += 32; - for (; i < 512; i++) - check += (signed char)bytes[i]; - if (sum == check) - return (1); - - return (0); -} - -/* - * Return true if this block contains only nulls. - */ -static int -archive_block_is_null(const unsigned char *p) -{ - unsigned i; - - for (i = 0; i < ARCHIVE_BYTES_PER_RECORD / sizeof(*p); i++) - if (*p++) - return (0); - return (1); -} - -/* - * Interpret 'A' Solaris ACL header - */ -static int -header_Solaris_ACL(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - int err, err2; - char *p; - wchar_t *wp; - - err = read_body_to_string(a, tar, &(tar->acl_text), h); - err2 = tar_read_header(a, tar, entry, st); - err = err_combine(err, err2); - - /* XXX Ensure p doesn't overrun acl_text */ - - /* Skip leading octal number. */ - /* XXX TODO: Parse the octal number and sanity-check it. */ - p = tar->acl_text.s; - while (*p != '\0') - p++; - p++; - - wp = malloc((strlen(p) + 1) * sizeof(wchar_t)); - if (wp != NULL) { - utf8_decode(wp, p, strlen(p)); - err2 = __archive_entry_acl_parse_w(entry, wp, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); - err = err_combine(err, err2); - free(wp); - } - - return (err); -} - -/* - * Interpret 'K' long linkname header. - */ -static int -header_longlink(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - int err, err2; - - err = read_body_to_string(a, tar, &(tar->longlink), h); - err2 = tar_read_header(a, tar, entry, st); - if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) { - /* Set symlink if symlink already set, else hardlink. */ - archive_entry_set_link(entry, tar->longlink.s); - } - return (err_combine(err, err2)); -} - -/* - * Interpret 'L' long filename header. - */ -static int -header_longname(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - int err, err2; - - err = read_body_to_string(a, tar, &(tar->longname), h); - /* Read and parse "real" header, then override name. */ - err2 = tar_read_header(a, tar, entry, st); - if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) - archive_entry_set_pathname(entry, tar->longname.s); - return (err_combine(err, err2)); -} - - -/* - * Interpret 'V' GNU tar volume header. - */ -static int -header_volume(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - (void)h; - - /* Just skip this and read the next header. */ - return (tar_read_header(a, tar, entry, st)); -} - -/* - * Read body of an archive entry into an archive_string object. - */ -static int -read_body_to_string(struct archive *a, struct tar *tar, - struct archive_string *as, const void *h) -{ - off_t size, padded_size; - ssize_t bytes_read, bytes_to_copy; - const struct archive_entry_header_ustar *header; - const void *src; - char *dest; - - (void)tar; /* UNUSED */ - header = h; - size = tar_atol(header->size, sizeof(header->size)); - - /* Read the body into the string. */ - archive_string_ensure(as, size+1); - padded_size = (size + 511) & ~ 511; - dest = as->s; - while (padded_size > 0) { - bytes_read = (a->compression_read_ahead)(a, &src, padded_size); - if (bytes_read < 0) - return (ARCHIVE_FATAL); - if (bytes_read > padded_size) - bytes_read = padded_size; - (a->compression_read_consume)(a, bytes_read); - bytes_to_copy = bytes_read; - if ((off_t)bytes_to_copy > size) - bytes_to_copy = (ssize_t)size; - memcpy(dest, src, bytes_to_copy); - dest += bytes_to_copy; - size -= bytes_to_copy; - padded_size -= bytes_read; - } - *dest = '\0'; - return (ARCHIVE_OK); -} - -/* - * Parse out common header elements. - * - * This would be the same as header_old_tar, except that the - * filename is handled slightly differently for old and POSIX - * entries (POSIX entries support a 'prefix'). This factoring - * allows header_old_tar and header_ustar - * to handle filenames differently, while still putting most of the - * common parsing into one place. - */ -static int -header_common(struct archive *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) -{ - const struct archive_entry_header_ustar *header; - char tartype; - - (void)a; /* UNUSED */ - - header = h; - if (header->linkname[0]) - archive_strncpy(&(tar->entry_linkname), header->linkname, - sizeof(header->linkname)); - else - archive_string_empty(&(tar->entry_linkname)); - - /* Parse out the numeric fields (all are octal) */ - st->st_mode = tar_atol(header->mode, sizeof(header->mode)); - st->st_uid = tar_atol(header->uid, sizeof(header->uid)); - st->st_gid = tar_atol(header->gid, sizeof(header->gid)); - st->st_size = tar_atol(header->size, sizeof(header->size)); - st->st_mtime = tar_atol(header->mtime, sizeof(header->mtime)); - - /* Handle the tar type flag appropriately. */ - tartype = header->typeflag[0]; - st->st_mode &= ~S_IFMT; - - switch (tartype) { - case '1': /* Hard link */ - archive_entry_set_hardlink(entry, tar->entry_linkname.s); - /* - * The following may seem odd, but: Technically, tar - * does not store the file type for a "hard link" - * entry, only the fact that it is a hard link. So, I - * leave the type zero normally. But, pax interchange - * format allows hard links to have data, which - * implies that the underlying entry is a regular - * file. - */ - if (st->st_size > 0) - st->st_mode |= S_IFREG; - - /* - * A tricky point: Traditionally, tar readers have - * ignored the size field when reading hardlink - * entries, and some writers put non-zero sizes even - * though the body is empty. POSIX.1-2001 broke with - * this tradition by permitting hardlink entries to - * store valid bodies in pax interchange format, but - * not in ustar format. Since there is no hard and - * fast way to distinguish pax interchange from - * earlier archives (the 'x' and 'g' entries are - * optional, after all), we need a heuristic. Here, I - * use the bid function to test whether or not there's - * a valid header following. Of course, if we know - * this is pax interchange format, then we must obey - * the size. - * - * This heuristic will only fail for a pax interchange - * archive that is storing hardlink bodies, no pax - * extended attribute entries have yet occurred, and - * we encounter a hardlink entry for a file that is - * itself an uncompressed tar archive. - */ - if (st->st_size > 0 && - a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE && - archive_read_format_tar_bid(a) > 50) - st->st_size = 0; - break; - case '2': /* Symlink */ - st->st_mode |= S_IFLNK; - st->st_size = 0; - archive_entry_set_symlink(entry, tar->entry_linkname.s); - break; - case '3': /* Character device */ - st->st_mode |= S_IFCHR; - st->st_size = 0; - break; - case '4': /* Block device */ - st->st_mode |= S_IFBLK; - st->st_size = 0; - break; - case '5': /* Dir */ - st->st_mode |= S_IFDIR; - st->st_size = 0; - break; - case '6': /* FIFO device */ - st->st_mode |= S_IFIFO; - st->st_size = 0; - break; - case 'D': /* GNU incremental directory type */ - /* - * No special handling is actually required here. - * It might be nice someday to preprocess the file list and - * provide it to the client, though. - */ - st->st_mode |= S_IFDIR; - break; - case 'M': /* GNU "Multi-volume" (remainder of file from last archive)*/ - /* - * As far as I can tell, this is just like a regular file - * entry, except that the contents should be _appended_ to - * the indicated file at the indicated offset. This may - * require some API work to fully support. - */ - break; - case 'N': /* Old GNU "long filename" entry. */ - /* The body of this entry is a script for renaming - * previously-extracted entries. Ugh. It will never - * be supported by libarchive. */ - st->st_mode |= S_IFREG; - break; - case 'S': /* GNU sparse files */ - /* - * Sparse files are really just regular files with - * sparse information in the extended area. - */ - /* FALL THROUGH */ - default: /* Regular file and non-standard types */ - /* - * Per POSIX: non-recognized types should always be - * treated as regular files. - */ - st->st_mode |= S_IFREG; - break; - } - return (0); -} - -/* - * Parse out header elements for "old-style" tar archives. - */ -static int -header_old_tar(struct archive *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) -{ - const struct archive_entry_header_ustar *header; - - /* Copy filename over (to ensure null termination). */ - header = h; - archive_strncpy(&(tar->entry_name), header->name, sizeof(header->name)); - archive_entry_set_pathname(entry, tar->entry_name.s); - - /* Grab rest of common fields */ - header_common(a, tar, entry, st, h); - - tar->entry_bytes_remaining = st->st_size; - tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); - return (0); -} - -/* - * Parse a file header for a pax extended archive entry. - */ -static int -header_pax_global(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - int err, err2; - - err = read_body_to_string(a, tar, &(tar->pax_global), h); - err2 = tar_read_header(a, tar, entry, st); - return (err_combine(err, err2)); -} - -static int -header_pax_extensions(struct archive *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) -{ - int err, err2; - - read_body_to_string(a, tar, &(tar->pax_header), h); - - /* Parse the next header. */ - err = tar_read_header(a, tar, entry, st); - - /* - * TODO: Parse global/default options into 'entry' struct here - * before handling file-specific options. - * - * This design (parse standard header, then overwrite with pax - * extended attribute data) usually works well, but isn't ideal; - * it would be better to parse the pax extended attributes first - * and then skip any fields in the standard header that were - * defined in the pax header. - */ - err2 = pax_header(a, tar, entry, st, tar->pax_header.s); - err = err_combine(err, err2); - tar->entry_bytes_remaining = st->st_size; - tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); - return (err); -} - - -/* - * Parse a file header for a Posix "ustar" archive entry. This also - * handles "pax" or "extended ustar" entries. - */ -static int -header_ustar(struct archive *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) -{ - const struct archive_entry_header_ustar *header; - struct archive_string *as; - - header = h; - - /* Copy name into an internal buffer to ensure null-termination. */ - as = &(tar->entry_name); - if (header->prefix[0]) { - archive_strncpy(as, header->prefix, sizeof(header->prefix)); - if (as->s[archive_strlen(as) - 1] != '/') - archive_strappend_char(as, '/'); - archive_strncat(as, header->name, sizeof(header->name)); - } else - archive_strncpy(as, header->name, sizeof(header->name)); - - archive_entry_set_pathname(entry, as->s); - - /* Handle rest of common fields. */ - header_common(a, tar, entry, st, h); - - /* Handle POSIX ustar fields. */ - archive_strncpy(&(tar->entry_uname), header->uname, - sizeof(header->uname)); - archive_entry_set_uname(entry, tar->entry_uname.s); - - archive_strncpy(&(tar->entry_gname), header->gname, - sizeof(header->gname)); - archive_entry_set_gname(entry, tar->entry_gname.s); - - /* Parse out device numbers only for char and block specials. */ - if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { - st->st_rdev = makedev( - tar_atol(header->rdevmajor, sizeof(header->rdevmajor)), - tar_atol(header->rdevminor, sizeof(header->rdevminor))); - } - - tar->entry_bytes_remaining = st->st_size; - tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); - - return (0); -} - - -/* - * Parse the pax extended attributes record. - * - * Returns non-zero if there's an error in the data. - */ -static int -pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, char *attr) -{ - size_t attr_length, l, line_length; - char *line, *p; - wchar_t *key, *wp, *value; - int err, err2; - - attr_length = strlen(attr); - err = ARCHIVE_OK; - while (attr_length > 0) { - /* Parse decimal length field at start of line. */ - line_length = 0; - l = attr_length; - line = p = attr; /* Record start of line. */ - while (l>0) { - if (*p == ' ') { - p++; - l--; - break; - } - if (*p < '0' || *p > '9') - return (-1); - line_length *= 10; - line_length += *p - '0'; - if (line_length > 999999) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Rejecting pax extended attribute > 1MB"); - return (ARCHIVE_WARN); - } - p++; - l--; - } - - if (line_length > attr_length) - return (0); - - /* Ensure pax_entry buffer is big enough. */ - if (tar->pax_entry_length <= line_length) { - wchar_t *old_entry = tar->pax_entry; - - if (tar->pax_entry_length <= 0) - tar->pax_entry_length = 1024; - while (tar->pax_entry_length <= line_length + 1) - tar->pax_entry_length *= 2; - - old_entry = tar->pax_entry; - tar->pax_entry = realloc(tar->pax_entry, - tar->pax_entry_length * sizeof(wchar_t)); - if (tar->pax_entry == NULL) { - free(old_entry); - archive_set_error(a, ENOMEM, - "No memory"); - return (ARCHIVE_FATAL); - } - } - - /* Decode UTF-8 to wchar_t, null-terminate result. */ - if (utf8_decode(tar->pax_entry, p, - line_length - (p - attr) - 1)) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid UTF8 character in pax extended attribute"); - err = err_combine(err, ARCHIVE_WARN); - } - - /* Null-terminate 'key' value. */ - wp = key = tar->pax_entry; - if (key[0] == L'=') - return (-1); - while (*wp && *wp != L'=') - ++wp; - if (*wp == L'\0' || wp == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid pax extended attributes"); - return (ARCHIVE_WARN); - } - *wp = 0; - - /* Identify null-terminated 'value' portion. */ - value = wp + 1; - - /* Identify this attribute and set it in the entry. */ - err2 = pax_attribute(entry, st, key, value); - err = err_combine(err, err2); - - /* Skip to next line */ - attr += line_length; - attr_length -= line_length; - } - return (err); -} - -static int -pax_attribute_xattr(struct archive_entry *entry, - wchar_t *name, wchar_t *value) -{ - char *name_decoded, *name_narrow; - void *value_decoded; - size_t value_len; - - if (wcslen(name) < 18 || (wcsncmp(name, L"LIBARCHIVE.xattr.", 17)) != 0) - return 3; - - name += 17; - - /* URL-decode name */ - name_narrow = wide_to_narrow(name); - if (name_narrow == NULL) - return 2; - name_decoded = url_decode(name_narrow); - free(name_narrow); - if (name_decoded == NULL) - return 2; - - /* Base-64 decode value */ - value_decoded = base64_decode(value, wcslen(value), &value_len); - if (value_decoded == NULL) { - free(name_decoded); - return 1; - } - - archive_entry_xattr_add_entry(entry, name_decoded, - value_decoded, value_len); - - free(name_decoded); - free(value_decoded); - return 0; -} - -/* - * Parse a single key=value attribute. key/value pointers are - * assumed to point into reasonably long-lived storage. - * - * Note that POSIX reserves all-lowercase keywords. Vendor-specific - * extensions should always have keywords of the form "VENDOR.attribute" - * In particular, it's quite feasible to support many different - * vendor extensions here. I'm using "LIBARCHIVE" for extensions - * unique to this library (currently, there are none). - * - * Investigate other vendor-specific extensions, as well and see if - * any of them look useful. - */ -static int -pax_attribute(struct archive_entry *entry, struct stat *st, - wchar_t *key, wchar_t *value) -{ - int64_t s; - long n; - - switch (key[0]) { - case 'L': - /* Our extensions */ -/* TODO: Handle arbitrary extended attributes... */ -/* - if (strcmp(key, "LIBARCHIVE.xxxxxxx")==0) - archive_entry_set_xxxxxx(entry, value); -*/ - if (wcsncmp(key, L"LIBARCHIVE.xattr.", 17)==0) - pax_attribute_xattr(entry, key, value); - break; - case 'S': - /* We support some keys used by the "star" archiver */ - if (wcscmp(key, L"SCHILY.acl.access")==0) - __archive_entry_acl_parse_w(entry, value, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); - else if (wcscmp(key, L"SCHILY.acl.default")==0) - __archive_entry_acl_parse_w(entry, value, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); - else if (wcscmp(key, L"SCHILY.devmajor")==0) - st->st_rdev = makedev(tar_atol10(value, wcslen(value)), - minor(st->st_rdev)); - else if (wcscmp(key, L"SCHILY.devminor")==0) - st->st_rdev = makedev(major(st->st_rdev), - tar_atol10(value, wcslen(value))); - else if (wcscmp(key, L"SCHILY.fflags")==0) - archive_entry_copy_fflags_text_w(entry, value); - else if (wcscmp(key, L"SCHILY.nlink")==0) - st->st_nlink = tar_atol10(value, wcslen(value)); - break; - case 'a': - if (wcscmp(key, L"atime")==0) { - pax_time(value, &s, &n); - st->st_atime = s; - ARCHIVE_STAT_SET_ATIME_NANOS(st, n); - } - break; - case 'c': - if (wcscmp(key, L"ctime")==0) { - pax_time(value, &s, &n); - st->st_ctime = s; - ARCHIVE_STAT_SET_CTIME_NANOS(st, n); - } else if (wcscmp(key, L"charset")==0) { - /* TODO: Publish charset information in entry. */ - } else if (wcscmp(key, L"comment")==0) { - /* TODO: Publish comment in entry. */ - } - break; - case 'g': - if (wcscmp(key, L"gid")==0) - st->st_gid = tar_atol10(value, wcslen(value)); - else if (wcscmp(key, L"gname")==0) - archive_entry_copy_gname_w(entry, value); - break; - case 'l': - /* pax interchange doesn't distinguish hardlink vs. symlink. */ - if (wcscmp(key, L"linkpath")==0) { - if (archive_entry_hardlink(entry)) - archive_entry_copy_hardlink_w(entry, value); - else - archive_entry_copy_symlink_w(entry, value); - } - break; - case 'm': - if (wcscmp(key, L"mtime")==0) { - pax_time(value, &s, &n); - st->st_mtime = s; - ARCHIVE_STAT_SET_MTIME_NANOS(st, n); - } - break; - case 'p': - if (wcscmp(key, L"path")==0) - archive_entry_copy_pathname_w(entry, value); - break; - case 'r': - /* POSIX has reserved 'realtime.*' */ - break; - case 's': - /* POSIX has reserved 'security.*' */ - /* Someday: if (wcscmp(key, L"security.acl")==0) { ... } */ - if (wcscmp(key, L"size")==0) - st->st_size = tar_atol10(value, wcslen(value)); - break; - case 'u': - if (wcscmp(key, L"uid")==0) - st->st_uid = tar_atol10(value, wcslen(value)); - else if (wcscmp(key, L"uname")==0) - archive_entry_copy_uname_w(entry, value); - break; - } - return (0); -} - - - -/* - * parse a decimal time value, which may include a fractional portion - */ -static void -pax_time(const wchar_t *p, int64_t *ps, long *pn) -{ - char digit; - int64_t s; - unsigned long l; - int sign; - int64_t limit, last_digit_limit; - - limit = max_int64 / 10; - last_digit_limit = max_int64 % 10; - - s = 0; - sign = 1; - if (*p == '-') { - sign = -1; - p++; - } - while (*p >= '0' && *p <= '9') { - digit = *p - '0'; - if (s > limit || - (s == limit && digit > last_digit_limit)) { - s = max_uint64; - break; - } - s = (s * 10) + digit; - ++p; - } - - *ps = s * sign; - - /* Calculate nanoseconds. */ - *pn = 0; - - if (*p != '.') - return; - - l = 100000000UL; - do { - ++p; - if (*p >= '0' && *p <= '9') - *pn += (*p - '0') * l; - else - break; - } while (l /= 10); -} - -/* - * Parse GNU tar header - */ -static int -header_gnutar(struct archive *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) -{ - const struct archive_entry_header_gnutar *header; - - (void)a; - - /* - * GNU header is like POSIX ustar, except 'prefix' is - * replaced with some other fields. This also means the - * filename is stored as in old-style archives. - */ - - /* Grab fields common to all tar variants. */ - header_common(a, tar, entry, st, h); - - /* Copy filename over (to ensure null termination). */ - header = h; - archive_strncpy(&(tar->entry_name), header->name, - sizeof(header->name)); - archive_entry_set_pathname(entry, tar->entry_name.s); - - /* Fields common to ustar and GNU */ - /* XXX Can the following be factored out since it's common - * to ustar and gnu tar? Is it okay to move it down into - * header_common, perhaps? */ - archive_strncpy(&(tar->entry_uname), - header->uname, sizeof(header->uname)); - archive_entry_set_uname(entry, tar->entry_uname.s); - - archive_strncpy(&(tar->entry_gname), - header->gname, sizeof(header->gname)); - archive_entry_set_gname(entry, tar->entry_gname.s); - - /* Parse out device numbers only for char and block specials */ - if (header->typeflag[0] == '3' || header->typeflag[0] == '4') - st->st_rdev = makedev ( - tar_atol(header->rdevmajor, sizeof(header->rdevmajor)), - tar_atol(header->rdevminor, sizeof(header->rdevminor))); - else - st->st_rdev = 0; - - tar->entry_bytes_remaining = st->st_size; - tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); - - /* Grab GNU-specific fields. */ - st->st_atime = tar_atol(header->atime, sizeof(header->atime)); - st->st_ctime = tar_atol(header->ctime, sizeof(header->ctime)); - if (header->realsize[0] != 0) { - st->st_size = tar_atol(header->realsize, - sizeof(header->realsize)); - } - - if (header->sparse[0].offset[0] != 0) { - gnu_read_sparse_data(a, tar, header); - } else { - if (header->isextended[0] != 0) { - /* XXX WTF? XXX */ - } - } - - return (0); -} - -static int -gnu_read_sparse_data(struct archive *a, struct tar *tar, - const struct archive_entry_header_gnutar *header) -{ - ssize_t bytes_read; - const void *data; - struct extended { - struct gnu_sparse sparse[21]; - char isextended[1]; - char padding[7]; - }; - const struct extended *ext; - - gnu_parse_sparse_data(a, tar, header->sparse, 4); - if (header->isextended[0] == 0) - return (ARCHIVE_OK); - - do { - bytes_read = (a->compression_read_ahead)(a, &data, 512); - if (bytes_read < 0) - return (ARCHIVE_FATAL); - if (bytes_read < 512) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated tar archive " - "detected while reading sparse file data"); - return (ARCHIVE_FATAL); - } - (a->compression_read_consume)(a, 512); - ext = (const struct extended *)data; - gnu_parse_sparse_data(a, tar, ext->sparse, 21); - } while (ext->isextended[0] != 0); - if (tar->sparse_list != NULL) - tar->entry_offset = tar->sparse_list->offset; - return (ARCHIVE_OK); -} - -static void -gnu_parse_sparse_data(struct archive *a, struct tar *tar, - const struct gnu_sparse *sparse, int length) -{ - struct sparse_block *last; - struct sparse_block *p; - - (void)a; /* UNUSED */ - - last = tar->sparse_list; - while (last != NULL && last->next != NULL) - last = last->next; - - while (length > 0 && sparse->offset[0] != 0) { - p = malloc(sizeof(*p)); - if (p == NULL) - __archive_errx(1, "Out of memory"); - memset(p, 0, sizeof(*p)); - if (last != NULL) - last->next = p; - else - tar->sparse_list = p; - last = p; - p->offset = tar_atol(sparse->offset, sizeof(sparse->offset)); - p->remaining = - tar_atol(sparse->numbytes, sizeof(sparse->numbytes)); - sparse++; - length--; - } -} - -/*- - * Convert text->integer. - * - * Traditional tar formats (including POSIX) specify base-8 for - * all of the standard numeric fields. This is a significant limitation - * in practice: - * = file size is limited to 8GB - * = rdevmajor and rdevminor are limited to 21 bits - * = uid/gid are limited to 21 bits - * - * There are two workarounds for this: - * = pax extended headers, which use variable-length string fields - * = GNU tar and STAR both allow either base-8 or base-256 in - * most fields. The high bit is set to indicate base-256. - * - * On read, this implementation supports both extensions. - */ -static int64_t -tar_atol(const char *p, unsigned char_cnt) -{ - /* - * Technically, GNU tar considers a field to be in base-256 - * only if the first byte is 0xff or 0x80. - */ - if (*p & 0x80) - return (tar_atol256(p, char_cnt)); - return (tar_atol8(p, char_cnt)); -} - -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ -static int64_t -tar_atol8(const char *p, unsigned char_cnt) -{ - int64_t l, limit, last_digit_limit; - int digit, sign, base; - - base = 8; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; - - while (*p == ' ' || *p == '\t') - p++; - if (*p == '-') { - sign = -1; - p++; - } else - sign = 1; - - l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { - if (l>limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ - break; - } - l = (l * base) + digit; - digit = *++p - '0'; - } - return (sign < 0) ? -l : l; -} - - -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ -static int64_t -tar_atol10(const wchar_t *p, unsigned char_cnt) -{ - int64_t l, limit, last_digit_limit; - int base, digit, sign; - - base = 10; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; - - while (*p == ' ' || *p == '\t') - p++; - if (*p == '-') { - sign = -1; - p++; - } else - sign = 1; - - l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { - if (l > limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ - break; - } - l = (l * base) + digit; - digit = *++p - '0'; - } - return (sign < 0) ? -l : l; -} - -/* - * Parse a base-256 integer. This is just a straight signed binary - * value in big-endian order, except that the high-order bit is - * ignored. Remember that "int64_t" may or may not be exactly 64 - * bits; the implementation here tries to avoid making any assumptions - * about the actual size of an int64_t. It does assume we're using - * twos-complement arithmetic, though. - */ -static int64_t -tar_atol256(const char *_p, unsigned char_cnt) -{ - int64_t l, upper_limit, lower_limit; - const unsigned char *p = (const unsigned char *)_p; - - upper_limit = max_int64 / 256; - lower_limit = min_int64 / 256; - - /* Pad with 1 or 0 bits, depending on sign. */ - if ((0x40 & *p) == 0x40) - l = (int64_t)-1; - else - l = 0; - l = (l << 6) | (0x3f & *p++); - while (--char_cnt > 0) { - if (l > upper_limit) { - l = max_int64; /* Truncate on overflow */ - break; - } else if (l < lower_limit) { - l = min_int64; - break; - } - l = (l << 8) | (0xff & (int64_t)*p++); - } - return (l); -} - -static int -utf8_decode(wchar_t *dest, const char *src, size_t length) -{ - size_t n; - int err; - - err = 0; - while (length > 0) { - n = UTF8_mbrtowc(dest, src, length); - if (n == 0) - break; - dest++; - src += n; - length -= n; - } - *dest++ = L'\0'; - return (err); -} - -/* - * Copied and simplified from FreeBSD libc/locale. - */ -static size_t -UTF8_mbrtowc(wchar_t *pwc, const char *s, size_t n) -{ - int ch, i, len, mask; - unsigned long wch; - - if (s == NULL || n == 0 || pwc == NULL) - return (0); - - /* - * Determine the number of octets that make up this character from - * the first octet, and a mask that extracts the interesting bits of - * the first octet. - */ - ch = (unsigned char)*s; - if ((ch & 0x80) == 0) { - mask = 0x7f; - len = 1; - } else if ((ch & 0xe0) == 0xc0) { - mask = 0x1f; - len = 2; - } else if ((ch & 0xf0) == 0xe0) { - mask = 0x0f; - len = 3; - } else if ((ch & 0xf8) == 0xf0) { - mask = 0x07; - len = 4; - } else if ((ch & 0xfc) == 0xf8) { - mask = 0x03; - len = 5; - } else if ((ch & 0xfe) == 0xfc) { - mask = 0x01; - len = 6; - } else { - /* Invalid first byte; convert to '?' */ - *pwc = '?'; - return (1); - } - - if (n < (size_t)len) { - /* Invalid first byte; convert to '?' */ - *pwc = '?'; - return (1); - } - - /* - * Decode the octet sequence representing the character in chunks - * of 6 bits, most significant first. - */ - wch = (unsigned char)*s++ & mask; - i = len; - while (--i != 0) { - if ((*s & 0xc0) != 0x80) { - /* Invalid intermediate byte; consume one byte and - * emit '?' */ - *pwc = '?'; - return (1); - } - wch <<= 6; - wch |= *s++ & 0x3f; - } - - /* Assign the value to the output; out-of-range values - * just get truncated. */ - *pwc = (wchar_t)wch; -#ifdef WCHAR_MAX - /* - * If platform has WCHAR_MAX, we can do something - * more sensible with out-of-range values. - */ - if (wch >= WCHAR_MAX) - *pwc = '?'; -#endif - /* Return number of bytes input consumed: 0 for end-of-string. */ - return (wch == L'\0' ? 0 : len); -} - - -/* - * base64_decode - Base64 decode - * - * This accepts most variations of base-64 encoding, including: - * * with or without line breaks - * * with or without the final group padded with '=' or '_' characters - * (The most economical Base-64 variant does not pad the last group and - * omits line breaks; RFC1341 used for MIME requires both.) - */ -static char * -base64_decode(const wchar_t *src, size_t len, size_t *out_len) -{ - static const unsigned char digits[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - static unsigned char decode_table[128]; - char *out, *d; - - /* If the decode table is not yet initialized, prepare it. */ - if (decode_table[digits[1]] != 1) { - size_t i; - memset(decode_table, 0xff, sizeof(decode_table)); - for (i = 0; i < sizeof(digits); i++) - decode_table[digits[i]] = i; - } - - /* Allocate enough space to hold the entire output. */ - /* Note that we may not use all of this... */ - out = malloc((len * 3 + 3) / 4); - if (out == NULL) { - *out_len = 0; - return (NULL); - } - d = out; - - while (len > 0) { - /* Collect the next group of (up to) four characters. */ - int v = 0; - int group_size = 0; - while (group_size < 4 && len > 0) { - /* '=' or '_' padding indicates final group. */ - if (*src == '=' || *src == '_') { - len = 0; - break; - } - /* Skip illegal characters (including line breaks) */ - if (*src > 127 || *src < 32 - || decode_table[*src] == 0xff) { - len--; - src++; - continue; - } - v <<= 6; - v |= decode_table[*src++]; - len --; - group_size++; - } - /* Align a short group properly. */ - v <<= 6 * (4 - group_size); - /* Unpack the group we just collected. */ - switch (group_size) { - case 4: d[2] = v & 0xff; - /* FALLTHROUGH */ - case 3: d[1] = (v >> 8) & 0xff; - /* FALLTHROUGH */ - case 2: d[0] = (v >> 16) & 0xff; - break; - case 1: /* this is invalid! */ - break; - } - d += group_size * 3 / 4; - } - - *out_len = d - out; - return (out); -} - -/* - * This is a little tricky because the C99 standard wcstombs() - * function returns the number of bytes that were converted, - * not the number that should be converted. As a result, - * we can never accurately size the output buffer (without - * doing a tedious output size calculation in advance). - * This approach (try a conversion, then try again if it fails) - * will almost always succeed on the first try, and is thus - * much faster, at the cost of sometimes requiring multiple - * passes while we expand the buffer. - */ -static char * -wide_to_narrow(const wchar_t *wval) -{ - int converted_length; - /* Guess an output buffer size and try the conversion. */ - int alloc_length = wcslen(wval) * 3; - char *mbs_val = malloc(alloc_length + 1); - if (mbs_val == NULL) - return (NULL); - converted_length = wcstombs(mbs_val, wval, alloc_length); - - /* If we exhausted the buffer, resize and try again. */ - while (converted_length >= alloc_length) { - free(mbs_val); - alloc_length *= 2; - mbs_val = malloc(alloc_length + 1); - if (mbs_val == NULL) - return (NULL); - converted_length = wcstombs(mbs_val, wval, alloc_length); - } - - /* Ensure a trailing null and return the final string. */ - mbs_val[alloc_length] = '\0'; - return (mbs_val); -} - -static char * -url_decode(const char *in) -{ - char *out, *d; - const char *s; - - out = malloc(strlen(in) + 1); - if (out == NULL) - return (NULL); - for (s = in, d = out; *s != '\0'; ) { - if (*s == '%') { - /* Try to convert % escape */ - int digit1 = tohex(s[1]); - int digit2 = tohex(s[2]); - if (digit1 >= 0 && digit2 >= 0) { - /* Looks good, consume three chars */ - s += 3; - /* Convert output */ - *d++ = ((digit1 << 4) | digit2); - continue; - } - /* Else fall through and treat '%' as normal char */ - } - *d++ = *s++; - } - *d = '\0'; - return (out); -} - -static int -tohex(int c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - else if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - else if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - else - return (-1); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_zip.c b/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_zip.c deleted file mode 100644 index c1f456d53d..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_read_support_format_zip.c +++ /dev/null @@ -1,797 +0,0 @@ -/*- - * Copyright (c) 2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.8 2005/10/12 15:38:45 kientzle Exp $"); - -#include -#include -#include -#include -#include -#ifdef HAVE_ZLIB_H -#include -#endif - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct zip { - /* entry_bytes_remaining is the number of bytes we expect. */ - off_t entry_bytes_remaining; - off_t entry_offset; - - /* These count the number of bytes actually read for the entry. */ - off_t entry_compressed_bytes_read; - off_t entry_uncompressed_bytes_read; - - unsigned version; - unsigned system; - unsigned flags; - unsigned compression; - const char * compression_name; - time_t mtime; - time_t ctime; - time_t atime; - mode_t mode; - uid_t uid; - gid_t gid; - - /* Flags to mark progress of decompression. */ - char decompress_init; - char end_of_entry; - char end_of_entry_cleanup; - - long crc32; - ssize_t filename_length; - ssize_t extra_length; - off_t uncompressed_size; - off_t compressed_size; - - unsigned char *uncompressed_buffer; - size_t uncompressed_buffer_size; -#ifdef HAVE_ZLIB_H - z_stream stream; -#endif - - struct archive_string pathname; - struct archive_string extra; - char format_name[64]; -}; - -#define ZIP_LENGTH_AT_END 8 - -struct zip_file_header { - char signature[4]; - char version[2]; - char flags[2]; - char compression[2]; - char timedate[4]; - char crc32[4]; - char compressed_size[4]; - char uncompressed_size[4]; - char filename_length[2]; - char extra_length[2]; -}; - -static const char *compression_names[] = { - "uncompressed", - "shrinking", - "reduced-1", - "reduced-2", - "reduced-3", - "reduced-4", - "imploded", - "reserved", - "deflation" -}; - -static int archive_read_format_zip_bid(struct archive *); -static int archive_read_format_zip_cleanup(struct archive *); -static int archive_read_format_zip_read_data(struct archive *, - const void **, size_t *, off_t *); -static int archive_read_format_zip_read_data_skip(struct archive *a); -static int archive_read_format_zip_read_header(struct archive *, - struct archive_entry *); -static int i2(const char *); -static int i4(const char *); -static unsigned int u2(const char *); -static unsigned int u4(const char *); -static uint64_t u8(const char *); -static int zip_read_data_deflate(struct archive *a, const void **buff, - size_t *size, off_t *offset); -static int zip_read_data_none(struct archive *a, const void **buff, - size_t *size, off_t *offset); -static int zip_read_file_header(struct archive *a, - struct archive_entry *entry, struct zip *zip); -static time_t zip_time(const char *); -static void process_extra(const void* extra, struct zip* zip); - -int -archive_read_support_format_zip(struct archive *a) -{ - struct zip *zip; - int r; - - zip = malloc(sizeof(*zip)); - if (zip == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate zip data"); - return (ARCHIVE_FATAL); - } - memset(zip, 0, sizeof(*zip)); - - r = __archive_read_register_format(a, - zip, - archive_read_format_zip_bid, - archive_read_format_zip_read_header, - archive_read_format_zip_read_data, - archive_read_format_zip_read_data_skip, - archive_read_format_zip_cleanup); - - if (r != ARCHIVE_OK) - free(zip); - return (ARCHIVE_OK); -} - - -static int -archive_read_format_zip_bid(struct archive *a) -{ - int bytes_read; - int bid = 0; - const void *h; - const char *p; - - if (a->archive_format == ARCHIVE_FORMAT_ZIP) - bid += 1; - - bytes_read = (a->compression_read_ahead)(a, &h, 4); - if (bytes_read < 4) - return (-1); - p = h; - - if (p[0] == 'P' && p[1] == 'K') { - bid += 16; - if (p[2] == '\001' && p[3] == '\002') - bid += 16; - else if (p[2] == '\003' && p[3] == '\004') - bid += 16; - else if (p[2] == '\005' && p[3] == '\006') - bid += 16; - else if (p[2] == '\007' && p[3] == '\010') - bid += 16; - } - return (bid); -} - -static int -archive_read_format_zip_read_header(struct archive *a, - struct archive_entry *entry) -{ - int bytes_read; - const void *h; - const char *signature; - struct zip *zip; - - a->archive_format = ARCHIVE_FORMAT_ZIP; - if (a->archive_format_name == NULL) - a->archive_format_name = "ZIP"; - - zip = *(a->pformat_data); - zip->decompress_init = 0; - zip->end_of_entry = 0; - zip->end_of_entry_cleanup = 0; - zip->entry_uncompressed_bytes_read = 0; - zip->entry_compressed_bytes_read = 0; - bytes_read = (a->compression_read_ahead)(a, &h, 4); - if (bytes_read < 4) - return (ARCHIVE_FATAL); - - signature = h; - if (signature[0] != 'P' || signature[1] != 'K') { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Bad ZIP file"); - return (ARCHIVE_FATAL); - } - - if (signature[2] == '\001' && signature[3] == '\002') { - /* Beginning of central directory. */ - return (ARCHIVE_EOF); - } - - if (signature[2] == '\003' && signature[3] == '\004') { - /* Regular file entry. */ - return (zip_read_file_header(a, entry, zip)); - } - - if (signature[2] == '\005' && signature[3] == '\006') { - /* End-of-archive record. */ - return (ARCHIVE_EOF); - } - - if (signature[2] == '\007' && signature[3] == '\010') { - /* - * We should never encounter this record here; - * see ZIP_LENGTH_AT_END handling below for details. - */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Bad ZIP file: Unexpected end-of-entry record"); - return (ARCHIVE_FATAL); - } - - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Damaged ZIP file or unsupported format variant (%d,%d)", - signature[2], signature[3]); - return (ARCHIVE_FATAL); -} - -int -zip_read_file_header(struct archive *a, struct archive_entry *entry, - struct zip *zip) -{ - const struct zip_file_header *p; - const void *h; - int bytes_read; - struct stat st; - - bytes_read = - (a->compression_read_ahead)(a, &h, sizeof(struct zip_file_header)); - if (bytes_read < (int)sizeof(struct zip_file_header)) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file header"); - return (ARCHIVE_FATAL); - } - p = h; - - zip->version = p->version[0]; - zip->system = p->version[1]; - zip->flags = i2(p->flags); - zip->compression = i2(p->compression); - if (zip->compression < - sizeof(compression_names)/sizeof(compression_names[0])) - zip->compression_name = compression_names[zip->compression]; - else - zip->compression_name = "??"; - zip->mtime = zip_time(p->timedate); - zip->ctime = 0; - zip->atime = 0; - zip->mode = 0; - zip->uid = 0; - zip->gid = 0; - zip->crc32 = i4(p->crc32); - zip->filename_length = i2(p->filename_length); - zip->extra_length = i2(p->extra_length); - zip->uncompressed_size = u4(p->uncompressed_size); - zip->compressed_size = u4(p->compressed_size); - - (a->compression_read_consume)(a, sizeof(struct zip_file_header)); - - - /* Read the filename. */ - bytes_read = (a->compression_read_ahead)(a, &h, zip->filename_length); - if (bytes_read < zip->filename_length) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file header"); - return (ARCHIVE_FATAL); - } - archive_string_ensure(&zip->pathname, zip->filename_length); - archive_strncpy(&zip->pathname, h, zip->filename_length); - (a->compression_read_consume)(a, zip->filename_length); - archive_entry_set_pathname(entry, zip->pathname.s); - - if (zip->pathname.s[archive_strlen(&zip->pathname) - 1] == '/') - zip->mode = S_IFDIR | 0777; - else - zip->mode = S_IFREG | 0777; - - /* Read the extra data. */ - bytes_read = (a->compression_read_ahead)(a, &h, zip->extra_length); - if (bytes_read < zip->extra_length) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file header"); - return (ARCHIVE_FATAL); - } - process_extra(h, zip); - (a->compression_read_consume)(a, zip->extra_length); - - /* Populate some additional entry fields: */ - memset(&st, 0, sizeof(st)); - st.st_mode = zip->mode; - st.st_uid = zip->uid; - st.st_gid = zip->gid; - st.st_mtime = zip->mtime; - st.st_ctime = zip->ctime; - st.st_atime = zip->atime; - st.st_size = zip->uncompressed_size; - archive_entry_copy_stat(entry, &st); - - zip->entry_bytes_remaining = zip->compressed_size; - zip->entry_offset = 0; - - /* Set up a more descriptive format name. */ - sprintf(zip->format_name, "ZIP %d.%d (%s)", - zip->version / 10, zip->version % 10, - zip->compression_name); - a->archive_format_name = zip->format_name; - - return (ARCHIVE_OK); -} - -/* Convert an MSDOS-style date/time into Unix-style time. */ -static time_t -zip_time(const char *p) -{ - int msTime, msDate; - struct tm ts; - - msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]); - msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]); - - memset(&ts, 0, sizeof(ts)); - ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ - ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ - ts.tm_mday = msDate & 0x1f; /* Day of month. */ - ts.tm_hour = (msTime >> 11) & 0x1f; - ts.tm_min = (msTime >> 5) & 0x3f; - ts.tm_sec = (msTime << 1) & 0x3e; - ts.tm_isdst = -1; - return mktime(&ts); -} - -static int -archive_read_format_zip_read_data(struct archive *a, - const void **buff, size_t *size, off_t *offset) -{ - int r; - struct zip *zip; - - zip = *(a->pformat_data); - - /* - * If we hit end-of-entry last time, clean up and return - * ARCHIVE_EOF this time. - */ - if (zip->end_of_entry) { - if (!zip->end_of_entry_cleanup) { - if (zip->flags & ZIP_LENGTH_AT_END) { - const void *h; - const char *p; - int bytes_read = - (a->compression_read_ahead)(a, &h, 16); - if (bytes_read < 16) { - archive_set_error(a, - ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP end-of-file record"); - return (ARCHIVE_FATAL); - } - p = h; - zip->crc32 = i4(p + 4); - zip->compressed_size = u4(p + 8); - zip->uncompressed_size = u4(p + 12); - bytes_read = (a->compression_read_consume)(a, 16); - } - - /* Check file size, CRC against these values. */ - if (zip->compressed_size != zip->entry_compressed_bytes_read) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "ZIP compressed data is wrong size"); - return (ARCHIVE_WARN); - } - if (zip->uncompressed_size != zip->entry_uncompressed_bytes_read) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "ZIP uncompressed data is wrong size"); - return (ARCHIVE_WARN); - } -/* TODO: Compute CRC. */ -/* - if (zip->crc32 != zip->entry_crc32_calculated) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "ZIP data CRC error"); - return (ARCHIVE_WARN); - } -*/ - /* End-of-entry cleanup done. */ - zip->end_of_entry_cleanup = 1; - } - return (ARCHIVE_EOF); - } - - switch(zip->compression) { - case 0: /* No compression. */ - r = zip_read_data_none(a, buff, size, offset); - break; - case 8: /* Deflate compression. */ - r = zip_read_data_deflate(a, buff, size, offset); - break; - default: /* Unsupported compression. */ - *buff = NULL; - *size = 0; - *offset = 0; - /* Return a warning. */ - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Unsupported ZIP compression method (%s)", - zip->compression_name); - if (zip->flags & ZIP_LENGTH_AT_END) { - /* - * ZIP_LENGTH_AT_END requires us to - * decompress the entry in order to - * skip it, but we don't know this - * compression method, so we give up. - */ - r = ARCHIVE_FATAL; - } else { - /* We know compressed size; just skip it. */ - archive_read_format_zip_read_data_skip(a); - r = ARCHIVE_WARN; - } - break; - } - return (r); -} - -/* - * Read "uncompressed" data. According to the current specification, - * if ZIP_LENGTH_AT_END is specified, then the size fields in the - * initial file header are supposed to be set to zero. This would, of - * course, make it impossible for us to read the archive, since we - * couldn't determine the end of the file data. Info-ZIP seems to - * include the real size fields both before and after the data in this - * case (the CRC only appears afterwards), so this works as you would - * expect. - * - * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets - * zip->end_of_entry if it consumes all of the data. - */ -static int -zip_read_data_none(struct archive *a, const void **buff, - size_t *size, off_t *offset) -{ - struct zip *zip; - ssize_t bytes_avail; - - zip = *(a->pformat_data); - - if (zip->entry_bytes_remaining == 0) { - *buff = NULL; - *size = 0; - *offset = zip->entry_offset; - zip->end_of_entry = 1; - return (ARCHIVE_OK); - } - /* - * Note: '1' here is a performance optimization. - * Recall that the decompression layer returns a count of - * available bytes; asking for more than that forces the - * decompressor to combine reads by copying data. - */ - bytes_avail = (a->compression_read_ahead)(a, buff, 1); - if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file data"); - return (ARCHIVE_FATAL); - } - if (bytes_avail > zip->entry_bytes_remaining) - bytes_avail = zip->entry_bytes_remaining; - (a->compression_read_consume)(a, bytes_avail); - *size = bytes_avail; - *offset = zip->entry_offset; - zip->entry_offset += *size; - zip->entry_bytes_remaining -= *size; - zip->entry_uncompressed_bytes_read += *size; - zip->entry_compressed_bytes_read += *size; - return (ARCHIVE_OK); -} - -#ifdef HAVE_ZLIB_H -static int -zip_read_data_deflate(struct archive *a, const void **buff, - size_t *size, off_t *offset) -{ - struct zip *zip; - ssize_t bytes_avail; - const void *compressed_buff; - int r; - - zip = *(a->pformat_data); - - /* If the buffer hasn't been allocated, allocate it now. */ - if (zip->uncompressed_buffer == NULL) { - zip->uncompressed_buffer_size = 32 * 1024; - zip->uncompressed_buffer - = malloc(zip->uncompressed_buffer_size); - if (zip->uncompressed_buffer == NULL) { - archive_set_error(a, ENOMEM, - "No memory for ZIP decompression"); - return (ARCHIVE_FATAL); - } - } - - /* If we haven't yet read any data, initialize the decompressor. */ - if (!zip->decompress_init) { - r = inflateInit2(&zip->stream, - -15 /* Don't check for zlib header */); - if (r != Z_OK) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Can't initialize ZIP decompression."); - return (ARCHIVE_FATAL); - } - zip->decompress_init = 1; - } - - /* - * Note: '1' here is a performance optimization. - * Recall that the decompression layer returns a count of - * available bytes; asking for more than that forces the - * decompressor to combine reads by copying data. - */ - bytes_avail = (a->compression_read_ahead)(a, &compressed_buff, 1); - if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file body"); - return (ARCHIVE_FATAL); - } - - /* - * A bug in zlib.h: stream.next_in should be marked 'const' - * but isn't (the library never alters data through the - * next_in pointer, only reads it). The result: this ugly - * cast to remove 'const'. - */ - zip->stream.next_in = (void *)(uintptr_t)(const void *)compressed_buff; - zip->stream.avail_in = bytes_avail; - zip->stream.total_in = 0; - zip->stream.next_out = zip->uncompressed_buffer; - zip->stream.avail_out = zip->uncompressed_buffer_size; - zip->stream.total_out = 0; - - r = inflate(&zip->stream, 0); - switch (r) { - case Z_OK: - break; - case Z_STREAM_END: - zip->end_of_entry = 1; - break; - case Z_MEM_ERROR: - archive_set_error(a, ENOMEM, - "Out of memory for ZIP decompression"); - return (ARCHIVE_FATAL); - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "ZIP decompression failed (%d)", r); - return (ARCHIVE_FATAL); - } - - /* Consume as much as the compressor actually used. */ - bytes_avail = zip->stream.total_in; - (a->compression_read_consume)(a, bytes_avail); - zip->entry_bytes_remaining -= bytes_avail; - zip->entry_compressed_bytes_read += bytes_avail; - - *offset = zip->entry_offset; - *size = zip->stream.total_out; - zip->entry_uncompressed_bytes_read += *size; - *buff = zip->uncompressed_buffer; - zip->entry_offset += *size; - return (ARCHIVE_OK); -} -#else -static int -zip_read_data_deflate(struct archive *a, const void **buff, - size_t *size, off_t *offset) -{ - int r; - - *buff = NULL; - *size = 0; - *offset = 0; - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "libarchive compiled without deflate support (no libz)"); - return (ARCHIVE_FATAL); -} -#endif - -static int -archive_read_format_zip_read_data_skip(struct archive *a) -{ - struct zip *zip; - const void *buff = NULL; - ssize_t bytes_avail; - - zip = *(a->pformat_data); - - /* - * If the length is at the end, we have no choice but - * to decompress all the data to find the end marker. - */ - if (zip->flags & ZIP_LENGTH_AT_END) { - size_t size; - off_t offset; - int r; - do { - r = archive_read_format_zip_read_data(a, &buff, - &size, &offset); - } while (r == ARCHIVE_OK); - return (r); - } - - /* - * If the length is at the beginning, we can skip the - * compressed data much more quickly. - */ - while (zip->entry_bytes_remaining > 0) { - bytes_avail = (a->compression_read_ahead)(a, &buff, 1); - if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated ZIP file body"); - return (ARCHIVE_FATAL); - } - if (bytes_avail > zip->entry_bytes_remaining) - bytes_avail = zip->entry_bytes_remaining; - (a->compression_read_consume)(a, bytes_avail); - zip->entry_bytes_remaining -= bytes_avail; - } - /* This entry is finished and done. */ - zip->end_of_entry_cleanup = zip->end_of_entry = 1; - return (ARCHIVE_OK); -} - -static int -archive_read_format_zip_cleanup(struct archive *a) -{ - struct zip *zip; - - zip = *(a->pformat_data); - if (zip->uncompressed_buffer != NULL) - free(zip->uncompressed_buffer); - archive_string_free(&(zip->pathname)); - archive_string_free(&(zip->extra)); - free(zip); - *(a->pformat_data) = NULL; - return (ARCHIVE_OK); -} - -static int -i2(const char *p) -{ - return ((0xff & (int)p[0]) + 256 * (0xff & (int)p[1])); -} - - -static int -i4(const char *p) -{ - return ((0xffff & i2(p)) + 0x10000 * (0xffff & i2(p+2))); -} - -static unsigned int -u2(const char *p) -{ - return ((0xff & (unsigned int)p[0]) + 256 * (0xff & (unsigned int)p[1])); -} - -static unsigned int -u4(const char *p) -{ - return u2(p) + 0x10000 * u2(p+2); -} - -static uint64_t -u8(const char *p) -{ - return u4(p) + 0x100000000LL * u4(p+4); -} - -/* - * The extra data is stored as a list of - * id1+size1+data1 + id2+size2+data2 ... - * triplets. id and size are 2 bytes each. - */ -static void -process_extra(const void* extra, struct zip* zip) -{ - int offset = 0; - const char *p = extra; - while (offset < zip->extra_length - 4) - { - unsigned short headerid = u2(p + offset); - unsigned short datasize = u2(p + offset + 2); - offset += 4; - if (offset + datasize > zip->extra_length) - break; -#ifdef DEBUG - fprintf(stderr, "Header id 0x%04x, length %d\n", - headerid, datasize); -#endif - switch (headerid) { - case 0x0001: - /* Zip64 extended information extra field. */ - if (datasize >= 8) - zip->uncompressed_size = u8(p + offset); - if (datasize >= 16) - zip->compressed_size = u8(p + offset + 8); - break; - case 0x5455: - { - /* Extended time field "UT". */ - int flags = p[offset]; - offset++; - datasize--; - /* Flag bits indicate which dates are present. */ - if (flags & 0x01) - { -#ifdef DEBUG - fprintf(stderr, "mtime: %d -> %d\n", - zip->mtime, i4(p + offset)); -#endif - if (datasize < 4) - break; - zip->mtime = i4(p + offset); - offset += 4; - datasize -= 4; - } - if (flags & 0x02) - { - if (datasize < 4) - break; - zip->atime = i4(p + offset); - offset += 4; - datasize -= 4; - } - if (flags & 0x04) - { - if (datasize < 4) - break; - zip->ctime = i4(p + offset); - offset += 4; - datasize -= 4; - } - break; - } - case 0x7855: - /* Info-ZIP Unix Extra Field (type 2) "Ux". */ -#ifdef DEBUG - fprintf(stderr, "uid %d gid %d\n", - i2(p + offset), i2(p + offset + 2)); -#endif - if (datasize >= 2) - zip->uid = i2(p + offset); - if (datasize >= 4) - zip->gid = i2(p + offset + 2); - break; - default: - break; - } - offset += datasize; - } -#ifdef DEBUG - if (offset != zip->extra_length) - { - fprintf(stderr, - "Extra data field contents do not match reported size!"); - } -#endif -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_string.c b/contrib/libarchive-1.3.1/libarchive/archive_string.c deleted file mode 100644 index 2227afc148..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_string.c +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_string.c,v 1.6 2004/12/22 06:12:40 kientzle Exp $"); - -/* - * Basic resizable string support, to simplify manipulating arbitrary-sized - * strings while minimizing heap activity. - */ - -#include -#include - -#include "archive_private.h" -#include "archive_string.h" - -struct archive_string * -__archive_string_append(struct archive_string *as, const char *p, size_t s) -{ - __archive_string_ensure(as, as->length + s + 1); - memcpy(as->s + as->length, p, s); - as->s[as->length + s] = 0; - as->length += s; - return (as); -} - -void -__archive_string_free(struct archive_string *as) -{ - as->length = 0; - as->buffer_length = 0; - if (as->s != NULL) - free(as->s); -} - -struct archive_string * -__archive_string_ensure(struct archive_string *as, size_t s) -{ - if (as->s && (s <= as->buffer_length)) - return (as); - - if (as->buffer_length < 32) - as->buffer_length = 32; - while (as->buffer_length < s) - as->buffer_length *= 2; - as->s = realloc(as->s, as->buffer_length); - /* TODO: Return null instead and fix up all of our callers to - * handle this correctly. */ - if (as->s == NULL) - __archive_errx(1, "Out of memory"); - return (as); -} - -struct archive_string * -__archive_strncat(struct archive_string *as, const char *p, size_t n) -{ - size_t s; - const char *pp; - - /* Like strlen(p), except won't examine positions beyond p[n]. */ - s = 0; - pp = p; - while (*pp && s < n) { - pp++; - s++; - } - return (__archive_string_append(as, p, s)); -} - -struct archive_string * -__archive_strappend_char(struct archive_string *as, char c) -{ - return (__archive_string_append(as, &c, 1)); -} - -struct archive_string * -__archive_strappend_int(struct archive_string *as, int d, int base) -{ - static const char *digits = "0123457890abcdef"; - - if (d < 0) { - __archive_strappend_char(as, '-'); - d = -d; - } - if (d >= base) - __archive_strappend_int(as, d/base, base); - __archive_strappend_char(as, digits[d % base]); - return (as); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_string.h b/contrib/libarchive-1.3.1/libarchive/archive_string.h deleted file mode 100644 index b8b3b598f2..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_string.h +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/lib/libarchive/archive_string.h,v 1.6 2005/01/16 22:13:51 kientzle Exp $ - * - */ - -#ifndef ARCHIVE_STRING_H_INCLUDED -#define ARCHIVE_STRING_H_INCLUDED - -#include -#include - -/* - * Basic resizable/reusable string support a la Java's "StringBuffer." - * - * Unlike sbuf(9), the buffers here are fully reusable and track the - * length throughout. - * - * Note that all visible symbols here begin with "__archive" as they - * are internal symbols not intended for anyone outside of this library - * to see or use. - */ - -struct archive_string { - char *s; /* Pointer to the storage */ - size_t length; /* Length of 's' */ - size_t buffer_length; /* Length of malloc-ed storage */ -}; - -/* Initialize an archive_string object on the stack or elsewhere. */ -#define archive_string_init(a) \ - do { (a)->s = NULL; (a)->length = 0; (a)->buffer_length = 0; } while(0) - -/* Append a C char to an archive_string, resizing as necessary. */ -struct archive_string * -__archive_strappend_char(struct archive_string *, char); -#define archive_strappend_char __archive_strappend_char - -/* Append a char to an archive_string using UTF8. */ -struct archive_string * -__archive_strappend_char_UTF8(struct archive_string *, int); -#define archive_strappend_char_UTF8 __archive_strappend_char_UTF8 - -/* Append an integer in the specified base (2 <= base <= 16). */ -struct archive_string * -__archive_strappend_int(struct archive_string *as, int d, int base); -#define archive_strappend_int __archive_strappend_int - -/* Basic append operation. */ -struct archive_string * -__archive_string_append(struct archive_string *as, const char *p, size_t s); - -/* Ensure that the underlying buffer is at least as large as the request. */ -struct archive_string * -__archive_string_ensure(struct archive_string *, size_t); -#define archive_string_ensure __archive_string_ensure - -/* Append C string, which may lack trailing \0. */ -struct archive_string * -__archive_strncat(struct archive_string *, const char *, size_t); -#define archive_strncat __archive_strncat - -/* Append a C string to an archive_string, resizing as necessary. */ -#define archive_strcat(as,p) __archive_string_append((as),(p),strlen(p)) - -/* Copy a C string to an archive_string, resizing as necessary. */ -#define archive_strcpy(as,p) \ - ((as)->length = 0, __archive_string_append((as), (p), strlen(p))) - -/* Copy a C string to an archive_string with limit, resizing as necessary. */ -#define archive_strncpy(as,p,l) \ - ((as)->length=0, archive_strncat((as), (p), (l))) - -/* Return length of string. */ -#define archive_strlen(a) ((a)->length) - -/* Set string length to zero. */ -#define archive_string_empty(a) ((a)->length = 0) - -/* Release any allocated storage resources. */ -void __archive_string_free(struct archive_string *); -#define archive_string_free __archive_string_free - -/* Like 'vsprintf', but resizes the underlying string as necessary. */ -void __archive_string_vsprintf(struct archive_string *, const char *, - va_list); -#define archive_string_vsprintf __archive_string_vsprintf - -#endif diff --git a/contrib/libarchive-1.3.1/libarchive/archive_string_sprintf.c b/contrib/libarchive-1.3.1/libarchive/archive_string_sprintf.c deleted file mode 100644 index 63a06d7248..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_string_sprintf.c +++ /dev/null @@ -1,129 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_string_sprintf.c,v 1.7 2005/01/16 22:13:51 kientzle Exp $"); - -/* - * The use of printf()-family functions can be troublesome - * for space-constrained applications. In addition, correctly - * implementing this function in terms of vsnprintf() requires - * two calls (one to determine the size, another to format the - * result), which in turn requires duplicating the argument list - * using va_copy, which isn't yet universally available. - * - * So, I've implemented a bare minimum of printf()-like capability - * here. This is only used to format error messages, so doesn't - * require any floating-point support or field-width handling. - */ - -#include - -#include "archive_string.h" - -/* - * Like 'vsprintf', but ensures the target is big enough, resizing if - * necessary. - */ -void -__archive_string_vsprintf(struct archive_string *as, const char *fmt, - va_list ap) -{ - char long_flag; - intmax_t s; /* Signed integer temp. */ - uintmax_t u; /* Unsigned integer temp. */ - const char *p, *p2; - - __archive_string_ensure(as, 64); - - if (fmt == NULL) { - as->s[0] = 0; - return; - } - - long_flag = '\0'; - for (p = fmt; *p != '\0'; p++) { - const char *saved_p = p; - - if (*p != '%') { - archive_strappend_char(as, *p); - continue; - } - - p++; - - switch(*p) { - case 'j': - long_flag = 'j'; - p++; - break; - case 'l': - long_flag = 'l'; - p++; - break; - } - - switch (*p) { - case '%': - __archive_strappend_char(as, '%'); - break; - case 'c': - s = va_arg(ap, int); - __archive_strappend_char(as, s); - break; - case 'd': - switch(long_flag) { - case 'j': s = va_arg(ap, intmax_t); break; - case 'l': s = va_arg(ap, long); break; - default: s = va_arg(ap, int); break; - } - archive_strappend_int(as, s, 10); - break; - case 's': - p2 = va_arg(ap, char *); - archive_strcat(as, p2); - break; - case 'o': case 'u': case 'x': case 'X': - /* Common handling for unsigned integer formats. */ - switch(long_flag) { - case 'j': u = va_arg(ap, uintmax_t); break; - case 'l': u = va_arg(ap, unsigned long); break; - default: u = va_arg(ap, unsigned int); break; - } - /* Format it in the correct base. */ - switch (*p) { - case 'o': archive_strappend_int(as, u, 8); break; - case 'u': archive_strappend_int(as, u, 10); break; - default: archive_strappend_int(as, u, 16); break; - } - break; - default: - /* Rewind and print the initial '%' literally. */ - p = saved_p; - archive_strappend_char(as, *p); - } - } -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_util.3 b/contrib/libarchive-1.3.1/libarchive/archive_util.3 deleted file mode 100644 index 9a4517c3e2..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_util.3 +++ /dev/null @@ -1,135 +0,0 @@ -.\" Copyright (c) 2003-2004 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 AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/archive_util.3,v 1.4 2005/11/24 10:06:05 ru Exp $ -.\" -.Dd January 8, 2005 -.Dt archive_util 3 -.Os -.Sh NAME -.Nm archive_compression , -.Nm archive_compression_name , -.Nm archive_errno , -.Nm archive_error_string , -.Nm archive_format , -.Nm archive_format_name , -.Nm archive_set_error -.Nd libarchive utility functions -.Sh SYNOPSIS -.In archive.h -.Ft int -.Fn archive_compression "struct archive *" -.Ft const char * -.Fn archive_compression_name "struct archive *" -.Ft int -.Fn archive_errno "struct archive *" -.Ft const char * -.Fn archive_error_string "struct archive *" -.Ft int -.Fn archive_format "struct archive *" -.Ft const char * -.Fn archive_format_name "struct archive *" -.Ft void -.Fn archive_set_error "struct archive *" "int error_code" "const char *fmt" "..." -.Sh DESCRIPTION -These functions provide access to various information about the -.Tn struct archive -object used in the -.Xr libarchive 3 -library. -.Bl -tag -compact -width indent -.It Fn archive_compression -Returns a numeric code indicating the current compression. -This value is set by -.Fn archive_read_open . -.It Fn archive_compression_name -Returns a text description of the current compression suitable for display. -.It Fn archive_errno -Returns a numeric error code (see -.Xr errno 2 ) -indicating the reason for the most recent error return. -.It Fn archive_error_string -Returns a textual error message suitable for display. -The error message here is usually more specific than that -obtained from passing the result of -.Fn archive_errno -to -.Xr strerror 3 . -.It Fn archive_format -Returns a numeric code indicating the format of the current -archive entry. -This value is set by a successful call to -.Fn archive_read_next_header . -Note that it is common for this value to change from -entry to entry. -For example, a tar archive might have several entries that -utilize GNU tar extensions and several entries that do not. -These entries will have different format codes. -.It Fn archive_format_name -A textual description of the format of the current entry. -.It Fn archive_set_error -Sets the numeric error code and error description that will be returned -by -.Fn archive_errno -and -.Fn archive_error_string . -This function should be used within I/O callbacks to set system-specific -error codes and error descriptions. -This function accepts a printf-like format string and arguments. -However, you should be careful to use only the following printf -format specifiers: -.Dq %c , -.Dq %d , -.Dq %jd , -.Dq %jo , -.Dq %ju , -.Dq %jx , -.Dq %ld , -.Dq %lo , -.Dq %lu , -.Dq %lx , -.Dq %o , -.Dq %u , -.Dq %s , -.Dq %x , -.Dq %% . -Field-width specifiers and other printf features are -not uniformly supported and should not be used. -.El -.Sh SEE ALSO -.Xr archive_read 3 , -.Xr archive_write 3 , -.Xr libarchive 3 , -.Xr printf 3 -.Sh HISTORY -The -.Nm libarchive -library first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm libarchive -library was written by -.An Tim Kientzle Aq kientzle@acm.org . diff --git a/contrib/libarchive-1.3.1/libarchive/archive_util.c b/contrib/libarchive-1.3.1/libarchive/archive_util.c deleted file mode 100644 index 0d275060ea..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_util.c +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_util.c,v 1.10 2005/09/21 04:25:05 kientzle Exp $"); - -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -int -archive_api_feature(void) -{ - return (ARCHIVE_API_FEATURE); -} - -int -archive_api_version(void) -{ - return (ARCHIVE_API_VERSION); -} - -const char * -archive_version(void) -{ - return (PACKAGE_NAME " " PACKAGE_VERSION); -} - -int -archive_errno(struct archive *a) -{ - return (a->archive_error_number); -} - -const char * -archive_error_string(struct archive *a) -{ - - if (a->error != NULL && *a->error != '\0') - return (a->error); - else - return ("(Empty error message)"); -} - - -int -archive_format(struct archive *a) -{ - return (a->archive_format); -} - -const char * -archive_format_name(struct archive *a) -{ - return (a->archive_format_name); -} - - -int -archive_compression(struct archive *a) -{ - return (a->compression_code); -} - -const char * -archive_compression_name(struct archive *a) -{ - return (a->compression_name); -} - - -/* - * Return a count of the number of compressed bytes processed. - */ -int64_t -archive_position_compressed(struct archive *a) -{ - return (a->raw_position); -} - -/* - * Return a count of the number of uncompressed bytes processed. - */ -int64_t -archive_position_uncompressed(struct archive *a) -{ - return (a->file_position); -} - - -void -archive_set_error(struct archive *a, int error_number, const char *fmt, ...) -{ - va_list ap; -#ifdef HAVE_STRERROR_R - char errbuff[512]; -#endif - char *errp; - - a->archive_error_number = error_number; - if (fmt == NULL) { - a->error = NULL; - return; - } - - va_start(ap, fmt); - archive_string_vsprintf(&(a->error_string), fmt, ap); - if (error_number > 0) { - archive_strcat(&(a->error_string), ": "); -#ifdef HAVE_STRERROR_R -#ifdef STRERROR_R_CHAR_P - errp = strerror_r(error_number, errbuff, sizeof(errbuff)); -#else - strerror_r(error_number, errbuff, sizeof(errbuff)); - errp = errbuff; -#endif -#else - /* Note: this is not threadsafe! */ - errp = strerror(error_number); -#endif - archive_strcat(&(a->error_string), errp); - } - a->error = a->error_string.s; - va_end(ap); -} - -void -__archive_errx(int retvalue, const char *msg) -{ - static const char *msg1 = "Fatal Internal Error in libarchive: "; - write(2, msg1, strlen(msg1)); - write(2, msg, strlen(msg)); - write(2, "\n", 1); - exit(retvalue); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write.3 b/contrib/libarchive-1.3.1/libarchive/archive_write.3 deleted file mode 100644 index e7aec4b90b..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write.3 +++ /dev/null @@ -1,490 +0,0 @@ -.\" 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/archive_write.3,v 1.13 2005/11/24 10:06:05 ru Exp $ -.\" -.Dd August 19, 2006 -.Dt archive_write 3 -.Os -.Sh NAME -.Nm archive_write_new , -.Nm archive_write_set_format_cpio , -.Nm archive_write_set_format_pax , -.Nm archive_write_set_format_pax_restricted , -.Nm archive_write_set_format_shar , -.Nm archive_write_set_format_shar_binary , -.Nm archive_write_set_format_ustar , -.Nm archive_write_set_bytes_per_block , -.Nm archive_write_set_bytes_in_last_block , -.Nm archive_write_set_compressor_gzip , -.Nm archive_write_set_compressor_bzip2 , -.Nm archive_write_open , -.Nm archive_write_open_fd , -.Nm archive_write_open_FILE , -.Nm archive_write_open_filename , -.Nm archive_write_open_memory , -.Nm archive_write_prepare , -.Nm archive_write_header , -.Nm archive_write_data , -.Nm archive_write_close , -.Nm archive_write_finish -.Nd functions for creating archives -.Sh SYNOPSIS -.In archive.h -.Ft struct archive * -.Fn archive_write_new "void" -.Ft int -.Fn archive_write_set_bytes_per_block "struct archive *" "int bytes_per_block" -.Ft int -.Fn archive_write_set_bytes_in_last_block "struct archive *" "int" -.Ft int -.Fn archive_write_set_compressor_gzip "struct archive *" -.Ft int -.Fn archive_write_set_compressor_bzip2 "struct archive *" -.Ft int -.Fn archive_write_set_format_cpio "struct archive *" -.Ft int -.Fn archive_write_set_format_pax "struct archive *" -.Ft int -.Fn archive_write_set_format_pax_restricted "struct archive *" -.Ft int -.Fn archive_write_set_format_shar "struct archive *" -.Ft int -.Fn archive_write_set_format_shar_binary "struct archive *" -.Ft int -.Fn archive_write_set_format_ustar "struct archive *" -.Ft int -.Fn archive_write_open "struct archive *" "void *client_data" "archive_open_callback *" "archive_write_callback *" "archive_close_callback *" -.Ft int -.Fn archive_write_open_fd "struct archive *" "int fd" -.Ft int -.Fn archive_write_open_FILE "struct archive *" "FILE *file" -.Ft int -.Fn archive_write_open_filename "struct archive *" "const char *filename" -.Ft int -.Fn archive_write_open_memory "struct archive *" "void *buffer" "size_t bufferSize" "size_t *outUsed" -.Ft int -.Fn archive_write_header "struct archive *" "struct archive_entry *" -.Ft ssize_t -.Fn archive_write_data "struct archive *" "const void *" "size_t" -.Ft int -.Fn archive_write_close "struct archive *" -.Ft int -.Fn archive_write_finish "struct archive *" -.Sh DESCRIPTION -These functions provide a complete API for creating streaming -archive files. -The general process is to first create the -.Tn struct archive -object, set any desired options, initialize the archive, append entries, then -close the archive and release all resources. -The following summary describes the functions in approximately -the order they are ordinarily used: -.Bl -tag -width indent -.It Fn archive_write_new -Allocates and initializes a -.Tn struct archive -object suitable for writing a tar archive. -.It Fn archive_write_set_bytes_per_block -Sets the block size used for writing the archive data. -Every call to the write callback function, except possibly the last one, will -use this value for the length. -The third parameter is a boolean that specifies whether or not the final block -written will be padded to the full block size. -If it is zero, the last block will not be padded. -If it is non-zero, padding will be added both before and after compression. -The default is to use a block size of 10240 bytes and to pad the last block. -.It Fn archive_write_set_bytes_in_last_block -Sets the block size used for writing the last block. -If this value is zero, the last block will be padded to the same size -as the other blocks. -Otherwise, the final block will be padded to a multiple of this size. -In particular, setting it to 1 will cause the final block to not be padded. -For compressed output, any padding generated by this option -is applied only after the compression. -The uncompressed data is always unpadded. -The default is to pad the last block to the full block size (note that -.Fn archive_write_open_file -will set this based on the file type). -Unlike the other -.Dq set -functions, this function can be called after the archive is opened. -.It Fn archive_write_set_format_cpio , Fn archive_write_set_format_pax , Fn archive_write_set_format_pax_restricted , Fn archive_write_set_format_shar , Fn archive_write_set_format_shar_binary , Fn archive_write_set_format_ustar -Sets the format that will be used for the archive. -The library can write -POSIX octet-oriented cpio format archives, -POSIX-standard -.Dq pax interchange -format archives, -traditional -.Dq shar -archives, -enhanced -.Dq binary -shar archives that store a variety of file attributes and handle binary files, -and -POSIX-standard -.Dq ustar -archives. -The pax interchange format is a backwards-compatible tar format that -adds key/value attributes to each entry and supports arbitrary -filenames, linknames, uids, sizes, etc. -.Dq Restricted pax interchange format -is the library default; this is the same as pax format, but suppresses -the pax extended header for most normal files. -In most cases, this will result in ordinary ustar archives. -.It Fn archive_write_set_compression_gzip , Fn archive_write_set_compression_bzip2 -The resulting archive will be compressed as specified. -Note that the compressed output is always properly blocked. -.It Fn archive_write_open -Freeze the settings, open the archive, and prepare for writing entries. -This is the most generic form of this function, which accepts -pointers to three callback functions which will be invoked by -the compression layer to write the constructed archive. -.It Fn archive_write_open_fd -A convenience form of -.Fn archive_write_open -that accepts a file descriptor. -The -.It Fn archive_write_open_FILE -A convenience form of -.Fn archive_write_open -that accepts a -.Ft "FILE *" -pointer. -Note that -.Fn archive_write_open_FILE -is not safe for writing to tape drives or other devices -that require correct blocking. -.Fn archive_write_open_fd -function is safe for use with tape drives or other -block-oriented devices. -.It Fn archive_write_open_file -A deprecated synonym for -.Fn archive_write_open_filename . -.It Fn archive_write_open_filename -A convenience form of -.Fn archive_write_open -that accepts a filename. -A NULL argument indicates that the output should be written to standard output; -an argument of -.Dq - -will open a file with that name. -If you have not invoked -.Fn archive_write_set_bytes_in_last_block , -then -.Fn archive_write_open_filename -will adjust the last-block padding depending on the file: -it will enable padding when writing to standard output or -to a character or block device node, it will disable padding otherwise. -You can override this by manually invoking -.Fn archive_write_set_bytes_in_last_block -either before or after calling -.Fn archive_write_open . -The -.Fn archive_write_open_filename -function is safe for use with tape drives or other -block-oriented devices. -.It Fn archive_write_open_memory -A convenience form of -.Fn archive_write_open -that accepts a pointer to a block of memory that will receive -the archive. -The final -.Ft "size_t *" -argument points to a variable that will be updated -after each write to reflect how much of the buffer -is currently in use. -You should be careful to ensure that this variable -remains allocated until after the archive is -closed. -.It Fn archive_write_header -Build and write a header using the data in the provided -.Tn struct archive_entry -structure. -See -.Xr archive_entry 3 -for information on creating and populating -.Tn struct archive_entry -objects. -.It Fn archive_write_data -Write data corresponding to the header just written. -Returns number of bytes written or -1 on error. -.It Fn archive_write_close -Complete the archive and invoke the close callback. -.It Fn archive_write_finish -Invokes -.Fn archive_write_close -if it was not invoked manually, then releases all resources. -Note that this function was declared to return -.Ft void -in libarchive 1.x, which made it impossible to detect errors when -.Fn archive_write_close -was invoked implicitly from this function. -This is corrected beginning with libarchive 2.0. -.El -More information about the -.Va struct archive -object and the overall design of the library can be found in the -.Xr libarchive 3 -overview. -.Sh IMPLEMENTATION -Compression support is built-in to libarchive, which uses zlib and bzlib -to handle gzip and bzip2 compression, respectively. -.Sh CLIENT CALLBACKS -To use this library, you will need to define and register -callback functions that will be invoked to write data to the -resulting archive. -These functions are registered by calling -.Fn archive_write_open : -.Bl -item -offset indent -.It -.Ft typedef int -.Fn archive_open_callback "struct archive *" "void *client_data" -.El -.Pp -The open callback is invoked by -.Fn archive_write_open . -It should return -.Cm ARCHIVE_OK -if the underlying file or data source is successfully -opened. -If the open fails, it should call -.Fn archive_set_error -to register an error code and message and return -.Cm ARCHIVE_FATAL . -.Bl -item -offset indent -.It -.Ft typedef ssize_t -.Fn archive_write_callback "struct archive *" "void *client_data" "void *buffer" "size_t length" -.El -.Pp -The write callback is invoked whenever the library -needs to write raw bytes to the archive. -For correct blocking, each call to the write callback function -should translate into a single -.Xr write 2 -system call. -This is especially critical when writing archives to tape drives. -On success, the write callback should return the -number of bytes actually written. -On error, the callback should invoke -.Fn archive_set_error -to register an error code and message and return -1. -.Bl -item -offset indent -.It -.Ft typedef int -.Fn archive_close_callback "struct archive *" "void *client_data" -.El -.Pp -The close callback is invoked by archive_close when -the archive processing is complete. -The callback should return -.Cm ARCHIVE_OK -on success. -On failure, the callback should invoke -.Fn archive_set_error -to register an error code and message and -regurn -.Cm ARCHIVE_FATAL. -.Sh EXAMPLE -The following sketch illustrates basic usage of the library. -In this example, -the callback functions are simply wrappers around the standard -.Xr open 2 , -.Xr write 2 , -and -.Xr close 2 -system calls. -.Bd -literal -offset indent -#include -#include -#include -#include -#include -#include - -struct mydata { - const char *name; - int fd; -}; - -int -myopen(struct archive *a, void *client_data) -{ - struct mydata *mydata = client_data; - - mydata->fd = open(mydata->name, O_WRONLY | O_CREAT, 0644); - if (mydata->fd >= 0) - return (ARCHIVE_OK); - else - return (ARCHIVE_FATAL); -} - -ssize_t -mywrite(struct archive *a, void *client_data, void *buff, size_t n) -{ - struct mydata *mydata = client_data; - - return (write(mydata->fd, buff, n)); -} - -int -myclose(struct archive *a, void *client_data) -{ - struct mydata *mydata = client_data; - - if (mydata->fd > 0) - close(mydata->fd); - return (0); -} - -void -write_archive(const char *outname, const char **filename) -{ - struct mydata *mydata = malloc(sizeof(struct mydata)); - struct archive *a; - struct archive_entry *entry; - struct stat st; - char buff[8192]; - int len; - int fd; - - a = archive_write_new(); - mydata->name = outname; - archive_write_set_compression_gzip(a); - archive_write_set_format_ustar(a); - archive_write_open(a, mydata, myopen, mywrite, myclose); - while (*filename) { - stat(*filename, &st); - entry = archive_entry_new(); - archive_entry_copy_stat(entry, &st); - archive_entry_set_pathname(entry, *filename); - archive_write_header(a, entry); - fd = open(*filename, O_RDONLY); - len = read(fd, buff, sizeof(buff)); - while ( len > 0 ) { - archive_write_data(a, buff, len); - len = read(fd, buff, sizeof(buff)); - } - archive_entry_free(entry); - filename++; - } - archive_write_finish(a); -} - -int main(int argc, const char **argv) -{ - const char *outname; - argv++; - outname = argv++; - write_archive(outname, argv); - return 0; -} -.Ed -.Sh RETURN VALUES -Most functions return -.Cm ARCHIVE_OK -(zero) on success, or one of several non-zero -error codes for errors. -Specific error codes include: -.Cm ARCHIVE_RETRY -for operations that might succeed if retried, -.Cm ARCHIVE_WARN -for unusual conditions that do not prevent further operations, and -.Cm ARCHIVE_FATAL -for serious errors that make remaining operations impossible. -The -.Fn archive_errno -and -.Fn archive_error_string -functions can be used to retrieve an appropriate error code and a -textual error message. -.Pp -.Fn archive_write_new -returns a pointer to a newly-allocated -.Tn struct archive -object. -.Pp -.Fn archive_write_data -returns a count of the number of bytes actually written. -On error, -1 is returned and the -.Fn archive_errno -and -.Fn archive_error_string -functions will return appropriate values. -Note that if the client-provided write callback function -returns a non-zero value, that error will be propagated back to the caller -through whatever API function resulted in that call, which -may include -.Fn archive_write_header , -.Fn archive_write_data , -.Fn archive_write_close , -or -.Fn archive_write_finish . -The client callback can call -.Fn archive_set_error -to provide values that can then be retrieved by -.Fn archive_errno -and -.Fn archive_error_string . -.Sh SEE ALSO -.Xr tar 1 , -.Xr libarchive 3 , -.Xr tar 5 -.Sh HISTORY -The -.Nm libarchive -library first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm libarchive -library was written by -.An Tim Kientzle Aq kientzle@acm.org . -.Sh BUGS -There are many peculiar bugs in historic tar implementations that may cause -certain programs to reject archives written by this library. -For example, several historic implementations calculated header checksums -incorrectly and will thus reject valid archives; GNU tar does not fully support -pax interchange format; some old tar implementations required specific -field terminations. -.Pp -The default pax interchange format eliminates most of the historic -tar limitations and provides a generic key/value attribute facility -for vendor-defined extensions. -One oversight in POSIX is the failure to provide a standard attribute -for large device numbers. -This library uses -.Dq SCHILY.devminor -and -.Dq SCHILY.devmajor -for device numbers that exceed the range supported by the backwards-compatible -ustar header. -These keys are compatible with Joerg Schilling's -.Nm star -archiver. -Other implementations may not recognize these keys and will thus be unable -to correctly restore device nodes with large device numbers. diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write.c b/contrib/libarchive-1.3.1/libarchive/archive_write.c deleted file mode 100644 index dd468cff5d..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write.c +++ /dev/null @@ -1,284 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write.c,v 1.18 2006/09/05 05:59:46 kientzle Exp $"); - -/* - * This file contains the "essential" portions of the write API, that - * is, stuff that will essentially always be used by any client that - * actually needs to write a archive. Optional pieces have been, as - * far as possible, separated out into separate files to reduce - * needlessly bloating statically-linked clients. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -extern char **environ; - -/* - * Allocate, initialize and return an archive object. - */ -struct archive * -archive_write_new(void) -{ - struct archive *a; - unsigned char *nulls; - - a = malloc(sizeof(*a)); - if (a == NULL) - return (NULL); - memset(a, 0, sizeof(*a)); - a->magic = ARCHIVE_WRITE_MAGIC; - a->user_uid = geteuid(); - a->bytes_per_block = ARCHIVE_DEFAULT_BYTES_PER_BLOCK; - a->bytes_in_last_block = -1; /* Default */ - a->state = ARCHIVE_STATE_NEW; - a->pformat_data = &(a->format_data); - - /* Initialize a block of nulls for padding purposes. */ - a->null_length = 1024; - nulls = malloc(a->null_length); - if (nulls == NULL) { - free(a); - return (NULL); - } - memset(nulls, 0, a->null_length); - a->nulls = nulls; - /* - * Set default compression, but don't set a default format. - * Were we to set a default format here, we would force every - * client to link in support for that format, even if they didn't - * ever use it. - */ - archive_write_set_compression_none(a); - return (a); -} - -/* - * Set the block size. Returns 0 if successful. - */ -int -archive_write_set_bytes_per_block(struct archive *a, int bytes_per_block) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_bytes_per_block"); - a->bytes_per_block = bytes_per_block; - return (ARCHIVE_OK); -} - -/* - * Get the current block size. -1 if it has never been set. - */ -int -archive_write_get_bytes_per_block(struct archive *a) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_get_bytes_per_block"); - return (a->bytes_per_block); -} - -/* - * Set the size for the last block. - * Returns 0 if successful. - */ -int -archive_write_set_bytes_in_last_block(struct archive *a, int bytes) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_set_bytes_in_last_block"); - a->bytes_in_last_block = bytes; - return (ARCHIVE_OK); -} - -/* - * Return the value set above. -1 indicates it has not been set. - */ -int -archive_write_get_bytes_in_last_block(struct archive *a) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_get_bytes_in_last_block"); - return (a->bytes_in_last_block); -} - - -/* - * dev/ino of a file to be rejected. Used to prevent adding - * an archive to itself recursively. - */ -int -archive_write_set_skip_file(struct archive *a, dev_t d, ino_t i) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_set_skip_file"); - a->skip_file_dev = d; - a->skip_file_ino = i; - return (ARCHIVE_OK); -} - - -/* - * Open the archive using the current settings. - */ -int -archive_write_open(struct archive *a, void *client_data, - archive_open_callback *opener, archive_write_callback *writer, - archive_close_callback *closer) -{ - int ret; - - ret = ARCHIVE_OK; - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_open"); - archive_string_empty(&a->error_string); - a->state = ARCHIVE_STATE_HEADER; - a->client_data = client_data; - a->client_writer = writer; - a->client_opener = opener; - a->client_closer = closer; - ret = (a->compression_init)(a); - if (a->format_init && ret == ARCHIVE_OK) - ret = (a->format_init)(a); - return (ret); -} - - -/* - * Close out the archive. - * - * Be careful: user might just call write_new and then write_finish. - * Don't assume we actually wrote anything or performed any non-trivial - * initialization. - */ -int -archive_write_close(struct archive *a) -{ - int r = ARCHIVE_OK, r1 = ARCHIVE_OK; - - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_close"); - - /* Finish the last entry. */ - if (a->state & ARCHIVE_STATE_DATA) - r = ((a->format_finish_entry)(a)); - - /* Finish off the archive. */ - if (a->format_finish != NULL) { - r1 = (a->format_finish)(a); - if (r1 < r) - r = r1; - } - - /* Finish the compression and close the stream. */ - if (a->compression_finish != NULL) { - r1 = (a->compression_finish)(a); - if (r1 < r) - r = r1; - } - - a->state = ARCHIVE_STATE_CLOSED; - return (r); -} - -/* - * Destroy the archive structure. - */ -#if ARCHIVE_API_VERSION > 1 -int -#else -/* Temporarily allow library to compile with either 1.x or 2.0 API. */ -void -#endif -archive_write_finish(struct archive *a) -{ - int r = ARCHIVE_OK; - - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_finish"); - if (a->state != ARCHIVE_STATE_CLOSED) - r = archive_write_close(a); - - /* Release various dynamic buffers. */ - free((void *)(uintptr_t)(const void *)a->nulls); - archive_string_free(&a->error_string); - a->magic = 0; - free(a); -#if ARCHIVE_API_VERSION > 1 - /* libarchive 1.x erroneously declares this function "void" */ - return (r); -#endif -} - - -/* - * Write the appropriate header. - */ -int -archive_write_header(struct archive *a, struct archive_entry *entry) -{ - int ret; - - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, - ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, "archive_write_header"); - archive_string_empty(&a->error_string); - - /* Finish last entry. */ - if (a->state & ARCHIVE_STATE_DATA) - ((a->format_finish_entry)(a)); - - if (a->skip_file_dev != 0 && - archive_entry_dev(entry) == a->skip_file_dev && - a->skip_file_ino != 0 && - archive_entry_ino(entry) == a->skip_file_ino) { - archive_set_error(a, 0, "Can't add archive to itself"); - return (ARCHIVE_WARN); - } - - /* Format and write header. */ - ret = ((a->format_write_header)(a, entry)); - - a->state = ARCHIVE_STATE_DATA; - return (ret); -} - -/* - * Note that the compressor is responsible for blocking. - */ -#if ARCHIVE_API_VERSION > 1 -ssize_t -#else -/* Temporarily allow library to compile with either 1.x or 2.0 API. */ -int -#endif -archive_write_data(struct archive *a, const void *buff, size_t s) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); - archive_string_empty(&a->error_string); - return ((a->format_write_data)(a, buff, s)); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_open_fd.c b/contrib/libarchive-1.3.1/libarchive/archive_write_open_fd.c deleted file mode 100644 index 30495bc580..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_open_fd.c +++ /dev/null @@ -1,133 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_fd.c,v 1.4 2004/10/17 23:47:30 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -struct write_fd_data { - off_t offset; - int fd; -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_write(struct archive *, void *, void *buff, size_t); - -int -archive_write_open_fd(struct archive *a, int fd) -{ - struct write_fd_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->fd = fd; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - struct write_fd_data *mine; - struct stat st, *pst; - - pst = NULL; - mine = client_data; - - /* - * If client hasn't explicitly set the last block handling, - * then set it here: If the output is a block or character - * device, pad the last block, otherwise leave it unpadded. - */ - if (mine->fd >= 0 && a->bytes_in_last_block < 0) { - /* Last block will be fully padded. */ - if (fstat(mine->fd, &st) == 0) { - pst = &st; - if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || - S_ISFIFO(st.st_mode)) - archive_write_set_bytes_in_last_block(a, 0); - else - archive_write_set_bytes_in_last_block(a, 1); - } - } - - if (mine->fd == 1) { - if (a->bytes_in_last_block < 0) /* Still default? */ - /* Last block will be fully padded. */ - archive_write_set_bytes_in_last_block(a, 0); - } - - if (mine->fd < 0) { - archive_set_error(a, errno, "Failed to open"); - return (ARCHIVE_FATAL); - } - - if (pst == NULL && fstat(mine->fd, &st) == 0) - pst = &st; - if (pst == NULL) { - archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd); - return (ARCHIVE_FATAL); - } - - return (ARCHIVE_OK); -} - -static ssize_t -file_write(struct archive *a, void *client_data, void *buff, size_t length) -{ - struct write_fd_data *mine; - ssize_t bytesWritten; - - mine = client_data; - bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { - archive_set_error(a, errno, "Write error"); - return (-1); - } - return (bytesWritten); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct write_fd_data *mine = client_data; - - (void)a; /* UNUSED */ - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_open_file.c b/contrib/libarchive-1.3.1/libarchive/archive_write_open_file.c deleted file mode 100644 index f38019304a..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_open_file.c +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_file.c,v 1.11 2005/03/13 01:47:31 kientzle Exp $"); - -#include -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -struct write_FILE_data { - FILE *f; -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_write(struct archive *, void *, void *buff, size_t); - -int -archive_write_open_FILE(struct archive *a, FILE *f) -{ - struct write_FILE_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->f = f; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - (void)a; /* UNUSED */ - (void)client_data; /* UNUSED */ - - return (ARCHIVE_OK); -} - -static ssize_t -file_write(struct archive *a, void *client_data, void *buff, size_t length) -{ - struct write_FILE_data *mine; - size_t bytesWritten; - - mine = client_data; - bytesWritten = fwrite(buff, 1, length, mine->f); - if (bytesWritten < length) { - archive_set_error(a, errno, "Write error"); - return (-1); - } - return (bytesWritten); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct write_FILE_data *mine = client_data; - - (void)a; /* UNUSED */ - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_open_filename.c b/contrib/libarchive-1.3.1/libarchive/archive_write_open_filename.c deleted file mode 100644 index 5590dde0c7..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_open_filename.c +++ /dev/null @@ -1,169 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include "archive.h" - -struct write_file_data { - int fd; - char filename[1]; -}; - -static int file_close(struct archive *, void *); -static int file_open(struct archive *, void *); -static ssize_t file_write(struct archive *, void *, void *buff, size_t); - -int -archive_write_open_file(struct archive *a, const char *filename) -{ - return (archive_write_open_filename(a, filename)); -} - -int -archive_write_open_filename(struct archive *a, const char *filename) -{ - struct write_file_data *mine; - - if (filename == NULL || filename[0] == '\0') { - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - mine->filename[0] = '\0'; /* Record that we're using stdout. */ - } else { - mine = malloc(sizeof(*mine) + strlen(filename)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - strcpy(mine->filename, filename); - } - mine->fd = -1; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); -} - -static int -file_open(struct archive *a, void *client_data) -{ - int flags; - struct write_file_data *mine; - struct stat st, *pst; - - pst = NULL; - mine = client_data; - flags = O_WRONLY | O_CREAT | O_TRUNC; - - if (mine->filename[0] != '\0') { - mine->fd = open(mine->filename, flags, 0666); - - /* - * If client hasn't explicitly set the last block - * handling, then set it here: If the output is a - * block or character device, pad the last block, - * otherwise leave it unpadded. - */ - if (mine->fd >= 0 && archive_write_get_bytes_in_last_block(a) < 0) { - if (fstat(mine->fd, &st) == 0) { - pst = &st; - if (S_ISCHR(st.st_mode) || - S_ISBLK(st.st_mode) || - S_ISFIFO(st.st_mode)) - /* Pad last block. */ - archive_write_set_bytes_in_last_block(a, 0); - else - /* Don't pad last block. */ - archive_write_set_bytes_in_last_block(a, 1); - } - } - } else { - mine->fd = 1; - if (archive_write_get_bytes_in_last_block(a) < 0) /* Still default? */ - /* Last block will be fully padded. */ - archive_write_set_bytes_in_last_block(a, 0); - } - - if (mine->fd < 0) { - archive_set_error(a, errno, "Failed to open '%s'", - mine->filename); - return (ARCHIVE_FATAL); - } - - if (pst == NULL && fstat(mine->fd, &st) == 0) - pst = &st; - if (pst == NULL) { - archive_set_error(a, errno, "Couldn't stat '%s'", - mine->filename); - return (ARCHIVE_FATAL); - } - - /* - * If the output file is a regular file, don't add it to - * itself. If it's a device file, it's okay to add the device - * entry to the output archive. - */ - if (S_ISREG(pst->st_mode)) - archive_write_set_skip_file(a, pst->st_dev, pst->st_ino); - - return (ARCHIVE_OK); -} - -static ssize_t -file_write(struct archive *a, void *client_data, void *buff, size_t length) -{ - struct write_file_data *mine; - ssize_t bytesWritten; - - mine = client_data; - bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { - archive_set_error(a, errno, "Write error"); - return (-1); - } - return (bytesWritten); -} - -static int -file_close(struct archive *a, void *client_data) -{ - struct write_file_data *mine = client_data; - - (void)a; /* UNUSED */ - if (mine->filename[0] != '\0') - close(mine->fd); - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_open_memory.c b/contrib/libarchive-1.3.1/libarchive/archive_write_open_memory.c deleted file mode 100644 index 1998f128bb..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_open_memory.c +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * 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. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -/* - * This is a little tricky. I used to allow the - * compression handling layer to fork the compressor, - * which means this write function gets invoked in - * a separate process. That would, of course, make it impossible - * to actually use the data stored into memory here. - * Fortunately, none of the compressors fork today and - * I'm reluctant to use that route in the future but, if - * forking compressors ever do reappear, this will have - * to get a lot more complicated. - */ - -struct write_memory_data { - size_t used; - size_t size; - size_t * client_size; - unsigned char * buff; -}; - -static int memory_write_close(struct archive *, void *); -static int memory_write_open(struct archive *, void *); -static ssize_t memory_write(struct archive *, void *, void *buff, size_t); - -/* - * Client provides a pointer to a block of memory to receive - * the data. The 'size' param both tells us the size of the - * client buffer and lets us tell the client the final size. - */ -int -archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t *used) -{ - struct write_memory_data *mine; - - mine = malloc(sizeof(*mine)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - memset(mine, 0, sizeof(*mine)); - mine->buff = buff; - mine->size = buffSize; - mine->client_size = used; - return (archive_write_open(a, mine, - memory_write_open, memory_write, memory_write_close)); -} - -static int -memory_write_open(struct archive *a, void *client_data) -{ - struct write_memory_data *mine; - mine = client_data; - mine->used = 0; - if (mine->client_size != NULL) - *mine->client_size = mine->used; - /* Disable padding if it hasn't been set explicitly. */ - if (-1 == archive_write_get_bytes_in_last_block(a)) - archive_write_set_bytes_in_last_block(a, 1); - return (ARCHIVE_OK); -} - -/* - * Copy the data into the client buffer. - * Note that we update mine->client_size on every write. - * In particular, this means the client can follow exactly - * how much has been written into their buffer at any time. - */ -static ssize_t -memory_write(struct archive *a, void *client_data, void *buff, size_t length) -{ - struct write_memory_data *mine; - mine = client_data; - - if (mine->used + length > mine->size) { - archive_set_error(a, ENOMEM, "Buffer exhausted"); - return (ARCHIVE_FATAL); - } - memcpy(mine->buff + mine->used, buff, length); - mine->used += length; - if (mine->client_size != NULL) - *mine->client_size = mine->used; - return (length); -} - -static int -memory_write_close(struct archive *a, void *client_data) -{ - struct write_memory_data *mine; - (void)a; /* UNUSED */ - mine = client_data; - free(mine); - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_bzip2.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_bzip2.c deleted file mode 100644 index 7dd43c4233..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_bzip2.c +++ /dev/null @@ -1,343 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" - -/* Don't compile this if we don't have bzlib. */ -#if HAVE_BZLIB_H - -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_bzip2.c,v 1.8 2005/06/01 15:52:39 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -struct private_data { - bz_stream stream; - int64_t total_in; - char *compressed; - size_t compressed_buffer_size; -}; - - -/* - * Yuck. bzlib.h is not const-correct, so I need this one bit - * of ugly hackery to convert a const * pointer to a non-const pointer. - */ -#define SET_NEXT_IN(st,src) \ - (st)->stream.next_in = (void *)(uintptr_t)(const void *)(src) - -static int archive_compressor_bzip2_finish(struct archive *); -static int archive_compressor_bzip2_init(struct archive *); -static int archive_compressor_bzip2_write(struct archive *, const void *, - size_t); -static int drive_compressor(struct archive *, struct private_data *, - int finishing); - -/* - * Allocate, initialize and return an archive object. - */ -int -archive_write_set_compression_bzip2(struct archive *a) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_bzip2"); - a->compression_init = &archive_compressor_bzip2_init; - a->compression_code = ARCHIVE_COMPRESSION_BZIP2; - a->compression_name = "bzip2"; - return (ARCHIVE_OK); -} - -/* - * Setup callback. - */ -static int -archive_compressor_bzip2_init(struct archive *a) -{ - int ret; - struct private_data *state; - - a->compression_code = ARCHIVE_COMPRESSION_BZIP2; - a->compression_name = "bzip2"; - - if (a->client_opener != NULL) { - ret = (a->client_opener)(a, a->client_data); - if (ret != 0) - return (ret); - } - - state = malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for compression"); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->compressed_buffer_size = a->bytes_per_block; - state->compressed = malloc(state->compressed_buffer_size); - - if (state->compressed == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for compression buffer"); - free(state); - return (ARCHIVE_FATAL); - } - - state->stream.next_out = state->compressed; - state->stream.avail_out = state->compressed_buffer_size; - a->compression_write = archive_compressor_bzip2_write; - a->compression_finish = archive_compressor_bzip2_finish; - - /* Initialize compression library */ - ret = BZ2_bzCompressInit(&(state->stream), 9, 0, 30); - if (ret == BZ_OK) { - a->compression_data = state; - return (ARCHIVE_OK); - } - - /* Library setup failed: clean up. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library"); - free(state->compressed); - free(state); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case BZ_PARAM_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid setup parameter"); - break; - case BZ_MEM_ERROR: - archive_set_error(a, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - case BZ_CONFIG_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "mis-compiled library"); - break; - } - - return (ARCHIVE_FATAL); - -} - -/* - * Write data to the compressed stream. - * - * Returns ARCHIVE_OK if all data written, error otherwise. - */ -static int -archive_compressor_bzip2_write(struct archive *a, const void *buff, - size_t length) -{ - struct private_data *state; - - state = a->compression_data; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - /* Update statistics */ - state->total_in += length; - - /* Compress input data to output buffer */ - SET_NEXT_IN(state, buff); - state->stream.avail_in = length; - if (drive_compressor(a, state, 0)) - return (ARCHIVE_FATAL); - a->file_position += length; - return (ARCHIVE_OK); -} - - -/* - * Finish the compression. - */ -static int -archive_compressor_bzip2_finish(struct archive *a) -{ - ssize_t block_length; - int ret; - struct private_data *state; - ssize_t target_block_length; - ssize_t bytes_written; - unsigned tocopy; - - state = a->compression_data; - ret = ARCHIVE_OK; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered?\n" - "This is probably an internal programming error."); - ret = ARCHIVE_FATAL; - goto cleanup; - } - - /* By default, always pad the uncompressed data. */ - if (a->pad_uncompressed) { - tocopy = a->bytes_per_block - - (state->total_in % a->bytes_per_block); - while (tocopy > 0 && tocopy < (unsigned)a->bytes_per_block) { - SET_NEXT_IN(state, a->nulls); - state->stream.avail_in = tocopy < a->null_length ? - tocopy : a->null_length; - state->total_in += state->stream.avail_in; - tocopy -= state->stream.avail_in; - ret = drive_compressor(a, state, 0); - if (ret != ARCHIVE_OK) - goto cleanup; - } - } - - /* Finish compression cycle. */ - if ((ret = drive_compressor(a, state, 1))) - goto cleanup; - - /* Optionally, pad the final compressed block. */ - block_length = state->stream.next_out - state->compressed; - - - /* Tricky calculation to determine size of last block. */ - target_block_length = block_length; - if (a->bytes_in_last_block <= 0) - /* Default or Zero: pad to full block */ - target_block_length = a->bytes_per_block; - else - /* Round length to next multiple of bytes_in_last_block. */ - target_block_length = a->bytes_in_last_block * - ( (block_length + a->bytes_in_last_block - 1) / - a->bytes_in_last_block); - if (target_block_length > a->bytes_per_block) - target_block_length = a->bytes_per_block; - if (block_length < target_block_length) { - memset(state->stream.next_out, 0, - target_block_length - block_length); - block_length = target_block_length; - } - - /* Write the last block */ - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, block_length); - - /* TODO: Handle short write of final block. */ - if (bytes_written <= 0) - ret = ARCHIVE_FATAL; - else { - a->raw_position += ret; - ret = ARCHIVE_OK; - } - - /* Cleanup: shut down compressor, release memory, etc. */ -cleanup: - switch (BZ2_bzCompressEnd(&(state->stream))) { - case BZ_OK: - break; - default: - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "Failed to clean up compressor"); - ret = ARCHIVE_FATAL; - } - - free(state->compressed); - free(state); - - /* Close the output */ - if (a->client_closer != NULL) - (a->client_closer)(a, a->client_data); - - return (ret); -} - -/* - * Utility function to push input data through compressor, writing - * full output blocks as necessary. - * - * Note that this handles both the regular write case (finishing == - * false) and the end-of-archive case (finishing == true). - */ -static int -drive_compressor(struct archive *a, struct private_data *state, int finishing) -{ - ssize_t bytes_written; - int ret; - - for (;;) { - if (state->stream.avail_out == 0) { - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { - /* TODO: Handle this write failure */ - return (ARCHIVE_FATAL); - } else if ((size_t)bytes_written < state->compressed_buffer_size) { - /* Short write: Move remainder to - * front and keep filling */ - memmove(state->compressed, - state->compressed + bytes_written, - state->compressed_buffer_size - bytes_written); - } - - a->raw_position += bytes_written; - state->stream.next_out = state->compressed + - state->compressed_buffer_size - bytes_written; - state->stream.avail_out = bytes_written; - } - - ret = BZ2_bzCompress(&(state->stream), - finishing ? BZ_FINISH : BZ_RUN); - - switch (ret) { - case BZ_RUN_OK: - /* In non-finishing case, did compressor - * consume everything? */ - if (!finishing && state->stream.avail_in == 0) - return (ARCHIVE_OK); - break; - case BZ_FINISH_OK: /* Finishing: There's more work to do */ - break; - case BZ_STREAM_END: /* Finishing: all done */ - /* Only occurs in finishing case */ - return (ARCHIVE_OK); - default: - /* Any other return value indicates an error */ - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "Bzip2 compression failed"); - return (ARCHIVE_FATAL); - } - } -} - -#endif /* HAVE_BZLIB_H */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_gzip.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_gzip.c deleted file mode 100644 index 908561d51d..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_gzip.c +++ /dev/null @@ -1,399 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" - -/* Don't compile this if we don't have zlib. */ -#if HAVE_ZLIB_H - -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_gzip.c,v 1.10 2005/06/01 15:52:39 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -struct private_data { - z_stream stream; - int64_t total_in; - unsigned char *compressed; - size_t compressed_buffer_size; - unsigned long crc; -}; - - -/* - * Yuck. zlib.h is not const-correct, so I need this one bit - * of ugly hackery to convert a const * pointer to a non-const pointer. - */ -#define SET_NEXT_IN(st,src) \ - (st)->stream.next_in = (void *)(uintptr_t)(const void *)(src) - -static int archive_compressor_gzip_finish(struct archive *); -static int archive_compressor_gzip_init(struct archive *); -static int archive_compressor_gzip_write(struct archive *, const void *, - size_t); -static int drive_compressor(struct archive *, struct private_data *, - int finishing); - - -/* - * Allocate, initialize and return a archive object. - */ -int -archive_write_set_compression_gzip(struct archive *a) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_gzip"); - a->compression_init = &archive_compressor_gzip_init; - a->compression_code = ARCHIVE_COMPRESSION_GZIP; - a->compression_name = "gzip"; - return (ARCHIVE_OK); -} - -/* - * Setup callback. - */ -static int -archive_compressor_gzip_init(struct archive *a) -{ - int ret; - struct private_data *state; - time_t t; - - a->compression_code = ARCHIVE_COMPRESSION_GZIP; - a->compression_name = "gzip"; - - if (a->client_opener != NULL) { - ret = (a->client_opener)(a, a->client_data); - if (ret != ARCHIVE_OK) - return (ret); - } - - state = (struct private_data *)malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for compression"); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->compressed_buffer_size = a->bytes_per_block; - state->compressed = malloc(state->compressed_buffer_size); - state->crc = crc32(0L, NULL, 0); - - if (state->compressed == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for compression buffer"); - free(state); - return (ARCHIVE_FATAL); - } - - state->stream.next_out = state->compressed; - state->stream.avail_out = state->compressed_buffer_size; - - /* Prime output buffer with a gzip header. */ - t = time(NULL); - state->compressed[0] = 0x1f; /* GZip signature bytes */ - state->compressed[1] = 0x8b; - state->compressed[2] = 0x08; /* "Deflate" compression */ - state->compressed[3] = 0; /* No options */ - state->compressed[4] = (t)&0xff; /* Timestamp */ - state->compressed[5] = (t>>8)&0xff; - state->compressed[6] = (t>>16)&0xff; - state->compressed[7] = (t>>24)&0xff; - state->compressed[8] = 0; /* No deflate options */ - state->compressed[9] = 3; /* OS=Unix */ - state->stream.next_out += 10; - state->stream.avail_out -= 10; - - a->compression_write = archive_compressor_gzip_write; - a->compression_finish = archive_compressor_gzip_finish; - - /* Initialize compression library. */ - ret = deflateInit2(&(state->stream), - Z_DEFAULT_COMPRESSION, - Z_DEFLATED, - -15 /* < 0 to suppress zlib header */, - 8, - Z_DEFAULT_STRATEGY); - - if (ret == Z_OK) { - a->compression_data = state; - return (0); - } - - /* Library setup failed: clean up. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, "Internal error " - "initializing compression library"); - free(state->compressed); - free(state); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case Z_STREAM_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: invalid setup parameter"); - break; - case Z_MEM_ERROR: - archive_set_error(a, ENOMEM, "Internal error initializing " - "compression library"); - break; - case Z_VERSION_ERROR: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: invalid library version"); - break; - } - - return (ARCHIVE_FATAL); -} - -/* - * Write data to the compressed stream. - */ -static int -archive_compressor_gzip_write(struct archive *a, const void *buff, - size_t length) -{ - struct private_data *state; - int ret; - - state = a->compression_data; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - /* Update statistics */ - state->crc = crc32(state->crc, buff, length); - state->total_in += length; - - /* Compress input data to output buffer */ - SET_NEXT_IN(state, buff); - state->stream.avail_in = length; - if ((ret = drive_compressor(a, state, 0)) != ARCHIVE_OK) - return (ret); - - a->file_position += length; - return (ARCHIVE_OK); -} - - -/* - * Finish the compression... - */ -static int -archive_compressor_gzip_finish(struct archive *a) -{ - ssize_t block_length, target_block_length, bytes_written; - int ret; - struct private_data *state; - unsigned tocopy; - unsigned char trailer[8]; - - state = a->compression_data; - ret = 0; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered? " - "This is probably an internal programming error."); - ret = ARCHIVE_FATAL; - goto cleanup; - } - - /* By default, always pad the uncompressed data. */ - if (a->pad_uncompressed) { - tocopy = a->bytes_per_block - - (state->total_in % a->bytes_per_block); - while (tocopy > 0 && tocopy < (unsigned)a->bytes_per_block) { - SET_NEXT_IN(state, a->nulls); - state->stream.avail_in = tocopy < a->null_length ? - tocopy : a->null_length; - state->crc = crc32(state->crc, a->nulls, - state->stream.avail_in); - state->total_in += state->stream.avail_in; - tocopy -= state->stream.avail_in; - ret = drive_compressor(a, state, 0); - if (ret != ARCHIVE_OK) - goto cleanup; - } - } - - /* Finish compression cycle */ - if (((ret = drive_compressor(a, state, 1))) != ARCHIVE_OK) - goto cleanup; - - /* Build trailer: 4-byte CRC and 4-byte length. */ - trailer[0] = (state->crc)&0xff; - trailer[1] = (state->crc >> 8)&0xff; - trailer[2] = (state->crc >> 16)&0xff; - trailer[3] = (state->crc >> 24)&0xff; - trailer[4] = (state->total_in)&0xff; - trailer[5] = (state->total_in >> 8)&0xff; - trailer[6] = (state->total_in >> 16)&0xff; - trailer[7] = (state->total_in >> 24)&0xff; - - /* Add trailer to current block. */ - tocopy = 8; - if (tocopy > state->stream.avail_out) - tocopy = state->stream.avail_out; - memcpy(state->stream.next_out, trailer, tocopy); - state->stream.next_out += tocopy; - state->stream.avail_out -= tocopy; - - /* If it overflowed, flush and start a new block. */ - if (tocopy < 8) { - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { - ret = ARCHIVE_FATAL; - goto cleanup; - } - a->raw_position += bytes_written; - state->stream.next_out = state->compressed; - state->stream.avail_out = state->compressed_buffer_size; - memcpy(state->stream.next_out, trailer + tocopy, 8-tocopy); - state->stream.next_out += 8-tocopy; - state->stream.avail_out -= 8-tocopy; - } - - /* Optionally, pad the final compressed block. */ - block_length = state->stream.next_out - state->compressed; - - - /* Tricky calculation to determine size of last block. */ - target_block_length = block_length; - if (a->bytes_in_last_block <= 0) - /* Default or Zero: pad to full block */ - target_block_length = a->bytes_per_block; - else - /* Round length to next multiple of bytes_in_last_block. */ - target_block_length = a->bytes_in_last_block * - ( (block_length + a->bytes_in_last_block - 1) / - a->bytes_in_last_block); - if (target_block_length > a->bytes_per_block) - target_block_length = a->bytes_per_block; - if (block_length < target_block_length) { - memset(state->stream.next_out, 0, - target_block_length - block_length); - block_length = target_block_length; - } - - /* Write the last block */ - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, block_length); - if (bytes_written <= 0) { - ret = ARCHIVE_FATAL; - goto cleanup; - } - a->raw_position += bytes_written; - - /* Cleanup: shut down compressor, release memory, etc. */ -cleanup: - switch (deflateEnd(&(state->stream))) { - case Z_OK: - break; - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Failed to clean up compressor"); - ret = ARCHIVE_FATAL; - } - free(state->compressed); - free(state); - - /* Close the output */ - if (a->client_closer != NULL) - (a->client_closer)(a, a->client_data); - - return (ret); -} - -/* - * Utility function to push input data through compressor, - * writing full output blocks as necessary. - * - * Note that this handles both the regular write case (finishing == - * false) and the end-of-archive case (finishing == true). - */ -static int -drive_compressor(struct archive *a, struct private_data *state, int finishing) -{ - ssize_t bytes_written; - int ret; - - for (;;) { - if (state->stream.avail_out == 0) { - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { - /* TODO: Handle this write failure */ - return (ARCHIVE_FATAL); - } else if ((size_t)bytes_written < state->compressed_buffer_size) { - /* Short write: Move remaining to - * front of block and keep filling */ - memmove(state->compressed, - state->compressed + bytes_written, - state->compressed_buffer_size - bytes_written); - } - a->raw_position += bytes_written; - state->stream.next_out - = state->compressed + - state->compressed_buffer_size - bytes_written; - state->stream.avail_out = bytes_written; - } - - ret = deflate(&(state->stream), - finishing ? Z_FINISH : Z_NO_FLUSH ); - - switch (ret) { - case Z_OK: - /* In non-finishing case, check if compressor - * consumed everything */ - if (!finishing && state->stream.avail_in == 0) - return (ARCHIVE_OK); - /* In finishing case, this return always means - * there's more work */ - break; - case Z_STREAM_END: - /* This return can only occur in finishing case. */ - return (ARCHIVE_OK); - default: - /* Any other return value indicates an error. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "GZip compression failed"); - return (ARCHIVE_FATAL); - } - } -} - -#endif /* HAVE_ZLIB_H */ diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_none.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_none.c deleted file mode 100644 index 7c3b51f6fa..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_compression_none.c +++ /dev/null @@ -1,218 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_none.c,v 1.8 2005/06/01 15:52:39 kientzle Exp $"); - -#include -#include -#include - -#include "archive.h" -#include "archive_private.h" - -static int archive_compressor_none_finish(struct archive *a); -static int archive_compressor_none_init(struct archive *); -static int archive_compressor_none_write(struct archive *, const void *, - size_t); - -struct archive_none { - char *buffer; - ssize_t buffer_size; - char *next; /* Current insert location */ - ssize_t avail; /* Free space left in buffer */ -}; - -int -archive_write_set_compression_none(struct archive *a) -{ - __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_none"); - a->compression_init = &archive_compressor_none_init; - a->compression_code = ARCHIVE_COMPRESSION_NONE; - a->compression_name = "none"; - return (0); -} - -/* - * Setup callback. - */ -static int -archive_compressor_none_init(struct archive *a) -{ - int ret; - struct archive_none *state; - - a->compression_code = ARCHIVE_COMPRESSION_NONE; - a->compression_name = "none"; - - if (a->client_opener != NULL) { - ret = (a->client_opener)(a, a->client_data); - if (ret != 0) - return (ret); - } - - state = (struct archive_none *)malloc(sizeof(*state)); - if (state == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate data for output buffering"); - return (ARCHIVE_FATAL); - } - memset(state, 0, sizeof(*state)); - - state->buffer_size = a->bytes_per_block; - state->buffer = malloc(state->buffer_size); - - if (state->buffer == NULL) { - archive_set_error(a, ENOMEM, - "Can't allocate output buffer"); - free(state); - return (ARCHIVE_FATAL); - } - - state->next = state->buffer; - state->avail = state->buffer_size; - - a->compression_data = state; - a->compression_write = archive_compressor_none_write; - a->compression_finish = archive_compressor_none_finish; - return (ARCHIVE_OK); -} - -/* - * Write data to the stream. - */ -static int -archive_compressor_none_write(struct archive *a, const void *vbuff, - size_t length) -{ - const char *buff; - ssize_t remaining, to_copy; - ssize_t bytes_written; - struct archive_none *state; - - state = a->compression_data; - buff = vbuff; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - remaining = length; - while (remaining > 0) { - /* - * If we have a full output block, write it and reset the - * output buffer. - */ - if (state->avail == 0) { - bytes_written = (a->client_writer)(a, a->client_data, - state->buffer, state->buffer_size); - if (bytes_written <= 0) - return (ARCHIVE_FATAL); - /* XXX TODO: if bytes_written < state->buffer_size */ - a->raw_position += bytes_written; - state->next = state->buffer; - state->avail = state->buffer_size; - } - - /* Now we have space in the buffer; copy new data into it. */ - to_copy = (remaining > state->avail) ? - state->avail : remaining; - memcpy(state->next, buff, to_copy); - state->next += to_copy; - state->avail -= to_copy; - buff += to_copy; - remaining -= to_copy; - } - a->file_position += length; - return (ARCHIVE_OK); -} - - -/* - * Finish the compression. - */ -static int -archive_compressor_none_finish(struct archive *a) -{ - ssize_t block_length; - ssize_t target_block_length; - ssize_t bytes_written; - int ret; - int ret2; - struct archive_none *state; - - state = a->compression_data; - ret = ret2 = ARCHIVE_OK; - if (a->client_writer == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, - "No write callback is registered? " - "This is probably an internal programming error."); - return (ARCHIVE_FATAL); - } - - /* If there's pending data, pad and write the last block */ - if (state->next != state->buffer) { - block_length = state->buffer_size - state->avail; - - /* Tricky calculation to determine size of last block */ - target_block_length = block_length; - if (a->bytes_in_last_block <= 0) - /* Default or Zero: pad to full block */ - target_block_length = a->bytes_per_block; - else - /* Round to next multiple of bytes_in_last_block. */ - target_block_length = a->bytes_in_last_block * - ( (block_length + a->bytes_in_last_block - 1) / - a->bytes_in_last_block); - if (target_block_length > a->bytes_per_block) - target_block_length = a->bytes_per_block; - if (block_length < target_block_length) { - memset(state->next, 0, - target_block_length - block_length); - block_length = target_block_length; - } - bytes_written = (a->client_writer)(a, a->client_data, - state->buffer, block_length); - if (bytes_written <= 0) - ret = ARCHIVE_FATAL; - else { - a->raw_position += bytes_written; - ret = ARCHIVE_OK; - } - } - - /* Close the output */ - if (a->client_closer != NULL) - ret2 = (a->client_closer)(a, a->client_data); - - free(state->buffer); - free(state); - a->compression_data = NULL; - - return (ret != ARCHIVE_OK ? ret : ret2); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format.c deleted file mode 100644 index 559b74b9f5..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format.c +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format.c,v 1.2 2004/03/09 19:50:41 kientzle Exp $"); - -#include - -#include -#include "archive.h" -#include "archive_private.h" - -/* A table that maps format codes to functions. */ -static -struct { int code; int (*setter)(struct archive *); } codes[] = -{ - { ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio }, - { ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio }, - { ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar }, - { ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar }, - { ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump }, - { ARCHIVE_FORMAT_TAR, archive_write_set_format_pax_restricted }, - { ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, archive_write_set_format_pax }, - { ARCHIVE_FORMAT_TAR_PAX_RESTRICTED, - archive_write_set_format_pax_restricted }, - { ARCHIVE_FORMAT_TAR_USTAR, archive_write_set_format_ustar }, - { 0, NULL } -}; - -int -archive_write_set_format(struct archive *a, int code) -{ - int i; - - for (i = 0; codes[i].code != 0; i++) { - if (code == codes[i].code) - return ((codes[i].setter)(a)); - } - - archive_set_error(a, EINVAL, "No such format"); - return (ARCHIVE_FATAL); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_by_name.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_by_name.c deleted file mode 100644 index 239e89f70c..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_by_name.c +++ /dev/null @@ -1,63 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_by_name.c,v 1.3 2004/07/25 23:10:38 kientzle Exp $"); - -#include - -#include -#include - -#include "archive.h" -#include "archive_private.h" - -/* A table that maps names to functions. */ -static -struct { const char *name; int (*setter)(struct archive *); } names[] = -{ - { "cpio", archive_write_set_format_cpio }, - { "pax", archive_write_set_format_pax }, - { "posix", archive_write_set_format_pax }, - { "shar", archive_write_set_format_shar }, - { "shardump", archive_write_set_format_shar_dump }, - { "ustar", archive_write_set_format_ustar }, - { NULL, NULL } -}; - -int -archive_write_set_format_by_name(struct archive *a, const char *name) -{ - int i; - - for (i = 0; names[i].name != NULL; i++) { - if (strcmp(name, names[i].name) == 0) - return ((names[i].setter)(a)); - } - - archive_set_error(a, EINVAL, "No such format '%s'", name); - return (ARCHIVE_FATAL); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_cpio.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_cpio.c deleted file mode 100644 index d813466c2a..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_cpio.c +++ /dev/null @@ -1,249 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_cpio.c,v 1.6 2005/09/21 04:25:05 kientzle Exp $"); - -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -static ssize_t archive_write_cpio_data(struct archive *, const void *buff, - size_t s); -static int archive_write_cpio_finish(struct archive *); -static int archive_write_cpio_finish_entry(struct archive *); -static int archive_write_cpio_header(struct archive *, - struct archive_entry *); -static int format_octal(int64_t, void *, int); -static int64_t format_octal_recursive(int64_t, char *, int); - -struct cpio { - uint64_t entry_bytes_remaining; -}; - -struct cpio_header { - char c_magic[6]; - char c_dev[6]; - char c_ino[6]; - char c_mode[6]; - char c_uid[6]; - char c_gid[6]; - char c_nlink[6]; - char c_rdev[6]; - char c_mtime[11]; - char c_namesize[6]; - char c_filesize[11]; -}; - -/* - * Set output format to 'cpio' format. - */ -int -archive_write_set_format_cpio(struct archive *a) -{ - struct cpio *cpio; - - /* If someone else was already registered, unregister them. */ - if (a->format_finish != NULL) - (a->format_finish)(a); - - cpio = malloc(sizeof(*cpio)); - if (cpio == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate cpio data"); - return (ARCHIVE_FATAL); - } - memset(cpio, 0, sizeof(*cpio)); - a->format_data = cpio; - - a->pad_uncompressed = 1; - a->format_write_header = archive_write_cpio_header; - a->format_write_data = archive_write_cpio_data; - a->format_finish_entry = archive_write_cpio_finish_entry; - a->format_finish = archive_write_cpio_finish; - a->archive_format = ARCHIVE_FORMAT_CPIO_POSIX; - a->archive_format_name = "POSIX cpio"; - return (ARCHIVE_OK); -} - -static int -archive_write_cpio_header(struct archive *a, struct archive_entry *entry) -{ - struct cpio *cpio; - const char *p, *path; - int pathlength, ret; - const struct stat *st; - struct cpio_header h; - - cpio = a->format_data; - ret = 0; - - path = archive_entry_pathname(entry); - pathlength = strlen(path) + 1; /* Include trailing null. */ - st = archive_entry_stat(entry); - - memset(&h, 0, sizeof(h)); - format_octal(070707, &h.c_magic, sizeof(h.c_magic)); - format_octal(st->st_dev, &h.c_dev, sizeof(h.c_dev)); - /* - * TODO: Generate artificial inode numbers rather than just - * re-using the ones off the disk. That way, the 18-bit c_ino - * field only limits the number of files in the archive. - */ - if (st->st_ino > 0777777) { - archive_set_error(a, ERANGE, "large inode number truncated"); - ret = ARCHIVE_WARN; - } - - format_octal(st->st_ino & 0777777, &h.c_ino, sizeof(h.c_ino)); - format_octal(st->st_mode, &h.c_mode, sizeof(h.c_mode)); - format_octal(st->st_uid, &h.c_uid, sizeof(h.c_uid)); - format_octal(st->st_gid, &h.c_gid, sizeof(h.c_gid)); - format_octal(st->st_nlink, &h.c_nlink, sizeof(h.c_nlink)); - if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) - format_octal(st->st_rdev, &h.c_rdev, sizeof(h.c_rdev)); - else - format_octal(0, &h.c_rdev, sizeof(h.c_rdev)); - format_octal(st->st_mtime, &h.c_mtime, sizeof(h.c_mtime)); - format_octal(pathlength, &h.c_namesize, sizeof(h.c_namesize)); - - /* Symlinks get the link written as the body of the entry. */ - p = archive_entry_symlink(entry); - if (p != NULL && *p != '\0') - format_octal(strlen(p), &h.c_filesize, sizeof(h.c_filesize)); - else - format_octal(st->st_size, &h.c_filesize, sizeof(h.c_filesize)); - - ret = (a->compression_write)(a, &h, sizeof(h)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); - - ret = (a->compression_write)(a, path, pathlength); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); - - cpio->entry_bytes_remaining = st->st_size; - - /* Write the symlink now. */ - if (p != NULL && *p != '\0') - ret = (a->compression_write)(a, p, strlen(p)); - - return (ret); -} - -static ssize_t -archive_write_cpio_data(struct archive *a, const void *buff, size_t s) -{ - struct cpio *cpio; - int ret; - - cpio = a->format_data; - if (s > cpio->entry_bytes_remaining) - s = cpio->entry_bytes_remaining; - - ret = (a->compression_write)(a, buff, s); - cpio->entry_bytes_remaining -= s; - if (ret >= 0) - return (s); - else - return (ret); -} - -/* - * Format a number into the specified field. - */ -static int -format_octal(int64_t v, void *p, int digits) -{ - int64_t max; - int ret; - - max = (((int64_t)1) << (digits * 3)) - 1; - if (v >= 0 && v <= max) { - format_octal_recursive(v, p, digits); - ret = 0; - } else { - format_octal_recursive(max, p, digits); - ret = -1; - } - return (ret); -} - -static int64_t -format_octal_recursive(int64_t v, char *p, int s) -{ - if (s == 0) - return (v); - v = format_octal_recursive(v, p+1, s-1); - *p = '0' + (v & 7); - return (v >>= 3); -} - -static int -archive_write_cpio_finish(struct archive *a) -{ - struct cpio *cpio; - struct stat st; - int er; - struct archive_entry *trailer; - - cpio = a->format_data; - trailer = archive_entry_new(); - memset(&st, 0, sizeof(st)); - st.st_nlink = 1; - archive_entry_copy_stat(trailer, &st); - archive_entry_set_pathname(trailer, "TRAILER!!!"); - er = archive_write_cpio_header(a, trailer); - archive_entry_free(trailer); - - free(cpio); - a->format_data = NULL; - return (er); -} - -static int -archive_write_cpio_finish_entry(struct archive *a) -{ - struct cpio *cpio; - int to_write, ret; - - cpio = a->format_data; - ret = ARCHIVE_OK; - while (cpio->entry_bytes_remaining > 0) { - to_write = cpio->entry_bytes_remaining < a->null_length ? - cpio->entry_bytes_remaining : a->null_length; - ret = (a->compression_write)(a, a->nulls, to_write); - if (ret != ARCHIVE_OK) - return (ret); - cpio->entry_bytes_remaining -= to_write; - } - return (ret); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_pax.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_pax.c deleted file mode 100644 index b2a25bc162..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_pax.c +++ /dev/null @@ -1,1190 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_pax.c,v 1.34 2006/03/21 16:55:46 kientzle Exp $"); - -#include -#ifdef MAJOR_IN_MKDEV -#include -#else -#ifdef MAJOR_IN_SYSMACROS -#include -#endif -#endif -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct pax { - uint64_t entry_bytes_remaining; - uint64_t entry_padding; - struct archive_string pax_header; - char written; -}; - -static void add_pax_attr(struct archive_string *, const char *key, - const char *value); -static void add_pax_attr_int(struct archive_string *, - const char *key, int64_t value); -static void add_pax_attr_time(struct archive_string *, - const char *key, int64_t sec, - unsigned long nanos); -static void add_pax_attr_w(struct archive_string *, - const char *key, const wchar_t *wvalue); -static ssize_t archive_write_pax_data(struct archive *, - const void *, size_t); -static int archive_write_pax_finish(struct archive *); -static int archive_write_pax_finish_entry(struct archive *); -static int archive_write_pax_header(struct archive *, - struct archive_entry *); -static char *base64_encode(const char *src, size_t len); -static char *build_pax_attribute_name(char *dest, const char *src); -static char *build_ustar_entry_name(char *dest, const char *src, - size_t src_length, const char *insert); -static char *format_int(char *dest, int64_t); -static int has_non_ASCII(const wchar_t *); -static char *url_encode(const char *in); -static int write_nulls(struct archive *, size_t); - -/* - * Set output format to 'restricted pax' format. - * - * This is the same as normal 'pax', but tries to suppress - * the pax header whenever possible. This is the default for - * bsdtar, for instance. - */ -int -archive_write_set_format_pax_restricted(struct archive *a) -{ - int r; - r = archive_write_set_format_pax(a); - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; - a->archive_format_name = "restricted POSIX pax interchange"; - return (r); -} - -/* - * Set output format to 'pax' format. - */ -int -archive_write_set_format_pax(struct archive *a) -{ - struct pax *pax; - - if (a->format_finish != NULL) - (a->format_finish)(a); - - pax = malloc(sizeof(*pax)); - if (pax == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate pax data"); - return (ARCHIVE_FATAL); - } - memset(pax, 0, sizeof(*pax)); - a->format_data = pax; - - a->pad_uncompressed = 1; - a->format_write_header = archive_write_pax_header; - a->format_write_data = archive_write_pax_data; - a->format_finish = archive_write_pax_finish; - a->format_finish_entry = archive_write_pax_finish_entry; - a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; - a->archive_format_name = "POSIX pax interchange"; - return (ARCHIVE_OK); -} - -/* - * Note: This code assumes that 'nanos' has the same sign as 'sec', - * which implies that sec=-1, nanos=200000000 represents -1.2 seconds - * and not -0.8 seconds. This is a pretty pedantic point, as we're - * unlikely to encounter many real files created before Jan 1, 1970, - * much less ones with timestamps recorded to sub-second resolution. - */ -static void -add_pax_attr_time(struct archive_string *as, const char *key, - int64_t sec, unsigned long nanos) -{ - int digit, i; - char *t; - /* - * Note that each byte contributes fewer than 3 base-10 - * digits, so this will always be big enough. - */ - char tmp[1 + 3*sizeof(sec) + 1 + 3*sizeof(nanos)]; - - tmp[sizeof(tmp) - 1] = 0; - t = tmp + sizeof(tmp) - 1; - - /* Skip trailing zeros in the fractional part. */ - for (digit = 0, i = 10; i > 0 && digit == 0; i--) { - digit = nanos % 10; - nanos /= 10; - } - - /* Only format the fraction if it's non-zero. */ - if (i > 0) { - while (i > 0) { - *--t = "0123456789"[digit]; - digit = nanos % 10; - nanos /= 10; - i--; - } - *--t = '.'; - } - t = format_int(t, sec); - - add_pax_attr(as, key, t); -} - -static char * -format_int(char *t, int64_t i) -{ - int sign; - - if (i < 0) { - sign = -1; - i = -i; - } else - sign = 1; - - do { - *--t = "0123456789"[i % 10]; - } while (i /= 10); - if (sign < 0) - *--t = '-'; - return (t); -} - -static void -add_pax_attr_int(struct archive_string *as, const char *key, int64_t value) -{ - char tmp[1 + 3 * sizeof(value)]; - - tmp[sizeof(tmp) - 1] = 0; - add_pax_attr(as, key, format_int(tmp + sizeof(tmp) - 1, value)); -} - -static char * -utf8_encode(const wchar_t *wval) -{ - int utf8len; - const wchar_t *wp; - unsigned long wc; - char *utf8_value, *p; - - utf8len = 0; - for (wp = wval; *wp != L'\0'; ) { - wc = *wp++; - if (wc <= 0x7f) - utf8len++; - else if (wc <= 0x7ff) - utf8len += 2; - else if (wc <= 0xffff) - utf8len += 3; - else if (wc <= 0x1fffff) - utf8len += 4; - else if (wc <= 0x3ffffff) - utf8len += 5; - else if (wc <= 0x7fffffff) - utf8len += 6; - /* Ignore larger values; UTF-8 can't encode them. */ - } - - utf8_value = malloc(utf8len + 1); - if (utf8_value == NULL) { - __archive_errx(1, "Not enough memory for attributes"); - return (NULL); - } - - for (wp = wval, p = utf8_value; *wp != L'\0'; ) { - wc = *wp++; - if (wc <= 0x7f) { - *p++ = (char)wc; - } else if (wc <= 0x7ff) { - p[0] = 0xc0 | ((wc >> 6) & 0x1f); - p[1] = 0x80 | (wc & 0x3f); - p += 2; - } else if (wc <= 0xffff) { - p[0] = 0xe0 | ((wc >> 12) & 0x0f); - p[1] = 0x80 | ((wc >> 6) & 0x3f); - p[2] = 0x80 | (wc & 0x3f); - p += 3; - } else if (wc <= 0x1fffff) { - p[0] = 0xf0 | ((wc >> 18) & 0x07); - p[1] = 0x80 | ((wc >> 12) & 0x3f); - p[2] = 0x80 | ((wc >> 6) & 0x3f); - p[3] = 0x80 | (wc & 0x3f); - p += 4; - } else if (wc <= 0x3ffffff) { - p[0] = 0xf8 | ((wc >> 24) & 0x03); - p[1] = 0x80 | ((wc >> 18) & 0x3f); - p[2] = 0x80 | ((wc >> 12) & 0x3f); - p[3] = 0x80 | ((wc >> 6) & 0x3f); - p[4] = 0x80 | (wc & 0x3f); - p += 5; - } else if (wc <= 0x7fffffff) { - p[0] = 0xfc | ((wc >> 30) & 0x01); - p[1] = 0x80 | ((wc >> 24) & 0x3f); - p[1] = 0x80 | ((wc >> 18) & 0x3f); - p[2] = 0x80 | ((wc >> 12) & 0x3f); - p[3] = 0x80 | ((wc >> 6) & 0x3f); - p[4] = 0x80 | (wc & 0x3f); - p += 6; - } - /* Ignore larger values; UTF-8 can't encode them. */ - } - *p = '\0'; - - return (utf8_value); -} - -static void -add_pax_attr_w(struct archive_string *as, const char *key, const wchar_t *wval) -{ - char *utf8_value = utf8_encode(wval); - if (utf8_value == NULL) - return; - add_pax_attr(as, key, utf8_value); - free(utf8_value); -} - -/* - * Add a key/value attribute to the pax header. This function handles - * the length field and various other syntactic requirements. - */ -static void -add_pax_attr(struct archive_string *as, const char *key, const char *value) -{ - int digits, i, len, next_ten; - char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */ - - /*- - * PAX attributes have the following layout: - * <=> - */ - len = 1 + strlen(key) + 1 + strlen(value) + 1; - - /* - * The field includes the length of the field, so - * computing the correct length is tricky. I start by - * counting the number of base-10 digits in 'len' and - * computing the next higher power of 10. - */ - next_ten = 1; - digits = 0; - i = len; - while (i > 0) { - i = i / 10; - digits++; - next_ten = next_ten * 10; - } - /* - * For example, if string without the length field is 99 - * chars, then adding the 2 digit length "99" will force the - * total length past 100, requiring an extra digit. The next - * statement adjusts for this effect. - */ - if (len + digits >= next_ten) - digits++; - - /* Now, we have the right length so we can build the line. */ - tmp[sizeof(tmp) - 1] = 0; /* Null-terminate the work area. */ - archive_strcat(as, format_int(tmp + sizeof(tmp) - 1, len + digits)); - archive_strappend_char(as, ' '); - archive_strcat(as, key); - archive_strappend_char(as, '='); - archive_strcat(as, value); - archive_strappend_char(as, '\n'); -} - -static void -archive_write_pax_header_xattrs(struct pax *pax, struct archive_entry *entry) -{ - struct archive_string s; - int i = archive_entry_xattr_reset(entry); - - while (i--) { - const char *name; - const void *value; - char *encoded_value; - char *url_encoded_name = NULL, *encoded_name = NULL; - wchar_t *wcs_name = NULL; - size_t size; - - archive_entry_xattr_next(entry, &name, &value, &size); - /* Name is URL-encoded, then converted to wchar_t, - * then UTF-8 encoded. */ - url_encoded_name = url_encode(name); - if (url_encoded_name != NULL) { - /* Convert narrow-character to wide-character. */ - int wcs_length = strlen(url_encoded_name); - wcs_name = malloc((wcs_length + 1) * sizeof(wchar_t)); - if (wcs_name == NULL) - __archive_errx(1, "No memory for xattr conversion"); - mbstowcs(wcs_name, url_encoded_name, wcs_length); - wcs_name[wcs_length] = 0; - free(url_encoded_name); /* Done with this. */ - } - if (wcs_name != NULL) { - encoded_name = utf8_encode(wcs_name); - free(wcs_name); /* Done with wchar_t name. */ - } - - encoded_value = base64_encode(value, size); - - if (encoded_name != NULL && encoded_value != NULL) { - archive_string_init(&s); - archive_strcpy(&s, "LIBARCHIVE.xattr."); - archive_strcat(&s, encoded_name); - add_pax_attr(&(pax->pax_header), s.s, encoded_value); - archive_string_free(&s); - } - free(encoded_name); - free(encoded_value); - } -} - -/* - * TODO: Consider adding 'comment' and 'charset' fields to - * archive_entry so that clients can specify them. Also, consider - * adding generic key/value tags so clients can add arbitrary - * key/value data. - */ -static int -archive_write_pax_header(struct archive *a, - struct archive_entry *entry_original) -{ - struct archive_entry *entry_main; - const char *linkname, *p; - const char *hardlink; - const wchar_t *wp; - const char *suffix_start; - int need_extension, r, ret; - struct pax *pax; - const struct stat *st_main, *st_original; - - char paxbuff[512]; - char ustarbuff[512]; - char ustar_entry_name[256]; - char pax_entry_name[256]; - - need_extension = 0; - pax = a->format_data; - pax->written = 1; - - st_original = archive_entry_stat(entry_original); - - hardlink = archive_entry_hardlink(entry_original); - - /* Make sure this is a type of entry that we can handle here */ - if (hardlink == NULL) { - switch (st_original->st_mode & S_IFMT) { - case S_IFREG: - case S_IFLNK: - case S_IFCHR: - case S_IFBLK: - case S_IFDIR: - case S_IFIFO: - break; - case S_IFSOCK: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "tar format cannot archive socket"); - return (ARCHIVE_WARN); - default: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "tar format cannot archive this (mode=0%lo)", - (unsigned long)st_original->st_mode); - return (ARCHIVE_WARN); - } - } - - /* Copy entry so we can modify it as needed. */ - entry_main = archive_entry_clone(entry_original); - archive_string_empty(&(pax->pax_header)); /* Blank our work area. */ - st_main = archive_entry_stat(entry_main); - - /* - * Determining whether or not the name is too big is ugly - * because of the rules for dividing names between 'name' and - * 'prefix' fields. Here, I pick out the longest possible - * suffix, then test whether the remaining prefix is too long. - */ - wp = archive_entry_pathname_w(entry_main); - p = archive_entry_pathname(entry_main); - if (strlen(p) <= 100) /* Short enough for just 'name' field */ - suffix_start = p; /* Record a zero-length prefix */ - else - /* Find the largest suffix that fits in 'name' field. */ - suffix_start = strchr(p + strlen(p) - 100 - 1, '/'); - - /* - * If name is too long, or has non-ASCII characters, add - * 'path' to pax extended attrs. - */ - if (suffix_start == NULL || suffix_start - p > 155 || has_non_ASCII(wp)) { - add_pax_attr_w(&(pax->pax_header), "path", wp); - archive_entry_set_pathname(entry_main, - build_ustar_entry_name(ustar_entry_name, p, strlen(p), NULL)); - need_extension = 1; - } - - /* If link name is too long or has non-ASCII characters, add - * 'linkpath' to pax extended attrs. */ - linkname = hardlink; - if (linkname == NULL) - linkname = archive_entry_symlink(entry_main); - - if (linkname != NULL) { - /* There is a link name, get the wide version as well. */ - if (hardlink != NULL) - wp = archive_entry_hardlink_w(entry_main); - else - wp = archive_entry_symlink_w(entry_main); - - /* If the link is long or has a non-ASCII character, - * store it as a pax extended attribute. */ - if (strlen(linkname) > 100 || has_non_ASCII(wp)) { - add_pax_attr_w(&(pax->pax_header), "linkpath", wp); - if (hardlink != NULL) - archive_entry_set_hardlink(entry_main, - "././@LongHardLink"); - else - archive_entry_set_symlink(entry_main, - "././@LongSymLink"); - need_extension = 1; - } - } - - /* If file size is too large, add 'size' to pax extended attrs. */ - if (st_main->st_size >= (((int64_t)1) << 33)) { - add_pax_attr_int(&(pax->pax_header), "size", st_main->st_size); - need_extension = 1; - } - - /* If numeric GID is too large, add 'gid' to pax extended attrs. */ - if (st_main->st_gid >= (1 << 18)) { - add_pax_attr_int(&(pax->pax_header), "gid", st_main->st_gid); - need_extension = 1; - } - - /* If group name is too large or has non-ASCII characters, add - * 'gname' to pax extended attrs. */ - p = archive_entry_gname(entry_main); - wp = archive_entry_gname_w(entry_main); - if (p != NULL && (strlen(p) > 31 || has_non_ASCII(wp))) { - add_pax_attr_w(&(pax->pax_header), "gname", wp); - archive_entry_set_gname(entry_main, NULL); - need_extension = 1; - } - - /* If numeric UID is too large, add 'uid' to pax extended attrs. */ - if (st_main->st_uid >= (1 << 18)) { - add_pax_attr_int(&(pax->pax_header), "uid", st_main->st_uid); - need_extension = 1; - } - - /* If user name is too large, add 'uname' to pax extended attrs. */ - /* TODO: If uname has non-ASCII characters, use pax attribute. */ - p = archive_entry_uname(entry_main); - wp = archive_entry_uname_w(entry_main); - if (p != NULL && (strlen(p) > 31 || has_non_ASCII(wp))) { - add_pax_attr_w(&(pax->pax_header), "uname", wp); - archive_entry_set_uname(entry_main, NULL); - need_extension = 1; - } - - /* - * POSIX/SUSv3 doesn't provide a standard key for large device - * numbers. I use the same keys here that Joerg Schilling - * used for 'star.' (Which, somewhat confusingly, are called - * "devXXX" even though they code "rdev" values.) No doubt, - * other implementations use other keys. Note that there's no - * reason we can't write the same information into a number of - * different keys. - * - * Of course, this is only needed for block or char device entries. - */ - if (S_ISBLK(st_main->st_mode) || - S_ISCHR(st_main->st_mode)) { - /* - * If rdevmajor is too large, add 'SCHILY.devmajor' to - * extended attributes. - */ - dev_t rdevmajor, rdevminor; - rdevmajor = major(st_main->st_rdev); - rdevminor = minor(st_main->st_rdev); - if (rdevmajor >= (1 << 18)) { - add_pax_attr_int(&(pax->pax_header), "SCHILY.devmajor", - rdevmajor); - /* - * Non-strict formatting below means we don't - * have to truncate here. Not truncating improves - * the chance that some more modern tar archivers - * (such as GNU tar 1.13) can restore the full - * value even if they don't understand the pax - * extended attributes. See my rant below about - * file size fields for additional details. - */ - /* archive_entry_set_rdevmajor(entry_main, - rdevmajor & ((1 << 18) - 1)); */ - need_extension = 1; - } - - /* - * If devminor is too large, add 'SCHILY.devminor' to - * extended attributes. - */ - if (rdevminor >= (1 << 18)) { - add_pax_attr_int(&(pax->pax_header), "SCHILY.devminor", - rdevminor); - /* Truncation is not necessary here, either. */ - /* archive_entry_set_rdevminor(entry_main, - rdevminor & ((1 << 18) - 1)); */ - need_extension = 1; - } - } - - /* - * Technically, the mtime field in the ustar header can - * support 33 bits, but many platforms use signed 32-bit time - * values. The cutoff of 0x7fffffff here is a compromise. - * Yes, this check is duplicated just below; this helps to - * avoid writing an mtime attribute just to handle a - * high-resolution timestamp in "restricted pax" mode. - */ - if (!need_extension && - ((st_main->st_mtime < 0) || (st_main->st_mtime >= 0x7fffffff))) - need_extension = 1; - - /* I use a star-compatible file flag attribute. */ - p = archive_entry_fflags_text(entry_main); - if (!need_extension && p != NULL && *p != '\0') - need_extension = 1; - - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0) - need_extension = 1; - - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0) - need_extension = 1; - - /* If there are extended attributes, we need an extension */ - if (!need_extension && archive_entry_xattr_count(entry_original) > 0) - need_extension = 1; - - /* - * The following items are handled differently in "pax - * restricted" format. In particular, in "pax restricted" - * format they won't be added unless need_extension is - * already set (we're already generating an extended header, so - * may as well include these). - */ - if (a->archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED || - need_extension) { - - if (st_main->st_mtime < 0 || - st_main->st_mtime >= 0x7fffffff || - ARCHIVE_STAT_MTIME_NANOS(st_main) != 0) - add_pax_attr_time(&(pax->pax_header), "mtime", - st_main->st_mtime, - ARCHIVE_STAT_MTIME_NANOS(st_main)); - - if (st_main->st_ctime != 0 || - ARCHIVE_STAT_CTIME_NANOS(st_main) != 0) - add_pax_attr_time(&(pax->pax_header), "ctime", - st_main->st_ctime, - ARCHIVE_STAT_CTIME_NANOS(st_main)); - - if (st_main->st_atime != 0 || - ARCHIVE_STAT_ATIME_NANOS(st_main) != 0) - add_pax_attr_time(&(pax->pax_header), "atime", - st_main->st_atime, - ARCHIVE_STAT_ATIME_NANOS(st_main)); - - /* I use a star-compatible file flag attribute. */ - p = archive_entry_fflags_text(entry_main); - if (p != NULL && *p != '\0') - add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p); - - /* I use star-compatible ACL attributes. */ - wp = archive_entry_acl_text_w(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); - if (wp != NULL && *wp != L'\0') - add_pax_attr_w(&(pax->pax_header), - "SCHILY.acl.access", wp); - wp = archive_entry_acl_text_w(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); - if (wp != NULL && *wp != L'\0') - add_pax_attr_w(&(pax->pax_header), - "SCHILY.acl.default", wp); - - /* Include star-compatible metadata info. */ - /* Note: "SCHILY.dev{major,minor}" are NOT the - * major/minor portions of "SCHILY.dev". */ - add_pax_attr_int(&(pax->pax_header), "SCHILY.dev", - st_main->st_dev); - add_pax_attr_int(&(pax->pax_header), "SCHILY.ino", - st_main->st_ino); - add_pax_attr_int(&(pax->pax_header), "SCHILY.nlink", - st_main->st_nlink); - - /* Store extended attributes */ - archive_write_pax_header_xattrs(pax, entry_original); - } - - /* Only regular files have data. */ - if (!S_ISREG(archive_entry_mode(entry_main))) - archive_entry_set_size(entry_main, 0); - - /* - * Pax-restricted does not store data for hardlinks, in order - * to improve compatibility with ustar. - */ - if (a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE && - hardlink != NULL) - archive_entry_set_size(entry_main, 0); - - /* - * XXX Full pax interchange format does permit a hardlink - * entry to have data associated with it. I'm not supporting - * that here because the client expects me to tell them whether - * or not this format expects data for hardlinks. If I - * don't check here, then every pax archive will end up with - * duplicated data for hardlinks. Someday, there may be - * need to select this behavior, in which case the following - * will need to be revisited. XXX - */ - if (hardlink != NULL) - archive_entry_set_size(entry_main, 0); - - /* Format 'ustar' header for main entry. - * - * The trouble with file size: If the reader can't understand - * the file size, they may not be able to locate the next - * entry and the rest of the archive is toast. Pax-compliant - * readers are supposed to ignore the file size in the main - * header, so the question becomes how to maximize portability - * for readers that don't support pax attribute extensions. - * For maximum compatibility, I permit numeric extensions in - * the main header so that the file size stored will always be - * correct, even if it's in a format that only some - * implementations understand. The technique used here is: - * - * a) If possible, follow the standard exactly. This handles - * files up to 8 gigabytes minus 1. - * - * b) If that fails, try octal but omit the field terminator. - * That handles files up to 64 gigabytes minus 1. - * - * c) Otherwise, use base-256 extensions. That handles files - * up to 2^63 in this implementation, with the potential to - * go up to 2^94. That should hold us for a while. ;-) - * - * The non-strict formatter uses similar logic for other - * numeric fields, though they're less critical. - */ - __archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0); - - /* If we built any extended attributes, write that entry first. */ - ret = ARCHIVE_OK; - if (archive_strlen(&(pax->pax_header)) > 0) { - struct stat st; - struct archive_entry *pax_attr_entry; - time_t s; - long ns; - - memset(&st, 0, sizeof(st)); - pax_attr_entry = archive_entry_new(); - p = archive_entry_pathname(entry_main); - archive_entry_set_pathname(pax_attr_entry, - build_pax_attribute_name(pax_entry_name, p)); - st.st_size = archive_strlen(&(pax->pax_header)); - /* Copy uid/gid (but clip to ustar limits). */ - st.st_uid = st_main->st_uid; - if (st.st_uid >= 1 << 18) - st.st_uid = (1 << 18) - 1; - st.st_gid = st_main->st_gid; - if (st.st_gid >= 1 << 18) - st.st_gid = (1 << 18) - 1; - /* Copy mode over (but not setuid/setgid bits) */ - st.st_mode = st_main->st_mode; -#ifdef S_ISUID - st.st_mode &= ~S_ISUID; -#endif -#ifdef S_ISGID - st.st_mode &= ~S_ISGID; -#endif -#ifdef S_ISVTX - st.st_mode &= ~S_ISVTX; -#endif - archive_entry_copy_stat(pax_attr_entry, &st); - - /* Copy uname/gname. */ - archive_entry_set_uname(pax_attr_entry, - archive_entry_uname(entry_main)); - archive_entry_set_gname(pax_attr_entry, - archive_entry_gname(entry_main)); - - /* Copy mtime, but clip to ustar limits. */ - s = archive_entry_mtime(entry_main); - ns = archive_entry_mtime_nsec(entry_main); - if (s < 0) { s = 0; ns = 0; } - if (s > 0x7fffffff) { s = 0x7fffffff; ns = 0; } - archive_entry_set_mtime(pax_attr_entry, s, ns); - - /* Ditto for atime. */ - s = archive_entry_atime(entry_main); - ns = archive_entry_atime_nsec(entry_main); - if (s < 0) { s = 0; ns = 0; } - if (s > 0x7fffffff) { s = 0x7fffffff; ns = 0; } - archive_entry_set_atime(pax_attr_entry, s, ns); - - /* Standard ustar doesn't support ctime. */ - archive_entry_set_ctime(pax_attr_entry, 0, 0); - - ret = __archive_write_format_header_ustar(a, paxbuff, - pax_attr_entry, 'x', 1); - - archive_entry_free(pax_attr_entry); - - /* Note that the 'x' header shouldn't ever fail to format */ - if (ret != 0) { - const char *msg = "archive_write_pax_header: " - "'x' header failed?! This can't happen.\n"; - write(2, msg, strlen(msg)); - exit(1); - } - r = (a->compression_write)(a, paxbuff, 512); - if (r != ARCHIVE_OK) { - pax->entry_bytes_remaining = 0; - pax->entry_padding = 0; - return (ARCHIVE_FATAL); - } - - pax->entry_bytes_remaining = archive_strlen(&(pax->pax_header)); - pax->entry_padding = 0x1ff & (- pax->entry_bytes_remaining); - - r = (a->compression_write)(a, pax->pax_header.s, - archive_strlen(&(pax->pax_header))); - if (r != ARCHIVE_OK) { - /* If a write fails, we're pretty much toast. */ - return (ARCHIVE_FATAL); - } - /* Pad out the end of the entry. */ - r = write_nulls(a, pax->entry_padding); - if (r != ARCHIVE_OK) { - /* If a write fails, we're pretty much toast. */ - return (ARCHIVE_FATAL); - } - pax->entry_bytes_remaining = pax->entry_padding = 0; - } - - /* Write the header for main entry. */ - r = (a->compression_write)(a, ustarbuff, 512); - if (r != ARCHIVE_OK) - return (r); - - /* - * Inform the client of the on-disk size we're using, so - * they can avoid unnecessarily writing a body for something - * that we're just going to ignore. - */ - archive_entry_set_size(entry_original, archive_entry_size(entry_main)); - pax->entry_bytes_remaining = archive_entry_size(entry_main); - pax->entry_padding = 0x1ff & (- pax->entry_bytes_remaining); - archive_entry_free(entry_main); - - return (ret); -} - -/* - * We need a valid name for the regular 'ustar' entry. This routine - * tries to hack something more-or-less reasonable. - * - * The approach here tries to preserve leading dir names. We do so by - * working with four sections: - * 1) "prefix" directory names, - * 2) "suffix" directory names, - * 3) inserted dir name (optional), - * 4) filename. - * - * These sections must satisfy the following requirements: - * * Parts 1 & 2 together form an initial portion of the dir name. - * * Part 3 is specified by the caller. (It should not contain a leading - * or trailing '/'.) - * * Part 4 forms an initial portion of the base filename. - * * The filename must be <= 99 chars to fit the ustar 'name' field. - * * Parts 2, 3, 4 together must be <= 99 chars to fit the ustar 'name' fld. - * * Part 1 must be <= 155 chars to fit the ustar 'prefix' field. - * * If the original name ends in a '/', the new name must also end in a '/' - * * Trailing '/.' sequences may be stripped. - * - * Note: Recall that the ustar format does not store the '/' separating - * parts 1 & 2, but does store the '/' separating parts 2 & 3. - */ -static char * -build_ustar_entry_name(char *dest, const char *src, size_t src_length, - const char *insert) -{ - const char *prefix, *prefix_end; - const char *suffix, *suffix_end; - const char *filename, *filename_end; - char *p; - int need_slash = 0; /* Was there a trailing slash? */ - size_t suffix_length = 99; - int insert_length; - - /* Length of additional dir element to be added. */ - if (insert == NULL) - insert_length = 0; - else - /* +2 here allows for '/' before and after the insert. */ - insert_length = strlen(insert) + 2; - - /* Step 0: Quick bailout in a common case. */ - if (src_length < 100 && insert == NULL) { - strncpy(dest, src, src_length); - dest[src_length] = '\0'; - return (dest); - } - - /* Step 1: Locate filename and enforce the length restriction. */ - filename_end = src + src_length; - /* Remove trailing '/' chars and '/.' pairs. */ - for (;;) { - if (filename_end > src && filename_end[-1] == '/') { - filename_end --; - need_slash = 1; /* Remember to restore trailing '/'. */ - continue; - } - if (filename_end > src + 1 && filename_end[-1] == '.' - && filename_end[-2] == '/') { - filename_end -= 2; - need_slash = 1; /* "foo/." will become "foo/" */ - continue; - } - break; - } - if (need_slash) - suffix_length--; - /* Find start of filename. */ - filename = filename_end - 1; - while ((filename > src) && (*filename != '/')) - filename --; - if ((*filename == '/') && (filename < filename_end - 1)) - filename ++; - /* Adjust filename_end so that filename + insert fits in 99 chars. */ - suffix_length -= insert_length; - if (filename_end > filename + suffix_length) - filename_end = filename + suffix_length; - /* Calculate max size for "suffix" section (#3 above). */ - suffix_length -= filename_end - filename; - - /* Step 2: Locate the "prefix" section of the dirname, including - * trailing '/'. */ - prefix = src; - prefix_end = prefix + 155; - if (prefix_end > filename) - prefix_end = filename; - while (prefix_end > prefix && *prefix_end != '/') - prefix_end--; - if ((prefix_end < filename) && (*prefix_end == '/')) - prefix_end++; - - /* Step 3: Locate the "suffix" section of the dirname, - * including trailing '/'. */ - suffix = prefix_end; - suffix_end = suffix + suffix_length; /* Enforce limit. */ - if (suffix_end > filename) - suffix_end = filename; - if (suffix_end < suffix) - suffix_end = suffix; - while (suffix_end > suffix && *suffix_end != '/') - suffix_end--; - if ((suffix_end < filename) && (*suffix_end == '/')) - suffix_end++; - - /* Step 4: Build the new name. */ - /* The OpenBSD strlcpy function is safer, but less portable. */ - /* Rather than maintain two versions, just use the strncpy version. */ - p = dest; - if (prefix_end > prefix) { - strncpy(p, prefix, prefix_end - prefix); - p += prefix_end - prefix; - } - if (suffix_end > suffix) { - strncpy(p, suffix, suffix_end - suffix); - p += suffix_end - suffix; - } - if (insert != NULL) { - /* Note: assume insert does not have leading or trailing '/' */ - strcpy(p, insert); - p += strlen(insert); - *p++ = '/'; - } - strncpy(p, filename, filename_end - filename); - p += filename_end - filename; - if (need_slash) - *p++ = '/'; - *p++ = '\0'; - - return (dest); -} - -/* - * The ustar header for the pax extended attributes must have a - * reasonable name: SUSv3 suggests 'dirname'/PaxHeader/'filename' - * - * Joerg Schiling has argued that this is unnecessary because, in practice, - * if the pax extended attributes get extracted as regular files, noone is - * going to bother reading those attributes to manually restore them. - * Based on this, 'star' uses /tmp/PaxHeader/'basename' as the ustar header - * name. This is a tempting argument, but I'm not entirely convinced. - * I'm also uncomfortable with the fact that "/tmp" is a Unix-ism. - * - * The following routine implements the SUSv3 recommendation, and is - * much simpler because build_ustar_entry_name() above already does - * most of the work (we just need to give it an extra path element to - * insert and handle a few pathological cases). - */ -static char * -build_pax_attribute_name(char *dest, const char *src) -{ - const char *p; - - /* Handle the null filename case. */ - if (src == NULL || *src == '\0') { - strcpy(dest, "PaxHeader/blank"); - return (dest); - } - - /* Prune final '/' and other unwanted final elements. */ - p = src + strlen(src); - for (;;) { - /* Ends in "/", remove the '/' */ - if (p > src && p[-1] == '/') { - --p; - continue; - } - /* Ends in "/.", remove the '.' */ - if (p > src + 1 && p[-1] == '.' - && p[-2] == '/') { - --p; - continue; - } - break; - } - - /* Pathological case: After above, there was nothing left. - * This includes "/." "/./." "/.//./." etc. */ - if (p == src) { - strcpy(dest, "/PaxHeader/rootdir"); - return (dest); - } - - /* Convert unadorned "." into a suitable filename. */ - if (*src == '.' && p == src + 1) { - strcpy(dest, "PaxHeader/currentdir"); - return (dest); - } - - /* General case: build a ustar-compatible name adding "/PaxHeader/". */ - build_ustar_entry_name(dest, src, p - src, "PaxHeader"); - - return (dest); -} - -/* Write two null blocks for the end of archive */ -static int -archive_write_pax_finish(struct archive *a) -{ - struct pax *pax; - int r; - - r = ARCHIVE_OK; - pax = a->format_data; - if (pax->written && a->compression_write != NULL) - r = write_nulls(a, 512 * 2); - archive_string_free(&pax->pax_header); - free(pax); - a->format_data = NULL; - return (r); -} - -static int -archive_write_pax_finish_entry(struct archive *a) -{ - struct pax *pax; - int ret; - - pax = a->format_data; - ret = write_nulls(a, pax->entry_bytes_remaining + pax->entry_padding); - pax->entry_bytes_remaining = pax->entry_padding = 0; - return (ret); -} - -static int -write_nulls(struct archive *a, size_t padding) -{ - int ret, to_write; - - while (padding > 0) { - to_write = padding < a->null_length ? padding : a->null_length; - ret = (a->compression_write)(a, a->nulls, to_write); - if (ret != ARCHIVE_OK) - return (ret); - padding -= to_write; - } - return (ARCHIVE_OK); -} - -static ssize_t -archive_write_pax_data(struct archive *a, const void *buff, size_t s) -{ - struct pax *pax; - int ret; - - pax = a->format_data; - pax->written = 1; - if (s > pax->entry_bytes_remaining) - s = pax->entry_bytes_remaining; - - ret = (a->compression_write)(a, buff, s); - pax->entry_bytes_remaining -= s; - if (ret == ARCHIVE_OK) - return (s); - else - return (ret); -} - -static int -has_non_ASCII(const wchar_t *wp) -{ - while (*wp != L'\0' && *wp < 128) - wp++; - return (*wp != L'\0'); -} - -/* - * Used by extended attribute support; encodes the name - * so that there will be no '=' characters in the result. - */ -static char * -url_encode(const char *in) -{ - const char *s; - char *d; - int out_len = 0; - char *out; - - for (s = in; *s != '\0'; s++) { - if (*s < 33 || *s > 126 || *s == '%' || *s == '=') - out_len += 3; - else - out_len++; - } - - out = (char *)malloc(out_len + 1); - if (out == NULL) - return (NULL); - - for (s = in, d = out; *s != '\0'; s++) { - /* encode any non-printable ASCII character or '%' or '=' */ - if (*s < 33 || *s > 126 || *s == '%' || *s == '=') { - /* URL encoding is '%' followed by two hex digits */ - *d++ = '%'; - *d++ = "0123456789ABCDEF"[0x0f & (*s >> 4)]; - *d++ = "0123456789ABCDEF"[0x0f & *s]; - } else { - *d++ = *s; - } - } - *d = '\0'; - return (out); -} - -/* - * Encode a sequence of bytes into a C string using base-64 encoding. - * - * Returns a null-terminated C string allocated with malloc(); caller - * is responsible for freeing the result. - */ -static char * -base64_encode(const char *s, size_t len) -{ - static const char digits[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int v; - char *d, *out; - - /* 3 bytes becomes 4 chars, but round up and allow for trailing NUL */ - out = malloc((len * 4 + 2) / 3 + 1); - if (out == NULL) - return (NULL); - d = out; - - /* Convert each group of 3 bytes into 4 characters. */ - while (len >= 3) { - v = (((int)s[0] << 16) & 0xff0000) - | (((int)s[1] << 8) & 0xff00) - | (((int)s[2]) & 0x00ff); - s += 3; - len -= 3; - *d++ = digits[(v >> 18) & 0x3f]; - *d++ = digits[(v >> 12) & 0x3f]; - *d++ = digits[(v >> 6) & 0x3f]; - *d++ = digits[(v) & 0x3f]; - } - /* Handle final group of 1 byte (2 chars) or 2 bytes (3 chars). */ - switch (len) { - case 0: break; - case 1: - v = (((int)s[0] << 16) & 0xff0000); - *d++ = digits[(v >> 18) & 0x3f]; - *d++ = digits[(v >> 12) & 0x3f]; - break; - case 2: - v = (((int)s[0] << 16) & 0xff0000) - | (((int)s[1] << 8) & 0xff00); - *d++ = digits[(v >> 18) & 0x3f]; - *d++ = digits[(v >> 12) & 0x3f]; - *d++ = digits[(v >> 6) & 0x3f]; - break; - } - /* Add trailing NUL character so output is a valid C string. */ - *d++ = '\0'; - return (out); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_shar.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_shar.c deleted file mode 100644 index d55407e5fc..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_shar.c +++ /dev/null @@ -1,537 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_shar.c,v 1.11 2004/11/05 05:26:30 kientzle Exp $"); - -#include -#include -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct shar { - int dump; - int end_of_line; - struct archive_entry *entry; - int has_data; - char *last_dir; - char outbuff[1024]; - size_t outbytes; - size_t outpos; - int uuavail; - char uubuffer[3]; - int wrote_header; - struct archive_string work; -}; - -static int archive_write_shar_finish(struct archive *); -static int archive_write_shar_header(struct archive *, - struct archive_entry *); -static ssize_t archive_write_shar_data_sed(struct archive *, - const void * buff, size_t); -static ssize_t archive_write_shar_data_uuencode(struct archive *, - const void * buff, size_t); -static int archive_write_shar_finish_entry(struct archive *); -static int shar_printf(struct archive *, const char *fmt, ...); -static void uuencode_group(struct shar *); - -static int -shar_printf(struct archive *a, const char *fmt, ...) -{ - struct shar *shar; - va_list ap; - int ret; - - shar = a->format_data; - va_start(ap, fmt); - archive_string_empty(&(shar->work)); - archive_string_vsprintf(&(shar->work), fmt, ap); - ret = ((a->compression_write)(a, shar->work.s, strlen(shar->work.s))); - va_end(ap); - return (ret); -} - -/* - * Set output format to 'shar' format. - */ -int -archive_write_set_format_shar(struct archive *a) -{ - struct shar *shar; - - /* If someone else was already registered, unregister them. */ - if (a->format_finish != NULL) - (a->format_finish)(a); - - shar = malloc(sizeof(*shar)); - if (shar == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate shar data"); - return (ARCHIVE_FATAL); - } - memset(shar, 0, sizeof(*shar)); - a->format_data = shar; - - a->pad_uncompressed = 0; - a->format_write_header = archive_write_shar_header; - a->format_finish = archive_write_shar_finish; - a->format_write_data = archive_write_shar_data_sed; - a->format_finish_entry = archive_write_shar_finish_entry; - a->archive_format = ARCHIVE_FORMAT_SHAR_BASE; - a->archive_format_name = "shar"; - return (ARCHIVE_OK); -} - -/* - * An alternate 'shar' that uses uudecode instead of 'sed' to encode - * file contents and can therefore be used to archive binary files. - * In addition, this variant also attempts to restore ownership, file modes, - * and other extended file information. - */ -int -archive_write_set_format_shar_dump(struct archive *a) -{ - struct shar *shar; - - archive_write_set_format_shar(a); - shar = a->format_data; - shar->dump = 1; - a->format_write_data = archive_write_shar_data_uuencode; - a->archive_format = ARCHIVE_FORMAT_SHAR_DUMP; - a->archive_format_name = "shar dump"; - return (ARCHIVE_OK); -} - -static int -archive_write_shar_header(struct archive *a, struct archive_entry *entry) -{ - const char *linkname; - const char *name; - char *p, *pp; - struct shar *shar; - const struct stat *st; - int ret; - - shar = a->format_data; - if (!shar->wrote_header) { - ret = shar_printf(a, "#!/bin/sh\n"); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "# This is a shell archive\n"); - if (ret != ARCHIVE_OK) - return (ret); - shar->wrote_header = 1; - } - - /* Save the entry for the closing. */ - if (shar->entry) - archive_entry_free(shar->entry); - shar->entry = archive_entry_clone(entry); - name = archive_entry_pathname(entry); - st = archive_entry_stat(entry); - - /* Handle some preparatory issues. */ - switch(st->st_mode & S_IFMT) { - case S_IFREG: - /* Only regular files have non-zero size. */ - break; - case S_IFDIR: - archive_entry_set_size(entry, 0); - /* Don't bother trying to recreate '.' */ - if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) - return (ARCHIVE_OK); - break; - case S_IFIFO: - case S_IFCHR: - case S_IFBLK: - /* All other file types have zero size in the archive. */ - archive_entry_set_size(entry, 0); - break; - default: - archive_entry_set_size(entry, 0); - if (archive_entry_hardlink(entry) == NULL && - archive_entry_symlink(entry) == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "shar format cannot archive this"); - return (ARCHIVE_WARN); - } - } - - /* Stock preparation for all file types. */ - ret = shar_printf(a, "echo x %s\n", name); - if (ret != ARCHIVE_OK) - return (ret); - - if (!S_ISDIR(st->st_mode)) { - /* Try to create the dir. */ - p = strdup(name); - pp = strrchr(p, '/'); - /* If there is a / character, try to create the dir. */ - if (pp != NULL) { - *pp = '\0'; - - /* Try to avoid a lot of redundant mkdir commands. */ - if (strcmp(p, ".") == 0) { - /* Don't try to "mkdir ." */ - } else if (shar->last_dir == NULL) { - ret = shar_printf(a, - "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) - return (ret); - shar->last_dir = p; - } else if (strcmp(p, shar->last_dir) == 0) { - /* We've already created this exact dir. */ - free(p); - } else if (strlen(p) < strlen(shar->last_dir) && - strncmp(p, shar->last_dir, strlen(p)) == 0) { - /* We've already created a subdir. */ - free(p); - } else { - ret = shar_printf(a, - "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) - return (ret); - free(shar->last_dir); - shar->last_dir = p; - } - } - } - - /* Handle file-type specific issues. */ - shar->has_data = 0; - if ((linkname = archive_entry_hardlink(entry)) != NULL) { - ret = shar_printf(a, "ln -f %s %s\n", linkname, name); - if (ret != ARCHIVE_OK) - return (ret); - } else if ((linkname = archive_entry_symlink(entry)) != NULL) { - ret = shar_printf(a, "ln -fs %s %s\n", linkname, name); - if (ret != ARCHIVE_OK) - return (ret); - } else { - switch(st->st_mode & S_IFMT) { - case S_IFREG: - if (archive_entry_size(entry) == 0) { - /* More portable than "touch." */ - ret = shar_printf(a, "test -e \"%s\" || :> \"%s\"\n", name, name); - if (ret != ARCHIVE_OK) - return (ret); - } else { - if (shar->dump) { - ret = shar_printf(a, - "uudecode -o %s << 'SHAR_END'\n", - name); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "begin %o %s\n", - archive_entry_mode(entry) & 0777, - name); - if (ret != ARCHIVE_OK) - return (ret); - } else { - ret = shar_printf(a, - "sed 's/^X//' > %s << 'SHAR_END'\n", - name); - if (ret != ARCHIVE_OK) - return (ret); - } - shar->has_data = 1; - shar->end_of_line = 1; - shar->outpos = 0; - shar->outbytes = 0; - } - break; - case S_IFDIR: - ret = shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", - name); - if (ret != ARCHIVE_OK) - return (ret); - /* Record that we just created this directory. */ - if (shar->last_dir != NULL) - free(shar->last_dir); - - shar->last_dir = strdup(name); - /* Trim a trailing '/'. */ - pp = strrchr(shar->last_dir, '/'); - if (pp != NULL && pp[1] == '\0') - *pp = '\0'; - /* - * TODO: Put dir name/mode on a list to be fixed - * up at end of archive. - */ - break; - case S_IFIFO: - ret = shar_printf(a, "mkfifo %s\n", name); - if (ret != ARCHIVE_OK) - return (ret); - break; - case S_IFCHR: - ret = shar_printf(a, "mknod %s c %d %d\n", name, - archive_entry_rdevmajor(entry), - archive_entry_rdevminor(entry)); - if (ret != ARCHIVE_OK) - return (ret); - break; - case S_IFBLK: - ret = shar_printf(a, "mknod %s b %d %d\n", name, - archive_entry_rdevmajor(entry), - archive_entry_rdevminor(entry)); - if (ret != ARCHIVE_OK) - return (ret); - break; - default: - return (ARCHIVE_WARN); - } - } - - return (ARCHIVE_OK); -} - -/* XXX TODO: This could be more efficient XXX */ -static ssize_t -archive_write_shar_data_sed(struct archive *a, const void *buff, size_t n) -{ - struct shar *shar; - const char *src; - int ret; - size_t written = n; - - shar = a->format_data; - if (!shar->has_data) - return (0); - - src = buff; - ret = ARCHIVE_OK; - shar->outpos = 0; - while (n-- > 0) { - if (shar->end_of_line) { - shar->outbuff[shar->outpos++] = 'X'; - shar->end_of_line = 0; - } - if (*src == '\n') - shar->end_of_line = 1; - shar->outbuff[shar->outpos++] = *src++; - - if (shar->outpos > sizeof(shar->outbuff) - 2) { - ret = (a->compression_write)(a, shar->outbuff, - shar->outpos); - if (ret != ARCHIVE_OK) - return (ret); - shar->outpos = 0; - } - } - - if (shar->outpos > 0) - ret = (a->compression_write)(a, shar->outbuff, shar->outpos); - if (ret != ARCHIVE_OK) - return (ret); - return (written); -} - -#define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`') - -/* XXX This could be a lot more efficient. XXX */ -static void -uuencode_group(struct shar *shar) -{ - int t; - - t = 0; - if (shar->uuavail > 0) - t = 0xff0000 & (shar->uubuffer[0] << 16); - if (shar->uuavail > 1) - t |= 0x00ff00 & (shar->uubuffer[1] << 8); - if (shar->uuavail > 2) - t |= 0x0000ff & (shar->uubuffer[2]); - shar->outbuff[shar->outpos++] = UUENC( 0x3f & (t>>18) ); - shar->outbuff[shar->outpos++] = UUENC( 0x3f & (t>>12) ); - shar->outbuff[shar->outpos++] = UUENC( 0x3f & (t>>6) ); - shar->outbuff[shar->outpos++] = UUENC( 0x3f & (t) ); - shar->uuavail = 0; - shar->outbytes += shar->uuavail; - shar->outbuff[shar->outpos] = 0; -} - -static ssize_t -archive_write_shar_data_uuencode(struct archive *a, const void *buff, - size_t length) -{ - struct shar *shar; - const char *src; - size_t n; - int ret; - - shar = a->format_data; - if (!shar->has_data) - return (ARCHIVE_OK); - src = buff; - n = length; - while (n-- > 0) { - if (shar->uuavail == 3) - uuencode_group(shar); - if (shar->outpos >= 60) { - ret = shar_printf(a, "%c%s\n", UUENC(shar->outbytes), - shar->outbuff); - if (ret != ARCHIVE_OK) - return (ret); - shar->outpos = 0; - shar->outbytes = 0; - } - - shar->uubuffer[shar->uuavail++] = *src++; - shar->outbytes++; - } - return (length); -} - -static int -archive_write_shar_finish_entry(struct archive *a) -{ - const char *g, *p, *u; - struct shar *shar; - int ret; - - shar = a->format_data; - if (shar->entry == NULL) - return (0); - - if (shar->dump) { - /* Finish uuencoded data. */ - if (shar->has_data) { - if (shar->uuavail > 0) - uuencode_group(shar); - if (shar->outpos > 0) { - ret = shar_printf(a, "%c%s\n", - UUENC(shar->outbytes), shar->outbuff); - if (ret != ARCHIVE_OK) - return (ret); - shar->outpos = 0; - shar->uuavail = 0; - shar->outbytes = 0; - } - ret = shar_printf(a, "%c\n", UUENC(0)); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "end\n", UUENC(0)); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "SHAR_END\n"); - if (ret != ARCHIVE_OK) - return (ret); - } - /* Restore file mode, owner, flags. */ - /* - * TODO: Don't immediately restore mode for - * directories; defer that to end of script. - */ - ret = shar_printf(a, "chmod %o %s\n", - archive_entry_mode(shar->entry) & 07777, - archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); - - u = archive_entry_uname(shar->entry); - g = archive_entry_gname(shar->entry); - if (u != NULL || g != NULL) { - ret = shar_printf(a, "chown %s%s%s %s\n", - (u != NULL) ? u : "", - (g != NULL) ? ":" : "", (g != NULL) ? g : "", - archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); - } - - if ((p = archive_entry_fflags_text(shar->entry)) != NULL) { - ret = shar_printf(a, "chflags %s %s\n", p, - archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); - } - - /* TODO: restore ACLs */ - - } else { - if (shar->has_data) { - /* Finish sed-encoded data: ensure last line ends. */ - if (!shar->end_of_line) { - ret = shar_printf(a, "\n"); - if (ret != ARCHIVE_OK) - return (ret); - } - ret = shar_printf(a, "SHAR_END\n"); - if (ret != ARCHIVE_OK) - return (ret); - } - } - - archive_entry_free(shar->entry); - shar->entry = NULL; - return (0); -} - -static int -archive_write_shar_finish(struct archive *a) -{ - struct shar *shar; - int ret; - - /* - * TODO: Accumulate list of directory names/modes and - * fix them all up at end-of-archive. - */ - - shar = a->format_data; - - /* - * Only write the end-of-archive markers if the archive was - * actually started. This avoids problems if someone sets - * shar format, then sets another format (which would invoke - * shar_finish to free the format-specific data). - */ - if (shar->wrote_header) { - ret = shar_printf(a, "exit\n"); - if (ret != ARCHIVE_OK) - return (ret); - /* Shar output is never padded. */ - archive_write_set_bytes_in_last_block(a, 1); - /* - * TODO: shar should also suppress padding of - * uncompressed data within gzip/bzip2 streams. - */ - } - if (shar->entry != NULL) - archive_entry_free(shar->entry); - if (shar->last_dir != NULL) - free(shar->last_dir); - archive_string_free(&(shar->work)); - free(shar); - a->format_data = NULL; - return (ARCHIVE_OK); -} diff --git a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_ustar.c b/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_ustar.c deleted file mode 100644 index 7235361856..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/archive_write_set_format_ustar.c +++ /dev/null @@ -1,500 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ustar.c,v 1.14 2005/11/08 03:52:42 kientzle Exp $"); - -#include -#ifdef MAJOR_IN_MKDEV -#include -#else -#ifdef MAJOR_IN_SYSMACROS -#include -#endif -#endif -#include -#include -#include -#include - -#include "archive.h" -#include "archive_entry.h" -#include "archive_private.h" - -struct ustar { - uint64_t entry_bytes_remaining; - uint64_t entry_padding; - char written; -}; - -/* - * Define structure of POSIX 'ustar' tar header. - */ -struct archive_entry_header_ustar { - char name[100]; - char mode[6]; - char mode_padding[2]; - char uid[6]; - char uid_padding[2]; - char gid[6]; - char gid_padding[2]; - char size[11]; - char size_padding[1]; - char mtime[11]; - char mtime_padding[1]; - char checksum[8]; - char typeflag[1]; - char linkname[100]; - char magic[6]; /* For POSIX: "ustar\0" */ - char version[2]; /* For POSIX: "00" */ - char uname[32]; - char gname[32]; - char rdevmajor[6]; - char rdevmajor_padding[2]; - char rdevminor[6]; - char rdevminor_padding[2]; - char prefix[155]; - char padding[12]; -}; - -/* - * A filled-in copy of the header for initialization. - */ -static const struct archive_entry_header_ustar template_header = { - { "" }, /* name */ - { "000000" }, { ' ', '\0' }, /* mode, space-null termination. */ - { "000000" }, { ' ', '\0' }, /* uid, space-null termination. */ - { "000000" }, { ' ', '\0' }, /* gid, space-null termination. */ - { "00000000000" }, { ' ' }, /* size, space termination. */ - { "00000000000" }, { ' ' }, /* mtime, space termination. */ - { " " }, /* Initial checksum value. */ - { '0' }, /* default: regular file */ - { "" }, /* linkname */ - { "ustar" }, /* magic */ - { '0', '0' }, /* version */ - { "" }, /* uname */ - { "" }, /* gname */ - { "000000" }, { ' ', '\0' }, /* rdevmajor, space-null termination */ - { "000000" }, { ' ', '\0' }, /* rdevminor, space-null termination */ - { "" }, /* prefix */ - { "" } /* padding */ -}; - -static ssize_t archive_write_ustar_data(struct archive *a, const void *buff, - size_t s); -static int archive_write_ustar_finish(struct archive *); -static int archive_write_ustar_finish_entry(struct archive *); -static int archive_write_ustar_header(struct archive *, - struct archive_entry *entry); -static int format_256(int64_t, char *, int); -static int format_number(int64_t, char *, int size, int max, int strict); -static int format_octal(int64_t, char *, int); -static int write_nulls(struct archive *a, size_t); - -/* - * Set output format to 'ustar' format. - */ -int -archive_write_set_format_ustar(struct archive *a) -{ - struct ustar *ustar; - - /* If someone else was already registered, unregister them. */ - if (a->format_finish != NULL) - (a->format_finish)(a); - - ustar = malloc(sizeof(*ustar)); - if (ustar == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate ustar data"); - return (ARCHIVE_FATAL); - } - memset(ustar, 0, sizeof(*ustar)); - a->format_data = ustar; - - a->pad_uncompressed = 1; /* Mimic gtar in this respect. */ - a->format_write_header = archive_write_ustar_header; - a->format_write_data = archive_write_ustar_data; - a->format_finish = archive_write_ustar_finish; - a->format_finish_entry = archive_write_ustar_finish_entry; - a->archive_format = ARCHIVE_FORMAT_TAR_USTAR; - a->archive_format_name = "POSIX ustar"; - return (ARCHIVE_OK); -} - -static int -archive_write_ustar_header(struct archive *a, struct archive_entry *entry) -{ - char buff[512]; - int ret; - struct ustar *ustar; - - ustar = a->format_data; - ustar->written = 1; - - /* Only regular files (not hardlinks) have data. */ - if (archive_entry_hardlink(entry) != NULL || - archive_entry_symlink(entry) != NULL || - !S_ISREG(archive_entry_mode(entry))) - archive_entry_set_size(entry, 0); - - ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1); - if (ret != ARCHIVE_OK) - return (ret); - ret = (a->compression_write)(a, buff, 512); - if (ret != ARCHIVE_OK) - return (ret); - - ustar->entry_bytes_remaining = archive_entry_size(entry); - ustar->entry_padding = 0x1ff & (- ustar->entry_bytes_remaining); - return (ARCHIVE_OK); -} - -/* - * Format a basic 512-byte "ustar" header. - * - * Returns -1 if format failed (due to field overflow). - * Note that this always formats as much of the header as possible. - * If "strict" is set to zero, it will extend numeric fields as - * necessary (overwriting terminators or using base-256 extensions). - * - * This is exported so that other 'tar' formats can use it. - */ -int -__archive_write_format_header_ustar(struct archive *a, char buff[512], - struct archive_entry *entry, int tartype, int strict) -{ - unsigned int checksum; - struct archive_entry_header_ustar *h; - int i, ret; - size_t copy_length; - const char *p, *pp; - const struct stat *st; - int mytartype; - - ret = 0; - mytartype = -1; - /* - * The "template header" already includes the "ustar" - * signature, various end-of-field markers and other required - * elements. - */ - memcpy(buff, &template_header, 512); - - h = (struct archive_entry_header_ustar *)buff; - - /* - * Because the block is already null-filled, and strings - * are allowed to exactly fill their destination (without null), - * I use memcpy(dest, src, strlen()) here a lot to copy strings. - */ - - pp = archive_entry_pathname(entry); - if (strlen(pp) <= sizeof(h->name)) - memcpy(h->name, pp, strlen(pp)); - else { - /* Store in two pieces, splitting at a '/'. */ - p = strchr(pp + strlen(pp) - sizeof(h->name) - 1, '/'); - /* - * If there is no path separator, or the prefix or - * remaining name are too large, return an error. - */ - if (!p) { - archive_set_error(a, ENAMETOOLONG, - "Pathname too long"); - ret = ARCHIVE_WARN; - } else if (p > pp + sizeof(h->prefix)) { - archive_set_error(a, ENAMETOOLONG, - "Pathname too long"); - ret = ARCHIVE_WARN; - } else { - /* Copy prefix and remainder to appropriate places */ - memcpy(h->prefix, pp, p - pp); - memcpy(h->name, p + 1, pp + strlen(pp) - p - 1); - } - } - - p = archive_entry_hardlink(entry); - if (p != NULL) - mytartype = '1'; - else - p = archive_entry_symlink(entry); - if (p != NULL && p[0] != '\0') { - copy_length = strlen(p); - if (copy_length > sizeof(h->linkname)) { - archive_set_error(a, ENAMETOOLONG, - "Link contents too long"); - ret = ARCHIVE_WARN; - copy_length = sizeof(h->linkname); - } - memcpy(h->linkname, p, copy_length); - } - - p = archive_entry_uname(entry); - if (p != NULL && p[0] != '\0') { - copy_length = strlen(p); - if (copy_length > sizeof(h->uname)) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Username too long"); - ret = ARCHIVE_WARN; - copy_length = sizeof(h->uname); - } - memcpy(h->uname, p, copy_length); - } - - p = archive_entry_gname(entry); - if (p != NULL && p[0] != '\0') { - copy_length = strlen(p); - if (strlen(p) > sizeof(h->gname)) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Group name too long"); - ret = ARCHIVE_WARN; - copy_length = sizeof(h->gname); - } - memcpy(h->gname, p, copy_length); - } - - st = archive_entry_stat(entry); - - if (format_number(st->st_mode & 07777, h->mode, sizeof(h->mode), 8, strict)) { - archive_set_error(a, ERANGE, "Numeric mode too large"); - ret = ARCHIVE_WARN; - } - - if (format_number(st->st_uid, h->uid, sizeof(h->uid), 8, strict)) { - archive_set_error(a, ERANGE, "Numeric user ID too large"); - ret = ARCHIVE_WARN; - } - - if (format_number(st->st_gid, h->gid, sizeof(h->gid), 8, strict)) { - archive_set_error(a, ERANGE, "Numeric group ID too large"); - ret = ARCHIVE_WARN; - } - - if (format_number(st->st_size, h->size, sizeof(h->size), 12, strict)) { - archive_set_error(a, ERANGE, "File size out of range"); - ret = ARCHIVE_WARN; - } - - if (format_number(st->st_mtime, h->mtime, sizeof(h->mtime), 12, strict)) { - archive_set_error(a, ERANGE, - "File modification time too large"); - ret = ARCHIVE_WARN; - } - - if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) { - if (format_number(major(st->st_rdev), h->rdevmajor, - sizeof(h->rdevmajor), 8, strict)) { - archive_set_error(a, ERANGE, - "Major device number too large"); - ret = ARCHIVE_WARN; - } - - if (format_number(minor(st->st_rdev), h->rdevminor, - sizeof(h->rdevminor), 8, strict)) { - archive_set_error(a, ERANGE, - "Minor device number too large"); - ret = ARCHIVE_WARN; - } - } - - if (tartype >= 0) { - h->typeflag[0] = tartype; - } else if (mytartype >= 0) { - h->typeflag[0] = mytartype; - } else { - switch (st->st_mode & S_IFMT) { - case S_IFREG: h->typeflag[0] = '0' ; break; - case S_IFLNK: h->typeflag[0] = '2' ; break; - case S_IFCHR: h->typeflag[0] = '3' ; break; - case S_IFBLK: h->typeflag[0] = '4' ; break; - case S_IFDIR: h->typeflag[0] = '5' ; break; - case S_IFIFO: h->typeflag[0] = '6' ; break; - case S_IFSOCK: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "tar format cannot archive socket"); - ret = ARCHIVE_WARN; - break; - default: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, - "tar format cannot archive this (mode=0%lo)", - (unsigned long)st->st_mode); - ret = ARCHIVE_WARN; - } - } - - checksum = 0; - for (i = 0; i < 512; i++) - checksum += 255 & (unsigned int)buff[i]; - h->checksum[6] = '\0'; /* Can't be pre-set in the template. */ - /* h->checksum[7] = ' '; */ /* This is pre-set in the template. */ - format_octal(checksum, h->checksum, 6); - return (ret); -} - -/* - * Format a number into a field, with some intelligence. - */ -static int -format_number(int64_t v, char *p, int s, int maxsize, int strict) -{ - int64_t limit; - - limit = ((int64_t)1 << (s*3)); - - /* "Strict" only permits octal values with proper termination. */ - if (strict) - return (format_octal(v, p, s)); - - /* - * In non-strict mode, we allow the number to overwrite one or - * more bytes of the field termination. Even old tar - * implementations should be able to handle this with no - * problem. - */ - if (v >= 0) { - while (s <= maxsize) { - if (v < limit) - return (format_octal(v, p, s)); - s++; - limit <<= 3; - } - } - - /* Base-256 can handle any number, positive or negative. */ - return (format_256(v, p, maxsize)); -} - -/* - * Format a number into the specified field using base-256. - */ -static int -format_256(int64_t v, char *p, int s) -{ - p += s; - while (s-- > 0) { - *--p = (char)(v & 0xff); - v >>= 8; - } - *p |= 0x80; /* Set the base-256 marker bit. */ - return (0); -} - -/* - * Format a number into the specified field. - */ -static int -format_octal(int64_t v, char *p, int s) -{ - int len; - - len = s; - - /* Octal values can't be negative, so use 0. */ - if (v < 0) { - while (len-- > 0) - *p++ = '0'; - return (-1); - } - - p += s; /* Start at the end and work backwards. */ - while (s-- > 0) { - *--p = '0' + (v & 7); - v >>= 3; - } - - if (v == 0) - return (0); - - /* If it overflowed, fill field with max value. */ - while (len-- > 0) - *p++ = '7'; - - return (-1); -} - -static int -archive_write_ustar_finish(struct archive *a) -{ - struct ustar *ustar; - int r; - - r = ARCHIVE_OK; - ustar = a->format_data; - /* - * Suppress end-of-archive if nothing else was ever written. - * This fixes a problem where setting one format, then another - * ends up writing a gratuitous end-of-archive marker. - */ - if (ustar->written && a->compression_write != NULL) - r = write_nulls(a, 512*2); - free(ustar); - a->format_data = NULL; - return (r); -} - -static int -archive_write_ustar_finish_entry(struct archive *a) -{ - struct ustar *ustar; - int ret; - - ustar = a->format_data; - ret = write_nulls(a, - ustar->entry_bytes_remaining + ustar->entry_padding); - ustar->entry_bytes_remaining = ustar->entry_padding = 0; - return (ret); -} - -static int -write_nulls(struct archive *a, size_t padding) -{ - int ret, to_write; - - while (padding > 0) { - to_write = padding < a->null_length ? padding : a->null_length; - ret = (a->compression_write)(a, a->nulls, to_write); - if (ret != ARCHIVE_OK) - return (ret); - padding -= to_write; - } - return (ARCHIVE_OK); -} - -static ssize_t -archive_write_ustar_data(struct archive *a, const void *buff, size_t s) -{ - struct ustar *ustar; - int ret; - - ustar = a->format_data; - if (s > ustar->entry_bytes_remaining) - s = ustar->entry_bytes_remaining; - ret = (a->compression_write)(a, buff, s); - ustar->entry_bytes_remaining -= s; - if (ret != ARCHIVE_OK) - return (ret); - return (s); -} diff --git a/contrib/libarchive-1.3.1/libarchive/libarchive-formats.5 b/contrib/libarchive-1.3.1/libarchive/libarchive-formats.5 deleted file mode 100644 index 3112274977..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/libarchive-formats.5 +++ /dev/null @@ -1,245 +0,0 @@ -.\" Copyright (c) 2003-2004 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 AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/libarchive-formats.5,v 1.11 2006/07/29 23:49:25 kientzle Exp $ -.\" -.Dd April 27, 2004 -.Dt libarchive-formats 3 -.Os -.Sh NAME -.Nm libarchive-formats -.Nd archive formats supported by the libarchive library -.Sh DESCRIPTION -The -.Xr libarchive 3 -library reads and writes a variety of streaming archive formats. -Generally speaking, all of these archive formats consist of a series of -.Dq entries . -Each entry stores a single file system object, such as a file, directory, -or symbolic link. -.Pp -The following provides a brief description of each format supported -by libarchive, with some information about recognized extensions or -limitations of the current library support. -Note that just because a format is supported by libarchive does not -imply that a program that uses libarchive will support that format. -Applications that use libarchive specify which formats they wish -to support. -.Ss Tar Formats -The -.Xr libarchive 3 -library can read most tar archives. -However, it only writes POSIX-standard -.Dq ustar -and -.Dq pax interchange -formats. -.Pp -All tar formats store each entry in one or more 512-byte records. -The first record is used for file metadata, including filename, -timestamp, and mode information, and the file data is stored in -subsequent records. -Later variants have extended this by either appropriating undefined -areas of the header record, extending the header to multiple records, -or by storing special entries that modify the interpretation of -subsequent entries. -.Pp -.Bl -tag -width indent -.It Cm gnutar -The -.Xr libarchive 3 -library can read GNU-format tar archives. -It currently supports the most popular GNU extensions, including -modern long filename and linkname support, as well as atime and ctime data. -The libarchive library does not support multi-volume -archives, nor the old GNU long filename format. -.It Cm pax -The -.Xr libarchive 3 -library can read and write POSIX-compliant pax interchange format -archives. -Pax interchange format archives are an extension of the older ustar -format that adds a separate entry with additional attributes stored -as key/value pairs. -The presence of this additional entry is the only difference between -pax interchange format and the older ustar format. -The extended attributes are of unlimited length and are stored -as UTF-8 Unicode strings. -Keywords defined in the standard are in all lowercase; vendors are allowed -to define custom keys by preceding them with the vendor name in all uppercase. -When writing pax archives, libarchive uses many of the SCHILY keys -defined by Joerg Schilling's -.Dq star -archiver. -The libarchive library can read most of the SCHILY keys. -It ignores any keywords that it does not understand. -.It Cm restricted pax -The libarchive library can also write pax archives in which it -attempts to suppress the extended attributes entry whenever -possible. -The result will be identical to a ustar archive unless the -extended attributes entry is required to store a long file -name, long linkname, extended ACL, file flags, or if any of the standard -ustar data (user name, group name, UID, GID, etc) cannot be fully -represented in the ustar header. -In all cases, the result can be dearchived by any program that -can read POSIX-compliant pax interchange format archives. -Programs that correctly read ustar format (see below) will also be -able to read this format; any extended attributes will be extracted as -separate files stored in -.Pa PaxHeader -directories. -.It Cm ustar -The libarchive library can both read and write this format. -This format has the following limitations: -.Bl -bullet -compact -.It -Device major and minor numbers are limited to 21 bits. -Nodes with larger numbers will not be added to the archive. -.It -Path names in the archive are limited to 255 bytes. -(Shorter if there is no / character in exactly the right place.) -.It -Symbolic links and hard links are stored in the archive with -the name of the referenced file. -This name is limited to 100 bytes. -.It -Extended attributes, file flags, and other extended -security information cannot be stored. -.It -Archive entries are limited to 2 gigabytes in size. -.El -Note that the pax interchange format has none of these restrictions. -.El -.Pp -The libarchive library can also read a variety of commonly-used extensions to -the basic tar format. -In particular, it supports base-256 values in certain numeric fields. -This essentially removes the limitations on file size, modification time, -and device numbers. -.Pp -The first tar program appeared in Sixth Edition Unix (circa 1976). -This makes the tar format one of the oldest and most widely-supported -archive formats. -The first official standard for the tar file format was the -.Dq ustar -(Unix Standard Tar) format defined by POSIX in 1988. -POSIX.1-2001 extended the ustar format to create the -.Dq pax interchange -format. -There have also been many custom variations. -.Ss Cpio Formats -The libarchive library can read a number of common cpio variants and can write -.Dq odc -format archives. -A cpio archive stores each entry as a fixed-size header followed -by a variable-length filename and variable-length data. -Unlike tar, cpio does only minimal padding of the header or file data. -There are a variety of cpio formats, which differ primarily in -how they store the initial header: some store the values as -octal or hexadecimal numbers in ASCII, others as binary values of -varying byte order and length. -.Bl -tag -width indent -.It Cm binary -The libarchive library can read both big-endian and little-endian -variants of the original binary cpio format. -This format used 32-bit binary values for file size and mtime, -and 16-bit binary values for the other fields. -.It Cm odc -The libarchive library can both read and write this -POSIX-standard format. -This format stores the header contents as octal values in ASCII. -It is standard, portable, and immune from byte-order confusion. -File sizes and mtime are limited to 33 bits (8GB file size), -other fields are limited to 18 bits. -.It Cm SVR4 -The libarchive library can read both CRC and non-CRC variants of -this format. -The SVR4 format uses eight-digit hexadecimal values for -all header fields. -This limits file size to 4GB, and also limits the mtime and -other fields to 32 bits. -The SVR4 format can optionally include a CRC of the file -contents, although libarchive does not currently verify this CRC. -.El -.Pp -Cpio is an old format that was widely used because of its simplicity -and its support for very long filenames. -Unfortunately, it has many limitations that make it unsuitable -for widespread use. -Only the POSIX format permits files over 4GB, and its 18-bit -limit for most other fields makes it unsuitable for modern systems. -In addition, cpio formats only store numeric UID/GID values (not -usernames and group names), which can make it very difficult to correctly -transfer archives across systems. -.Ss Shar Formats -A -.Dq shell archive -is a shell script that, when executed on a POSIX-compliant -system, will recreate a collection of file system objects. -The libarchive library can write two different kinds of shar archives: -.Bl -tag -width indent -.It Cm shar -The traditional shar format uses a limited set of POSIX -commands, including -.Xr echo 1 , -.Xr mkdir 1 , -and -.Xr sed 1 . -It is suitable for portably archiving small collections of plain text files. -However, it is not generally well-suited for large archives -(many implementations of -.Xr sh 1 -have limits on the size of a script) nor should it be used with non-text files. -.It Cm shardump -This format is similar to shar but encodes files using -.Xr uuencode 1 -so that the result will be a plain text file regardless of the file contents. -It also includes additional shell commands that attempt to reproduce as -many file attributes as possible, including owner, mode, and flags. -The additional commands used to restore file attributes make -shardump archives less portable than plain shar archives. -.El -.Ss ISO9660 format -Libarchive can read and extract from files containing ISO9660-compliant -CDROM images. -It also has partial support for Rockridge extensions. -In many cases, this can remove the need to burn a physical CDROM. -It also avoids security and complexity issues that come with -virtual mounts and loopback devices. -.Ss Zip format -Libarchive can extract from most zip format archives. -It currently only supports uncompressed entries and entries -compressed with the -.Dq deflate -algorithm. -Older zip compression algorithms are not supported. -.Sh SEE ALSO -.Xr cpio 1 , -.Xr mkisofs 1 , -.Xr shar 1 , -.Xr tar 1 , -.Xr zip 1 , -.Xr zlib 3 , -.Xr tar 5 diff --git a/contrib/libarchive-1.3.1/libarchive/libarchive.3 b/contrib/libarchive-1.3.1/libarchive/libarchive.3 deleted file mode 100644 index 9cf4bc8e4d..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/libarchive.3 +++ /dev/null @@ -1,331 +0,0 @@ -.\" 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/libarchive.3,v 1.7 2005/01/21 20:50:38 ru Exp $ -.\" -.Dd August 19, 2006 -.Dt LIBARCHIVE 3 -.Os -.Sh NAME -.Nm libarchive -.Nd functions for reading and writing streaming archives -.Sh LIBRARY -.Lb libarchive -.Sh OVERVIEW -The -.Nm -library provides a flexible interface for reading and writing -streaming archive files such as tar and cpio. -The library is inherently stream-oriented; readers serially iterate through -the archive, writers serially add things to the archive. -In particular, note that there is no built-in support for -random access nor for in-place modification. -.Pp -When reading an archive, the library automatically detects the -format and the compression. -The library currently has read support for: -.Bl -bullet -compact -.It -old-style tar archives, -.It -most variants of the POSIX -.Dq ustar -format, -.It -the POSIX -.Dq pax interchange -format, -.It -GNU-format tar archives, -.It -most common cpio archive formats, -.It -ISO9660 CD images (with or without RockRidge extensions), -.It -Zip archives. -.El -The library automatically detects archives compressed with -.Xr gzip 1 , -.Xr bzip2 1 , -or -.Xr compress 1 -and decompresses them transparently. -.Pp -When writing an archive, you can specify the compression -to be used and the format to use. -The library can write -.Bl -bullet -compact -.It -POSIX-standard -.Dq ustar -archives, -.It -POSIX -.Dq pax interchange format -archives, -.It -POSIX octet-oriented cpio archives, -.It -two different variants of shar archives. -.El -Pax interchange format is an extension of the tar archive format that -eliminates essentially all of the limitations of historic tar formats -in a standard fashion that is supported -by POSIX-compliant -.Xr pax 1 -implementations on many systems as well as several newer implementations of -.Xr tar 1 . -Note that the default write format will suppress the pax extended -attributes for most entries; explicitly requesting pax format will -enable those attributes for all entries. -.Pp -The read and write APIs are accessed through the -.Fn archive_read_XXX -functions and the -.Fn archive_write_XXX -functions, respectively, and either can be used independently -of the other. -.Pp -The rest of this manual page provides an overview of the library -operation. -More detailed information can be found in the individual manual -pages for each API or utility function. -.Sh READING AN ARCHIVE -To read an archive, you must first obtain an initialized -.Tn struct archive -object from -.Fn archive_read_new . -You can then modify this object for the desired operations with the -various -.Fn archive_read_set_XXX -and -.Fn archive_read_support_XXX -functions. -In particular, you will need to invoke appropriate -.Fn archive_read_support_XXX -functions to enable the corresponding compression and format -support. -Note that these latter functions perform two distinct operations: -they cause the corresponding support code to be linked into your -program, and they enable the corresponding auto-detect code. -Unless you have specific constraints, you will generally want -to invoke -.Fn archive_read_support_compression_all -and -.Fn archive_read_support_format_all -to enable auto-detect for all formats and compression types -currently supported by the library. -.Pp -Once you have prepared the -.Tn struct archive -object, you call -.Fn archive_read_open -to actually open the archive and prepare it for reading. -There are several variants of this function; -the most basic expects you to provide pointers to several -functions that can provide blocks of bytes from the archive. -There are convenience forms that allow you to -specify a filename, file descriptor, -.Ft "FILE *" -object, or a block of memory from which to read the archive data. -Note that the core library makes no assumptions about the -size of the blocks read; -callback functions are free to read whatever block size is -most appropriate for the medium. -.Pp -Each archive entry consists of a header followed by a certain -amount of data. -You can obtain the next header with -.Fn archive_read_next_header , -which returns a pointer to an -.Tn struct archive_entry -structure with information about the current archive element. -If the entry is a regular file, then the header will be followed -by the file data. -You can use -.Fn archive_read_data -(which works much like the -.Xr read 2 -system call) -to read this data from the archive. -You may prefer to use the higher-level -.Fn archive_read_data_skip , -which reads and discards the data for this entry, -.Fn archive_read_data_to_buffer , -which reads the data into an in-memory buffer, -.Fn archive_read_data_to_file , -which copies the data to the provided file descriptor, or -.Fn archive_read_extract , -which recreates the specified entry on disk and copies data -from the archive. -In particular, note that -.Fn archive_read_extract -uses the -.Tn struct archive_entry -structure that you provide it, which may differ from the -entry just read from the archive. -In particular, many applications will want to override the -pathname, file permissions, or ownership. -.Pp -Once you have finished reading data from the archive, you -should call -.Fn archive_read_close -to close the archive, then call -.Fn archive_read_finish -to release all resources, including all memory allocated by the library. -.Pp -The -.Xr archive_read 3 -manual page provides more detailed calling information for this API. -.Sh WRITING AN ARCHIVE -You use a similar process to write an archive. -The -.Fn archive_write_new -function creates an archive object useful for writing, -the various -.Fn archive_write_set_XXX -functions are used to set parameters for writing the archive, and -.Fn archive_write_open -completes the setup and opens the archive for writing. -.Pp -Individual archive entries are written in a three-step -process: -You first initialize a -.Tn struct archive_entry -structure with information about the new entry. -At a minimum, you should set the pathname of the -entry and provide a -.Va struct stat -with a valid -.Va st_mode -field, which specifies the type of object and -.Va st_size -field, which specifies the size of the data portion of the object. -The -.Fn archive_write_header -function actually writes the header data to the archive. -You can then use -.Fn archive_write_data -to write the actual data. -.Pp -After all entries have been written, use the -.Fn archive_write_finish -function to release all resources. -.Pp -The -.Xr archive_write 3 -manual page provides more detailed calling information for this API. -.Sh DESCRIPTION -Detailed descriptions of each function are provided by the -corresponding manual pages. -.Pp -All of the functions utilize an opaque -.Tn struct archive -datatype that provides access to the archive contents. -.Pp -The -.Tn struct archive_entry -structure contains a complete description of a single archive -entry. -It uses an opaque interface that is fully documented in -.Xr archive_entry 3 . -.Pp -Users familiar with historic formats should be aware that the newer -variants have eliminated most restrictions on the length of textual fields. -Clients should not assume that filenames, link names, user names, or -group names are limited in length. -In particular, pax interchange format can easily accomodate pathnames -in arbitrary character sets that exceed -.Va PATH_MAX . -.Sh RETURN VALUES -Most functions return zero on success, non-zero on error. -The return value indicates the general severity of the error, ranging -from -.Cm ARCHIVE_WARN , -which indicates a minor problem that should probably be reported -to the user, to -.Cm ARCHIVE_FATAL , -which indicates a serious problem that will prevent any further -operations on this archive. -On error, the -.Fn archive_errno -function can be used to retrieve a numeric error code (see -.Xr errno 2 ) . -The -.Fn archive_error_string -returns a textual error message suitable for display. -.Pp -.Fn archive_read_new -and -.Fn archive_write_new -return pointers to an allocated and initialized -.Tn struct archive -object. -.Pp -.Fn archive_read_data -and -.Fn archive_write_data -return a count of the number of bytes actually read or written. -A value of zero indicates the end of the data for this entry. -A negative value indicates an error, in which case the -.Fn archive_errno -and -.Fn archive_error_string -functions can be used to obtain more information. -.Sh ENVIRONMENT -There are character set conversions within the -.Xr archive_entry 3 -functions that are impacted by the currently-selected locale. -.Sh SEE ALSO -.Xr tar 1 , -.Xr archive_entry 3 , -.Xr archive_read 3 , -.Xr archive_util 3 , -.Xr archive_write 3 , -.Xr tar 5 -.Sh HISTORY -The -.Nm libarchive -library first appeared in -.Fx 5.3 . -.Sh AUTHORS -.An -nosplit -The -.Nm libarchive -library was written by -.An Tim Kientzle Aq kientzle@acm.org . -.Sh BUGS -Some archive formats support information that is not supported by -.Tn struct archive_entry . -Such information cannot be fully archived or restored using this library. -This includes, for example, comments, character sets, -or the arbitrary key/value pairs that can appear in -pax interchange format archives. -.Pp -Conversely, of course, not all of the information that can be -stored in an -.Tn struct archive_entry -is supported by all formats. -For example, cpio formats do not support nanosecond timestamps; -old tar formats do not support large device numbers. diff --git a/contrib/libarchive-1.3.1/libarchive/tar.5 b/contrib/libarchive-1.3.1/libarchive/tar.5 deleted file mode 100644 index bdbfa043c0..0000000000 --- a/contrib/libarchive-1.3.1/libarchive/tar.5 +++ /dev/null @@ -1,729 +0,0 @@ -.\" Copyright (c) 2003-2004 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 AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/lib/libarchive/tar.5,v 1.15 2006/07/29 23:51:10 kientzle Exp $ -.\" -.Dd May 20, 2004 -.Dt TAR 5 -.Os -.Sh NAME -.Nm tar -.Nd format of tape archive files -.Sh DESCRIPTION -The -.Nm -archive format collects any number of files, directories, and other -file system objects (symbolic links, device nodes, etc.) into a single -stream of bytes. -The format was originally designed to be used with -tape drives that operate with fixed-size blocks, but is widely used as -a general packaging mechanism. -.Ss General Format -A -.Nm -archive consists of a series of 512-byte records. -Each file system object requires a header record which stores basic metadata -(pathname, owner, permissions, etc.) and zero or more records containing any -file data. -The end of the archive is indicated by two records consisting -entirely of zero bytes. -.Pp -For compatibility with tape drives that use fixed block sizes, -programs that read or write tar files always read or write a fixed -number of records with each I/O operation. -These -.Dq blocks -are always a multiple of the record size. -The most common block size\(emand the maximum supported by historic -implementations\(emis 10240 bytes or 20 records. -(Note: the terms -.Dq block -and -.Dq record -here are not entirely standard; this document follows the -convention established by John Gilmore in documenting -.Nm pdtar . ) -.Ss Old-Style Archive Format -The original tar archive format has been extended many times to -include additional information that various implementors found -necessary. -This section describes the variant implemented by the tar command -included in -.At v7 , -which is one of the earliest widely-used versions of the tar program. -.Pp -The header record for an old-style -.Nm -archive consists of the following: -.Bd -literal -offset indent -struct header_old_tar { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char checksum[8]; - char linkflag[1]; - char linkname[100]; - char pad[255]; -}; -.Ed -All unused bytes in the header record are filled with nulls. -.Bl -tag -width indent -.It Va name -Pathname, stored as a null-terminated string. -Early tar implementations only stored regular files (including -hardlinks to those files). -One common early convention used a trailing "/" character to indicate -a directory name, allowing directory permissions and owner information -to be archived and restored. -.It Va mode -File mode, stored as an octal number in ASCII. -.It Va uid , Va gid -User id and group id of owner, as octal numbers in ASCII. -.It Va size -Size of file, as octal number in ASCII. -For regular files only, this indicates the amount of data -that follows the header. -In particular, this field was ignored by early tar implementations -when extracting hardlinks. -Modern writers should always store a zero length for hardlink entries. -.It Va mtime -Modification time of file, as an octal number in ASCII. -This indicates the number of seconds since the start of the epoch, -00:00:00 UTC January 1, 1970. -Note that negative values should be avoided -here, as they are handled inconsistently. -.It Va checksum -Header checksum, stored as an octal number in ASCII. -To compute the checksum, set the checksum field to all spaces, -then sum all bytes in the header using unsigned arithmetic. -This field should be stored as six octal digits followed by a null and a space -character. -Note that many early implementations of tar used signed arithmetic -for the checksum field, which can cause interoperability problems -when transferring archives between systems. -Modern robust readers compute the checksum both ways and accept the -header if either computation matches. -.It Va linkflag , Va linkname -In order to preserve hardlinks and conserve tape, a file -with multiple links is only written to the archive the first -time it is encountered. -The next time it is encountered, the -.Va linkflag -is set to an ASCII -.Sq 1 -and the -.Va linkname -field holds the first name under which this file appears. -(Note that regular files have a null value in the -.Va linkflag -field.) -.El -.Pp -Early tar implementations varied in how they terminated these fields. -The tar command in -.At v7 -used the following conventions (this is also documented in early BSD manpages): -the pathname must be null-terminated; -the mode, uid, and gid fields must end in a space and a null byte; -the size and mtime fields must end in a space; -the checksum is terminated by a null and a space. -Early implementations filled the numeric fields with leading spaces. -This seems to have been common practice until the -.St -p1003.1-88 -standard was released. -For best portability, modern implementations should fill the numeric -fields with leading zeros. -.Ss Pre-POSIX Archives -An early draft of -.St -p1003.1-88 -served as the basis for John Gilmore's -.Nm pdtar -program and many system implementations from the late 1980s -and early 1990s. -These archives generally follow the POSIX ustar -format described below with the following variations: -.Bl -bullet -compact -width indent -.It -The magic value is -.Dq ustar\ \& -(note the following space). -The version field contains a space character followed by a null. -.It -The numeric fields are generally filled with leading spaces -(not leading zeros as recommended in the final standard). -.It -The prefix field is often not used, limiting pathnames to -the 100 characters of old-style archives. -.El -.Ss POSIX ustar Archives -.St -p1003.1-88 -defined a standard tar file format to be read and written -by compliant implementations of -.Xr tar 1 . -This format is often called the -.Dq ustar -format, after the magic value used -in the header. -(The name is an acronym for -.Dq Unix Standard TAR . ) -It extends the historic format with new fields: -.Bd -literal -offset indent -struct header_posix_ustar { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char checksum[8]; - char typeflag[1]; - char linkname[100]; - char magic[6]; - char version[2]; - char uname[32]; - char gname[32]; - char devmajor[8]; - char devminor[8]; - char prefix[155]; - char pad[12]; -}; -.Ed -.Bl -tag -width indent -.It Va typeflag -Type of entry. -POSIX extended the earlier -.Va linkflag -field with several new type values: -.Bl -tag -width indent -compact -.It Dq 0 -Regular file. -NULL should be treated as a synonym, for compatibility purposes. -.It Dq 1 -Hard link. -.It Dq 2 -Symbolic link. -.It Dq 3 -Character device node. -.It Dq 4 -Block device node. -.It Dq 5 -Directory. -.It Dq 6 -FIFO node. -.It Dq 7 -Reserved. -.It Other -A POSIX-compliant implementation must treat any unrecognized typeflag value -as a regular file. -In particular, writers should ensure that all entries -have a valid filename so that they can be restored by readers that do not -support the corresponding extension. -Uppercase letters "A" through "Z" are reserved for custom extensions. -Note that sockets and whiteout entries are not archivable. -.El -It is worth noting that the -.Va size -field, in particular, has different meanings depending on the type. -For regular files, of course, it indicates the amount of data -following the header. -For directories, it may be used to indicate the total size of all -files in the directory, for use by operating systems that pre-allocate -directory space. -For all other types, it should be set to zero by writers and ignored -by readers. -.It Va magic -Contains the magic value -.Dq ustar -followed by a NULL byte to indicate that this is a POSIX standard archive. -Full compliance requires the uname and gname fields be properly set. -.It Va version -Version. -This should be -.Dq 00 -(two copies of the ASCII digit zero) for POSIX standard archives. -.It Va uname , Va gname -User and group names, as null-terminated ASCII strings. -These should be used in preference to the uid/gid values -when they are set and the corresponding names exist on -the system. -.It Va devmajor , Va devminor -Major and minor numbers for character device or block device entry. -.It Va prefix -First part of pathname. -If the pathname is too long to fit in the 100 bytes provided by the standard -format, it can be split at any -.Pa / -character with the first portion going here. -If the prefix field is not empty, the reader will prepend -the prefix value and a -.Pa / -character to the regular name field to obtain the full pathname. -.El -.Pp -Note that all unused bytes must be set to -.Dv NULL . -.Pp -Field termination is specified slightly differently by POSIX -than by previous implementations. -The -.Va magic , -.Va uname , -and -.Va gname -fields must have a trailing -.Dv NULL . -The -.Va pathname , -.Va linkname , -and -.Va prefix -fields must have a trailing -.Dv NULL -unless they fill the entire field. -(In particular, it is possible to store a 256-character pathname if it -happens to have a -.Pa / -as the 156th character.) -POSIX requires numeric fields to be zero-padded in the front, and allows -them to be terminated with either space or -.Dv NULL -characters. -.Pp -Currently, most tar implementations comply with the ustar -format, occasionally extending it by adding new fields to the -blank area at the end of the header record. -.Ss Pax Interchange Format -There are many attributes that cannot be portably stored in a -POSIX ustar archive. -.St -p1003.1-2001 -defined a -.Dq pax interchange format -that uses two new types of entries to hold text-formatted -metadata that applies to following entries. -Note that a pax interchange format archive is a ustar archive in every -respect. -The new data is stored in ustar-compatible archive entries that use the -.Dq x -or -.Dq g -typeflag. -In particular, older implementations that do not fully support these -extensions will extract the metadata into regular files, where the -metadata can be examined as necessary. -.Pp -An entry in a pax interchange format archive consists of one or -two standard ustar entries, each with its own header and data. -The first optional entry stores the extended attributes -for the following entry. -This optional first entry has an "x" typeflag and a size field that -indicates the total size of the extended attributes. -The extended attributes themselves are stored as a series of text-format -lines encoded in the portable UTF-8 encoding. -Each line consists of a decimal number, a space, a key string, an equals -sign, a value string, and a new line. -The decimal number indicates the length of the entire line, including the -initial length field and the trailing newline. -An example of such a field is: -.Dl 25 ctime=1084839148.1212\en -Keys in all lowercase are standard keys. -Vendors can add their own keys by prefixing them with an all uppercase -vendor name and a period. -Note that, unlike the historic header, numeric values are stored using -decimal, not octal. -A description of some common keys follows: -.Bl -tag -width indent -.It Cm atime , Cm ctime , Cm mtime -File access, inode change, and modification times. -These fields can be negative or include a decimal point and a fractional value. -.It Cm uname , Cm uid , Cm gname , Cm gid -User name, group name, and numeric UID and GID values. -The user name and group name stored here are encoded in UTF8 -and can thus include non-ASCII characters. -The UID and GID fields can be of arbitrary length. -.It Cm linkpath -The full path of the linked-to file. -Note that this is encoded in UTF8 and can thus include non-ASCII characters. -.It Cm path -The full pathname of the entry. -Note that this is encoded in UTF8 and can thus include non-ASCII characters. -.It Cm realtime.* , Cm security.* -These keys are reserved and may be used for future standardization. -.It Cm size -The size of the file. -Note that there is no length limit on this field, allowing conforming -archives to store files much larger than the historic 8GB limit. -.It Cm SCHILY.* -Vendor-specific attributes used by Joerg Schilling's -.Nm star -implementation. -.It Cm SCHILY.acl.access , Cm SCHILY.acl.default -Stores the access and default ACLs as textual strings in a format -that is an extension of the format specified by POSIX.1e draft 17. -In particular, each user or group access specification can include a fourth -colon-separated field with the numeric UID or GID. -This allows ACLs to be restored on systems that may not have complete -user or group information available (such as when NIS/YP or LDAP services -are temporarily unavailable). -.It Cm SCHILY.devminor , Cm SCHILY.devmajor -The full minor and major numbers for device nodes. -.It Cm SCHILY.dev, Cm SCHILY.ino , Cm SCHILY.nlinks -The device number, inode number, and link count for the entry. -In particular, note that a pax interchange format archive using Joerg -Schilling's -.Cm SCHILY.* -extensions can store all of the data from -.Va struct stat . -.It Cm LIBARCHIVE.xattr. Ns Ar namespace Ns . Ns Ar key -Libarchive stores POSIX.1e-style extended attributes using -keys of this form. The -.Ar key -value is URL-encoded: -All non-ASCII characters and the two special characters -.Dq = -and -.Dq % -are encoded as -.Dq % -followed by two uppercase hexadecimal digits. -The value of this key is the extended attribute value -encoded in base 64. -XXX Detail the base-64 format here XXX -.It Cm VENDOR.* -XXX document other vendor-specific extensions XXX -.El -.Pp -Any values stored in an extended attribute override the corresponding -values in the regular tar header. -Note that compliant readers should ignore the regular fields when they -are overridden. -This is important, as existing archivers are known to store non-compliant -values in the standard header fields in this situation. -There are no limits on length for any of these fields. -In particular, numeric fields can be arbitrarily large. -All text fields are encoded in UTF8. -Compliant writers should store only portable 7-bit ASCII characters in -the standard ustar header and use extended -attributes whenever a text value contains non-ASCII characters. -.Pp -In addition to the -.Cm x -entry described above, the pax interchange format -also supports a -.Cm g -entry. -The -.Cm g -entry is identical in format, but specifies attributes that serve as -defaults for all subsequent archive entries. -The -.Cm g -entry is not widely used. -.Pp -Besides the new -.Cm x -and -.Cm g -entries, the pax interchange format has a few other minor variations -from the earlier ustar format. -The most troubling one is that hardlinks are permitted to have -data following them. -This allows readers to restore any hardlink to a file without -having to rewind the archive to find an earlier entry. -However, it creates complications for robust readers, as it is no longer -clear whether or not they should ignore the size field for hardlink entries. -.Ss GNU Tar Archives -The GNU tar program started with a pre-POSIX format similar to that -described earlier and has extended it using several different mechanisms: -It added new fields to the empty space in the header (some of which was later -used by POSIX for conflicting purposes); -it allowed the header to be continued over multiple records; -and it defined new entries that modify following entries -(similar in principle to the -.Cm x -entry described above, but each GNU special entry is single-purpose, -unlike the general-purpose -.Cm x -entry). -As a result, GNU tar archives are not POSIX compatible, although -more lenient POSIX-compliant readers can successfully extract most -GNU tar archives. -.Bd -literal -offset indent -struct header_gnu_tar { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char checksum[8]; - char typeflag[1]; - char linkname[100]; - char magic[6]; - char version[2]; - char uname[32]; - char gname[32]; - char devmajor[8]; - char devminor[8]; - char atime[12]; - char ctime[12]; - char offset[12]; - char longnames[4]; - char unused[1]; - struct { - char offset[12]; - char numbytes[12]; - } sparse[4]; - char isextended[1]; - char realsize[12]; - char pad[17]; -}; -.Ed -.Bl -tag -width indent -.It Va typeflag -GNU tar uses the following special entry types, in addition to -those defined by POSIX: -.Bl -tag -width indent -.It "7" -GNU tar treats type "7" records identically to type "0" records, -except on one obscure RTOS where they are used to indicate the -pre-allocation of a contiguous file on disk. -.It "D" -This indicates a directory entry. -Unlike the POSIX-standard "5" -typeflag, the header is followed by data records listing the names -of files in this directory. -Each name is preceded by an ASCII "Y" -if the file is stored in this archive or "N" if the file is not -stored in this archive. -Each name is terminated with a null, and -an extra null marks the end of the name list. -The purpose of this -entry is to support incremental backups; a program restoring from -such an archive may wish to delete files on disk that did not exist -in the directory when the archive was made. -.Pp -Note that the "D" typeflag specifically violates POSIX, which requires -that unrecognized typeflags be restored as normal files. -In this case, restoring the "D" entry as a file could interfere -with subsequent creation of the like-named directory. -.It "K" -The data for this entry is a long linkname for the following regular entry. -.It "L" -The data for this entry is a long pathname for the following regular entry. -.It "M" -This is a continuation of the last file on the previous volume. -GNU multi-volume archives guarantee that each volume begins with a valid -entry header. -To ensure this, a file may be split, with part stored at the end of one volume, -and part stored at the beginning of the next volume. -The "M" typeflag indicates that this entry continues an existing file. -Such entries can only occur as the first or second entry -in an archive (the latter only if the first entry is a volume label). -The -.Va size -field specifies the size of this entry. -The -.Va offset -field at bytes 369-380 specifies the offset where this file fragment -begins. -The -.Va realsize -field specifies the total size of the file (which must equal -.Va size -plus -.Va offset ) . -When extracting, GNU tar checks that the header file name is the one it is -expecting, that the header offset is in the correct sequence, and that -the sum of offset and size is equal to realsize. -FreeBSD's version of GNU tar does not handle the corner case of an -archive's being continued in the middle of a long name or other -extension header. -.It "N" -Type "N" records are no longer generated by GNU tar. -They contained a -list of files to be renamed or symlinked after extraction; this was -originally used to support long names. -The contents of this record -are a text description of the operations to be done, in the form -.Dq Rename %s to %s\en -or -.Dq Symlink %s to %s\en ; -in either case, both -filenames are escaped using K&R C syntax. -.It "S" -This is a -.Dq sparse -regular file. -Sparse files are stored as a series of fragments. -The header contains a list of fragment offset/length pairs. -If more than four such entries are required, the header is -extended as necessary with -.Dq extra -header extensions (an older format that is no longer used), or -.Dq sparse -extensions. -.It "V" -The -.Va name -field should be interpreted as a tape/volume header name. -This entry should generally be ignored on extraction. -.El -.It Va magic -The magic field holds the five characters -.Dq ustar -followed by a space. -Note that POSIX ustar archives have a trailing null. -.It Va version -The version field holds a space character followed by a null. -Note that POSIX ustar archives use two copies of the ASCII digit -.Dq 0 . -.It Va atime , Va ctime -The time the file was last accessed and the time of -last change of file information, stored in octal as with -.Va mtime . -.It Va longnames -This field is apparently no longer used. -.It Sparse Va offset / Va numbytes -Each such structure specifies a single fragment of a sparse -file. -The two fields store values as octal numbers. -The fragments are each padded to a multiple of 512 bytes -in the archive. -On extraction, the list of fragments is collected from the -header (including any extension headers), and the data -is then read and written to the file at appropriate offsets. -.It Va isextended -If this is set to non-zero, the header will be followed by additional -.Dq sparse header -records. -Each such record contains information about as many as 21 additional -sparse blocks as shown here: -.Bd -literal -offset indent -struct gnu_sparse_header { - struct { - char offset[12]; - char numbytes[12]; - } sparse[21]; - char isextended[1]; - char padding[7]; -}; -.Ed -.It Va realsize -A binary representation of the file's complete size, with a much larger range -than the POSIX file size. -In particular, with -.Cm M -type files, the current entry is only a portion of the file. -In that case, the POSIX size field will indicate the size of this -entry; the -.Va realsize -field will indicate the total size of the file. -.El -.Ss Solaris Tar -XXX More Details Needed XXX -.Pp -Solaris tar (beginning with SunOS XXX 5.7 ?? XXX) supports an -.Dq extended -format that is fundamentally similar to pax interchange format, -with the following differences: -.Bl -bullet -compact -width indent -.It -Extended attributes are stored in an entry whose type is -.Cm X , -not -.Cm x , -as used by pax interchange format. -The detailed format of this entry appears to be the same -as detailed above for the -.Cm x -entry. -.It -An additional -.Cm A -entry is used to store an ACL for the following regular entry. -The body of this entry contains a seven-digit octal number -(whose value is 01000000 plus the number of ACL entries) -followed by a zero byte, followed by the -textual ACL description. -.El -.Ss Other Extensions -One common extension, utilized by GNU tar, star, and other newer -.Nm -implementations, permits binary numbers in the standard numeric -fields. -This is flagged by setting the high bit of the first character. -This permits 95-bit values for the length and time fields -and 63-bit values for the uid, gid, and device numbers. -GNU tar supports this extension for the -length, mtime, ctime, and atime fields. -Joerg Schilling's star program supports this extension for -all numeric fields. -Note that this extension is largely obsoleted by the extended attribute -record provided by the pax interchange format. -.Pp -Another early GNU extension allowed base-64 values rather -than octal. -This extension was short-lived and such archives are almost never seen. -However, there is still code in GNU tar to support them; this code is -responsible for a very cryptic warning message that is sometimes seen when -GNU tar encounters a damaged archive. -.Sh SEE ALSO -.Xr ar 1 , -.Xr pax 1 , -.Xr tar 1 -.Sh STANDARDS -The -.Nm tar -utility is no longer a part of POSIX or the Single Unix Standard. -It last appeared in -.St -susv2 . -It has been supplanted in subsequent standards by -.Xr pax 1 . -The ustar format is currently part of the specification for the -.Xr pax 1 -utility. -The pax interchange file format is new with -.St -p1003.1-2001 . -.Sh HISTORY -A -.Nm tar -command appeared in Seventh Edition Unix, which was released in January, 1979. -It replaced the -.Nm tp -program from Fourth Edition Unix which in turn replaced the -.Nm tap -program from First Edition Unix. -John Gilmore's -.Nm pdtar -public-domain implementation (circa 1987) was highly influential -and formed the basis of -.Nm GNU tar . -Joerg Shilling's -.Nm star -archiver is another open-source (GPL) archiver (originally developed -circa 1985) which features complete support for pax interchange -format. diff --git a/contrib/libarchive-1.3.1/tar/bsdtar.1 b/contrib/libarchive-1.3.1/tar/bsdtar.1 deleted file mode 100644 index 72dc43a246..0000000000 --- a/contrib/libarchive-1.3.1/tar/bsdtar.1 +++ /dev/null @@ -1,759 +0,0 @@ -.\" Copyright (c) 2003 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 AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.32 2006/05/01 01:34:21 kientzle Exp $ -.\" -.Dd April 13, 2004 -.Dt BSDTAR 1 -.Os -.Sh NAME -.Nm tar -.Nd manipulate tape archives -.Sh SYNOPSIS -.Nm -.Op Ar bundled-flags Ao args Ac -.Op Ao Ar file Ac | Ao Ar pattern Ac ... -.Nm -.Brq Fl c -.Op Ar options -.Op Ar files | directories -.Nm -.Brq Fl r | Fl u -.Fl f Ar archive-file -.Op Ar options -.Op Ar files | directories -.Nm -.Brq Fl t | Fl x -.Op Ar options -.Op Ar patterns -.Sh DESCRIPTION -.Nm -creates and manipulates streaming archive files. -.Pp -The first synopsis form shows a -.Dq bundled -option word. -This usage is provided for compatibility with historical implementations. -See COMPATIBILITY below for details. -.Pp -The other synopsis forms show the preferred usage. -The first option to -.Nm -is a mode indicator from the following list: -.Bl -tag -compact -width indent -.It Fl c -Create a new archive containing the specified items. -.It Fl r -Like -.Fl c , -but new entries are appended to the archive. -Note that this only works on uncompressed archives stored in regular files. -The -.Fl f -option is required. -.It Fl t -List archive contents to stdout. -.It Fl u -Like -.Fl r , -but new entries are added only if they have a modification date -newer than the corresponding entry in the archive. -Note that this only works on uncompressed archives stored in regular files. -The -.Fl f -option is required. -.It Fl x -Extract to disk from the archive. -If a file with the same name appears more than once in the archive, -each copy will be extracted, with later copies overwriting (replacing) -earlier copies. -.El -.Pp -In -.Fl c , -.Fl r , -or -.Fl u -mode, each specified file or directory is added to the -archive in the order specified on the command line. -By default, the contents of each directory are also archived. -.Pp -In extract or list mode, the entire command line -is read and parsed before the archive is opened. -The pathnames or patterns on the command line indicate -which items in the archive should be processed. -Patterns are shell-style globbing patterns as -documented in -.Xr tcsh 1 . -.Sh OPTIONS -Unless specifically stated otherwise, options are applicable in -all operating modes. -.Bl -tag -width indent -.It Cm @ Ns Pa archive -(c and r mode only) -The specified archive is opened and the entries -in it will be appended to the current archive. -As a simple example, -.Dl Nm Fl c Fl f Pa - Pa newfile Cm @ Ns Pa original.tar -writes a new archive to standard output containing a file -.Pa newfile -and all of the entries from -.Pa original.tar . -In contrast, -.Dl Nm Fl c Fl f Pa - Pa newfile Pa original.tar -creates a new archive with only two entries. -Similarly, -.Dl Nm Fl czf Pa - Fl -format Cm pax Cm @ Ns Pa - -reads an archive from standard input (whose format will be determined -automatically) and converts it into a gzip-compressed -pax-format archive on stdout. -In this way, -.Nm -can be used to convert archives from one format to another. -.It Fl b Ar blocksize -Specify the block size, in 512-byte records, for tape drive I/O. -As a rule, this argument is only needed when reading from or writing -to tape drives, and usually not even then as the default block size of -20 records (10240 bytes) is very common. -.It Fl C Ar directory -In c and r mode, this changes the directory before adding -the following files. -In x mode, change directories after opening the archive -but before extracting entries from the archive. -.It Fl -check-links ( Fl W Cm check-links ) -(c and r modes only) -Issue a warning message unless all links to each file are archived. -.It Fl -exclude Ar pattern ( Fl W Cm exclude Ns = Ns Ar pattern ) -Do not process files or directories that match the -specified pattern. -Note that exclusions take precedence over patterns or filenames -specified on the command line. -.It Fl -format Ar format ( Fl W Cm format Ns = Ns Ar format ) -(c mode only) -Use the specified format for the created archive. -Supported formats include -.Dq cpio , -.Dq pax , -.Dq shar , -and -.Dq ustar . -Other formats may also be supported; see -.Xr libarchive-formats 5 -for more information about currently-supported formats. -.It Fl f Ar file -Read the archive from or write the archive to the specified file. -The filename can be -.Pa - -for standard input or standard output. -If not specified, the default tape device will be used. -(On -.Fx , -the default tape device is -.Pa /dev/sa0 . ) -.It Fl -fast-read ( Fl W Cm fast-read ) -(x and t mode only) -Extract or list only the first archive entry that matches each pattern -or filename operand. -Exit as soon as each specified pattern or filename has been matched. -By default, the archive is always read to the very end, since -there can be multiple entries with the same name and, by convention, -later entries overwrite earlier entries. -This option is provided as a performance optimization. -.It Fl H -(c and r mode only) -Symbolic links named on the command line will be followed; the -target of the link will be archived, not the link itself. -.It Fl h -(c and r mode only) -Synonym for -.Fl L . -.It Fl I -Synonym for -.Fl T . -.It Fl -include Ar pattern ( Fl W Cm include Ns = Ns Ar pattern ) -Process only files or directories that match the specified pattern. -Note that exclusions specified with -.Fl -exclude -take precedence over inclusions. -If no inclusions are explicitly specified, all entries are processed by -default. -The -.Fl -include -option is especially useful when filtering archives. -For example, the command -.Dl Nm Fl c Fl f Pa new.tar Fl -include='*foo*' Cm @ Ns Pa old.tgz -creates a new archive -.Pa new.tar -containing only the entries from -.Pa old.tgz -containing the string -.Sq foo . -.It Fl j -(c mode only) -Compress the resulting archive with -.Xr bzip2 1 . -In extract or list modes, this option is ignored. -Note that, unlike other -.Nm tar -implementations, this implementation recognizes bzip2 compression -automatically when reading archives. -.It Fl k -(x mode only) -Do not overwrite existing files. -In particular, if a file appears more than once in an archive, -later copies will not overwrite earlier copies. -.It Fl L -(c and r mode only) -All symbolic links will be followed. -Normally, symbolic links are archived as such. -With this option, the target of the link will be archived instead. -.It Fl l -If -.Ev POSIXLY_CORRECT -is specified in the environment, this is a synonym for the -.Fl -check-links -option. -Otherwise, an error will be displayed. -Users who desire behavior compatible with GNU tar should use -the -.Fl -one-file-system -option instead. -.It Fl m -(x mode only) -Do not extract modification time. -By default, the modification time is set to the time stored in the archive. -.It Fl n -(c, r, u modes only) -Do not recursively archive the contents of directories. -.It Fl -newer Ar date ( Fl W Cm newer Ns = Ns Ar date ) -(c, r, u modes only) -Only include files and directories newer than the specified date. -This compares ctime entries. -.It Fl -newer-mtime Ar date ( Fl W Cm newer-mtime Ns = Ns Ar date ) -(c, r, u modes only) -Like -.Fl -newer , -except it compares mtime entries instead of ctime entries. -.It Fl -newer-than Pa file ( Fl W Cm newer-than Ns = Ns Pa file ) -(c, r, u modes only) -Only include files and directories newer than the specified file. -This compares ctime entries. -.It Fl -newer-mtime-than Pa file ( Fl W Cm newer-mtime-than Ns = Ns Pa file ) -(c, r, u modes only) -Like -.Fl -newer-than , -except it compares mtime entries instead of ctime entries. -.It Fl -nodump ( Fl W Cm nodump ) -(c and r modes only) -Honor the nodump file flag by skipping this file. -.It Fl -null ( Fl W Cm null ) -(use with -.Fl I , -.Fl T , -or -.Fl X ) -Filenames or patterns are separated by null characters, -not by newlines. -This is often used to read filenames output by the -.Fl print0 -option to -.Xr find 1 . -.It Fl O -(x, t modes only) -In extract (-x) mode, files will be written to standard out rather than -being extracted to disk. -In list (-t) mode, the file listing will be written to stderr rather than -the usual stdout. -.It Fl o -(x mode only) -Use the user and group of the user running the program rather -than those specified in the archive. -Note that this has no significance unless -.Fl p -is specified, and the program is being run by the root user. -In this case, the file modes and flags from -the archive will be restored, but ACLs or owner information in -the archive will be discarded. -.It Fl -one-file-system ( Fl W Cm one-file-system ) -(c, r, and u modes) -Do not cross mount points. -.It Fl P -Preserve pathnames. -By default, absolute pathnames (those that begin with a / -character) have the leading slash removed both when creating archives -and extracting from them. -Also, -.Nm -will refuse to extract archive entries whose pathnames contain -.Pa .. -or whose target directory would be altered by a symlink. -This option suppresses these behaviors. -.It Fl p -(x mode only) -Preserve file permissions. -Attempt to restore the full permissions, including owner, file modes, file -flags and ACLs, if available, for each item extracted from the archive. -By default, newly-created files are owned by the user running -.Nm , -the file mode is restored for newly-created regular files, and -all other types of entries receive default permissions. -If -.Nm -is being run by root, the default is to restore the owner unless the -.Fl o -option is also specified. -.It Fl -strip-components Ar count ( Fl W Cm strip-components Ns = Ns Ar count ) -(x and t mode only) -Remove the specified number of leading path elements. -Pathnames with fewer elements will be silently skipped. -Note that the pathname is edited after checking inclusion/exclusion patterns -but before security checks. -.It Fl T Ar filename -In x or t mode, -.Nm -will read the list of names to be extracted from -.Pa filename . -In c mode, -.Nm -will read names to be archived from -.Pa filename . -The special name -.Dq -C -on a line by itself will cause the current directory to be changed to -the directory specified on the following line. -Names are terminated by newlines unless -.Fl -null -is specified. -Note that -.Fl -null -also disables the special handling of lines containing -.Dq -C . -.It Fl U -(x mode only) -Unlink files before creating them. -Without this option, -.Nm -overwrites existing files, which preserves existing hardlinks. -With this option, existing hardlinks will be broken, as will any -symlink that would affect the location of an extracted file. -.It Fl v -Produce verbose output. -In create and extract modes, -.Nm -will list each file name as it is read from or written to -the archive. -In list mode, -.Nm -will produce output similar to that of -.Xr ls 1 . -Additional -.Fl v -options will provide additional detail. -.It Fl W Ar longopt=value -Long options (preceded by -.Fl - ) -are only supported directly on systems that have the -.Xr getopt_long 3 -function. -The -.Fl W -option can be used to access long options on systems that -do not support this function. -.It Fl w -Ask for confirmation for every action. -.It Fl X Ar filename -Read a list of exclusion patterns from the specified file. -See -.Fl -exclude -for more information about the handling of exclusions. -.It Fl y -(c mode only) -Compress the resulting archive with -.Xr bzip2 1 . -In extract or list modes, this option is ignored. -Note that, unlike other -.Nm tar -implementations, this implementation recognizes bzip2 compression -automatically when reading archives. -.It Fl z -(c mode only) -Compress the resulting archive with -.Xr gzip 1 . -In extract or list modes, this option is ignored. -Note that, unlike other -.Nm tar -implementations, this implementation recognizes gzip compression -automatically when reading archives. -.El -.Sh ENVIRONMENT -The following environment variables affect the execution of -.Nm : -.Bl -tag -width ".Ev BLOCKSIZE" -.It Ev LANG -The locale to use. -See -.Xr environ 7 -for more information. -.It Ev POSIXLY_CORRECT -If this environment variable is defined, the -.Fl l -option will be interpreted in accordance with -.St -p1003.1-96 . -.It Ev TAPE -The default tape device. -The -.Fl f -option overrides this. -.It Ev TZ -The timezone to use when displaying dates. -See -.Xr environ 7 -for more information. -.El -.Sh FILES -.Bl -tag -width ".Ev BLOCKSIZE" -.It Pa /dev/sa0 -The default tape device, if not overridden by the -.Ev TAPE -environment variable or the -.Fl f -option. -.El -.Sh EXIT STATUS -.Ex -std -.Sh EXAMPLES -The following creates a new archive -called -.Ar file.tar.gz -that contains two files -.Ar source.c -and -.Ar source.h : -.Dl Nm Fl czf Pa file.tar.gz Pa source.c Pa source.h -.Pp -To view a detailed table of contents for this -archive: -.Dl Nm Fl tvf Pa file.tar.gz -.Pp -To extract all entries from the archive on -the default tape drive: -.Dl Nm Fl x -.Pp -To move file hierarchies, invoke -.Nm -as -.Dl Nm Fl cf Pa - Fl C Pa srcdir\ . | Nm Fl xpf Pa - Fl C Pa destdir -or more traditionally -.Dl cd srcdir \&; Nm Fl cf Pa -\ . | ( cd destdir \&; Nm Fl xpf Pa - ) -.Pp -In create mode, the list of files and directories to be archived -can also include directory change instructions of the form -.Cm -C Ns Pa foo/baz -and archive inclusions of the form -.Cm @ Ns Pa archive-file . -For example, the command line -.Dl Nm Fl c Fl f Pa new.tar Pa foo1 Cm @ Ns Pa old.tgz Cm -C Ns Pa /tmp Pa foo2 -will create a new archive -.Pa new.tar . -.Nm -will read the file -.Pa foo1 -from the current directory and add it to the output archive. -It will then read each entry from -.Pa old.tgz -and add those entries to the output archive. -Finally, it will switch to the -.Pa /tmp -directory and add -.Pa foo2 -to the output archive. -.Pp -The -.Fl -newer -and -.Fl -newer-mtime -switches accept a variety of common date and time specifications, including -.Dq 12 Mar 2005 7:14:29pm , -.Dq 2005-03-12 19:14 , -.Dq 5 minutes ago , -and -.Dq 19:14 PST May 1 . -.Sh COMPATIBILITY -The bundled-arguments format is supported for compatibility -with historic implementations. -It consists of an initial word (with no leading - character) in which -each character indicates an option. -Arguments follow as separate words. -The order of the arguments must match the order -of the corresponding characters in the bundled command word. -For example, -.Dl Nm Cm tbf 32 Pa file.tar -specifies three flags -.Cm t , -.Cm b , -and -.Cm f . -The -.Cm b -and -.Cm f -flags both require arguments, -so there must be two additional items -on the command line. -The -.Ar 32 -is the argument to the -.Cm b -flag, and -.Ar file.tar -is the argument to the -.Cm f -flag. -.Pp -The mode options c, r, t, u, and x and the options -b, f, l, m, o, v, and w comply with SUSv2. -.Pp -For maximum portability, scripts that invoke -.Nm tar -should use the bundled-argument format above, should limit -themselves to the -.Cm c , -.Cm t , -and -.Cm x -modes, and the -.Cm b , -.Cm f , -.Cm m , -.Cm v , -and -.Cm w -options. -.Pp -On systems that support getopt_long(), additional long options -are available to improve compatibility with other tar implementations. -.Sh SECURITY -Certain security issues are common to many archiving programs, including -.Nm . -In particular, carefully-crafted archives can request that -.Nm -extract files to locations outside of the target directory. -This can potentially be used to cause unwitting users to overwrite -files they did not intend to overwrite. -If the archive is being extracted by the superuser, any file -on the system can potentially be overwritten. -There are three ways this can happen. -Although -.Nm -has mechanisms to protect against each one, -savvy users should be aware of the implications: -.Bl -bullet -width indent -.It -Archive entries can have absolute pathnames. -By default, -.Nm -removes the leading -.Pa / -character from filenames before restoring them to guard against this problem. -.It -Archive entries can have pathnames that include -.Pa .. -components. -By default, -.Nm -will not extract files containing -.Pa .. -components in their pathname. -.It -Archive entries can exploit symbolic links to restore -files to other directories. -An archive can restore a symbolic link to another directory, -then use that link to restore a file into that directory. -To guard against this, -.Nm -checks each extracted path for symlinks. -If the final path element is a symlink, it will be removed -and replaced with the archive entry. -If -.Fl U -is specified, any intermediate symlink will also be unconditionally removed. -If neither -.Fl U -nor -.Fl P -is specified, -.Nm -will refuse to extract the entry. -.El -To protect yourself, you should be wary of any archives that -come from untrusted sources. -You should examine the contents of an archive with -.Dl Nm Fl tf Pa filename -before extraction. -You should use the -.Fl k -option to ensure that -.Nm -will not overwrite any existing files or the -.Fl U -option to remove any pre-existing files. -You should generally not extract archives while running with super-user -privileges. -Note that the -.Fl P -option to -.Nm -disables the security checks above and allows you to extract -an archive while preserving any absolute pathnames, -.Pa .. -components, or symlinks to other directories. -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr cpio 1 , -.Xr gzip 1 , -.Xr mt 1 , -.Xr pax 1 , -.Xr shar 1 , -.Xr libarchive 3 , -.Xr libarchive-formats 5 , -.Xr tar 5 -.Sh STANDARDS -There is no current POSIX standard for the tar command; it appeared -in -.St -p1003.1-96 -but was dropped from -.St -p1003.1-2001 . -The options used by this implementation were developed by surveying a -number of existing tar implementations as well as the old POSIX specification -for tar and the current POSIX specification for pax. -.Pp -The ustar and pax interchange file formats are defined by -.St -p1003.1-2001 -for the pax command. -.Sh HISTORY -A -.Nm tar -command appeared in Seventh Edition Unix. -There have been numerous other implementations, -many of which extended the file format. -John Gilmore's -.Nm pdtar -public-domain implementation (circa November, 1987) -was quite influential, and formed the basis of GNU tar. -GNU tar was included as the standard system tar -in -.Fx -beginning with -.Fx 1.0 . -.Pp -This is a complete re-implementation based on the -.Xr libarchive 3 -library. -.Sh BUGS -POSIX and GNU violently disagree about the meaning of the -.Fl l -option. -Because of the potential for disaster if someone expects -one behavior and gets the other, the -.Fl l -option is deliberately broken in this implementation. -.Pp -The -.Fl C Pa dir -option may differ from historic implementations. -.Pp -All archive output is written in correctly-sized blocks, even -if the output is being compressed. -Whether or not the last output block is padded to a full -block size varies depending on the format and the -output device. -For tar and cpio formats, the last block of output is padded -to a full block size if the output is being -written to standard output or to a character or block device such as -a tape drive. -If the output is being written to a regular file, the last block -will not be padded. -Many compressors, including -.Xr gzip 1 -and -.Xr bzip2 1 , -complain about the null padding when decompressing an archive created by -.Nm , -although they still extract it correctly. -.Pp -The compression and decompression is implemented internally, so -there may be insignificant differences between the compressed output -generated by -.Dl Nm Fl czf Pa - file -and that generated by -.Dl Nm Fl cf Pa - file | Nm gzip -.Pp -The default should be to read and write archives to the standard I/O paths, -but tradition (and POSIX) dictates otherwise. -.Pp -The -.Cm r -and -.Cm u -modes require that the archive be uncompressed -and located in a regular file on disk. -Other archives can be modified using -.Cm c -mode with the -.Pa @archive-file -extension. -.Pp -To archive a file called -.Pa @foo -or -.Pa -foo -you must specify it as -.Pa ./@foo -or -.Pa ./-foo , -respectively. -.Pp -In create mode, a leading -.Pa ./ -is always removed. -A leading -.Pa / -is stripped unless the -.Fl P -option is specified. -.Pp -There needs to be better support for file selection on both create -and extract. -.Pp -There is not yet any support for multi-volume archives or for archiving -sparse files. -.Pp -Converting between dissimilar archive formats (such as tar and cpio) using the -.Cm @ Ns Pa - -convention can cause hard link information to be lost. -(This is a consequence of the incompatible ways that different archive -formats store hardlink information.) -.Pp -There are alternative long options for many of the short options that -are deliberately not documented. diff --git a/contrib/libarchive-1.3.1/tar/bsdtar.c b/contrib/libarchive-1.3.1/tar/bsdtar.c deleted file mode 100644 index 5726af3c99..0000000000 --- a/contrib/libarchive-1.3.1/tar/bsdtar.c +++ /dev/null @@ -1,831 +0,0 @@ -/*- - * Copyright (c) 2003-2005 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.67 2006/03/21 17:03:51 kientzle Exp $"); - -#include -#include -#include -#include -#ifdef HAVE_GETOPT_LONG -#include -#else -struct option { - const char *name; - int has_arg; - int *flag; - int val; -}; -#define no_argument 0 -#define required_argument 1 -#endif -#ifdef HAVE_LANGINFO_H -#include -#endif -#include -#ifdef HAVE_PATHS_H -#include -#endif -#include -#include -#include -#include -#include -#if HAVE_ZLIB_H -#include -#endif - -#include "bsdtar.h" - -#ifdef __linux -#define _PATH_DEFTAPE "/dev/st0" -#endif - -#ifndef _PATH_DEFTAPE -#define _PATH_DEFTAPE "/dev/tape" -#endif - -/* External function to parse a date/time string (from getdate.y) */ -time_t get_date(const char *); - -static int bsdtar_getopt(struct bsdtar *, const char *optstring, - const struct option **poption); -static void long_help(struct bsdtar *); -static void only_mode(struct bsdtar *, const char *opt, - const char *valid); -static char ** rewrite_argv(struct bsdtar *, - int *argc, char ** src_argv, - const char *optstring); -static void set_mode(struct bsdtar *, char opt); -static void version(void); - -/* - * The leading '+' here forces the GNU version of getopt() (as well as - * both the GNU and BSD versions of getopt_long) to stop at the first - * non-option. Otherwise, GNU getopt() permutes the arguments and - * screws up -C processing. - */ -static const char *tar_opts = "+Bb:C:cF:f:HhI:jkLlmnOoPprtT:UuvW:wX:xyZz"; - -/* - * Most of these long options are deliberately not documented. They - * are provided only to make life easier for people who also use GNU tar. - * The only long options documented in the manual page are the ones - * with no corresponding short option, such as --exclude, --nodump, - * and --fast-read. - * - * On systems that lack getopt_long, long options can be specified - * using -W longopt and -W longopt=value, e.g. "-W nodump" is the same - * as "--nodump" and "-W exclude=pattern" is the same as "--exclude - * pattern". This does not rely the GNU getopt() "W;" extension, so - * should work correctly on any system with a POSIX-compliant getopt(). - */ - -/* Fake short equivalents for long options that otherwise lack them. */ -enum { - OPTION_CHECK_LINKS=1, - OPTION_EXCLUDE, - OPTION_FAST_READ, - OPTION_FORMAT, - OPTION_HELP, - OPTION_INCLUDE, - OPTION_NEWER_CTIME, - OPTION_NEWER_CTIME_THAN, - OPTION_NEWER_MTIME, - OPTION_NEWER_MTIME_THAN, - OPTION_NODUMP, - OPTION_NO_SAME_PERMISSIONS, - OPTION_NULL, - OPTION_ONE_FILE_SYSTEM, - OPTION_STRIP_COMPONENTS, - OPTION_TOTALS, - OPTION_VERSION -}; - -/* - * If you add anything, be very careful to keep this list properly - * sorted, as the -W logic relies on it. - */ -static const struct option tar_longopts[] = { - { "absolute-paths", no_argument, NULL, 'P' }, - { "append", no_argument, NULL, 'r' }, - { "block-size", required_argument, NULL, 'b' }, - { "bunzip2", no_argument, NULL, 'j' }, - { "bzip", no_argument, NULL, 'j' }, - { "bzip2", no_argument, NULL, 'j' }, - { "cd", required_argument, NULL, 'C' }, - { "check-links", no_argument, NULL, OPTION_CHECK_LINKS }, - { "confirmation", no_argument, NULL, 'w' }, - { "create", no_argument, NULL, 'c' }, - { "dereference", no_argument, NULL, 'L' }, - { "directory", required_argument, NULL, 'C' }, - { "exclude", required_argument, NULL, OPTION_EXCLUDE }, - { "exclude-from", required_argument, NULL, 'X' }, - { "extract", no_argument, NULL, 'x' }, - { "fast-read", no_argument, NULL, OPTION_FAST_READ }, - { "file", required_argument, NULL, 'f' }, - { "files-from", required_argument, NULL, 'T' }, - { "format", required_argument, NULL, OPTION_FORMAT }, - { "gunzip", no_argument, NULL, 'z' }, - { "gzip", no_argument, NULL, 'z' }, - { "help", no_argument, NULL, OPTION_HELP }, - { "include", required_argument, NULL, OPTION_INCLUDE }, - { "interactive", no_argument, NULL, 'w' }, - { "keep-old-files", no_argument, NULL, 'k' }, - { "list", no_argument, NULL, 't' }, - { "modification-time", no_argument, NULL, 'm' }, - { "newer", required_argument, NULL, OPTION_NEWER_CTIME }, - { "newer-ctime", required_argument, NULL, OPTION_NEWER_CTIME }, - { "newer-ctime-than", required_argument, NULL, OPTION_NEWER_CTIME_THAN }, - { "newer-mtime", required_argument, NULL, OPTION_NEWER_MTIME }, - { "newer-mtime-than", required_argument, NULL, OPTION_NEWER_MTIME_THAN }, - { "newer-than", required_argument, NULL, OPTION_NEWER_CTIME_THAN }, - { "nodump", no_argument, NULL, OPTION_NODUMP }, - { "norecurse", no_argument, NULL, 'n' }, - { "no-recursion", no_argument, NULL, 'n' }, - { "no-same-owner", no_argument, NULL, 'o' }, - { "no-same-permissions",no_argument, NULL, OPTION_NO_SAME_PERMISSIONS }, - { "null", no_argument, NULL, OPTION_NULL }, - { "one-file-system", no_argument, NULL, OPTION_ONE_FILE_SYSTEM }, - { "preserve-permissions", no_argument, NULL, 'p' }, - { "read-full-blocks", no_argument, NULL, 'B' }, - { "same-permissions", no_argument, NULL, 'p' }, - { "strip-components", required_argument, NULL, OPTION_STRIP_COMPONENTS }, - { "to-stdout", no_argument, NULL, 'O' }, - { "totals", no_argument, NULL, OPTION_TOTALS }, - { "unlink", no_argument, NULL, 'U' }, - { "unlink-first", no_argument, NULL, 'U' }, - { "update", no_argument, NULL, 'u' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, OPTION_VERSION }, - { NULL, 0, NULL, 0 } -}; - -int -main(int argc, char **argv) -{ - struct bsdtar *bsdtar, bsdtar_storage; - const struct option *option; - int opt, t; - char option_o; - char possible_help_request; - char buff[16]; - - /* - * Use a pointer for consistency, but stack-allocated storage - * for ease of cleanup. - */ - bsdtar = &bsdtar_storage; - memset(bsdtar, 0, sizeof(*bsdtar)); - bsdtar->fd = -1; /* Mark as "unused" */ - option_o = 0; - - /* Need bsdtar->progname before calling bsdtar_warnc. */ - if (*argv == NULL) - bsdtar->progname = "bsdtar"; - else { - bsdtar->progname = strrchr(*argv, '/'); - if (bsdtar->progname != NULL) - bsdtar->progname++; - else - bsdtar->progname = *argv; - } - - if (setlocale(LC_ALL, "") == NULL) - bsdtar_warnc(bsdtar, 0, "Failed to set default locale"); -#if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) - bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); -#endif - possible_help_request = 0; - - /* Look up uid of current user for future reference */ - bsdtar->user_uid = geteuid(); - - /* Default: open tape drive. */ - bsdtar->filename = getenv("TAPE"); - if (bsdtar->filename == NULL) - bsdtar->filename = _PATH_DEFTAPE; - - /* Default: preserve mod time on extract */ - bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; - - /* Default for root user: preserve ownership on extract. */ - if (bsdtar->user_uid == 0) - bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; - - /* Rewrite traditional-style tar arguments, if used. */ - argv = rewrite_argv(bsdtar, &argc, argv, tar_opts); - - bsdtar->argv = argv; - bsdtar->argc = argc; - - /* Process all remaining arguments now. */ - while ((opt = bsdtar_getopt(bsdtar, tar_opts, &option)) != -1) { - switch (opt) { - case 'B': /* GNU tar */ - /* libarchive doesn't need this; just ignore it. */ - break; - case 'b': /* SUSv2 */ - t = atoi(optarg); - if (t <= 0 || t > 1024) - bsdtar_errc(bsdtar, 1, 0, - "Argument to -b is out of range (1..1024)"); - bsdtar->bytes_per_block = 512 * t; - break; - case 'C': /* GNU tar */ - set_chdir(bsdtar, optarg); - break; - case 'c': /* SUSv2 */ - set_mode(bsdtar, opt); - break; - case OPTION_CHECK_LINKS: /* GNU tar */ - bsdtar->option_warn_links = 1; - break; - case OPTION_EXCLUDE: /* GNU tar */ - if (exclude(bsdtar, optarg)) - bsdtar_errc(bsdtar, 1, 0, - "Couldn't exclude %s\n", optarg); - break; - case OPTION_FORMAT: - bsdtar->create_format = optarg; - break; - case 'f': /* SUSv2 */ - bsdtar->filename = optarg; - if (strcmp(bsdtar->filename, "-") == 0) - bsdtar->filename = NULL; - break; - case OPTION_FAST_READ: /* GNU tar */ - bsdtar->option_fast_read = 1; - break; - case 'H': /* BSD convention */ - bsdtar->symlink_mode = 'H'; - break; - case 'h': /* Linux Standards Base, gtar; synonym for -L */ - bsdtar->symlink_mode = 'L'; - /* Hack: -h by itself is the "help" command. */ - possible_help_request = 1; - break; - case OPTION_HELP: - long_help(bsdtar); - exit(0); - break; - case 'I': /* GNU tar */ - bsdtar->names_from_file = optarg; - break; - case OPTION_INCLUDE: - if (include(bsdtar, optarg)) - bsdtar_errc(bsdtar, 1, 0, - "Failed to add %s to inclusion list", - optarg); - break; - case 'j': /* GNU tar */ -#if HAVE_LIBBZ2 - if (bsdtar->create_compression != '\0') - bsdtar_errc(bsdtar, 1, 0, - "Can't specify both -%c and -%c", opt, - bsdtar->create_compression); - bsdtar->create_compression = opt; -#else - bsdtar_warnc(bsdtar, 0, "-j compression not supported by this version of bsdtar"); - usage(bsdtar); -#endif - break; - case 'k': /* GNU tar */ - bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; - break; - case 'L': /* BSD convention */ - bsdtar->symlink_mode = 'L'; - break; - case 'l': /* SUSv2 and GNU conflict badly here */ - if (getenv("POSIXLY_CORRECT") != NULL) { - /* User has asked for POSIX/SUS behavior. */ - bsdtar->option_warn_links = 1; - } else { - fprintf(stderr, -"Error: -l has different behaviors in different tar programs.\n"); - fprintf(stderr, -" For the GNU behavior, use --one-file-system instead.\n"); - fprintf(stderr, -" For the POSIX behavior, use --check-links instead.\n"); - usage(bsdtar); - } - break; - case 'm': /* SUSv2 */ - bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; - break; - case 'n': /* GNU tar */ - bsdtar->option_no_subdirs = 1; - break; - case OPTION_NEWER_CTIME: /* GNU tar */ - bsdtar->newer_ctime_sec = get_date(optarg); - break; - case OPTION_NEWER_CTIME_THAN: - { - struct stat st; - if (stat(optarg, &st) != 0) - bsdtar_errc(bsdtar, 1, 0, - "Can't open file %s", optarg); - bsdtar->newer_ctime_sec = st.st_ctime; - bsdtar->newer_ctime_nsec = - ARCHIVE_STAT_CTIME_NANOS(&st); - } - break; - case OPTION_NEWER_MTIME: /* GNU tar */ - bsdtar->newer_mtime_sec = get_date(optarg); - break; - case OPTION_NEWER_MTIME_THAN: - { - struct stat st; - if (stat(optarg, &st) != 0) - bsdtar_errc(bsdtar, 1, 0, - "Can't open file %s", optarg); - bsdtar->newer_mtime_sec = st.st_mtime; - bsdtar->newer_mtime_nsec = - ARCHIVE_STAT_MTIME_NANOS(&st); - } - break; - case OPTION_NODUMP: /* star */ - bsdtar->option_honor_nodump = 1; - break; - case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ - /* - * This is always the default in FreeBSD's - * version of GNU tar; it's also the default - * behavior for bsdtar, so treat the - * command-line option as a no-op. - */ - break; - case OPTION_NULL: /* GNU tar */ - bsdtar->option_null++; - break; - case 'O': /* GNU tar */ - bsdtar->option_stdout = 1; - break; - case 'o': /* SUSv2 and GNU conflict here */ - option_o = 1; /* Record it and resolve it later. */ - break; - case OPTION_ONE_FILE_SYSTEM: /* -l in GNU tar */ - bsdtar->option_dont_traverse_mounts = 1; - break; -#if 0 - /* - * The common BSD -P option is not necessary, since - * our default is to archive symlinks, not follow - * them. This is convenient, as -P conflicts with GNU - * tar anyway. - */ - case 'P': /* BSD convention */ - /* Default behavior, no option necessary. */ - break; -#endif - case 'P': /* GNU tar */ - bsdtar->option_absolute_paths = 1; - break; - case 'p': /* GNU tar, star */ - bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; - bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; - bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; - bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; - break; - case 'r': /* SUSv2 */ - set_mode(bsdtar, opt); - break; - case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ - bsdtar->strip_components = atoi(optarg); - break; - case 'T': /* GNU tar */ - bsdtar->names_from_file = optarg; - break; - case 't': /* SUSv2 */ - set_mode(bsdtar, opt); - bsdtar->verbose++; - break; - case OPTION_TOTALS: /* GNU tar */ - bsdtar->option_totals++; - break; - case 'U': /* GNU tar */ - bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; - bsdtar->option_unlink_first = 1; - break; - case 'u': /* SUSv2 */ - set_mode(bsdtar, opt); - break; - case 'v': /* SUSv2 */ - bsdtar->verbose++; - break; - case OPTION_VERSION: - version(); - break; - case 'w': /* SUSv2 */ - bsdtar->option_interactive = 1; - break; - case 'X': /* GNU tar */ - if (exclude_from_file(bsdtar, optarg)) - bsdtar_errc(bsdtar, 1, 0, - "failed to process exclusions from file %s", - optarg); - break; - case 'x': /* SUSv2 */ - set_mode(bsdtar, opt); - break; - case 'y': /* FreeBSD version of GNU tar */ -#if HAVE_LIBBZ2 - if (bsdtar->create_compression != '\0') - bsdtar_errc(bsdtar, 1, 0, - "Can't specify both -%c and -%c", opt, - bsdtar->create_compression); - bsdtar->create_compression = opt; -#else - bsdtar_warnc(bsdtar, 0, "-y compression not supported by this version of bsdtar"); - usage(bsdtar); -#endif - break; - case 'Z': /* GNU tar */ - if (bsdtar->create_compression != '\0') - bsdtar_errc(bsdtar, 1, 0, - "Can't specify both -%c and -%c", opt, - bsdtar->create_compression); - bsdtar->create_compression = opt; - break; - case 'z': /* GNU tar, star, many others */ -#if HAVE_LIBZ - if (bsdtar->create_compression != '\0') - bsdtar_errc(bsdtar, 1, 0, - "Can't specify both -%c and -%c", opt, - bsdtar->create_compression); - bsdtar->create_compression = opt; -#else - bsdtar_warnc(bsdtar, 0, "-z compression not supported by this version of bsdtar"); - usage(bsdtar); -#endif - break; - default: - usage(bsdtar); - } - } - - /* - * Sanity-check options. - */ - if ((bsdtar->mode == '\0') && possible_help_request) { - long_help(bsdtar); - exit(0); - } - - if (bsdtar->mode == '\0') - bsdtar_errc(bsdtar, 1, 0, - "Must specify one of -c, -r, -t, -u, -x"); - - /* Check boolean options only permitted in certain modes. */ - if (bsdtar->option_dont_traverse_mounts) - only_mode(bsdtar, "-X", "cru"); - if (bsdtar->option_fast_read) - only_mode(bsdtar, "--fast-read", "xt"); - if (bsdtar->option_honor_nodump) - only_mode(bsdtar, "--nodump", "cru"); - if (option_o > 0) { - switch (bsdtar->mode) { - case 'c': - /* - * In GNU tar, -o means "old format." The - * "ustar" format is the closest thing - * supported by libarchive. - */ - bsdtar->create_format = "ustar"; - /* TODO: bsdtar->create_format = "v7"; */ - break; - case 'x': - /* POSIX-compatible behavior. */ - bsdtar->option_no_owner = 1; - bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; - break; - default: - only_mode(bsdtar, "-o", "xc"); - break; - } - } - if (bsdtar->option_no_subdirs) - only_mode(bsdtar, "-n", "cru"); - if (bsdtar->option_stdout) - only_mode(bsdtar, "-O", "xt"); - if (bsdtar->option_warn_links) - only_mode(bsdtar, "--check-links", "cr"); - - /* Check other parameters only permitted in certain modes. */ - if (bsdtar->create_compression == 'Z' && bsdtar->mode == 'c') { - bsdtar_warnc(bsdtar, 0, ".Z compression not supported"); - usage(bsdtar); - } - if (bsdtar->create_compression != '\0') { - strcpy(buff, "-?"); - buff[1] = bsdtar->create_compression; - only_mode(bsdtar, buff, "cxt"); - } - if (bsdtar->create_format != NULL) - only_mode(bsdtar, "--format", "c"); - if (bsdtar->symlink_mode != '\0') { - strcpy(buff, "-?"); - buff[1] = bsdtar->symlink_mode; - only_mode(bsdtar, buff, "cru"); - } - - bsdtar->argc -= optind; - bsdtar->argv += optind; - - switch(bsdtar->mode) { - case 'c': - tar_mode_c(bsdtar); - break; - case 'r': - tar_mode_r(bsdtar); - break; - case 't': - tar_mode_t(bsdtar); - break; - case 'u': - tar_mode_u(bsdtar); - break; - case 'x': - tar_mode_x(bsdtar); - break; - } - - cleanup_exclusions(bsdtar); - return (bsdtar->return_value); -} - -static void -set_mode(struct bsdtar *bsdtar, char opt) -{ - if (bsdtar->mode != '\0' && bsdtar->mode != opt) - bsdtar_errc(bsdtar, 1, 0, - "Can't specify both -%c and -%c", opt, bsdtar->mode); - bsdtar->mode = opt; -} - -/* - * Verify that the mode is correct. - */ -static void -only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) -{ - if (strchr(valid_modes, bsdtar->mode) == NULL) - bsdtar_errc(bsdtar, 1, 0, - "Option %s is not permitted in mode -%c", - opt, bsdtar->mode); -} - - -/*- - * Convert traditional tar arguments into new-style. - * For example, - * tar tvfb file.tar 32 --exclude FOO - * will be converted to - * tar -t -v -f file.tar -b 32 --exclude FOO - * - * This requires building a new argv array. The initial bundled word - * gets expanded into a new string that looks like "-t\0-v\0-f\0-b\0". - * The new argv array has pointers into this string intermingled with - * pointers to the existing arguments. Arguments are moved to - * immediately follow their options. - * - * The optstring argument here is the same one passed to getopt(3). - * It is used to determine which option letters have trailing arguments. - */ -char ** -rewrite_argv(struct bsdtar *bsdtar, int *argc, char **src_argv, - const char *optstring) -{ - char **new_argv, **dest_argv; - const char *p; - char *src, *dest; - - if (src_argv[0] == NULL || - src_argv[1] == NULL || src_argv[1][0] == '-') - return (src_argv); - - *argc += strlen(src_argv[1]) - 1; - new_argv = malloc((*argc + 1) * sizeof(new_argv[0])); - if (new_argv == NULL) - bsdtar_errc(bsdtar, 1, errno, "No Memory"); - - dest_argv = new_argv; - *dest_argv++ = *src_argv++; - - dest = malloc(strlen(*src_argv) * 3); - if (dest == NULL) - bsdtar_errc(bsdtar, 1, errno, "No memory"); - for (src = *src_argv++; *src != '\0'; src++) { - *dest_argv++ = dest; - *dest++ = '-'; - *dest++ = *src; - *dest++ = '\0'; - /* If option takes an argument, insert that into the list. */ - for (p = optstring; p != NULL && *p != '\0'; p++) { - if (*p != *src) - continue; - if (p[1] != ':') /* No arg required, done. */ - break; - if (*src_argv == NULL) /* No arg available? Error. */ - bsdtar_errc(bsdtar, 1, 0, - "Option %c requires an argument", - *src); - *dest_argv++ = *src_argv++; - break; - } - } - - /* Copy remaining arguments, including trailing NULL. */ - while ((*dest_argv++ = *src_argv++) != NULL) - ; - - return (new_argv); -} - -void -usage(struct bsdtar *bsdtar) -{ - const char *p; - - p = bsdtar->progname; - - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " List: %s -tf \n", p); - fprintf(stderr, " Extract: %s -xf \n", p); - fprintf(stderr, " Create: %s -cf [filenames...]\n", p); -#ifdef HAVE_GETOPT_LONG - fprintf(stderr, " Help: %s --help\n", p); -#else - fprintf(stderr, " Help: %s -h\n", p); -#endif - exit(1); -} - -static void -version(void) -{ - printf("bsdtar %s - %s\n", PACKAGE_VERSION, archive_version()); - exit(1); -} - -static const char *long_help_msg = - "First option must be a mode specifier:\n" - " -c Create -r Add/Replace -t List -u Update -x Extract\n" - "Common Options:\n" - " -b # Use # 512-byte records per I/O block\n" - " -f Location of archive (default " _PATH_DEFTAPE ")\n" - " -v Verbose\n" - " -w Interactive\n" - "Create: %p -c [options] [ | | @ | -C ]\n" - " , add these items to archive\n" - " -z, -j Compress archive with gzip/bzip2\n" - " --format {ustar|pax|cpio|shar} Select archive format\n" -#ifdef HAVE_GETOPT_LONG - " --exclude Skip files that match pattern\n" -#else - " -W exclude= Skip files that match pattern\n" -#endif - " -C Change to before processing remaining files\n" - " @ Add entries from to output\n" - "List: %p -t [options] []\n" - " If specified, list only entries that match\n" - "Extract: %p -x [options] []\n" - " If specified, extract only entries that match\n" - " -k Keep (don't overwrite) existing files\n" - " -m Don't restore modification times\n" - " -O Write entries to stdout, don't restore to disk\n" - " -p Restore permissions (including ACLs, owner, file flags)\n"; - - -/* - * Note that the word 'bsdtar' will always appear in the first line - * of output. - * - * In particular, /bin/sh scripts that need to test for the presence - * of bsdtar can use the following template: - * - * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ - * echo bsdtar; else echo not bsdtar; fi - */ -static void -long_help(struct bsdtar *bsdtar) -{ - const char *prog; - const char *p; - - prog = bsdtar->progname; - - fflush(stderr); - - p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; - printf("%s%s: manipulate archive files\n", prog, p); - - for (p = long_help_msg; *p != '\0'; p++) { - if (*p == '%') { - if (p[1] == 'p') { - fputs(prog, stdout); - p++; - } else - putchar('%'); - } else - putchar(*p); - } - version(); -} - -static int -bsdtar_getopt(struct bsdtar *bsdtar, const char *optstring, - const struct option **poption) -{ - char *p, *q; - const struct option *option; - int opt; - int option_index; - size_t option_length; - - option_index = -1; - *poption = NULL; - -#ifdef HAVE_GETOPT_LONG - opt = getopt_long(bsdtar->argc, bsdtar->argv, optstring, - tar_longopts, &option_index); - if (option_index > -1) - *poption = tar_longopts + option_index; -#else - opt = getopt(bsdtar->argc, bsdtar->argv, optstring); -#endif - - /* Support long options through -W longopt=value */ - if (opt == 'W') { - p = optarg; - q = strchr(optarg, '='); - if (q != NULL) { - option_length = (size_t)(q - p); - optarg = q + 1; - } else { - option_length = strlen(p); - optarg = NULL; - } - option = tar_longopts; - while (option->name != NULL && - (strlen(option->name) < option_length || - strncmp(p, option->name, option_length) != 0 )) { - option++; - } - - if (option->name != NULL) { - *poption = option; - opt = option->val; - - /* If the first match was exact, we're done. */ - if (strncmp(p, option->name, strlen(option->name)) == 0) { - while (option->name != NULL) - option++; - } else { - /* Check if there's another match. */ - option++; - while (option->name != NULL && - (strlen(option->name) < option_length || - strncmp(p, option->name, option_length) != 0)) { - option++; - } - } - if (option->name != NULL) - bsdtar_errc(bsdtar, 1, 0, - "Ambiguous option %s " - "(matches both %s and %s)", - p, (*poption)->name, option->name); - - } else { - opt = '?'; - /* TODO: Set up a fake 'struct option' for - * error reporting... ? ? ? */ - } - } - - return (opt); -} diff --git a/contrib/libarchive-1.3.1/tar/bsdtar.h b/contrib/libarchive-1.3.1/tar/bsdtar.h deleted file mode 100644 index 53e4084e38..0000000000 --- a/contrib/libarchive-1.3.1/tar/bsdtar.h +++ /dev/null @@ -1,127 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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. - * 3. The name(s) of the author(s) may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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/usr.bin/tar/bsdtar.h,v 1.24 2006/03/21 17:03:51 kientzle Exp $ - */ - -#include "bsdtar_platform.h" -#include - -#define DEFAULT_BYTES_PER_BLOCK (20*512) - -/* - * The internal state for the "bsdtar" program. - * - * Keeping all of the state in a structure like this simplifies memory - * leak testing (at exit, anything left on the heap is suspect). A - * pointer to this structure is passed to most bsdtar internal - * functions. - */ -struct bsdtar { - /* Options */ - const char *filename; /* -f filename */ - const char *create_format; /* -F format */ - char *pending_chdir; /* -C dir */ - const char *names_from_file; /* -T file */ - time_t newer_ctime_sec; /* --newer/--newer-than */ - long newer_ctime_nsec; /* --newer/--newer-than */ - time_t newer_mtime_sec; /* --newer-mtime */ - long newer_mtime_nsec; /* --newer-mtime-than */ - int bytes_per_block; /* -b block_size */ - int verbose; /* -v */ - int extract_flags; /* Flags for extract operation */ - int strip_components; /* Remove this many leading dirs */ - char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */ - char symlink_mode; /* H or L, per BSD conventions */ - char create_compression; /* j, y, or z */ - char option_absolute_paths; /* -P */ - char option_dont_traverse_mounts; /* -X */ - char option_fast_read; /* --fast-read */ - char option_honor_nodump; /* --nodump */ - char option_interactive; /* -w */ - char option_no_owner; /* -o */ - char option_no_subdirs; /* -d */ - char option_null; /* --null */ - char option_stdout; /* -p */ - char option_totals; /* --totals */ - char option_unlink_first; /* -U */ - char option_warn_links; /* -l */ - char day_first; /* show day before month in -tv output */ - - /* If >= 0, then close this when done. */ - int fd; - - /* Miscellaneous state information */ - struct archive *archive; - const char *progname; - int argc; - char **argv; - size_t gs_width; /* For 'list_item' in read.c */ - size_t u_width; /* for 'list_item' in read.c */ - uid_t user_uid; /* UID running this program */ - int return_value; /* Value returned by main() */ - char warned_lead_slash; /* Already displayed warning */ - char next_line_is_dir; /* Used for -C parsing in -cT */ - - /* - * Data for various subsystems. Full definitions are located in - * the file where they are used. - */ - struct archive_dir *archive_dir; /* for write.c */ - struct name_cache *gname_cache; /* for write.c */ - struct links_cache *links_cache; /* for write.c */ - struct matching *matching; /* for matching.c */ - struct security *security; /* for read.c */ - struct name_cache *uname_cache; /* for write.c */ -}; - -void bsdtar_errc(struct bsdtar *, int _eval, int _code, - const char *fmt, ...); -void bsdtar_strmode(struct archive_entry *entry, char *bp); -void bsdtar_warnc(struct bsdtar *, int _code, const char *fmt, ...); -void cleanup_exclusions(struct bsdtar *); -void do_chdir(struct bsdtar *); -int edit_pathname(struct bsdtar *, struct archive_entry *); -int exclude(struct bsdtar *, const char *pattern); -int exclude_from_file(struct bsdtar *, const char *pathname); -int excluded(struct bsdtar *, const char *pathname); -int include(struct bsdtar *, const char *pattern); -int include_from_file(struct bsdtar *, const char *pathname); -int process_lines(struct bsdtar *bsdtar, const char *pathname, - int (*process)(struct bsdtar *, const char *)); -void safe_fprintf(FILE *, const char *fmt, ...); -void set_chdir(struct bsdtar *, const char *newdir); -void tar_mode_c(struct bsdtar *bsdtar); -void tar_mode_r(struct bsdtar *bsdtar); -void tar_mode_t(struct bsdtar *bsdtar); -void tar_mode_u(struct bsdtar *bsdtar); -void tar_mode_x(struct bsdtar *bsdtar); -int unmatched_inclusions(struct bsdtar *bsdtar); -void usage(struct bsdtar *); -int yes(const char *fmt, ...); - diff --git a/contrib/libarchive-1.3.1/tar/bsdtar_platform.h b/contrib/libarchive-1.3.1/tar/bsdtar_platform.h deleted file mode 100644 index 7d355d7301..0000000000 --- a/contrib/libarchive-1.3.1/tar/bsdtar_platform.h +++ /dev/null @@ -1,209 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/usr.bin/tar/bsdtar_platform.h,v 1.20 2006/03/21 17:03:51 kientzle Exp $ - */ - -/* - * This header is the first thing included in any of the bsdtar - * source files. As far as possible, platform-specific issues should - * be dealt with here and not within individual source files. - */ - -#ifndef BSDTAR_PLATFORM_H_INCLUDED -#define BSDTAR_PLATFORM_H_INCLUDED - -#if HAVE_CONFIG_H -#include "../config.h" -#else - -#ifdef __FreeBSD__ -#include /* __FreeBSD_version */ -/* A default configuration for FreeBSD, used if there is no config.h. */ -#define PACKAGE_NAME "bsdtar" - -#if __FreeBSD__ > 4 -#define HAVE_ACL_GET_PERM 0 -#define HAVE_ACL_GET_PERM_NP 1 -#define HAVE_ACL_PERMSET_T 1 -#endif -#define HAVE_BZLIB_H 1 -#define HAVE_CHFLAGS 1 -#define HAVE_DIRENT_D_NAMLEN 1 -#define HAVE_DIRENT_H 1 -#define HAVE_D_MD_ORDER 1 -#define HAVE_FCHDIR 1 -#define HAVE_FCNTL_H 1 -#define HAVE_FNMATCH 1 -#define HAVE_FNM_LEADING_DIR 1 -#define HAVE_FTRUNCATE 1 -#define HAVE_GETOPT_LONG 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_LANGINFO_H 1 -#define HAVE_LIBARCHIVE 1 -#define HAVE_LIBBZ2 1 -#define HAVE_LIBZ 1 -#define HAVE_LIMITS_H 1 -#define HAVE_LOCALE_H 1 -#define HAVE_MALLOC 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMORY_H 1 -#define HAVE_MEMSET 1 -#if __FreeBSD_version >= 450002 /* nl_langinfo introduced */ -#define HAVE_NL_LANGINFO 1 -#endif -#define HAVE_PATHS_H 1 -#define HAVE_SETLOCALE 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRCHR 1 -#define HAVE_STRDUP 1 -#define HAVE_STRERROR 1 -#define HAVE_STRFTIME 1 -#define HAVE_STRINGS_H 1 -#define HAVE_STRING_H 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_STAT_ST_RDEV 1 -#define HAVE_SYS_ACL_H 1 -#define HAVE_SYS_IOCTL_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_UINTMAX_T 1 -#define HAVE_UNISTD_H 1 -#define HAVE_VPRINTF 1 -#define HAVE_ZLIB_H 1 -#define STDC_HEADERS 1 - -#else /* !__FreeBSD__ */ -/* Warn if bsdtar hasn't been (automatically or manually) configured. */ -#error Oops: No config.h and no built-in configuration in bsdtar_platform.h. -#endif /* !__FreeBSD__ */ - -#endif /* !HAVE_CONFIG_H */ - -/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ -#ifdef __FreeBSD__ -#include /* For __FBSDID */ -#else -#define __FBSDID(a) /* null */ -#endif - -#ifdef HAVE_LIBARCHIVE -/* If we're using the platform libarchive, include system headers. */ -#include -#include -#else -/* Otherwise, include user headers. */ -#include "archive.h" -#include "archive_entry.h" -#endif - -/* - * Does this platform have complete-looking POSIX-style ACL support, - * including some variant of the acl_get_perm() function (which was - * omitted from the POSIX.1e draft)? - */ -#if HAVE_SYS_ACL_H && HAVE_ACL_PERMSET_T && HAVE_ACL_USER -#if HAVE_ACL_GET_PERM || HAVE_ACL_GET_PERM_NP -#define HAVE_POSIX_ACL 1 -#endif -#endif - -#ifdef HAVE_LIBACL -#include -#endif - -#if HAVE_ACL_GET_PERM -#define ACL_GET_PERM acl_get_perm -#else -#if HAVE_ACL_GET_PERM_NP -#define ACL_GET_PERM acl_get_perm_np -#endif -#endif - -/* - * Include "dirent.h" (or it's equivalent on several different platforms). - * - * This is slightly modified from the GNU autoconf recipe. - * In particular, FreeBSD includes d_namlen in it's dirent structure, - * so my configure script includes an explicit test for the d_namlen - * field. - */ -#if HAVE_DIRENT_H -# include -# if HAVE_DIRENT_D_NAMLEN -# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen -# else -# define DIRENT_NAMLEN(dirent) strlen((dirent)->d_name) -# endif -#else -# define dirent direct -# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -#endif - - -/* - * We need to be able to display a filesize using printf(). The type - * and format string here must be compatible with one another and - * large enough for any file. - */ -#if HAVE_UINTMAX_T -#define BSDTAR_FILESIZE_TYPE uintmax_t -#define BSDTAR_FILESIZE_PRINTF "%ju" -#else -#if HAVE_UNSIGNED_LONG_LONG -#define BSDTAR_FILESIZE_TYPE unsigned long long -#define BSDTAR_FILESIZE_PRINTF "%llu" -#else -#define BSDTAR_FILESIZE_TYPE unsigned long -#define BSDTAR_FILESIZE_PRINTF "%lu" -#endif -#endif - -#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC -#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctimespec.tv_nsec -#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtimespec.tv_nsec -#else -#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC -#define ARCHIVE_STAT_CTIME_NANOS(st) (st)->st_ctim.tv_nsec -#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtim.tv_nsec -#else -#define ARCHIVE_STAT_CTIME_NANOS(st) (0) -#define ARCHIVE_STAT_MTIME_NANOS(st) (0) -#endif -#endif - -#endif /* !BSDTAR_PLATFORM_H_INCLUDED */ diff --git a/contrib/libarchive-1.3.1/tar/getdate.y b/contrib/libarchive-1.3.1/tar/getdate.y deleted file mode 100644 index 9ac6c96677..0000000000 --- a/contrib/libarchive-1.3.1/tar/getdate.y +++ /dev/null @@ -1,810 +0,0 @@ -%{ -/* - * March 2005: Further modified and simplified by Tim Kientzle: - * Eliminate minutes-based calculations (just do everything in - * seconds), have lexer only recognize unsigned integers (handle '+' - * and '-' characters in grammar), combine tables into one table with - * explicit abbreviation notes, do am/pm adjustments in the grammar - * (eliminate some state variables and post-processing). Among other - * things, these changes eliminated two shift/reduce conflicts. (Went - * from 10 to 8.) - */ - -/* -** Originally written by Steven M. Bellovin while -** at the University of North Carolina at Chapel Hill. Later tweaked by -** a couple of people on Usenet. Completely overhauled by Rich $alz -** and Jim Berets in August, 1990; -** -** This grammar has 10 shift/reduce conflicts. -** -** This code is in the public domain and has no copyright. -*/ -/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */ -/* SUPPRESS 288 on yyerrlab *//* Label unused */ - -#ifdef __FreeBSD__ -#include -__FBSDID("$FreeBSD: src/usr.bin/tar/getdate.y,v 1.6 2006/03/21 17:03:51 kientzle Exp $"); -#endif - -#include -#include -#include -#include -#include - -#define yyparse getdate_yyparse -#define yylex getdate_yylex -#define yyerror getdate_yyerror - -static int yyparse(void); -static int yylex(void); -static int yyerror(const char *); - -time_t get_date(char *); - -#define EPOCH 1970 -#define HOUR(x) ((time_t)(x) * 60) -#define SECSPERDAY (24L * 60L * 60L) - -/* -** Daylight-savings mode: on, off, or not yet known. -*/ -typedef enum _DSTMODE { - DSTon, DSToff, DSTmaybe -} DSTMODE; - -/* -** Meridian: am or pm. -*/ -enum { tAM, tPM }; - -/* -** Global variables. We could get rid of most of these by using a good -** union as the yacc stack. (This routine was originally written before -** yacc had the %union construct.) Maybe someday; right now we only use -** the %union very rarely. -*/ -static char *yyInput; - -static DSTMODE yyDSTmode; -static time_t yyDayOrdinal; -static time_t yyDayNumber; -static int yyHaveDate; -static int yyHaveDay; -static int yyHaveRel; -static int yyHaveTime; -static int yyHaveZone; -static time_t yyTimezone; -static time_t yyDay; -static time_t yyHour; -static time_t yyMinutes; -static time_t yyMonth; -static time_t yySeconds; -static time_t yyYear; -static time_t yyRelMonth; -static time_t yyRelSeconds; - -%} - -%union { - time_t Number; -} - -%token tAGO tDAY tDAYZONE tAMPM tMONTH tMONTH_UNIT tSEC_UNIT tUNUMBER -%token tZONE tDST - -%type tDAY tDAYZONE tMONTH tMONTH_UNIT -%type tSEC_UNIT tUNUMBER tZONE tAMPM - -%% - -spec : /* NULL */ - | spec item - ; - -item : time { yyHaveTime++; } - | zone { yyHaveZone++; } - | date { yyHaveDate++; } - | day { yyHaveDay++; } - | rel { yyHaveRel++; } - | number - ; - -time : tUNUMBER tAMPM { - /* "7am" */ - yyHour = $1; - if (yyHour == 12) - yyHour = 0; - yyMinutes = 0; - yySeconds = 0; - if ($2 == tPM) - yyHour += 12; - } - | bare_time { - /* "7:12:18" "19:17" */ - } - | bare_time tAMPM { - /* "7:12pm", "12:20:13am" */ - if (yyHour == 12) - yyHour = 0; - if ($2 == tPM) - yyHour += 12; - } - | bare_time '+' tUNUMBER { - /* "7:14+0700" */ - yyDSTmode = DSToff; - yyTimezone = - ($3 % 100 + ($3 / 100) * 60); - } - | bare_time '-' tUNUMBER { - /* "19:14:12-0530" */ - yyDSTmode = DSToff; - yyTimezone = + ($3 % 100 + ($3 / 100) * 60); - } - ; - -bare_time : tUNUMBER ':' tUNUMBER { - yyHour = $1; - yyMinutes = $3; - yySeconds = 0; - } - | tUNUMBER ':' tUNUMBER ':' tUNUMBER { - yyHour = $1; - yyMinutes = $3; - yySeconds = $5; - } - ; - -zone : tZONE { - yyTimezone = $1; - yyDSTmode = DSToff; - } - | tDAYZONE { - yyTimezone = $1; - yyDSTmode = DSTon; - } - | tZONE tDST { - yyTimezone = $1; - yyDSTmode = DSTon; - } - ; - -day : tDAY { - yyDayOrdinal = 1; - yyDayNumber = $1; - } - | tDAY ',' { - /* "tue," "wednesday," */ - yyDayOrdinal = 1; - yyDayNumber = $1; - } - | tUNUMBER tDAY { - /* "second tues" "3 wed" */ - yyDayOrdinal = $1; - yyDayNumber = $2; - } - ; - -date : tUNUMBER '/' tUNUMBER { - /* "1/15" */ - yyMonth = $1; - yyDay = $3; - } - | tUNUMBER '/' tUNUMBER '/' tUNUMBER { - if ($1 >= 13) { - /* First number is big: 2004/01/29, 99/02/17 */ - yyYear = $1; - yyMonth = $3; - yyDay = $5; - } else if (($5 >= 13) || ($3 >= 13)) { - /* Last number is big: 01/07/98 */ - /* Middle number is big: 01/29/04 */ - yyMonth = $1; - yyDay = $3; - yyYear = $5; - } else { - /* No significant clues: 02/03/04 */ - yyMonth = $1; - yyDay = $3; - yyYear = $5; - } - } - | tUNUMBER '-' tUNUMBER '-' tUNUMBER { - /* ISO 8601 format. yyyy-mm-dd. */ - yyYear = $1; - yyMonth = $3; - yyDay = $5; - } - | tUNUMBER '-' tMONTH '-' tUNUMBER { - if ($1 > 31) { - /* e.g. 1992-Jun-17 */ - yyYear = $1; - yyMonth = $3; - yyDay = $5; - } else { - /* e.g. 17-JUN-1992. */ - yyDay = $1; - yyMonth = $3; - yyYear = $5; - } - } - | tMONTH tUNUMBER { - /* "May 3" */ - yyMonth = $1; - yyDay = $2; - } - | tMONTH tUNUMBER ',' tUNUMBER { - /* "June 17, 2001" */ - yyMonth = $1; - yyDay = $2; - yyYear = $4; - } - | tUNUMBER tMONTH { - /* "12 Sept" */ - yyDay = $1; - yyMonth = $2; - } - | tUNUMBER tMONTH tUNUMBER { - /* "12 Sept 1997" */ - yyDay = $1; - yyMonth = $2; - yyYear = $3; - } - ; - -rel : relunit tAGO { - yyRelSeconds = -yyRelSeconds; - yyRelMonth = -yyRelMonth; - } - | relunit - ; - -relunit : '-' tUNUMBER tSEC_UNIT { - /* "-3 hours" */ - yyRelSeconds -= $2 * $3; - } - | '+' tUNUMBER tSEC_UNIT { - /* "+1 minute" */ - yyRelSeconds += $2 * $3; - } - | tUNUMBER tSEC_UNIT { - /* "1 day" */ - yyRelSeconds += $1; - } - | tSEC_UNIT { - /* "hour" */ - yyRelSeconds++; - } - | '-' tUNUMBER tMONTH_UNIT { - /* "-3 months" */ - yyRelMonth -= $2 * $3; - } - | '+' tUNUMBER tMONTH_UNIT { - /* "+5 years" */ - yyRelMonth += $2 * $3; - } - | tUNUMBER tMONTH_UNIT { - /* "2 years" */ - yyRelMonth += $1 * $2; - } - | tMONTH_UNIT { - /* "6 months" */ - yyRelMonth += $1; - } - ; - -number : tUNUMBER { - if (yyHaveTime && yyHaveDate && !yyHaveRel) - yyYear = $1; - else { - if($1>10000) { - /* "20040301" */ - yyHaveDate++; - yyDay= ($1)%100; - yyMonth= ($1/100)%100; - yyYear = $1/10000; - } - else { - /* "513" is same as "5:13" */ - yyHaveTime++; - if ($1 < 100) { - yyHour = $1; - yyMinutes = 0; - } - else { - yyHour = $1 / 100; - yyMinutes = $1 % 100; - } - yySeconds = 0; - } - } - } - ; - - -%% - -static struct TABLE { - size_t abbrev; - const char *name; - int type; - time_t value; -} const TimeWords[] = { - /* am/pm */ - { 0, "am", tAMPM, tAM }, - { 0, "pm", tAMPM, tPM }, - - /* Month names. */ - { 3, "january", tMONTH, 1 }, - { 3, "february", tMONTH, 2 }, - { 3, "march", tMONTH, 3 }, - { 3, "april", tMONTH, 4 }, - { 3, "may", tMONTH, 5 }, - { 3, "june", tMONTH, 6 }, - { 3, "july", tMONTH, 7 }, - { 3, "august", tMONTH, 8 }, - { 3, "september", tMONTH, 9 }, - { 3, "october", tMONTH, 10 }, - { 3, "november", tMONTH, 11 }, - { 3, "december", tMONTH, 12 }, - - /* Days of the week. */ - { 2, "sunday", tDAY, 0 }, - { 3, "monday", tDAY, 1 }, - { 2, "tuesday", tDAY, 2 }, - { 3, "wednesday", tDAY, 3 }, - { 2, "thursday", tDAY, 4 }, - { 2, "friday", tDAY, 5 }, - { 2, "saturday", tDAY, 6 }, - - /* Timezones: Offsets are in minutes. */ - { 0, "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ - { 0, "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ - { 0, "utc", tZONE, HOUR( 0) }, - { 0, "wet", tZONE, HOUR( 0) }, /* Western European */ - { 0, "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ - { 0, "wat", tZONE, HOUR( 1) }, /* West Africa */ - { 0, "at", tZONE, HOUR( 2) }, /* Azores */ - /* { 0, "bst", tZONE, HOUR( 3) }, */ /* Brazil Standard: Conflict */ - /* { 0, "gst", tZONE, HOUR( 3) }, */ /* Greenland Standard: Conflict*/ - { 0, "nft", tZONE, HOUR(3)+30 }, /* Newfoundland */ - { 0, "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */ - { 0, "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */ - { 0, "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ - { 0, "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ - { 0, "est", tZONE, HOUR( 5) }, /* Eastern Standard */ - { 0, "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ - { 0, "cst", tZONE, HOUR( 6) }, /* Central Standard */ - { 0, "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ - { 0, "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ - { 0, "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ - { 0, "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ - { 0, "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ - { 0, "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ - { 0, "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ - { 0, "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ - { 0, "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ - { 0, "cat", tZONE, HOUR(10) }, /* Central Alaska */ - { 0, "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ - { 0, "nt", tZONE, HOUR(11) }, /* Nome */ - { 0, "idlw", tZONE, HOUR(12) }, /* Intl Date Line West */ - { 0, "cet", tZONE, -HOUR(1) }, /* Central European */ - { 0, "met", tZONE, -HOUR(1) }, /* Middle European */ - { 0, "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */ - { 0, "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */ - { 0, "swt", tZONE, -HOUR(1) }, /* Swedish Winter */ - { 0, "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */ - { 0, "fwt", tZONE, -HOUR(1) }, /* French Winter */ - { 0, "fst", tDAYZONE, -HOUR(1) }, /* French Summer */ - { 0, "eet", tZONE, -HOUR(2) }, /* Eastern Eur, USSR Zone 1 */ - { 0, "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */ - { 0, "it", tZONE, -HOUR(3)-30 },/* Iran */ - { 0, "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */ - { 0, "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */ - { 0, "ist", tZONE, -HOUR(5)-30 },/* Indian Standard */ - { 0, "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */ - /* { 0, "nst", tZONE, -HOUR(6.5) }, */ /* North Sumatra: Conflict */ - /* { 0, "sst", tZONE, -HOUR(7) }, */ /* So Sumatra, USSR 6: Conflict */ - { 0, "wast", tZONE, -HOUR(7) }, /* West Australian Standard */ - { 0, "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */ - { 0, "jt", tZONE, -HOUR(7)-30 },/* Java (3pm in Cronusland!)*/ - { 0, "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */ - { 0, "jst", tZONE, -HOUR(9) }, /* Japan Std, USSR Zone 8 */ - { 0, "cast", tZONE, -HOUR(9)-30 },/* Central Australian Std */ - { 0, "cadt", tDAYZONE, -HOUR(9)-30 },/* Central Australian Daylt */ - { 0, "east", tZONE, -HOUR(10) }, /* Eastern Australian Std */ - { 0, "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylt */ - { 0, "gst", tZONE, -HOUR(10) }, /* Guam Std, USSR Zone 9 */ - { 0, "nzt", tZONE, -HOUR(12) }, /* New Zealand */ - { 0, "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ - { 0, "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ - { 0, "idle", tZONE, -HOUR(12) }, /* Intl Date Line East */ - - { 0, "dst", tDST, 0 }, - - /* Time units. */ - { 4, "years", tMONTH_UNIT, 12 }, - { 5, "months", tMONTH_UNIT, 1 }, - { 9, "fortnights", tSEC_UNIT, 14 * 24 * 60 * 60 }, - { 4, "weeks", tSEC_UNIT, 7 * 24 * 60 * 60 }, - { 3, "days", tSEC_UNIT, 1 * 24 * 60 * 60 }, - { 4, "hours", tSEC_UNIT, 60 * 60 }, - { 3, "minutes", tSEC_UNIT, 60 }, - { 3, "seconds", tSEC_UNIT, 1 }, - - /* Relative-time words. */ - { 0, "tomorrow", tSEC_UNIT, 1 * 24 * 60 * 60 }, - { 0, "yesterday", tSEC_UNIT, -1 * 24 * 60 * 60 }, - { 0, "today", tSEC_UNIT, 0 }, - { 0, "now", tSEC_UNIT, 0 }, - { 0, "last", tUNUMBER, -1 }, - { 0, "this", tSEC_UNIT, 0 }, - { 0, "next", tUNUMBER, 2 }, - { 0, "first", tUNUMBER, 1 }, - { 0, "1st", tUNUMBER, 1 }, -/* { 0, "second", tUNUMBER, 2 }, */ - { 0, "2nd", tUNUMBER, 2 }, - { 0, "third", tUNUMBER, 3 }, - { 0, "3rd", tUNUMBER, 3 }, - { 0, "fourth", tUNUMBER, 4 }, - { 0, "4th", tUNUMBER, 4 }, - { 0, "fifth", tUNUMBER, 5 }, - { 0, "5th", tUNUMBER, 5 }, - { 0, "sixth", tUNUMBER, 6 }, - { 0, "seventh", tUNUMBER, 7 }, - { 0, "eighth", tUNUMBER, 8 }, - { 0, "ninth", tUNUMBER, 9 }, - { 0, "tenth", tUNUMBER, 10 }, - { 0, "eleventh", tUNUMBER, 11 }, - { 0, "twelfth", tUNUMBER, 12 }, - { 0, "ago", tAGO, 1 }, - - /* Military timezones. */ - { 0, "a", tZONE, HOUR( 1) }, - { 0, "b", tZONE, HOUR( 2) }, - { 0, "c", tZONE, HOUR( 3) }, - { 0, "d", tZONE, HOUR( 4) }, - { 0, "e", tZONE, HOUR( 5) }, - { 0, "f", tZONE, HOUR( 6) }, - { 0, "g", tZONE, HOUR( 7) }, - { 0, "h", tZONE, HOUR( 8) }, - { 0, "i", tZONE, HOUR( 9) }, - { 0, "k", tZONE, HOUR( 10) }, - { 0, "l", tZONE, HOUR( 11) }, - { 0, "m", tZONE, HOUR( 12) }, - { 0, "n", tZONE, HOUR(- 1) }, - { 0, "o", tZONE, HOUR(- 2) }, - { 0, "p", tZONE, HOUR(- 3) }, - { 0, "q", tZONE, HOUR(- 4) }, - { 0, "r", tZONE, HOUR(- 5) }, - { 0, "s", tZONE, HOUR(- 6) }, - { 0, "t", tZONE, HOUR(- 7) }, - { 0, "u", tZONE, HOUR(- 8) }, - { 0, "v", tZONE, HOUR(- 9) }, - { 0, "w", tZONE, HOUR(-10) }, - { 0, "x", tZONE, HOUR(-11) }, - { 0, "y", tZONE, HOUR(-12) }, - { 0, "z", tZONE, HOUR( 0) }, - - /* End of table. */ - { 0, NULL, 0, 0 } -}; - - - - -/* ARGSUSED */ -static int -yyerror(const char *s) -{ - (void)s; - return 0; -} - -static time_t -ToSeconds(time_t Hours, time_t Minutes, time_t Seconds) -{ - if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) - return -1; - if (Hours < 0 || Hours > 23) - return -1; - return (Hours * 60L + Minutes) * 60L + Seconds; -} - - -/* Year is either - * A number from 0 to 99, which means a year from 1970 to 2069, or - * The actual year (>=100). */ -static time_t -Convert(time_t Month, time_t Day, time_t Year, - time_t Hours, time_t Minutes, time_t Seconds, DSTMODE DSTmode) -{ - static int DaysInMonth[12] = { - 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - time_t tod; - time_t Julian; - int i; - - if (Year < 69) - Year += 2000; - else if (Year < 100) - Year += 1900; - DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) - ? 29 : 28; - /* Checking for 2038 bogusly assumes that time_t is 32 bits. But - I'm too lazy to try to check for time_t overflow in another way. */ - if (Year < EPOCH || Year > 2038 - || Month < 1 || Month > 12 - /* Lint fluff: "conversion from long may lose accuracy" */ - || Day < 1 || Day > DaysInMonth[(int)--Month]) - return -1; - - Julian = Day - 1; - for (i = 0; i < Month; i++) - Julian += DaysInMonth[i]; - for (i = EPOCH; i < Year; i++) - Julian += 365 + (i % 4 == 0); - Julian *= SECSPERDAY; - Julian += yyTimezone * 60L; - if ((tod = ToSeconds(Hours, Minutes, Seconds)) < 0) - return -1; - Julian += tod; - if (DSTmode == DSTon - || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst)) - Julian -= 60 * 60; - return Julian; -} - - -static time_t -DSTcorrect(time_t Start, time_t Future) -{ - time_t StartDay; - time_t FutureDay; - - StartDay = (localtime(&Start)->tm_hour + 1) % 24; - FutureDay = (localtime(&Future)->tm_hour + 1) % 24; - return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; -} - - -static time_t -RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber) -{ - struct tm *tm; - time_t now; - - now = Start; - tm = localtime(&now); - now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); - now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); - return DSTcorrect(Start, now); -} - - -static time_t -RelativeMonth(time_t Start, time_t RelMonth) -{ - struct tm *tm; - time_t Month; - time_t Year; - - if (RelMonth == 0) - return 0; - tm = localtime(&Start); - Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth; - Year = Month / 12; - Month = Month % 12 + 1; - return DSTcorrect(Start, - Convert(Month, (time_t)tm->tm_mday, Year, - (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, - DSTmaybe)); -} - -static int -yylex(void) -{ - char c; - char buff[64]; - - for ( ; ; ) { - while (isspace(*yyInput)) - yyInput++; - - /* Skip parenthesized comments. */ - if (*yyInput == '(') { - int Count = 0; - do { - c = *yyInput++; - if (c == '\0') - return c; - if (c == '(') - Count++; - else if (c == ')') - Count--; - } while (Count > 0); - continue; - } - - /* Try the next token in the word table first. */ - /* This allows us to match "2nd", for example. */ - { - char *src = yyInput; - const struct TABLE *tp; - unsigned i = 0; - - /* Force to lowercase and strip '.' characters. */ - while (*src != '\0' - && (isalnum(*src) || *src == '.') - && i < sizeof(buff)-1) { - if (*src != '.') { - if (isupper(*src)) - buff[i++] = tolower(*src); - else - buff[i++] = *src; - } - src++; - } - buff[i++] = '\0'; - - /* - * Find the first match. If the word can be - * abbreviated, make sure we match at least - * the minimum abbreviation. - */ - for (tp = TimeWords; tp->name; tp++) { - size_t abbrev = tp->abbrev; - if (abbrev == 0) - abbrev = strlen(tp->name); - if (strlen(buff) >= abbrev - && strncmp(tp->name, buff, strlen(buff)) - == 0) { - /* Skip over token. */ - yyInput = src; - /* Return the match. */ - yylval.Number = tp->value; - return tp->type; - } - } - } - - /* - * Not in the word table, maybe it's a number. Note: - * Because '-' and '+' have other special meanings, I - * don't deal with signed numbers here. - */ - if (isdigit(c = *yyInput)) { - for (yylval.Number = 0; isdigit(c = *yyInput++); ) - yylval.Number = 10 * yylval.Number + c - '0'; - yyInput--; - return (tUNUMBER); - } - - return (*yyInput++); - } -} - -#define TM_YEAR_ORIGIN 1900 - -/* Yield A - B, measured in seconds. */ -static long -difftm (struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); - int by = b->tm_year + (TM_YEAR_ORIGIN - 1); - int days = ( - /* difference in day of year */ - a->tm_yday - b->tm_yday - /* + intervening leap days */ - + ((ay >> 2) - (by >> 2)) - - (ay/100 - by/100) - + ((ay/100 >> 2) - (by/100 >> 2)) - /* + difference in years * 365 */ - + (long)(ay-by) * 365 - ); - return (60*(60*(24*days + (a->tm_hour - b->tm_hour)) - + (a->tm_min - b->tm_min)) - + (a->tm_sec - b->tm_sec)); -} - -time_t -get_date(char *p) -{ - struct tm *tm; - struct tm gmt, *gmt_ptr; - time_t Start; - time_t tod; - time_t nowtime; - long tzone; - - memset(&gmt, 0, sizeof(gmt)); - yyInput = p; - - (void)time (&nowtime); - - gmt_ptr = gmtime (&nowtime); - if (gmt_ptr != NULL) { - /* Copy, in case localtime and gmtime use the same buffer. */ - gmt = *gmt_ptr; - } - - if (! (tm = localtime (&nowtime))) - return -1; - - if (gmt_ptr != NULL) - tzone = difftm (&gmt, tm) / 60; - else - /* This system doesn't understand timezones; fake it. */ - tzone = 0; - if(tm->tm_isdst) - tzone += 60; - - yyYear = tm->tm_year + 1900; - yyMonth = tm->tm_mon + 1; - yyDay = tm->tm_mday; - yyTimezone = tzone; - yyDSTmode = DSTmaybe; - yyHour = 0; - yyMinutes = 0; - yySeconds = 0; - yyRelSeconds = 0; - yyRelMonth = 0; - yyHaveDate = 0; - yyHaveDay = 0; - yyHaveRel = 0; - yyHaveTime = 0; - yyHaveZone = 0; - - if (yyparse() - || yyHaveTime > 1 || yyHaveZone > 1 - || yyHaveDate > 1 || yyHaveDay > 1) - return -1; - - if (yyHaveDate || yyHaveTime || yyHaveDay) { - Start = Convert(yyMonth, yyDay, yyYear, - yyHour, yyMinutes, yySeconds, yyDSTmode); - if (Start < 0) - return -1; - } else { - Start = nowtime; - if (!yyHaveRel) - Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec; - } - - Start += yyRelSeconds; - Start += RelativeMonth(Start, yyRelMonth); - - if (yyHaveDay && !yyHaveDate) { - tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber); - Start += tod; - } - - /* Have to do *something* with a legitimate -1 so it's - * distinguishable from the error return value. (Alternately - * could set errno on error.) */ - return Start == -1 ? 0 : Start; -} - - -#if defined(TEST) - -/* ARGSUSED */ -int -main(int argc, char **argv) -{ - time_t d; - - while (*++argv != NULL) { - (void)printf("Input: %s\n", *argv); - d = get_date(*argv); - if (d == -1) - (void)printf("Bad format - couldn't convert.\n"); - else - (void)printf("Output: %s\n", ctime(&d)); - } - exit(0); - /* NOTREACHED */ -} -#endif /* defined(TEST) */ diff --git a/contrib/libarchive-1.3.1/tar/matching.c b/contrib/libarchive-1.3.1/tar/matching.c deleted file mode 100644 index 1f2cb89327..0000000000 --- a/contrib/libarchive-1.3.1/tar/matching.c +++ /dev/null @@ -1,416 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/matching.c,v 1.9 2005/03/14 00:30:35 kientzle Exp $"); - -#include -#include -#include - -#include "bsdtar.h" - -struct match { - struct match *next; - int matches; - char pattern[1]; -}; - -struct matching { - struct match *exclusions; - int exclusions_count; - struct match *inclusions; - int inclusions_count; - int inclusions_unmatched_count; -}; - - -static void add_pattern(struct bsdtar *, struct match **list, - const char *pattern); -static int bsdtar_fnmatch(const char *p, const char *s); -static void initialize_matching(struct bsdtar *); -static int match_exclusion(struct match *, const char *pathname); -static int match_inclusion(struct match *, const char *pathname); - -/* - * The matching logic here needs to be re-thought. I started out to - * try to mimic gtar's matching logic, but it's not entirely - * consistent. In particular 'tar -t' and 'tar -x' interpret patterns - * on the command line as anchored, but --exclude doesn't. - */ - -/* - * Utility functions to manage exclusion/inclusion patterns - */ - -int -exclude(struct bsdtar *bsdtar, const char *pattern) -{ - struct matching *matching; - - if (bsdtar->matching == NULL) - initialize_matching(bsdtar); - matching = bsdtar->matching; - add_pattern(bsdtar, &(matching->exclusions), pattern); - matching->exclusions_count++; - return (0); -} - -int -exclude_from_file(struct bsdtar *bsdtar, const char *pathname) -{ - return (process_lines(bsdtar, pathname, &exclude)); -} - -int -include(struct bsdtar *bsdtar, const char *pattern) -{ - struct matching *matching; - - if (bsdtar->matching == NULL) - initialize_matching(bsdtar); - matching = bsdtar->matching; - add_pattern(bsdtar, &(matching->inclusions), pattern); - matching->inclusions_count++; - matching->inclusions_unmatched_count++; - return (0); -} - -int -include_from_file(struct bsdtar *bsdtar, const char *pathname) -{ - return (process_lines(bsdtar, pathname, &include)); -} - -static void -add_pattern(struct bsdtar *bsdtar, struct match **list, const char *pattern) -{ - struct match *match; - - match = malloc(sizeof(*match) + strlen(pattern) + 1); - if (match == NULL) - bsdtar_errc(bsdtar, 1, errno, "Out of memory"); - if (pattern[0] == '/') - pattern++; - strcpy(match->pattern, pattern); - /* Both "foo/" and "foo" should match "foo/bar". */ - if (match->pattern[strlen(match->pattern)-1] == '/') - match->pattern[strlen(match->pattern)-1] = '\0'; - match->next = *list; - *list = match; - match->matches = 0; -} - - -int -excluded(struct bsdtar *bsdtar, const char *pathname) -{ - struct matching *matching; - struct match *match; - struct match *matched; - - matching = bsdtar->matching; - if (matching == NULL) - return (0); - - /* Exclusions take priority */ - for (match = matching->exclusions; match != NULL; match = match->next){ - if (match_exclusion(match, pathname)) - return (1); - } - - /* Then check for inclusions */ - matched = NULL; - for (match = matching->inclusions; match != NULL; match = match->next){ - if (match_inclusion(match, pathname)) { - /* - * If this pattern has never been matched, - * then we're done. - */ - if (match->matches == 0) { - match->matches++; - matching->inclusions_unmatched_count++; - return (0); - } - /* - * Otherwise, remember the match but keep checking - * in case we can tick off an unmatched pattern. - */ - matched = match; - } - } - /* - * We didn't find a pattern that had never been matched, but - * we did find a match, so count it and exit. - */ - if (matched != NULL) { - matched->matches++; - return (0); - } - - /* If there were inclusions, default is to exclude. */ - if (matching->inclusions != NULL) - return (1); - - /* No explicit inclusions, default is to match. */ - return (0); -} - -/* - * This is a little odd, but it matches the default behavior of - * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' - * - */ -int -match_exclusion(struct match *match, const char *pathname) -{ - const char *p; - - if (*match->pattern == '*' || *match->pattern == '/') - return (bsdtar_fnmatch(match->pattern, pathname) == 0); - - for (p = pathname; p != NULL; p = strchr(p, '/')) { - if (*p == '/') - p++; - if (bsdtar_fnmatch(match->pattern, p) == 0) - return (1); - } - return (0); -} - -/* - * Again, mimic gtar: inclusions are always anchored (have to match - * the beginning of the path) even though exclusions are not anchored. - */ -int -match_inclusion(struct match *match, const char *pathname) -{ - return (bsdtar_fnmatch(match->pattern, pathname) == 0); -} - -void -cleanup_exclusions(struct bsdtar *bsdtar) -{ - struct match *p, *q; - - if (bsdtar->matching) { - p = bsdtar->matching->inclusions; - while (p != NULL) { - q = p; - p = p->next; - free(q); - } - p = bsdtar->matching->exclusions; - while (p != NULL) { - q = p; - p = p->next; - free(q); - } - free(bsdtar->matching); - } -} - -static void -initialize_matching(struct bsdtar *bsdtar) -{ - bsdtar->matching = malloc(sizeof(*bsdtar->matching)); - if (bsdtar->matching == NULL) - bsdtar_errc(bsdtar, 1, errno, "No memory"); - memset(bsdtar->matching, 0, sizeof(*bsdtar->matching)); -} - -int -unmatched_inclusions(struct bsdtar *bsdtar) -{ - struct matching *matching; - - matching = bsdtar->matching; - if (matching == NULL) - return (0); - return (matching->inclusions_unmatched_count); -} - - - -#if defined(HAVE_FNMATCH) && defined(HAVE_FNM_LEADING_DIR) - -/* Use system fnmatch() if it suits our needs. */ -/* On Linux, _GNU_SOURCE must be defined to get FNM_LEADING_DIR. */ -#define _GNU_SOURCE -#include -static int -bsdtar_fnmatch(const char *pattern, const char *string) -{ - return (fnmatch(pattern, string, FNM_LEADING_DIR)); -} - -#else -/* - * The following was hacked from BSD C library - * code: src/lib/libc/gen/fnmatch.c,v 1.15 2002/02/01 - * - * In particular, most of the flags were ripped out: this always - * behaves like FNM_LEADING_DIR is set and other flags specified - * by POSIX are unset. - * - * Normally, I would not conditionally compile something like this: If - * I have to support it anyway, everyone may as well use it. ;-) - * However, the full POSIX spec for fnmatch() includes a lot of - * advanced character handling that I'm not ready to put in here, so - * it's probably best if people use a local version when it's available. - */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Guido van Rossum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -static int -bsdtar_fnmatch(const char *pattern, const char *string) -{ - const char *saved_pattern; - int negate, matched; - char c; - - for (;;) { - switch (c = *pattern++) { - case '\0': - if (*string == '/' || *string == '\0') - return (0); - return (1); - case '?': - if (*string == '\0') - return (1); - ++string; - break; - case '*': - c = *pattern; - /* Collapse multiple stars. */ - while (c == '*') - c = *++pattern; - - /* Optimize for pattern with * at end. */ - if (c == '\0') - return (0); - - /* General case, use recursion. */ - while (*string != '\0') { - if (!bsdtar_fnmatch(pattern, string)) - return (0); - ++string; - } - return (1); - case '[': - if (*string == '\0') - return (1); - saved_pattern = pattern; - if (*pattern == '!' || *pattern == '^') { - negate = 1; - ++pattern; - } else - negate = 0; - matched = 0; - c = *pattern++; - do { - if (c == '\\') - c = *pattern++; - if (c == '\0') { - pattern = saved_pattern; - c = '['; - goto norm; - } - if (*pattern == '-') { - char c2 = *(pattern + 1); - if (c2 == '\0') { - pattern = saved_pattern; - c = '['; - goto norm; - } - if (c2 == ']') { - /* [a-] is not a range. */ - if (c == *string - || '-' == *string) - matched = 1; - pattern ++; - } else { - if (c <= *string - && *string <= c2) - matched = 1; - pattern += 2; - } - } else if (c == *string) - matched = 1; - c = *pattern++; - } while (c != ']'); - if (matched == negate) - return (1); - ++string; - break; - case '\\': - if ((c = *pattern++) == '\0') { - c = '\\'; - --pattern; - } - /* FALLTHROUGH */ - default: - norm: - if (c != *string) - return (1); - string++; - break; - } - } - /* NOTREACHED */ -} - -#endif diff --git a/contrib/libarchive-1.3.1/tar/read.c b/contrib/libarchive-1.3.1/tar/read.c deleted file mode 100644 index 60a60c4faa..0000000000 --- a/contrib/libarchive-1.3.1/tar/read.c +++ /dev/null @@ -1,470 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.26 2006/07/30 18:34:40 kientzle Exp $"); - -#ifdef MAJOR_IN_MKDEV -#include -#endif -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bsdtar.h" - -static void cleanup_security(struct bsdtar *); -static void list_item_verbose(struct bsdtar *, FILE *, - struct archive_entry *); -static void read_archive(struct bsdtar *bsdtar, char mode); -static int security_problem(struct bsdtar *, struct archive_entry *); - -void -tar_mode_t(struct bsdtar *bsdtar) -{ - read_archive(bsdtar, 't'); -} - -void -tar_mode_x(struct bsdtar *bsdtar) -{ - read_archive(bsdtar, 'x'); -} - -/* - * Handle 'x' and 't' modes. - */ -static void -read_archive(struct bsdtar *bsdtar, char mode) -{ - FILE *out; - struct archive *a; - struct archive_entry *entry; - const struct stat *st; - int r; - - while (*bsdtar->argv) { - include(bsdtar, *bsdtar->argv); - bsdtar->argv++; - } - - if (bsdtar->names_from_file != NULL) - include_from_file(bsdtar, bsdtar->names_from_file); - - a = archive_read_new(); - archive_read_support_compression_all(a); - archive_read_support_format_all(a); - if (archive_read_open_file(a, bsdtar->filename, - bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block : - DEFAULT_BYTES_PER_BLOCK)) - bsdtar_errc(bsdtar, 1, 0, "Error opening archive: %s", - archive_error_string(a)); - - do_chdir(bsdtar); - for (;;) { - /* Support --fast-read option */ - if (bsdtar->option_fast_read && - unmatched_inclusions(bsdtar) == 0) - break; - - r = archive_read_next_header(a, &entry); - if (r == ARCHIVE_EOF) - break; - if (r == ARCHIVE_WARN) - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); - if (r == ARCHIVE_FATAL) { - bsdtar->return_value = 1; - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); - break; - } - if (r == ARCHIVE_RETRY) { - /* Retryable error: try again */ - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); - bsdtar_warnc(bsdtar, 0, "Retrying..."); - continue; - } - - /* - * Exclude entries that are too old. - */ - st = archive_entry_stat(entry); - if (bsdtar->newer_ctime_sec > 0) { - if (st->st_ctime < bsdtar->newer_ctime_sec) - continue; /* Too old, skip it. */ - if (st->st_ctime == bsdtar->newer_ctime_sec - && ARCHIVE_STAT_CTIME_NANOS(st) - <= bsdtar->newer_ctime_nsec) - continue; /* Too old, skip it. */ - } - if (bsdtar->newer_mtime_sec > 0) { - if (st->st_mtime < bsdtar->newer_mtime_sec) - continue; /* Too old, skip it. */ - if (st->st_mtime == bsdtar->newer_mtime_sec - && ARCHIVE_STAT_MTIME_NANOS(st) - <= bsdtar->newer_mtime_nsec) - continue; /* Too old, skip it. */ - } - - /* - * Note that pattern exclusions are checked before - * pathname rewrites are handled. This gives more - * control over exclusions, since rewrites always lose - * information. (For example, consider a rewrite - * s/foo[0-9]/foo/. If we check exclusions after the - * rewrite, there would be no way to exclude foo1/bar - * while allowing foo2/bar.) - */ - if (excluded(bsdtar, archive_entry_pathname(entry))) - continue; /* Excluded by a pattern test. */ - - /* - * Modify the pathname as requested by the user. We - * do this for -t as well to give users a way to - * preview the effects of their rewrites. We also do - * this before extraction security checks (including - * leading '/' removal). Note that some rewrite - * failures prevent extraction. - */ - if (edit_pathname(bsdtar, entry)) - continue; /* Excluded by a rewrite failure. */ - - if (mode == 't') { - /* Perversely, gtar uses -O to mean "send to stderr" - * when used with -t. */ - out = bsdtar->option_stdout ? stderr : stdout; - - if (bsdtar->verbose < 2) - safe_fprintf(out, "%s", - archive_entry_pathname(entry)); - else - list_item_verbose(bsdtar, out, entry); - fflush(out); - r = archive_read_data_skip(a); - if (r == ARCHIVE_WARN) { - fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", - archive_error_string(a)); - } - if (r == ARCHIVE_RETRY) { - fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", - archive_error_string(a)); - } - if (r == ARCHIVE_FATAL) { - fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", - archive_error_string(a)); - break; - } - fprintf(out, "\n"); - } else { - /* - * Skip security problems before prompting. - * Otherwise, the user may be confused that a - * file they wanted to extract was - * subsequently skipped. - */ - if (security_problem(bsdtar, entry)) - continue; - - if (bsdtar->option_interactive && - !yes("extract '%s'", archive_entry_pathname(entry))) - continue; - - /* - * Format here is from SUSv2, including the - * deferred '\n'. - */ - if (bsdtar->verbose) { - safe_fprintf(stderr, "x %s", - archive_entry_pathname(entry)); - fflush(stderr); - } - if (bsdtar->option_stdout) { - /* TODO: Catch/recover any errors here. */ - archive_read_data_into_fd(a, 1); - } else if (archive_read_extract(a, entry, - bsdtar->extract_flags)) { - if (!bsdtar->verbose) - safe_fprintf(stderr, "%s", - archive_entry_pathname(entry)); - safe_fprintf(stderr, ": %s", - archive_error_string(a)); - if (!bsdtar->verbose) - fprintf(stderr, "\n"); - /* - * TODO: Decide how to handle - * extraction error... - */ - bsdtar->return_value = 1; - } - if (bsdtar->verbose) - fprintf(stderr, "\n"); - } - } - - if (bsdtar->verbose > 2) - fprintf(stdout, "Archive Format: %s, Compression: %s\n", - archive_format_name(a), archive_compression_name(a)); - - archive_read_finish(a); - cleanup_security(bsdtar); -} - - -/* - * Display information about the current file. - * - * The format here roughly duplicates the output of 'ls -l'. - * This is based on SUSv2, where 'tar tv' is documented as - * listing additional information in an "unspecified format," - * and 'pax -l' is documented as using the same format as 'ls -l'. - */ -static void -list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) -{ - const struct stat *st; - char tmp[100]; - size_t w; - const char *p; - const char *fmt; - time_t tim; - static time_t now; - - st = archive_entry_stat(entry); - - /* - * We avoid collecting the entire list in memory at once by - * listing things as we see them. However, that also means we can't - * just pre-compute the field widths. Instead, we start with guesses - * and just widen them as necessary. These numbers are completely - * arbitrary. - */ - if (!bsdtar->u_width) { - bsdtar->u_width = 6; - bsdtar->gs_width = 13; - } - if (!now) - time(&now); - bsdtar_strmode(entry, tmp); - fprintf(out, "%s %d ", tmp, (int)(st->st_nlink)); - - /* Use uname if it's present, else uid. */ - p = archive_entry_uname(entry); - if ((p == NULL) || (*p == '\0')) { - sprintf(tmp, "%d ", st->st_uid); - p = tmp; - } - w = strlen(p); - if (w > bsdtar->u_width) - bsdtar->u_width = w; - fprintf(out, "%-*s ", (int)bsdtar->u_width, p); - - /* Use gname if it's present, else gid. */ - p = archive_entry_gname(entry); - if (p != NULL && p[0] != '\0') { - fprintf(out, "%s", p); - w = strlen(p); - } else { - sprintf(tmp, "%d", st->st_gid); - w = strlen(tmp); - fprintf(out, "%s", tmp); - } - - /* - * Print device number or file size, right-aligned so as to make - * total width of group and devnum/filesize fields be gs_width. - * If gs_width is too small, grow it. - */ - if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { - sprintf(tmp, "%d,%u", - major(st->st_rdev), - (unsigned)minor(st->st_rdev)); /* ls(1) also casts here. */ - } else { - /* - * Note the use of platform-dependent macros to format - * the filesize here. We need the format string and the - * corresponding type for the cast. - */ - sprintf(tmp, BSDTAR_FILESIZE_PRINTF, - (BSDTAR_FILESIZE_TYPE)st->st_size); - } - if (w + strlen(tmp) >= bsdtar->gs_width) - bsdtar->gs_width = w+strlen(tmp)+1; - fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp); - - /* Format the time using 'ls -l' conventions. */ - tim = (time_t)st->st_mtime; - if (abs(tim - now) > (365/2)*86400) - fmt = bsdtar->day_first ? "%e %b %Y" : "%b %e %Y"; - else - fmt = bsdtar->day_first ? "%e %b %R" : "%b %e %R"; - strftime(tmp, sizeof(tmp), fmt, localtime(&tim)); - fprintf(out, " %s ", tmp); - safe_fprintf(out, "%s", archive_entry_pathname(entry)); - - /* Extra information for links. */ - if (archive_entry_hardlink(entry)) /* Hard link */ - safe_fprintf(out, " link to %s", - archive_entry_hardlink(entry)); - else if (S_ISLNK(st->st_mode)) /* Symbolic link */ - safe_fprintf(out, " -> %s", archive_entry_symlink(entry)); -} - -/* - * Structure for storing path of last successful security check. - */ -struct security { - char *path; - size_t path_size; -}; - -/* - * Check for a variety of security issues. Fix what we can here, - * generate warnings as appropriate, return non-zero to prevent - * this entry from being extracted. - */ -static int -security_problem(struct bsdtar *bsdtar, struct archive_entry *entry) -{ - struct stat st; - const char *name, *pn; - char *p; - int r; - - /* -P option forces us to just accept all pathnames as-is. */ - if (bsdtar->option_absolute_paths) - return (0); - - name = archive_entry_pathname(entry); - - /* Reject any archive entry with '..' as a path element. */ - pn = name; - while (pn != NULL && pn[0] != '\0') { - if (pn[0] == '.' && pn[1] == '.' && - (pn[2] == '\0' || pn[2] == '/')) { - bsdtar_warnc(bsdtar, 0, - "Skipping pathname containing .."); - bsdtar->return_value = 1; - return (1); - } - pn = strchr(pn, '/'); - if (pn != NULL) - pn++; - } - - /* - * Gaurd against symlink tricks. Reject any archive entry whose - * destination would be altered by a symlink. - */ - /* XXX TODO: Make this faster by comparing current path to - * prefix of last successful check to avoid duplicate lstat() - * calls. XXX */ - pn = name; - if (bsdtar->security == NULL) { - bsdtar->security = malloc(sizeof(*bsdtar->security)); - if (bsdtar->security == NULL) - bsdtar_errc(bsdtar, 1, errno, "No Memory"); - bsdtar->security->path_size = MAXPATHLEN + 1; - bsdtar->security->path = malloc(bsdtar->security->path_size); - if (bsdtar->security->path == NULL) - bsdtar_errc(bsdtar, 1, errno, "No Memory"); - } - if (strlen(name) >= bsdtar->security->path_size) { - free(bsdtar->security->path); - while (strlen(name) >= bsdtar->security->path_size) - bsdtar->security->path_size *= 2; - bsdtar->security->path = malloc(bsdtar->security->path_size); - if (bsdtar->security->path == NULL) - bsdtar_errc(bsdtar, 1, errno, "No Memory"); - } - p = bsdtar->security->path; - while (pn != NULL && pn[0] != '\0') { - *p++ = *pn++; - while (*pn != '\0' && *pn != '/') - *p++ = *pn++; - p[0] = '\0'; - r = lstat(bsdtar->security->path, &st); - if (r != 0) { - if (errno == ENOENT) - break; - } else if (S_ISLNK(st.st_mode)) { - if (pn[0] == '\0') { - /* - * Last element is symlink; remove it - * so we can overwrite it with the - * item being extracted. - */ - if (!S_ISLNK(archive_entry_mode(entry))) { - /* - * Warn only if the symlink is being - * replaced with a non-symlink. - */ - bsdtar_warnc(bsdtar, 0, - "Removing symlink %s", - bsdtar->security->path); - } - if (unlink(bsdtar->security->path)) - bsdtar_errc(bsdtar, 1, errno, - "Unlink failed"); - /* Symlink gone. No more problem! */ - return (0); - } else if (bsdtar->option_unlink_first) { - /* User asked us to remove problems. */ - if (unlink(bsdtar->security->path)) - bsdtar_errc(bsdtar, 1, errno, - "Unlink failed"); - } else { - bsdtar_warnc(bsdtar, 0, - "Cannot extract %s through symlink %s", - name, bsdtar->security->path); - bsdtar->return_value = 1; - return (1); - } - } - } - - return (0); -} - -static void -cleanup_security(struct bsdtar *bsdtar) -{ - if (bsdtar->security != NULL) { - free(bsdtar->security->path); - free(bsdtar->security); - } -} diff --git a/contrib/libarchive-1.3.1/tar/tree.c b/contrib/libarchive-1.3.1/tar/tree.c deleted file mode 100644 index 8803685ae0..0000000000 --- a/contrib/libarchive-1.3.1/tar/tree.c +++ /dev/null @@ -1,507 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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. - */ - -/*- - * This is a new directory-walking system that addresses a number - * of problems I've had with fts(3). In particular, it has no - * pathname-length limits (other than the size of 'int'), handles - * deep logical traversals, uses considerably less memory, and has - * an opaque interface (easier to modify in the future). - * - * Internally, it keeps a single list of "tree_entry" items that - * represent filesystem objects that require further attention. - * Non-directories are not kept in memory: they are pulled from - * readdir(), returned to the client, then freed as soon as possible. - * Any directory entry to be traversed gets pushed onto the stack. - * - * There is surprisingly little information that needs to be kept for - * each item on the stack. Just the name, depth (represented here as the - * string length of the parent directory's pathname), and some markers - * indicating how to get back to the parent (via chdir("..") for a - * regular dir or via fchdir(2) for a symlink). - */ -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/tree.c,v 1.4 2006/03/21 17:03:51 kientzle Exp $"); - -#include -#include -#include -#include -#include -#include -#include - -#include "tree.h" - -/* - * TODO: - * 1) Loop checking. - * 3) Arbitrary logical traversals by closing/reopening intermediate fds. - */ - -struct tree_entry { - struct tree_entry *next; - struct tree_entry *parent; - char *name; - size_t dirname_length; - dev_t dev; - ino_t ino; - int fd; - int flags; -}; - -/* Definitions for tree_entry.flags bitmap. */ -#define isDir 1 /* This entry is a regular directory. */ -#define isDirLink 2 /* This entry is a symbolic link to a directory. */ -#define needsPreVisit 4 /* This entry needs to be previsited. */ -#define needsPostVisit 8 /* This entry needs to be postvisited. */ - -/* - * Local data for this package. - */ -struct tree { - struct tree_entry *stack; - struct tree_entry *current; - DIR *d; - int initialDirFd; - int flags; - int visit_type; - int tree_errno; /* Error code from last failed operation. */ - - char *buff; - const char *basename; - size_t buff_length; - size_t path_length; - size_t dirname_length; - - int depth; - int openCount; - int maxOpenCount; - - struct stat lst; - struct stat st; -}; - -/* Definitions for tree.flags bitmap. */ -#define needsReturn 8 /* Marks first entry as not having been returned yet. */ -#define hasStat 16 /* The st entry is set. */ -#define hasLstat 32 /* The lst entry is set. */ - - -#ifdef HAVE_DIRENT_D_NAMLEN -/* BSD extension; avoids need for a strlen() call. */ -#define D_NAMELEN(dp) (dp)->d_namlen -#else -#define D_NAMELEN(dp) (strlen((dp)->d_name)) -#endif - -#if 0 -#include -void -tree_dump(struct tree *t, FILE *out) -{ - struct tree_entry *te; - - fprintf(out, "\tdepth: %d\n", t->depth); - fprintf(out, "\tbuff: %s\n", t->buff); - fprintf(out, "\tpwd: "); fflush(stdout); system("pwd"); - fprintf(out, "\taccess: %s\n", t->basename); - fprintf(out, "\tstack:\n"); - for (te = t->stack; te != NULL; te = te->next) { - fprintf(out, "\t\tte->name: %s%s%s\n", te->name, - te->flags & needsPreVisit ? "" : " *", - t->current == te ? " (current)" : ""); - } -} -#endif - -/* - * Add a directory path to the current stack. - */ -static void -tree_push(struct tree *t, const char *path) -{ - struct tree_entry *te; - - te = malloc(sizeof(*te)); - memset(te, 0, sizeof(*te)); - te->next = t->stack; - t->stack = te; - te->fd = -1; - te->name = strdup(path); - te->flags = needsPreVisit | needsPostVisit; - te->dirname_length = t->dirname_length; -} - -/* - * Append a name to the current path. - */ -static void -tree_append(struct tree *t, const char *name, size_t name_length) -{ - char *p; - - if (t->buff != NULL) - t->buff[t->dirname_length] = '\0'; - /* Strip trailing '/' from name, unless entire name is "/". */ - while (name_length > 1 && name[name_length - 1] == '/') - name_length--; - - /* Resize pathname buffer as needed. */ - while (name_length + 1 + t->dirname_length >= t->buff_length) { - t->buff_length *= 2; - if (t->buff_length < 1024) - t->buff_length = 1024; - t->buff = realloc(t->buff, t->buff_length); - } - p = t->buff + t->dirname_length; - t->path_length = t->dirname_length + name_length; - /* Add a separating '/' if it's needed. */ - if (t->dirname_length > 0 && p[-1] != '/') { - *p++ = '/'; - t->path_length ++; - } - strncpy(p, name, name_length); - p[name_length] = '\0'; - t->basename = p; -} - -/* - * Open a directory tree for traversal. - */ -struct tree * -tree_open(const char *path) -{ - struct tree *t; - - t = malloc(sizeof(*t)); - memset(t, 0, sizeof(*t)); - tree_append(t, path, strlen(path)); - t->initialDirFd = open(".", O_RDONLY); - /* - * During most of the traversal, items are set up and then - * returned immediately from tree_next(). That doesn't work - * for the very first entry, so we set a flag for this special - * case. - */ - t->flags = needsReturn; - return (t); -} - -/* - * We've finished a directory; ascend back to the parent. - */ -static void -tree_ascend(struct tree *t) -{ - struct tree_entry *te; - - te = t->stack; - t->depth--; - if (te->flags & isDirLink) { - fchdir(te->fd); - close(te->fd); - t->openCount--; - } else { - chdir(".."); - } -} - -/* - * Pop the working stack. - */ -static void -tree_pop(struct tree *t) -{ - struct tree_entry *te; - - t->buff[t->dirname_length] = '\0'; - if (t->stack == t->current && t->current != NULL) - t->current = t->current->parent; - te = t->stack; - t->stack = te->next; - t->dirname_length = te->dirname_length; - t->basename = t->buff + t->dirname_length; - /* Special case: starting dir doesn't skip leading '/'. */ - if (t->dirname_length > 0) - t->basename++; - free(te->name); - free(te); -} - -/* - * Get the next item in the tree traversal. - */ -int -tree_next(struct tree *t) -{ - struct dirent *de = NULL; - - /* Handle the startup case by returning the initial entry. */ - if (t->flags & needsReturn) { - t->flags &= ~needsReturn; - return (t->visit_type = TREE_REGULAR); - } - - while (t->stack != NULL) { - /* If there's an open dir, get the next entry from there. */ - while (t->d != NULL) { - de = readdir(t->d); - if (de == NULL) { - closedir(t->d); - t->d = NULL; - } else if (de->d_name[0] == '.' - && de->d_name[1] == '\0') { - /* Skip '.' */ - } else if (de->d_name[0] == '.' - && de->d_name[1] == '.' - && de->d_name[2] == '\0') { - /* Skip '..' */ - } else { - /* - * Append the path to the current path - * and return it. - */ - tree_append(t, de->d_name, D_NAMELEN(de)); - t->flags &= ~hasLstat; - t->flags &= ~hasStat; - return (t->visit_type = TREE_REGULAR); - } - } - - /* If the current dir needs to be visited, set it up. */ - if (t->stack->flags & needsPreVisit) { - t->current = t->stack; - tree_append(t, t->stack->name, strlen(t->stack->name)); - t->stack->flags &= ~needsPreVisit; - /* If it is a link, set up fd for the ascent. */ - if (t->stack->flags & isDirLink) { - t->stack->fd = open(".", O_RDONLY); - t->openCount++; - if (t->openCount > t->maxOpenCount) - t->maxOpenCount = t->openCount; - } - t->dirname_length = t->path_length; - if (chdir(t->stack->name) != 0) { - /* chdir() failed; return error */ - tree_pop(t); - t->tree_errno = errno; - return (t->visit_type = TREE_ERROR_DIR); - } - t->depth++; - t->d = opendir("."); - if (t->d == NULL) { - tree_ascend(t); /* Undo "chdir" */ - tree_pop(t); - t->tree_errno = errno; - return (t->visit_type = TREE_ERROR_DIR); - } - t->flags &= ~hasLstat; - t->flags &= ~hasStat; - t->basename = "."; - return (t->visit_type = TREE_POSTDESCENT); - } - - /* We've done everything necessary for the top stack entry. */ - if (t->stack->flags & needsPostVisit) { - tree_ascend(t); - tree_pop(t); - t->flags &= ~hasLstat; - t->flags &= ~hasStat; - return (t->visit_type = TREE_POSTASCENT); - } - } - return (t->visit_type = 0); -} - -/* - * Return error code. - */ -int -tree_errno(struct tree *t) -{ - return (t->tree_errno); -} - -/* - * Called by the client to mark the directory just returned from - * tree_next() as needing to be visited. - */ -void -tree_descend(struct tree *t) -{ - if (t->visit_type != TREE_REGULAR) - return; - - if (tree_current_is_physical_dir(t)) { - tree_push(t, t->basename); - t->stack->flags |= isDir; - } else if (tree_current_is_dir(t)) { - tree_push(t, t->basename); - t->stack->flags |= isDirLink; - } -} - -/* - * Get the stat() data for the entry just returned from tree_next(). - */ -const struct stat * -tree_current_stat(struct tree *t) -{ - if (!(t->flags & hasStat)) { - if (stat(t->basename, &t->st) != 0) - return NULL; - t->flags |= hasStat; - } - return (&t->st); -} - -/* - * Get the lstat() data for the entry just returned from tree_next(). - */ -const struct stat * -tree_current_lstat(struct tree *t) -{ - if (!(t->flags & hasLstat)) { - if (lstat(t->basename, &t->lst) != 0) - return NULL; - t->flags |= hasLstat; - } - return (&t->lst); -} - -/* - * Test whether current entry is a dir or dir link. - */ -int -tree_current_is_dir(struct tree *t) -{ - /* If we've already pulled stat(), just use that. */ - if (t->flags & hasStat) - return (S_ISDIR(tree_current_stat(t)->st_mode)); - - /* If we've already pulled lstat(), we may be able to use that. */ - if (t->flags & hasLstat) { - /* If lstat() says it's a dir, it must be a dir. */ - if (S_ISDIR(tree_current_lstat(t)->st_mode)) - return 1; - /* If it's not a dir and not a link, we're done. */ - if (!S_ISLNK(tree_current_lstat(t)->st_mode)) - return 0; - /* - * If the above two tests fail, then it's a link, but - * we don't know whether it's a link to a dir or a - * non-dir. - */ - } - - /* TODO: Use a more efficient mechanism when available. */ - return (S_ISDIR(tree_current_stat(t)->st_mode)); -} - -/* - * Test whether current entry is a physical directory. - */ -int -tree_current_is_physical_dir(struct tree *t) -{ - /* If we've already pulled lstat(), just use that. */ - if (t->flags & hasLstat) - return (S_ISDIR(tree_current_lstat(t)->st_mode)); - - /* TODO: Use a more efficient mechanism when available. */ - return (S_ISDIR(tree_current_lstat(t)->st_mode)); -} - -/* - * Test whether current entry is a symbolic link. - */ -int -tree_current_is_physical_link(struct tree *t) -{ - /* If we've already pulled lstat(), just use that. */ - if (t->flags & hasLstat) - return (S_ISLNK(tree_current_lstat(t)->st_mode)); - - /* TODO: Use a more efficient mechanism when available. */ - return (S_ISLNK(tree_current_lstat(t)->st_mode)); -} - -/* - * Return the access path for the entry just returned from tree_next(). - */ -const char * -tree_current_access_path(struct tree *t) -{ - return (t->basename); -} - -/* - * Return the full path for the entry just returned from tree_next(). - */ -const char * -tree_current_path(struct tree *t) -{ - return (t->buff); -} - -/* - * Return the length of the path for the entry just returned from tree_next(). - */ -size_t -tree_current_pathlen(struct tree *t) -{ - return (t->path_length); -} - -/* - * Return the nesting depth of the entry just returned from tree_next(). - */ -int -tree_current_depth(struct tree *t) -{ - return (t->depth); -} - -/* - * Terminate the traversal and release any resources. - */ -void -tree_close(struct tree *t) -{ - /* Release anything remaining in the stack. */ - while (t->stack != NULL) - tree_pop(t); - if (t->buff) - free(t->buff); - /* chdir() back to where we started. */ - if (t->initialDirFd >= 0) { - fchdir(t->initialDirFd); - close(t->initialDirFd); - t->initialDirFd = -1; - } - free(t); -} diff --git a/contrib/libarchive-1.3.1/tar/tree.h b/contrib/libarchive-1.3.1/tar/tree.h deleted file mode 100644 index 06b15fe540..0000000000 --- a/contrib/libarchive-1.3.1/tar/tree.h +++ /dev/null @@ -1,116 +0,0 @@ -/*- - * Copyright (c) 2003-2004 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: src/usr.bin/tar/tree.h,v 1.2 2005/05/08 06:25:15 kientzle Exp $ - */ - -/*- - * A set of routines for traversing directory trees. - * Similar in concept to the fts library, but with a few - * important differences: - * * Uses less memory. In particular, fts stores an entire directory - * in memory at a time. This package only keeps enough subdirectory - * information in memory to track the traversal. Information - * about non-directories is discarded as soon as possible. - * * Supports very deep logical traversals. The fts package - * uses "non-chdir" approach for logical traversals. This - * package does use a chdir approach for logical traversals - * and can therefore handle pathnames much longer than - * PATH_MAX. - * * Supports deep physical traversals "out of the box." - * Due to the memory optimizations above, there's no need to - * limit dir names to 32k. - */ - -#include -#include - -struct tree; - -/* Initiate/terminate a tree traversal. */ -struct tree *tree_open(const char * /* pathname */); -void tree_close(struct tree *); - -/* - * tree_next() returns Zero if there is no next entry, non-zero if there is. - * Note that directories are potentially visited three times. The first - * time as "regular" file. If tree_descend() is invoked at that time, - * the directory is added to a work list and will be visited two more - * times: once just after descending into the directory and again - * just after ascending back to the parent. - * - * TREE_ERROR is returned if the descent failed (because the - * directory couldn't be opened, for instance). This is returned - * instead of TREE_PREVISIT/TREE_POSTVISIT. - */ -#define TREE_REGULAR 1 -#define TREE_POSTDESCENT 2 -#define TREE_POSTASCENT 3 -#define TREE_ERROR_DIR -1 -int tree_next(struct tree *); - -int tree_errno(struct tree *); - -/* - * Request that current entry be visited. If you invoke it on every - * directory, you'll get a physical traversal. This is ignored if the - * current entry isn't a directory or a link to a directory. So, if - * you invoke this on every returned path, you'll get a full logical - * traversal. - */ -void tree_descend(struct tree *); - -/* - * Return information about the current entry. - */ - -int tree_current_depth(struct tree *); -/* - * The current full pathname, length of the full pathname, - * and a name that can be used to access the file. - * Because tree does use chdir extensively, the access path is - * almost never the same as the full current path. - */ -const char *tree_current_path(struct tree *); -size_t tree_current_pathlen(struct tree *); -const char *tree_current_access_path(struct tree *); -/* - * Request the lstat() or stat() data for the current path. Since the - * tree package needs to do some of this anyway, and caches the - * results, you should take advantage of it here if you need it rather - * than make a redundant stat() or lstat() call of your own. - */ -const struct stat *tree_current_stat(struct tree *); -const struct stat *tree_current_lstat(struct tree *); -/* The following tests may use mechanisms much faster than stat()/lstat(). */ -/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */ -int tree_current_is_physical_dir(struct tree *); -/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */ -int tree_current_is_physical_link(struct tree *); -/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */ -int tree_current_is_dir(struct tree *); - -/* For testing/debugging: Dump the internal status to the given filehandle. */ -void tree_dump(struct tree *, FILE *); diff --git a/contrib/libarchive-1.3.1/tar/util.c b/contrib/libarchive-1.3.1/tar/util.c deleted file mode 100644 index 6d3a13b31a..0000000000 --- a/contrib/libarchive-1.3.1/tar/util.c +++ /dev/null @@ -1,439 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.14 2006/03/21 17:03:51 kientzle Exp $"); - -#include -#include /* Linux doesn't define mode_t, etc. in sys/stat.h. */ -#include -#include -#include -#include -#include -#include - -#include "bsdtar.h" - -static void bsdtar_vwarnc(struct bsdtar *, int code, - const char *fmt, va_list ap); - -/* - * Print a string, taking care with any non-printable characters. - */ - -void -safe_fprintf(FILE *f, const char *fmt, ...) -{ - char *buff; - char *buff_heap; - int buff_length; - int length; - va_list ap; - char *p; - unsigned i; - char buff_stack[256]; - char copy_buff[256]; - - /* Use a stack-allocated buffer if we can, for speed and safety. */ - buff_heap = NULL; - buff_length = sizeof(buff_stack); - buff = buff_stack; - - va_start(ap, fmt); - length = vsnprintf(buff, buff_length, fmt, ap); - va_end(ap); - /* If the result is too large, allocate a buffer on the heap. */ - if (length >= buff_length) { - buff_length = length+1; - buff_heap = malloc(buff_length); - /* Failsafe: use the truncated string if malloc fails. */ - if (buff_heap != NULL) { - buff = buff_heap; - va_start(ap, fmt); - length = vsnprintf(buff, buff_length, fmt, ap); - va_end(ap); - } - } - - /* Write data, expanding unprintable characters. */ - p = buff; - i = 0; - while (*p != '\0') { - unsigned char c = *p++; - - if (isprint(c) && c != '\\') - copy_buff[i++] = c; - else { - copy_buff[i++] = '\\'; - switch (c) { - case '\a': copy_buff[i++] = 'a'; break; - case '\b': copy_buff[i++] = 'b'; break; - case '\f': copy_buff[i++] = 'f'; break; - case '\n': copy_buff[i++] = 'n'; break; -#if '\r' != '\n' - /* On some platforms, \n and \r are the same. */ - case '\r': copy_buff[i++] = 'r'; break; -#endif - case '\t': copy_buff[i++] = 't'; break; - case '\v': copy_buff[i++] = 'v'; break; - case '\\': copy_buff[i++] = '\\'; break; - default: - sprintf(copy_buff + i, "%03o", c); - i += 3; - } - } - - /* If our temp buffer is full, dump it and keep going. */ - if (i > (sizeof(copy_buff) - 8)) { - copy_buff[i++] = '\0'; - fprintf(f, "%s", copy_buff); - i = 0; - } - } - copy_buff[i++] = '\0'; - fprintf(f, "%s", copy_buff); - - /* If we allocated a heap-based buffer, free it now. */ - if (buff_heap != NULL) - free(buff_heap); -} - -static void -bsdtar_vwarnc(struct bsdtar *bsdtar, int code, const char *fmt, va_list ap) -{ - fprintf(stderr, "%s: ", bsdtar->progname); - vfprintf(stderr, fmt, ap); - if (code != 0) - fprintf(stderr, ": %s", strerror(code)); - fprintf(stderr, "\n"); -} - -void -bsdtar_warnc(struct bsdtar *bsdtar, int code, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - bsdtar_vwarnc(bsdtar, code, fmt, ap); - va_end(ap); -} - -void -bsdtar_errc(struct bsdtar *bsdtar, int eval, int code, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - bsdtar_vwarnc(bsdtar, code, fmt, ap); - va_end(ap); - exit(eval); -} - -int -yes(const char *fmt, ...) -{ - char buff[32]; - char *p; - ssize_t l; - - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, " (y/N)? "); - fflush(stderr); - - l = read(2, buff, sizeof(buff)); - if (l <= 0) - return (0); - buff[l] = 0; - - for (p = buff; *p != '\0'; p++) { - if (isspace(0xff & (int)*p)) - continue; - switch(*p) { - case 'y': case 'Y': - return (1); - case 'n': case 'N': - return (0); - default: - return (0); - } - } - - return (0); -} - -void -bsdtar_strmode(struct archive_entry *entry, char *bp) -{ - static const char *perms = "?rwxrwxrwx "; - static const mode_t permbits[] = - { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, - S_IROTH, S_IWOTH, S_IXOTH }; - mode_t mode; - int i; - - /* Fill in a default string, then selectively override. */ - strcpy(bp, perms); - - mode = archive_entry_mode(entry); - switch (mode & S_IFMT) { - case S_IFREG: bp[0] = '-'; break; - case S_IFBLK: bp[0] = 'b'; break; - case S_IFCHR: bp[0] = 'c'; break; - case S_IFDIR: bp[0] = 'd'; break; - case S_IFLNK: bp[0] = 'l'; break; - case S_IFSOCK: bp[0] = 's'; break; -#ifdef S_IFIFO - case S_IFIFO: bp[0] = 'p'; break; -#endif -#ifdef S_IFWHT - case S_IFWHT: bp[0] = 'w'; break; -#endif - } - - for (i = 0; i < 9; i++) - if (!(mode & permbits[i])) - bp[i+1] = '-'; - - if (mode & S_ISUID) { - if (mode & S_IXUSR) bp[3] = 's'; - else bp[3] = 'S'; - } - if (mode & S_ISGID) { - if (mode & S_IXGRP) bp[6] = 's'; - else bp[6] = 'S'; - } - if (mode & S_ISVTX) { - if (mode & S_IXOTH) bp[9] = 't'; - else bp[9] = 'T'; - } - if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)) - bp[10] = '+'; -} - - -/* - * Read lines from file and do something with each one. If option_null - * is set, lines are terminated with zero bytes; otherwise, they're - * terminated with newlines. - * - * This uses a self-sizing buffer to handle arbitrarily-long lines. - * If the "process" function returns non-zero for any line, this - * function will return non-zero after attempting to process all - * remaining lines. - */ -int -process_lines(struct bsdtar *bsdtar, const char *pathname, - int (*process)(struct bsdtar *, const char *)) -{ - FILE *f; - char *buff, *buff_end, *line_start, *line_end, *p; - size_t buff_length, bytes_read, bytes_wanted; - int separator; - int ret; - - separator = bsdtar->option_null ? '\0' : '\n'; - ret = 0; - - if (strcmp(pathname, "-") == 0) - f = stdin; - else - f = fopen(pathname, "r"); - if (f == NULL) - bsdtar_errc(bsdtar, 1, errno, "Couldn't open %s", pathname); - buff_length = 8192; - buff = malloc(buff_length); - if (buff == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read %s", pathname); - line_start = line_end = buff_end = buff; - for (;;) { - /* Get some more data into the buffer. */ - bytes_wanted = buff + buff_length - buff_end; - bytes_read = fread(buff_end, 1, bytes_wanted, f); - buff_end += bytes_read; - /* Process all complete lines in the buffer. */ - while (line_end < buff_end) { - if (*line_end == separator) { - *line_end = '\0'; - if ((*process)(bsdtar, line_start) != 0) - ret = -1; - line_start = line_end + 1; - line_end = line_start; - } else - line_end++; - } - if (feof(f)) - break; - if (ferror(f)) - bsdtar_errc(bsdtar, 1, errno, - "Can't read %s", pathname); - if (line_start > buff) { - /* Move a leftover fractional line to the beginning. */ - memmove(buff, line_start, buff_end - line_start); - buff_end -= line_start - buff; - line_end -= line_start - buff; - line_start = buff; - } else { - /* Line is too big; enlarge the buffer. */ - p = realloc(buff, buff_length *= 2); - if (p == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, - "Line too long in %s", pathname); - buff_end = p + (buff_end - buff); - line_end = p + (line_end - buff); - line_start = buff = p; - } - } - /* At end-of-file, handle the final line. */ - if (line_end > line_start) { - *line_end = '\0'; - if ((*process)(bsdtar, line_start) != 0) - ret = -1; - } - free(buff); - if (f != stdin) - fclose(f); - return (ret); -} - -/*- - * The logic here for -C attempts to avoid - * chdir() as long as possible. For example: - * "-C /foo -C /bar file" needs chdir("/bar") but not chdir("/foo") - * "-C /foo -C bar file" needs chdir("/foo/bar") - * "-C /foo -C bar /file1" does not need chdir() - * "-C /foo -C bar /file1 file2" needs chdir("/foo/bar") before file2 - * - * The only correct way to handle this is to record a "pending" chdir - * request and combine multiple requests intelligently until we - * need to process a non-absolute file. set_chdir() adds the new dir - * to the pending list; do_chdir() actually executes any pending chdir. - * - * This way, programs that build tar command lines don't have to worry - * about -C with non-existent directories; such requests will only - * fail if the directory must be accessed. - */ -void -set_chdir(struct bsdtar *bsdtar, const char *newdir) -{ - if (newdir[0] == '/') { - /* The -C /foo -C /bar case; dump first one. */ - free(bsdtar->pending_chdir); - bsdtar->pending_chdir = NULL; - } - if (bsdtar->pending_chdir == NULL) - /* Easy case: no previously-saved dir. */ - bsdtar->pending_chdir = strdup(newdir); - else { - /* The -C /foo -C bar case; concatenate */ - char *old_pending = bsdtar->pending_chdir; - size_t old_len = strlen(old_pending); - bsdtar->pending_chdir = malloc(old_len + strlen(newdir) + 2); - if (old_pending[old_len - 1] == '/') - old_pending[old_len - 1] = '\0'; - if (bsdtar->pending_chdir != NULL) - sprintf(bsdtar->pending_chdir, "%s/%s", - old_pending, newdir); - free(old_pending); - } - if (bsdtar->pending_chdir == NULL) - bsdtar_errc(bsdtar, 1, errno, "No memory"); -} - -void -do_chdir(struct bsdtar *bsdtar) -{ - if (bsdtar->pending_chdir == NULL) - return; - - if (chdir(bsdtar->pending_chdir) != 0) { - bsdtar_errc(bsdtar, 1, 0, "could not chdir to '%s'\n", - bsdtar->pending_chdir); - } - free(bsdtar->pending_chdir); - bsdtar->pending_chdir = NULL; -} - -/* - * Handle --strip-components and any future path-rewriting options. - * Returns non-zero if the pathname should not be extracted. - */ -int -edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) -{ - const char *name = archive_entry_pathname(entry); - - /* Strip leading dir names as per --strip-components option. */ - if (bsdtar->strip_components > 0) { - int r = bsdtar->strip_components; - const char *p = name; - - while (r > 0) { - switch (*p++) { - case '/': - r--; - name = p; - break; - case '\0': - /* Path is too short, skip it. */ - return (1); - } - } - } - - /* Strip redundant "./" from start of filename. */ - if (name[0] == '.' && name[1] == '/' && name[2] != '\0') - name += 2; - - /* Strip redundant leading '/' characters. */ - while (name[0] == '/' && name[1] == '/') - name++; - - /* Strip leading '/' unless user has asked us not to. */ - if (name[0] == '/' && !bsdtar->option_absolute_paths) { - /* Generate a warning the first time this happens. */ - if (!bsdtar->warned_lead_slash) { - bsdtar_warnc(bsdtar, 0, - "Removing leading '/' from member names"); - bsdtar->warned_lead_slash = 1; - } - name++; - /* Special case: Stripping leading '/' from "/" yields ".". */ - if (*name == '\0') - name = "."; - } - - /* Safely replace name in archive_entry. */ - if (name != archive_entry_pathname(entry)) { - char *q = strdup(name); - archive_entry_copy_pathname(entry, q); - free(q); - } - return (0); -} diff --git a/contrib/libarchive-1.3.1/tar/write.c b/contrib/libarchive-1.3.1/tar/write.c deleted file mode 100644 index 8ec1d91d62..0000000000 --- a/contrib/libarchive-1.3.1/tar/write.c +++ /dev/null @@ -1,1437 +0,0 @@ -/*- - * Copyright (c) 2003-2004 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.47 2006/07/31 04:57:46 kientzle Exp $"); - -#include -#include -#ifdef HAVE_POSIX_ACL -#include -#endif -#ifdef HAVE_ATTR_XATTR_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux -#include -#include -#endif - -#include "bsdtar.h" -#include "tree.h" - -/* Fixed size of uname/gname caches. */ -#define name_cache_size 101 - -static const char * const NO_NAME = "(noname)"; - -/* Initial size of link cache. */ -#define links_cache_initial_size 1024 - -struct archive_dir_entry { - struct archive_dir_entry *next; - time_t mtime_sec; - int mtime_nsec; - char *name; -}; - -struct archive_dir { - struct archive_dir_entry *head, *tail; -}; - -struct links_cache { - unsigned long number_entries; - size_t number_buckets; - struct links_entry **buckets; -}; - -struct links_entry { - struct links_entry *next; - struct links_entry *previous; - int links; - dev_t dev; - ino_t ino; - char *name; -}; - -struct name_cache { - int probes; - int hits; - size_t size; - struct { - id_t id; - const char *name; - } cache[name_cache_size]; -}; - -static void add_dir_list(struct bsdtar *bsdtar, const char *path, - time_t mtime_sec, int mtime_nsec); -static int append_archive(struct bsdtar *, struct archive *, - const char *fname); -static void archive_names_from_file(struct bsdtar *bsdtar, - struct archive *a); -static int archive_names_from_file_helper(struct bsdtar *bsdtar, - const char *line); -static void create_cleanup(struct bsdtar *); -static void free_buckets(struct bsdtar *, struct links_cache *); -static void free_cache(struct name_cache *cache); -static const char * lookup_gname(struct bsdtar *bsdtar, gid_t gid); -static int lookup_gname_helper(struct bsdtar *bsdtar, - const char **name, id_t gid); -static void lookup_hardlink(struct bsdtar *, - struct archive_entry *entry, const struct stat *); -static const char * lookup_uname(struct bsdtar *bsdtar, uid_t uid); -static int lookup_uname_helper(struct bsdtar *bsdtar, - const char **name, id_t uid); -static int new_enough(struct bsdtar *, const char *path, - const struct stat *); -static void setup_acls(struct bsdtar *, struct archive_entry *, - const char *path); -static void setup_xattrs(struct bsdtar *, struct archive_entry *, - const char *path); -static void test_for_append(struct bsdtar *); -static void write_archive(struct archive *, struct bsdtar *); -static void write_entry(struct bsdtar *, struct archive *, - const struct stat *, const char *pathname, - unsigned pathlen, const char *accpath); -static int write_file_data(struct bsdtar *, struct archive *, - int fd); -static void write_hierarchy(struct bsdtar *, struct archive *, - const char *); - -void -tar_mode_c(struct bsdtar *bsdtar) -{ - struct archive *a; - int r; - - if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) - bsdtar_errc(bsdtar, 1, 0, "no files or directories specified"); - - a = archive_write_new(); - - /* Support any format that the library supports. */ - if (bsdtar->create_format == NULL) { - r = archive_write_set_format_pax_restricted(a); - bsdtar->create_format = "pax restricted"; - } else { - r = archive_write_set_format_by_name(a, bsdtar->create_format); - } - if (r != ARCHIVE_OK) { - fprintf(stderr, "Can't use format %s: %s\n", - bsdtar->create_format, - archive_error_string(a)); - usage(bsdtar); - } - - /* - * If user explicitly set the block size, then assume they - * want the last block padded as well. Otherwise, use the - * default block size and accept archive_write_open_file()'s - * default padding decisions. - */ - if (bsdtar->bytes_per_block != 0) { - archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); - archive_write_set_bytes_in_last_block(a, - bsdtar->bytes_per_block); - } else - archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK); - - switch (bsdtar->create_compression) { - case 0: - break; -#ifdef HAVE_LIBBZ2 - case 'j': case 'y': - archive_write_set_compression_bzip2(a); - break; -#endif -#ifdef HAVE_LIBZ - case 'z': - archive_write_set_compression_gzip(a); - break; -#endif - default: - bsdtar_errc(bsdtar, 1, 0, - "Unrecognized compression option -%c", - bsdtar->create_compression); - } - - r = archive_write_open_file(a, bsdtar->filename); - if (r != ARCHIVE_OK) - bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); - - write_archive(a, bsdtar); - - if (bsdtar->option_totals) { - fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n", - (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a)); - } - - archive_write_finish(a); -} - -/* - * Same as 'c', except we only support tar formats in uncompressed - * files on disk. - */ -void -tar_mode_r(struct bsdtar *bsdtar) -{ - off_t end_offset; - int format; - struct archive *a; - struct archive_entry *entry; - - /* Sanity-test some arguments and the file. */ - test_for_append(bsdtar); - - format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; - - bsdtar->fd = open(bsdtar->filename, O_RDWR); - if (bsdtar->fd < 0) - bsdtar_errc(bsdtar, 1, errno, - "Cannot open %s", bsdtar->filename); - - a = archive_read_new(); - archive_read_support_compression_all(a); - archive_read_support_format_tar(a); - archive_read_support_format_gnutar(a); - archive_read_open_fd(a, bsdtar->fd, 10240); - while (0 == archive_read_next_header(a, &entry)) { - if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) { - archive_read_finish(a); - close(bsdtar->fd); - bsdtar_errc(bsdtar, 1, 0, - "Cannot append to compressed archive."); - } - /* Keep going until we hit end-of-archive */ - format = archive_format(a); - } - - end_offset = archive_read_header_position(a); - archive_read_finish(a); - - /* Re-open archive for writing */ - a = archive_write_new(); - archive_write_set_compression_none(a); - /* - * Set format to same one auto-detected above, except use - * ustar for appending to GNU tar, since the library doesn't - * write GNU tar format. - */ - if (format == ARCHIVE_FORMAT_TAR_GNUTAR) - format = ARCHIVE_FORMAT_TAR_USTAR; - archive_write_set_format(a, format); - lseek(bsdtar->fd, end_offset, SEEK_SET); /* XXX check return val XXX */ - archive_write_open_fd(a, bsdtar->fd); /* XXX check return val XXX */ - - write_archive(a, bsdtar); /* XXX check return val XXX */ - - if (bsdtar->option_totals) { - fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n", - (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a)); - } - - archive_write_finish(a); - close(bsdtar->fd); - bsdtar->fd = -1; -} - -void -tar_mode_u(struct bsdtar *bsdtar) -{ - off_t end_offset; - struct archive *a; - struct archive_entry *entry; - int format; - struct archive_dir_entry *p; - struct archive_dir archive_dir; - - bsdtar->archive_dir = &archive_dir; - memset(&archive_dir, 0, sizeof(archive_dir)); - - format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; - - /* Sanity-test some arguments and the file. */ - test_for_append(bsdtar); - - bsdtar->fd = open(bsdtar->filename, O_RDWR); - if (bsdtar->fd < 0) - bsdtar_errc(bsdtar, 1, errno, - "Cannot open %s", bsdtar->filename); - - a = archive_read_new(); - archive_read_support_compression_all(a); - archive_read_support_format_tar(a); - archive_read_support_format_gnutar(a); - if (archive_read_open_fd(a, bsdtar->fd, - bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block : - DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - bsdtar_errc(bsdtar, 1, 0, - "Can't open %s: %s", bsdtar->filename, - archive_error_string(a)); - } - - /* Build a list of all entries and their recorded mod times. */ - while (0 == archive_read_next_header(a, &entry)) { - if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) { - archive_read_finish(a); - close(bsdtar->fd); - bsdtar_errc(bsdtar, 1, 0, - "Cannot append to compressed archive."); - } - add_dir_list(bsdtar, archive_entry_pathname(entry), - archive_entry_mtime(entry), - archive_entry_mtime_nsec(entry)); - /* Record the last format determination we see */ - format = archive_format(a); - /* Keep going until we hit end-of-archive */ - } - - end_offset = archive_read_header_position(a); - archive_read_finish(a); - - /* Re-open archive for writing. */ - a = archive_write_new(); - archive_write_set_compression_none(a); - /* - * Set format to same one auto-detected above, except that - * we don't write GNU tar format, so use ustar instead. - */ - if (format == ARCHIVE_FORMAT_TAR_GNUTAR) - format = ARCHIVE_FORMAT_TAR_USTAR; - archive_write_set_format(a, format); - if (bsdtar->bytes_per_block != 0) { - archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); - archive_write_set_bytes_in_last_block(a, - bsdtar->bytes_per_block); - } else - archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK); - lseek(bsdtar->fd, end_offset, SEEK_SET); - ftruncate(bsdtar->fd, end_offset); - archive_write_open_fd(a, bsdtar->fd); - - write_archive(a, bsdtar); - - if (bsdtar->option_totals) { - fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n", - (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a)); - } - - archive_write_finish(a); - close(bsdtar->fd); - bsdtar->fd = -1; - - while (bsdtar->archive_dir->head != NULL) { - p = bsdtar->archive_dir->head->next; - free(bsdtar->archive_dir->head->name); - free(bsdtar->archive_dir->head); - bsdtar->archive_dir->head = p; - } - bsdtar->archive_dir->tail = NULL; -} - - -/* - * Write user-specified files/dirs to opened archive. - */ -static void -write_archive(struct archive *a, struct bsdtar *bsdtar) -{ - const char *arg; - - if (bsdtar->names_from_file != NULL) - archive_names_from_file(bsdtar, a); - - while (*bsdtar->argv) { - arg = *bsdtar->argv; - if (arg[0] == '-' && arg[1] == 'C') { - arg += 2; - if (*arg == '\0') { - bsdtar->argv++; - arg = *bsdtar->argv; - if (arg == NULL) { - bsdtar_warnc(bsdtar, 1, 0, - "Missing argument for -C"); - bsdtar->return_value = 1; - return; - } - } - set_chdir(bsdtar, arg); - } else { - if (*arg != '/' || (arg[0] == '@' && arg[1] != '/')) - do_chdir(bsdtar); /* Handle a deferred -C */ - if (*arg == '@') { - if (append_archive(bsdtar, a, arg + 1) != 0) - break; - } else - write_hierarchy(bsdtar, a, arg); - } - bsdtar->argv++; - } - - create_cleanup(bsdtar); - archive_write_close(a); -} - -/* - * Archive names specified in file. - * - * Unless --null was specified, a line containing exactly "-C" will - * cause the next line to be a directory to pass to chdir(). If - * --null is specified, then a line "-C" is just another filename. - */ -void -archive_names_from_file(struct bsdtar *bsdtar, struct archive *a) -{ - bsdtar->archive = a; - - bsdtar->next_line_is_dir = 0; - process_lines(bsdtar, bsdtar->names_from_file, - archive_names_from_file_helper); - if (bsdtar->next_line_is_dir) - bsdtar_errc(bsdtar, 1, errno, - "Unexpected end of filename list; " - "directory expected after -C"); -} - -static int -archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line) -{ - if (bsdtar->next_line_is_dir) { - set_chdir(bsdtar, line); - bsdtar->next_line_is_dir = 0; - } else if (!bsdtar->option_null && strcmp(line, "-C") == 0) - bsdtar->next_line_is_dir = 1; - else { - if (*line != '/') - do_chdir(bsdtar); /* Handle a deferred -C */ - write_hierarchy(bsdtar, bsdtar->archive, line); - } - return (0); -} - -/* - * Copy from specified archive to current archive. Returns non-zero - * for write errors (which force us to terminate the entire archiving - * operation). If there are errors reading the input archive, we set - * bsdtar->return_value but return zero, so the overall archiving - * operation will complete and return non-zero. - */ -static int -append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename) -{ - struct archive *ina; - struct archive_entry *in_entry; - int bytes_read, bytes_written; - char buff[8192]; - - if (strcmp(filename, "-") == 0) - filename = NULL; /* Library uses NULL for stdio. */ - - ina = archive_read_new(); - archive_read_support_format_all(ina); - archive_read_support_compression_all(ina); - if (archive_read_open_file(ina, filename, 10240)) { - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(ina)); - bsdtar->return_value = 1; - return (0); - } - while (0 == archive_read_next_header(ina, &in_entry)) { - if (!new_enough(bsdtar, archive_entry_pathname(in_entry), - archive_entry_stat(in_entry))) - continue; - if (excluded(bsdtar, archive_entry_pathname(in_entry))) - continue; - if (bsdtar->option_interactive && - !yes("copy '%s'", archive_entry_pathname(in_entry))) - continue; - if (bsdtar->verbose) - safe_fprintf(stderr, "a %s", - archive_entry_pathname(in_entry)); - /* XXX handle/report errors XXX */ - if (archive_write_header(a, in_entry)) { - bsdtar_warnc(bsdtar, 0, "%s", - archive_error_string(ina)); - bsdtar->return_value = 1; - return (-1); - } - bytes_read = archive_read_data(ina, buff, sizeof(buff)); - while (bytes_read > 0) { - bytes_written = - archive_write_data(a, buff, bytes_read); - if (bytes_written < bytes_read) { - bsdtar_warnc(bsdtar, archive_errno(a), "%s", - archive_error_string(a)); - return (-1); - } - bytes_read = - archive_read_data(ina, buff, sizeof(buff)); - } - if (bsdtar->verbose) - fprintf(stderr, "\n"); - - } - if (archive_errno(ina)) { - bsdtar_warnc(bsdtar, 0, "Error reading archive %s: %s", - filename, archive_error_string(ina)); - bsdtar->return_value = 1; - } - - /* Note: If we got here, we saw no write errors, so return success. */ - return (0); -} - -/* - * Add the file or dir hierarchy named by 'path' to the archive - */ -static void -write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) -{ - struct tree *tree; - char symlink_mode = bsdtar->symlink_mode; - dev_t first_dev = 0; - int dev_recorded = 0; - int tree_ret; -#ifdef __linux - int fd, r; - unsigned long fflags; -#endif - - tree = tree_open(path); - - if (!tree) { - bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path); - bsdtar->return_value = 1; - return; - } - - while ((tree_ret = tree_next(tree))) { - const char *name = tree_current_path(tree); - const struct stat *st = NULL, *lst = NULL; - int descend; - - if (tree_ret == TREE_ERROR_DIR) - bsdtar_warnc(bsdtar, errno, "%s: Couldn't visit directory", name); - if (tree_ret != TREE_REGULAR) - continue; - lst = tree_current_lstat(tree); - if (lst == NULL) { - /* Couldn't lstat(); must not exist. */ - bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", path); - bsdtar->return_value = 1; - continue; - } - if (S_ISLNK(lst->st_mode)) - st = tree_current_stat(tree); - /* Default: descend into any dir or symlink to dir. */ - /* We'll adjust this later on. */ - descend = 0; - if ((st != NULL) && S_ISDIR(st->st_mode)) - descend = 1; - if ((lst != NULL) && S_ISDIR(lst->st_mode)) - descend = 1; - - /* - * If user has asked us not to cross mount points, - * then don't descend into into a dir on a different - * device. - */ - if (!dev_recorded) { - first_dev = lst->st_dev; - dev_recorded = 1; - } - if (bsdtar->option_dont_traverse_mounts) { - if (lst != NULL && lst->st_dev != first_dev) - descend = 0; - } - - /* - * If this file/dir is flagged "nodump" and we're - * honoring such flags, skip this file/dir. - */ -#ifdef HAVE_CHFLAGS - if (bsdtar->option_honor_nodump && - (lst->st_flags & UF_NODUMP)) - continue; -#endif - -#ifdef __linux - /* - * Linux has a nodump flag too but to read it - * we have to open() the file/dir and do an ioctl on it... - */ - if (bsdtar->option_honor_nodump && - ((fd = open(name, O_RDONLY|O_NONBLOCK)) >= 0) && - ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags)), - close(fd), r) >= 0 && - (fflags & EXT2_NODUMP_FL)) - continue; -#endif - - /* - * If this file/dir is excluded by a filename - * pattern, skip it. - */ - if (excluded(bsdtar, name)) - continue; - - /* - * If the user vetoes this file/directory, skip it. - */ - if (bsdtar->option_interactive && - !yes("add '%s'", name)) - continue; - - /* - * If this is a dir, decide whether or not to recurse. - */ - if (bsdtar->option_no_subdirs) - descend = 0; - - /* - * Distinguish 'L'/'P'/'H' symlink following. - */ - switch(symlink_mode) { - case 'H': - /* 'H': After the first item, rest like 'P'. */ - symlink_mode = 'P'; - /* 'H': First item (from command line) like 'L'. */ - /* FALLTHROUGH */ - case 'L': - /* 'L': Do descend through a symlink to dir. */ - /* 'L': Archive symlink to file as file. */ - lst = tree_current_stat(tree); - /* If stat fails, we have a broken symlink; - * in that case, archive the link as such. */ - if (lst == NULL) - lst = tree_current_lstat(tree); - break; - default: - /* 'P': Don't descend through a symlink to dir. */ - if (!S_ISDIR(lst->st_mode)) - descend = 0; - /* 'P': Archive symlink to file as symlink. */ - /* lst = tree_current_lstat(tree); */ - break; - } - - if (descend) - tree_descend(tree); - - /* - * Write the entry. Note that write_entry() handles - * pathname editing and newness testing. - */ - write_entry(bsdtar, a, lst, name, - tree_current_pathlen(tree), - tree_current_access_path(tree)); - } - tree_close(tree); -} - -/* - * Add a single filesystem object to the archive. - */ -static void -write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st, - const char *pathname, unsigned pathlen, const char *accpath) -{ - struct archive_entry *entry; - int e; - int fd; -#ifdef __linux - int r; - unsigned long stflags; -#endif - static char linkbuffer[PATH_MAX+1]; - - (void)pathlen; /* UNUSED */ - - fd = -1; - entry = archive_entry_new(); - - archive_entry_set_pathname(entry, pathname); - - /* - * Rewrite the pathname to be archived. If rewrite - * fails, skip the entry. - */ - if (edit_pathname(bsdtar, entry)) - goto abort; - - /* - * In -u mode, check that the file is newer than what's - * already in the archive; in all modes, obey --newerXXX flags. - */ - if (!new_enough(bsdtar, archive_entry_pathname(entry), st)) - goto abort; - - if (!S_ISDIR(st->st_mode) && (st->st_nlink > 1)) - lookup_hardlink(bsdtar, entry, st); - - /* Display entry as we process it. This format is required by SUSv2. */ - if (bsdtar->verbose) - safe_fprintf(stderr, "a %s", archive_entry_pathname(entry)); - - /* Read symbolic link information. */ - if ((st->st_mode & S_IFMT) == S_IFLNK) { - int lnklen; - - lnklen = readlink(accpath, linkbuffer, PATH_MAX); - if (lnklen < 0) { - if (!bsdtar->verbose) - bsdtar_warnc(bsdtar, errno, - "%s: Couldn't read symbolic link", - pathname); - else - safe_fprintf(stderr, - ": Couldn't read symbolic link: %s", - strerror(errno)); - goto cleanup; - } - linkbuffer[lnklen] = 0; - archive_entry_set_symlink(entry, linkbuffer); - } - - /* Look up username and group name. */ - archive_entry_set_uname(entry, lookup_uname(bsdtar, st->st_uid)); - archive_entry_set_gname(entry, lookup_gname(bsdtar, st->st_gid)); - -#ifdef HAVE_CHFLAGS - if (st->st_flags != 0) - archive_entry_set_fflags(entry, st->st_flags, 0); -#endif - -#ifdef __linux - if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) && - ((fd = open(accpath, O_RDONLY|O_NONBLOCK)) >= 0) && - ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags)), close(fd), (fd = -1), r) >= 0 && - stflags) { - archive_entry_set_fflags(entry, stflags, 0); - } -#endif - - archive_entry_copy_stat(entry, st); - setup_acls(bsdtar, entry, accpath); - setup_xattrs(bsdtar, entry, accpath); - - /* - * If it's a regular file (and non-zero in size) make sure we - * can open it before we start to write. In particular, note - * that we can always archive a zero-length file, even if we - * can't read it. - */ - if (S_ISREG(st->st_mode) && st->st_size > 0) { - fd = open(accpath, O_RDONLY); - if (fd < 0) { - if (!bsdtar->verbose) - bsdtar_warnc(bsdtar, errno, "%s: could not open file", pathname); - else - fprintf(stderr, ": %s", strerror(errno)); - goto cleanup; - } - } - - /* Non-regular files get archived with zero size. */ - if (!S_ISREG(st->st_mode)) - archive_entry_set_size(entry, 0); - - e = archive_write_header(a, entry); - if (e != ARCHIVE_OK) { - if (!bsdtar->verbose) - bsdtar_warnc(bsdtar, 0, "%s: %s", pathname, - archive_error_string(a)); - else - fprintf(stderr, ": %s", archive_error_string(a)); - } - - if (e == ARCHIVE_FATAL) - exit(1); - - /* - * If we opened a file earlier, write it out now. Note that - * the format handler might have reset the size field to zero - * to inform us that the archive body won't get stored. In - * that case, just skip the write. - */ - if (fd >= 0 && archive_entry_size(entry) > 0) - write_file_data(bsdtar, a, fd); - -cleanup: - if (bsdtar->verbose) - fprintf(stderr, "\n"); - -abort: - if (fd >= 0) - close(fd); - - if (entry != NULL) - archive_entry_free(entry); -} - - -/* Helper function to copy file to archive, with stack-allocated buffer. */ -static int -write_file_data(struct bsdtar *bsdtar, struct archive *a, int fd) -{ - char buff[64*1024]; - ssize_t bytes_read; - ssize_t bytes_written; - - /* XXX TODO: Allocate buffer on heap and store pointer to - * it in bsdtar structure; arrange cleanup as well. XXX */ - (void)bsdtar; - - bytes_read = read(fd, buff, sizeof(buff)); - while (bytes_read > 0) { - bytes_written = archive_write_data(a, buff, bytes_read); - if (bytes_written <= 0) - return (-1); /* Write failed; this is bad */ - bytes_read = read(fd, buff, sizeof(buff)); - } - return 0; -} - - -static void -create_cleanup(struct bsdtar *bsdtar) -{ - /* Free inode->pathname map used for hardlink detection. */ - if (bsdtar->links_cache != NULL) { - free_buckets(bsdtar, bsdtar->links_cache); - free(bsdtar->links_cache); - bsdtar->links_cache = NULL; - } - - free_cache(bsdtar->uname_cache); - bsdtar->uname_cache = NULL; - free_cache(bsdtar->gname_cache); - bsdtar->gname_cache = NULL; -} - - -static void -free_buckets(struct bsdtar *bsdtar, struct links_cache *links_cache) -{ - size_t i; - - if (links_cache->buckets == NULL) - return; - - for (i = 0; i < links_cache->number_buckets; i++) { - while (links_cache->buckets[i] != NULL) { - struct links_entry *lp = links_cache->buckets[i]->next; - if (bsdtar->option_warn_links) - bsdtar_warnc(bsdtar, 0, "Missing links to %s", - links_cache->buckets[i]->name); - if (links_cache->buckets[i]->name != NULL) - free(links_cache->buckets[i]->name); - free(links_cache->buckets[i]); - links_cache->buckets[i] = lp; - } - } - free(links_cache->buckets); - links_cache->buckets = NULL; -} - -static void -lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry, - const struct stat *st) -{ - struct links_cache *links_cache; - struct links_entry *le, **new_buckets; - int hash; - size_t i, new_size; - - /* If necessary, initialize the links cache. */ - links_cache = bsdtar->links_cache; - if (links_cache == NULL) { - bsdtar->links_cache = malloc(sizeof(struct links_cache)); - if (bsdtar->links_cache == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, - "No memory for hardlink detection."); - links_cache = bsdtar->links_cache; - memset(links_cache, 0, sizeof(struct links_cache)); - links_cache->number_buckets = links_cache_initial_size; - links_cache->buckets = malloc(links_cache->number_buckets * - sizeof(links_cache->buckets[0])); - if (links_cache->buckets == NULL) { - bsdtar_errc(bsdtar, 1, ENOMEM, - "No memory for hardlink detection."); - } - for (i = 0; i < links_cache->number_buckets; i++) - links_cache->buckets[i] = NULL; - } - - /* If the links cache overflowed and got flushed, don't bother. */ - if (links_cache->buckets == NULL) - return; - - /* If the links cache is getting too full, enlarge the hash table. */ - if (links_cache->number_entries > links_cache->number_buckets * 2) - { - new_size = links_cache->number_buckets * 2; - new_buckets = malloc(new_size * sizeof(struct links_entry *)); - - if (new_buckets != NULL) { - memset(new_buckets, 0, - new_size * sizeof(struct links_entry *)); - for (i = 0; i < links_cache->number_buckets; i++) { - while (links_cache->buckets[i] != NULL) { - /* Remove entry from old bucket. */ - le = links_cache->buckets[i]; - links_cache->buckets[i] = le->next; - - /* Add entry to new bucket. */ - hash = (le->dev ^ le->ino) % new_size; - - if (new_buckets[hash] != NULL) - new_buckets[hash]->previous = - le; - le->next = new_buckets[hash]; - le->previous = NULL; - new_buckets[hash] = le; - } - } - free(links_cache->buckets); - links_cache->buckets = new_buckets; - links_cache->number_buckets = new_size; - } else { - free_buckets(bsdtar, links_cache); - bsdtar_warnc(bsdtar, ENOMEM, - "No more memory for recording hard links"); - bsdtar_warnc(bsdtar, 0, - "Remaining links will be dumped as full files"); - } - } - - /* Try to locate this entry in the links cache. */ - hash = ( st->st_dev ^ st->st_ino ) % links_cache->number_buckets; - for (le = links_cache->buckets[hash]; le != NULL; le = le->next) { - if (le->dev == st->st_dev && le->ino == st->st_ino) { - archive_entry_copy_hardlink(entry, le->name); - - /* - * Decrement link count each time and release - * the entry if it hits zero. This saves - * memory and is necessary for proper -l - * implementation. - */ - if (--le->links <= 0) { - if (le->previous != NULL) - le->previous->next = le->next; - if (le->next != NULL) - le->next->previous = le->previous; - if (le->name != NULL) - free(le->name); - if (links_cache->buckets[hash] == le) - links_cache->buckets[hash] = le->next; - links_cache->number_entries--; - free(le); - } - - return; - } - } - - /* Add this entry to the links cache. */ - le = malloc(sizeof(struct links_entry)); - if (le != NULL) - le->name = strdup(archive_entry_pathname(entry)); - if ((le == NULL) || (le->name == NULL)) { - free_buckets(bsdtar, links_cache); - bsdtar_warnc(bsdtar, ENOMEM, - "No more memory for recording hard links"); - bsdtar_warnc(bsdtar, 0, - "Remaining hard links will be dumped as full files"); - if (le != NULL) - free(le); - return; - } - if (links_cache->buckets[hash] != NULL) - links_cache->buckets[hash]->previous = le; - links_cache->number_entries++; - le->next = links_cache->buckets[hash]; - le->previous = NULL; - links_cache->buckets[hash] = le; - le->dev = st->st_dev; - le->ino = st->st_ino; - le->links = st->st_nlink - 1; -} - -#ifdef HAVE_POSIX_ACL -static void setup_acl(struct bsdtar *bsdtar, - struct archive_entry *entry, const char *accpath, - int acl_type, int archive_entry_acl_type); - -static void -setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath) -{ - archive_entry_acl_clear(entry); - - setup_acl(bsdtar, entry, accpath, - ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); - /* Only directories can have default ACLs. */ - if (S_ISDIR(archive_entry_mode(entry))) - setup_acl(bsdtar, entry, accpath, - ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); -} - -static void -setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath, int acl_type, int archive_entry_acl_type) -{ - acl_t acl; - acl_tag_t acl_tag; - acl_entry_t acl_entry; - acl_permset_t acl_permset; - int s, ae_id, ae_tag, ae_perm; - const char *ae_name; - - /* Retrieve access ACL from file. */ - acl = acl_get_file(accpath, acl_type); - if (acl != NULL) { - s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); - while (s == 1) { - ae_id = -1; - ae_name = NULL; - - acl_get_tag_type(acl_entry, &acl_tag); - if (acl_tag == ACL_USER) { - ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); - ae_name = lookup_uname(bsdtar, ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_USER; - } else if (acl_tag == ACL_GROUP) { - ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); - ae_name = lookup_gname(bsdtar, ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - } else if (acl_tag == ACL_MASK) { - ae_tag = ARCHIVE_ENTRY_ACL_MASK; - } else if (acl_tag == ACL_USER_OBJ) { - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (acl_tag == ACL_GROUP_OBJ) { - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (acl_tag == ACL_OTHER) { - ae_tag = ARCHIVE_ENTRY_ACL_OTHER; - } else { - /* Skip types that libarchive can't support. */ - continue; - } - - acl_get_permset(acl_entry, &acl_permset); - ae_perm = 0; - /* - * acl_get_perm() is spelled differently on different - * platforms; see bsdtar_platform.h for details. - */ - if (ACL_GET_PERM(acl_permset, ACL_EXECUTE)) - ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; - if (ACL_GET_PERM(acl_permset, ACL_READ)) - ae_perm |= ARCHIVE_ENTRY_ACL_READ; - if (ACL_GET_PERM(acl_permset, ACL_WRITE)) - ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; - - archive_entry_acl_add_entry(entry, - archive_entry_acl_type, ae_perm, ae_tag, - ae_id, ae_name); - - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); - } - acl_free(acl); - } -} -#else -static void -setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath) -{ - (void)bsdtar; - (void)entry; - (void)accpath; -} -#endif - -#if HAVE_LISTXATTR && HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR - -static void -setup_xattr(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath, const char *name) -{ - size_t size; - void *value = NULL; - char symlink_mode = bsdtar->symlink_mode; - - if (symlink_mode == 'H') - size = getxattr(accpath, name, NULL, 0); - else - size = lgetxattr(accpath, name, NULL, 0); - - if (size == -1) { - bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute"); - return; - } - - if (size > 0 && (value = malloc(size)) == NULL) { - bsdtar_errc(bsdtar, 1, errno, "Out of memory"); - return; - } - - if (symlink_mode == 'H') - size = getxattr(accpath, name, value, size); - else - size = lgetxattr(accpath, name, value, size); - - if (size == -1) { - bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute"); - return; - } - - archive_entry_xattr_add_entry(entry, name, value, size); - - free(value); -} - -/* - * Linux extended attribute support - */ -static void -setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath) -{ - char *list, *p; - size_t list_size; - char symlink_mode = bsdtar->symlink_mode; - - if (symlink_mode == 'H') - list_size = listxattr(accpath, NULL, 0); - else - list_size = llistxattr(accpath, NULL, 0); - - if (list_size == -1) { - bsdtar_warnc(bsdtar, errno, - "Couldn't list extended attributes"); - return; - } else if (list_size == 0) - return; - - if ((list = malloc(list_size)) == NULL) { - bsdtar_errc(bsdtar, 1, errno, "Out of memory"); - return; - } - - if (symlink_mode == 'H') - list_size = listxattr(accpath, list, list_size); - else - list_size = llistxattr(accpath, list, list_size); - - if (list_size == -1) { - bsdtar_warnc(bsdtar, errno, - "Couldn't list extended attributes"); - free(list); - return; - } - - for (p = list; (p - list) < list_size; p += strlen(p) + 1) { - if (strncmp(p, "system.", 7) == 0 || - strncmp(p, "xfsroot.", 8) == 0) - continue; - - setup_xattr(bsdtar, entry, accpath, p); - } - - free(list); -} - -#else - -/* - * Generic (stub) extended attribute support. - */ -static void -setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry, - const char *accpath) -{ - (void)bsdtar; /* UNUSED */ - (void)entry; /* UNUSED */ - (void)accpath; /* UNUSED */ -} - -#endif - -static void -free_cache(struct name_cache *cache) -{ - size_t i; - - if (cache != NULL) { - for (i = 0; i < cache->size; i++) { - if (cache->cache[i].name != NULL && - cache->cache[i].name != NO_NAME) - free((void *)(uintptr_t)cache->cache[i].name); - } - free(cache); - } -} - -/* - * Lookup uid/gid from uname/gname, return NULL if no match. - */ -static const char * -lookup_name(struct bsdtar *bsdtar, struct name_cache **name_cache_variable, - int (*lookup_fn)(struct bsdtar *, const char **, id_t), id_t id) -{ - struct name_cache *cache; - const char *name; - int slot; - - - if (*name_cache_variable == NULL) { - *name_cache_variable = malloc(sizeof(struct name_cache)); - if (*name_cache_variable == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, "No more memory"); - memset(*name_cache_variable, 0, sizeof(struct name_cache)); - (*name_cache_variable)->size = name_cache_size; - } - - cache = *name_cache_variable; - cache->probes++; - - slot = id % cache->size; - if (cache->cache[slot].name != NULL) { - if (cache->cache[slot].id == id) { - cache->hits++; - if (cache->cache[slot].name == NO_NAME) - return (NULL); - return (cache->cache[slot].name); - } - if (cache->cache[slot].name != NO_NAME) - free((void *)(uintptr_t)cache->cache[slot].name); - cache->cache[slot].name = NULL; - } - - if (lookup_fn(bsdtar, &name, id) == 0) { - if (name == NULL || name[0] == '\0') { - /* Cache the negative response. */ - cache->cache[slot].name = NO_NAME; - cache->cache[slot].id = id; - } else { - cache->cache[slot].name = strdup(name); - if (cache->cache[slot].name != NULL) { - cache->cache[slot].id = id; - return (cache->cache[slot].name); - } - /* - * Conveniently, NULL marks an empty slot, so - * if the strdup() fails, we've just failed to - * cache it. No recovery necessary. - */ - } - } - return (NULL); -} - -static const char * -lookup_uname(struct bsdtar *bsdtar, uid_t uid) -{ - return (lookup_name(bsdtar, &bsdtar->uname_cache, - &lookup_uname_helper, (id_t)uid)); -} - -static int -lookup_uname_helper(struct bsdtar *bsdtar, const char **name, id_t id) -{ - struct passwd *pwent; - - (void)bsdtar; /* UNUSED */ - - errno = 0; - pwent = getpwuid((uid_t)id); - if (pwent == NULL) { - *name = NULL; - if (errno != 0) - bsdtar_warnc(bsdtar, errno, "getpwuid(%d) failed", id); - return (errno); - } - - *name = pwent->pw_name; - return (0); -} - -static const char * -lookup_gname(struct bsdtar *bsdtar, gid_t gid) -{ - return (lookup_name(bsdtar, &bsdtar->gname_cache, - &lookup_gname_helper, (id_t)gid)); -} - -static int -lookup_gname_helper(struct bsdtar *bsdtar, const char **name, id_t id) -{ - struct group *grent; - - (void)bsdtar; /* UNUSED */ - - errno = 0; - grent = getgrgid((gid_t)id); - if (grent == NULL) { - *name = NULL; - if (errno != 0) - bsdtar_warnc(bsdtar, errno, "getgrgid(%d) failed", id); - return (errno); - } - - *name = grent->gr_name; - return (0); -} - -/* - * Test if the specified file is new enough to include in the archive. - */ -int -new_enough(struct bsdtar *bsdtar, const char *path, const struct stat *st) -{ - struct archive_dir_entry *p; - - /* - * If this file/dir is excluded by a time comparison, skip it. - */ - if (bsdtar->newer_ctime_sec > 0) { - if (st->st_ctime < bsdtar->newer_ctime_sec) - return (0); /* Too old, skip it. */ - if (st->st_ctime == bsdtar->newer_ctime_sec - && ARCHIVE_STAT_CTIME_NANOS(st) - <= bsdtar->newer_ctime_nsec) - return (0); /* Too old, skip it. */ - } - if (bsdtar->newer_mtime_sec > 0) { - if (st->st_mtime < bsdtar->newer_mtime_sec) - return (0); /* Too old, skip it. */ - if (st->st_mtime == bsdtar->newer_mtime_sec - && ARCHIVE_STAT_MTIME_NANOS(st) - <= bsdtar->newer_mtime_nsec) - return (0); /* Too old, skip it. */ - } - - /* - * In -u mode, we only write an entry if it's newer than - * what was already in the archive. - */ - if (bsdtar->archive_dir != NULL && - bsdtar->archive_dir->head != NULL) { - for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) { - if (strcmp(path, p->name)==0) - return (p->mtime_sec < st->st_mtime || - (p->mtime_sec == st->st_mtime && - p->mtime_nsec - < ARCHIVE_STAT_MTIME_NANOS(st))); - } - } - - /* If the file wasn't rejected, include it. */ - return (1); -} - -/* - * Add an entry to the dir list for 'u' mode. - * - * XXX TODO: Make this fast. - */ -static void -add_dir_list(struct bsdtar *bsdtar, const char *path, - time_t mtime_sec, int mtime_nsec) -{ - struct archive_dir_entry *p; - - if (path[0] == '.' && path[1] == '/' && path[2] != '\0') - path += 2; - - /* - * Search entire list to see if this file has appeared before. - * If it has, override the timestamp data. - */ - p = bsdtar->archive_dir->head; - while (p != NULL) { - if (strcmp(path, p->name)==0) { - p->mtime_sec = mtime_sec; - p->mtime_nsec = mtime_nsec; - return; - } - p = p->next; - } - - p = malloc(sizeof(*p)); - if (p == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory"); - - p->name = strdup(path); - if (p->name == NULL) - bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory"); - p->mtime_sec = mtime_sec; - p->mtime_nsec = mtime_nsec; - p->next = NULL; - if (bsdtar->archive_dir->tail == NULL) { - bsdtar->archive_dir->head = bsdtar->archive_dir->tail = p; - } else { - bsdtar->archive_dir->tail->next = p; - bsdtar->archive_dir->tail = p; - } -} - -void -test_for_append(struct bsdtar *bsdtar) -{ - struct stat s; - - if (*bsdtar->argv == NULL) - bsdtar_errc(bsdtar, 1, 0, "no files or directories specified"); - if (bsdtar->filename == NULL) - bsdtar_errc(bsdtar, 1, 0, "Cannot append to stdout."); - - if (bsdtar->create_compression != 0) - bsdtar_errc(bsdtar, 1, 0, - "Cannot append to %s with compression", bsdtar->filename); - - if (stat(bsdtar->filename, &s) != 0) - bsdtar_errc(bsdtar, 1, errno, - "Cannot stat %s", bsdtar->filename); - - if (!S_ISREG(s.st_mode)) - bsdtar_errc(bsdtar, 1, 0, - "Cannot append to %s: not a regular file.", - bsdtar->filename); -} diff --git a/contrib/libarchive-1.3.1/version b/contrib/libarchive-1.3.1/version deleted file mode 100644 index 6261a05bb0..0000000000 --- a/contrib/libarchive-1.3.1/version +++ /dev/null @@ -1 +0,0 @@ -1.3.1 \ No newline at end of file