libarchive 2.0
* libarchive_test program exercises many of the core features * Refactored old "read_extract" into new "archive_write_disk", which uses archive_write methods to put entries onto disk. In particular, you can now use archive_write_disk to create objects on disk without having an archive available. * Pushed some security checks from bsdtar down into libarchive, where they can be better optimized. * Rearchitected the logic for creating objects on disk to reduce the number of system calls. Several common cases now use a minimum number of system calls. * Virtualized some internal interfaces to provide a clearer separation of read and write handling and make it simpler to override key methods. * New "empty" format reader. * Corrected return types (this ABI breakage required the "2.0" version bump) * Many bug fixes.
This commit is contained in:
parent
4fce38ec78
commit
f81da3e584
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167186
@ -9,14 +9,14 @@ LDADD= -lbz2 -lz
|
||||
# Major: Bumped ONLY when API/ABI breakage happens (see SHLIB_MAJOR)
|
||||
# Minor: Bumped when significant new features are added
|
||||
# Revision: Bumped on any notable change
|
||||
VERSION= 1.3.1
|
||||
VERSION= 2.0.20
|
||||
|
||||
ARCHIVE_API_MAJOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/\..*//'
|
||||
ARCHIVE_API_MINOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/[0-9]*\.//' -e 's/\..*//'
|
||||
|
||||
# FreeBSD SHLIB_MAJOR value is managed as part of the FreeBSD system.
|
||||
# It has no real relation to the version number above.
|
||||
SHLIB_MAJOR= 3
|
||||
SHLIB_MAJOR= 4
|
||||
|
||||
CFLAGS+= -DPACKAGE_NAME=\"lib${LIB}\"
|
||||
CFLAGS+= -DPACKAGE_VERSION=\"${VERSION}\"
|
||||
@ -67,7 +67,10 @@ SRCS= archive.h \
|
||||
archive_string.c \
|
||||
archive_string_sprintf.c \
|
||||
archive_util.c \
|
||||
archive_virtual.c \
|
||||
archive_write.c \
|
||||
archive_write_disk.c \
|
||||
archive_write_disk_set_standard_lookup.c \
|
||||
archive_write_open_fd.c \
|
||||
archive_write_open_file.c \
|
||||
archive_write_open_filename.c \
|
||||
@ -87,6 +90,7 @@ MAN= archive_entry.3 \
|
||||
archive_read.3 \
|
||||
archive_util.3 \
|
||||
archive_write.3 \
|
||||
archive_write_disk.3 \
|
||||
libarchive.3 \
|
||||
libarchive-formats.5 \
|
||||
tar.5
|
||||
@ -173,6 +177,7 @@ MLINKS+= archive_read.3 archive_read_support_format_cpio.3
|
||||
MLINKS+= archive_read.3 archive_read_support_format_iso9660.3
|
||||
MLINKS+= archive_read.3 archive_read_support_format_tar.3
|
||||
MLINKS+= archive_read.3 archive_read_support_format_zip.3
|
||||
MLINKS+= archive_util.3 archive_clear_error.3
|
||||
MLINKS+= archive_util.3 archive_compression.3
|
||||
MLINKS+= archive_util.3 archive_compression_name.3
|
||||
MLINKS+= archive_util.3 archive_errno.3
|
||||
@ -201,6 +206,15 @@ MLINKS+= archive_write.3 archive_write_set_compression_gzip.3
|
||||
MLINKS+= archive_write.3 archive_write_set_format_pax.3
|
||||
MLINKS+= archive_write.3 archive_write_set_format_shar.3
|
||||
MLINKS+= archive_write.3 archive_write_set_format_ustar.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_new.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_set_group_lookup.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_set_options.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_set_skip_file.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_set_standard_lookup.3
|
||||
MLINKS+= archive_write_disk.3 archive_write_disk_set_user_lookup.3
|
||||
MLINKS+= libarchive.3 archive.3
|
||||
|
||||
test:
|
||||
cd ${.CURDIR}/test && make test
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
@ -6,16 +6,16 @@ This is all under a BSD license. Use, enjoy, but don't blame me if it breaks!
|
||||
|
||||
Documentation:
|
||||
* 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_read.3, archive_write.3, and archive_write_disk.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.
|
||||
code for the sample "bsdtar" and "minitar" programs 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
|
||||
@ -84,8 +84,10 @@ Notes:
|
||||
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.
|
||||
to read/write entries to disk, the archive_write_disk interface
|
||||
treats a directory as if it were an archive so you can copy
|
||||
from archive->disk using the same code you use for archive->archive
|
||||
transfers.
|
||||
|
||||
* Note: "pax interchange format" is really an extended tar format,
|
||||
despite what the name says.
|
||||
|
@ -37,7 +37,14 @@
|
||||
#include <sys/types.h> /* Linux requires this for off_t */
|
||||
@ARCHIVE_H_INCLUDE_INTTYPES_H@
|
||||
#include <stdio.h> /* For FILE * */
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h> /* For ssize_t and size_t */
|
||||
#else
|
||||
typedef long ssize_t;
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned int gid_t;
|
||||
typedef unsigned short mode_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -59,6 +66,7 @@ extern "C" {
|
||||
* 1 - Version tests are available.
|
||||
* 2 - archive_{read,write}_close available separately from _finish.
|
||||
* 3 - open_memory, open_memory2, open_FILE, open_fd available
|
||||
* 5 - archive_write_disk interface available
|
||||
*/
|
||||
#define ARCHIVE_API_VERSION @ARCHIVE_API_MAJOR@
|
||||
int archive_api_version(void);
|
||||
@ -138,8 +146,17 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
* Top 16 bits identifies the format family (e.g., "tar"); lower
|
||||
* 16 bits indicate the variant. This is updated by read_next_header.
|
||||
* Note that the lower 16 bits will often vary from entry to entry.
|
||||
* In some cases, this variation occurs as libarchive learns more about
|
||||
* the archive (for example, later entries might utilize extensions that
|
||||
* weren't necessary earlier in the archive; in this case, libarchive
|
||||
* will change the format code to indicate the extended format that
|
||||
* was used). In other cases, it's because different tools have
|
||||
* modified the archive and so different parts of the archive
|
||||
* actually have slightly different formts. (Both tar and cpio store
|
||||
* format codes in each entry, so it is quite possible for each
|
||||
* entry to be in a different format.)
|
||||
*/
|
||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000U
|
||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000
|
||||
#define ARCHIVE_FORMAT_CPIO 0x10000
|
||||
#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1)
|
||||
#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2)
|
||||
@ -274,15 +291,28 @@ int archive_read_data_into_fd(struct archive *, int fd);
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Default: Do not try to set owner/group. */
|
||||
#define ARCHIVE_EXTRACT_OWNER (1)
|
||||
/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
|
||||
#define ARCHIVE_EXTRACT_PERM (2)
|
||||
/* Default: Do not restore mtime/atime. */
|
||||
#define ARCHIVE_EXTRACT_TIME (4)
|
||||
/* Default: Replace existing files. */
|
||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE (8)
|
||||
/* Default: Try create first, unlink only if create fails with EEXIST. */
|
||||
#define ARCHIVE_EXTRACT_UNLINK (16)
|
||||
/* Default: Do not restore ACLs. */
|
||||
#define ARCHIVE_EXTRACT_ACL (32)
|
||||
/* Default: Do not restore fflags. */
|
||||
#define ARCHIVE_EXTRACT_FFLAGS (64)
|
||||
/* Default: Do not restore xattrs. */
|
||||
#define ARCHIVE_EXTRACT_XATTR (128)
|
||||
/* Default: Do not try to guard against extracts redirected by symlinks. */
|
||||
/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (256)
|
||||
/* Default: Do not reject entries with '..' as path elements. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (512)
|
||||
|
||||
int archive_read_extract(struct archive *, struct archive_entry *,
|
||||
int flags);
|
||||
@ -298,7 +328,13 @@ void archive_read_extract_set_skip_file(struct archive *,
|
||||
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:
|
||||
@ -362,11 +398,76 @@ int archive_write_open_memory(struct archive *,
|
||||
*/
|
||||
int archive_write_header(struct archive *,
|
||||
struct archive_entry *);
|
||||
/* TODO: should be ssize_t, but that might require .so version bump? */
|
||||
#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
|
||||
ssize_t archive_write_data_block(struct archive *, const void *, size_t, off_t);
|
||||
int archive_write_finish_entry(struct archive *);
|
||||
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
|
||||
|
||||
/*-
|
||||
* To create objects on disk:
|
||||
* 1) Ask archive_write_disk_new for a new archive_write_disk object.
|
||||
* 2) Set any global properties. In particular, you should set
|
||||
* the compression and format to use.
|
||||
* 3) For each entry:
|
||||
* - construct an appropriate struct archive_entry structure
|
||||
* - archive_write_header to create the file/dir/etc on disk
|
||||
* - archive_write_data to write the entry data
|
||||
* 4) archive_write_finish to cleanup the writer and release resources
|
||||
*
|
||||
* In particular, you can use this in conjunction with archive_read()
|
||||
* to pull entries out of an archive and create them on disk.
|
||||
*/
|
||||
struct archive *archive_write_disk_new(void);
|
||||
/* This file will not be overwritten. */
|
||||
int archive_write_disk_set_skip_file(struct archive *,
|
||||
dev_t, ino_t);
|
||||
/* Set flags to control how the next item gets created. */
|
||||
int archive_write_disk_set_options(struct archive *,
|
||||
int flags);
|
||||
/*
|
||||
* The lookup functions are given uname/uid (or gname/gid) pairs and
|
||||
* return a uid (gid) suitable for this system. These are used for
|
||||
* restoring ownership and for setting ACLs. The default functions
|
||||
* are naive, they just return the uid/gid. These are small, so reasonable
|
||||
* for applications that don't need to preserve ownership; they
|
||||
* are probably also appropriate for applications that are doing
|
||||
* same-system backup and restore.
|
||||
*/
|
||||
/*
|
||||
* The "standard" lookup functions use common system calls to lookup
|
||||
* the uname/gname, falling back to the uid/gid if the names can't be
|
||||
* found. They cache lookups and are reasonably fast, but can be very
|
||||
* large, so they are not used unless you ask for them. In
|
||||
* particular, these match the specifications of POSIX "pax" and old
|
||||
* POSIX "tar".
|
||||
*/
|
||||
int archive_write_disk_set_standard_lookup(struct archive *);
|
||||
/*
|
||||
* If neither the default (naive) nor the standard (big) functions suit
|
||||
* your needs, you can write your own and register them. Be sure to
|
||||
* include a cleanup function if you have allocated private data.
|
||||
*/
|
||||
int archive_write_disk_set_group_lookup(struct archive *,
|
||||
void *private_data,
|
||||
gid_t (*loookup)(void *, const char *gname, gid_t gid),
|
||||
void (*cleanup)(void *));
|
||||
int archive_write_disk_set_user_lookup(struct archive *,
|
||||
void *private_data,
|
||||
uid_t (*)(void *, const char *uname, uid_t uid),
|
||||
void (*cleanup)(void *));
|
||||
|
||||
/*
|
||||
* Accessor functions to read/set various information in
|
||||
@ -383,6 +484,7 @@ 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_clear_error(struct archive *);
|
||||
void archive_set_error(struct archive *, int _err, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,6 +46,7 @@
|
||||
.Nm archive_entry_copy_hardlink_w ,
|
||||
.Nm archive_entry_copy_pathname_w ,
|
||||
.Nm archive_entry_copy_stat ,
|
||||
.Nm archive_entry_copy_symlink ,
|
||||
.Nm archive_entry_copy_symlink_w ,
|
||||
.Nm archive_entry_copy_uname_w ,
|
||||
.Nm archive_entry_dev ,
|
||||
@ -124,6 +125,8 @@
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_stat "struct archive_entry *" "const struct stat *"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_symlink "struct archive_entry *" "const char *"
|
||||
.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 *"
|
||||
|
@ -33,6 +33,28 @@
|
||||
|
||||
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
||||
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
||||
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
||||
|
||||
#define ARCHIVE_STATE_ANY 0xFFFFU
|
||||
#define ARCHIVE_STATE_NEW 1U
|
||||
#define ARCHIVE_STATE_HEADER 2U
|
||||
#define ARCHIVE_STATE_DATA 4U
|
||||
#define ARCHIVE_STATE_DATA_END 8U
|
||||
#define ARCHIVE_STATE_EOF 0x10U
|
||||
#define ARCHIVE_STATE_CLOSED 0x20U
|
||||
#define ARCHIVE_STATE_FATAL 0x8000U
|
||||
|
||||
struct archive_vtable {
|
||||
int (*archive_write_close)(struct archive *);
|
||||
int (*archive_write_finish)(struct archive *);
|
||||
int (*archive_write_header)(struct archive *,
|
||||
struct archive_entry *);
|
||||
int (*archive_write_finish_entry)(struct archive *);
|
||||
ssize_t (*archive_write_data)(struct archive *,
|
||||
const void *, size_t);
|
||||
ssize_t (*archive_write_data_block)(struct archive *,
|
||||
const void *, size_t, off_t);
|
||||
};
|
||||
|
||||
struct archive {
|
||||
/*
|
||||
@ -44,202 +66,34 @@ struct archive {
|
||||
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.
|
||||
* Some public API functions depend on the "real" type of the
|
||||
* archive object.
|
||||
*/
|
||||
const char *read_data_block;
|
||||
off_t read_data_offset;
|
||||
off_t read_data_output_offset;
|
||||
size_t read_data_remaining;
|
||||
struct archive_vtable *vtable;
|
||||
|
||||
/* 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;
|
||||
int archive_format;
|
||||
const char *archive_format_name;
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
int compression_code; /* Currently active compression. */
|
||||
const char *compression_name;
|
||||
|
||||
/* 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);
|
||||
off_t (*compression_skip)(struct archive *, off_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 guaranteed 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
|
||||
|
@ -113,7 +113,7 @@
|
||||
.Fn archive_read_extract_set_progress_callback "struct archive *" "void (*func)(void *)" "void *user_data"
|
||||
.Ft int
|
||||
.Fn archive_read_close "struct archive *"
|
||||
.Ft void
|
||||
.Ft int
|
||||
.Fn archive_read_finish "struct archive *"
|
||||
.Sh DESCRIPTION
|
||||
These functions provide a complete API for reading streaming archives.
|
||||
@ -148,7 +148,7 @@ 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.
|
||||
Only empty archives are supported by default.
|
||||
.It Fn archive_read_open
|
||||
The same as
|
||||
.Fn archive_read_open2 ,
|
||||
@ -233,58 +233,27 @@ Note that the client is responsible for sizing the buffer appropriately.
|
||||
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
|
||||
.It Fn archive_read_extract , Fn archive_read_extract_set_skip_file
|
||||
A convenience function that wraps the corresponding
|
||||
.Xr archive_write_disk 3
|
||||
interfaces.
|
||||
The first call to
|
||||
.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.
|
||||
creates a restore object using
|
||||
.Xr archive_write_disk_new 3
|
||||
and
|
||||
.Xr archive_write_disk_set_standard_lookup 3 ,
|
||||
then transparently invokes
|
||||
.Xr archive_write_disk_set_options 3 ,
|
||||
.Xr archive_write_header 3 ,
|
||||
.Xr archive_write_data 3 ,
|
||||
and
|
||||
.Xr archive_write_finish_entry 3
|
||||
to create the entry on disk and copy data into it.
|
||||
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.)
|
||||
argument is passed unmodified to
|
||||
.Xr archiv_write_disk_set_options 3 .
|
||||
.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.
|
||||
@ -300,6 +269,12 @@ Complete the archive and invoke the close callback.
|
||||
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
|
||||
@ -523,26 +498,6 @@ The
|
||||
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.
|
||||
.Pp
|
||||
Many traditional archiver programs treat
|
||||
empty files as valid empty archives.
|
||||
For example, many implementations of
|
||||
|
@ -51,9 +51,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
static int choose_decompressor(struct archive *, const void*, size_t);
|
||||
static int choose_format(struct archive *);
|
||||
static int choose_decompressor(struct archive_read *, const void*, size_t);
|
||||
static int choose_format(struct archive_read *);
|
||||
|
||||
/*
|
||||
* Allocate, initialize and return a struct archive object.
|
||||
@ -61,44 +62,45 @@ static int choose_format(struct archive *);
|
||||
struct archive *
|
||||
archive_read_new(void)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_read *a;
|
||||
unsigned char *nulls;
|
||||
|
||||
a = (struct archive *)malloc(sizeof(*a));
|
||||
a = (struct archive_read *)malloc(sizeof(*a));
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
memset(a, 0, sizeof(*a));
|
||||
|
||||
a->user_uid = geteuid();
|
||||
a->magic = ARCHIVE_READ_MAGIC;
|
||||
a->archive.magic = ARCHIVE_READ_MAGIC;
|
||||
a->bytes_per_block = ARCHIVE_DEFAULT_BYTES_PER_BLOCK;
|
||||
|
||||
a->null_length = 1024;
|
||||
nulls = (unsigned char *)malloc(a->null_length);
|
||||
if (nulls == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate archive object 'nulls' element");
|
||||
archive_set_error(&a->archive, 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->archive.state = ARCHIVE_STATE_NEW;
|
||||
a->entry = archive_entry_new();
|
||||
|
||||
/* We always support uncompressed archives. */
|
||||
archive_read_support_compression_none((struct archive*)a);
|
||||
archive_read_support_compression_none(&a->archive);
|
||||
|
||||
return (a);
|
||||
return (&a->archive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
|
||||
*/
|
||||
void
|
||||
archive_read_extract_set_skip_file(struct archive *a, dev_t d, ino_t i)
|
||||
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");
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
__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;
|
||||
}
|
||||
@ -119,18 +121,19 @@ archive_read_open(struct archive *a, void *client_data,
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_open2(struct archive *a, void *client_data,
|
||||
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)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
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");
|
||||
__archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open");
|
||||
|
||||
if (client_reader == NULL)
|
||||
__archive_errx(1,
|
||||
@ -150,22 +153,22 @@ archive_read_open2(struct archive *a, void *client_data,
|
||||
|
||||
/* Open data source. */
|
||||
if (client_opener != NULL) {
|
||||
e =(client_opener)(a, client_data);
|
||||
e =(client_opener)(&a->archive, client_data);
|
||||
if (e != 0) {
|
||||
/* If the open failed, call the closer to clean up. */
|
||||
if (client_closer)
|
||||
(client_closer)(a, client_data);
|
||||
(client_closer)(&a->archive, client_data);
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read first block now for format detection. */
|
||||
bytes_read = (client_reader)(a, client_data, &buffer);
|
||||
bytes_read = (client_reader)(&a->archive, 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_closer)(&a->archive, client_data);
|
||||
/* client_reader should have already set error information. */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -186,7 +189,7 @@ archive_read_open2(struct archive *a, void *client_data,
|
||||
e = (a->decompressors[high_bidder].init)(a, buffer, bytes_read);
|
||||
|
||||
if (e == ARCHIVE_OK)
|
||||
a->state = ARCHIVE_STATE_HEADER;
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
|
||||
return (e);
|
||||
}
|
||||
@ -196,7 +199,8 @@ archive_read_open2(struct archive *a, void *client_data,
|
||||
* wants to handle this stream. Return index of winning bidder.
|
||||
*/
|
||||
static int
|
||||
choose_decompressor(struct archive *a, const void *buffer, size_t bytes_read)
|
||||
choose_decompressor(struct archive_read *a,
|
||||
const void *buffer, size_t bytes_read)
|
||||
{
|
||||
int decompression_slots, i, bid, best_bid, best_bid_slot;
|
||||
|
||||
@ -231,7 +235,7 @@ choose_decompressor(struct archive *a, const void *buffer, size_t bytes_read)
|
||||
* support this stream.
|
||||
*/
|
||||
if (best_bid < 1) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unrecognized archive format");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -243,28 +247,30 @@ choose_decompressor(struct archive *a, const void *buffer, size_t bytes_read)
|
||||
* Read header of next entry.
|
||||
*/
|
||||
int
|
||||
archive_read_next_header(struct archive *a, struct archive_entry **entryp)
|
||||
archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_entry *entry;
|
||||
int slot, ret;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, "archive_read_next_header");
|
||||
__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);
|
||||
archive_clear_error(&a->archive);
|
||||
|
||||
/*
|
||||
* If client didn't consume entire data, skip any remainder
|
||||
* (This is especially important for GNU incremental directories.)
|
||||
*/
|
||||
if (a->state == ARCHIVE_STATE_DATA) {
|
||||
ret = archive_read_data_skip(a);
|
||||
if (a->archive.state == ARCHIVE_STATE_DATA) {
|
||||
ret = archive_read_data_skip(&a->archive);
|
||||
if (ret == ARCHIVE_EOF) {
|
||||
archive_set_error(a, EIO, "Premature end-of-file.");
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
archive_set_error(&a->archive, EIO, "Premature end-of-file.");
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (ret != ARCHIVE_OK)
|
||||
@ -272,11 +278,11 @@ archive_read_next_header(struct archive *a, struct archive_entry **entryp)
|
||||
}
|
||||
|
||||
/* Record start-of-header. */
|
||||
a->header_position = a->file_position;
|
||||
a->header_position = a->archive.file_position;
|
||||
|
||||
slot = choose_format(a);
|
||||
if (slot < 0) {
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
a->format = &(a->formats[slot]);
|
||||
@ -290,18 +296,18 @@ archive_read_next_header(struct archive *a, struct archive_entry **entryp)
|
||||
*/
|
||||
switch (ret) {
|
||||
case ARCHIVE_EOF:
|
||||
a->state = ARCHIVE_STATE_EOF;
|
||||
a->archive.state = ARCHIVE_STATE_EOF;
|
||||
break;
|
||||
case ARCHIVE_OK:
|
||||
a->state = ARCHIVE_STATE_DATA;
|
||||
a->archive.state = ARCHIVE_STATE_DATA;
|
||||
break;
|
||||
case ARCHIVE_WARN:
|
||||
a->state = ARCHIVE_STATE_DATA;
|
||||
a->archive.state = ARCHIVE_STATE_DATA;
|
||||
break;
|
||||
case ARCHIVE_RETRY:
|
||||
break;
|
||||
case ARCHIVE_FATAL:
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -316,7 +322,7 @@ archive_read_next_header(struct archive *a, struct archive_entry **entryp)
|
||||
* the next entry. Return index of winning bidder.
|
||||
*/
|
||||
static int
|
||||
choose_format(struct archive *a)
|
||||
choose_format(struct archive_read *a)
|
||||
{
|
||||
int slots;
|
||||
int i;
|
||||
@ -356,7 +362,7 @@ choose_format(struct archive *a)
|
||||
* can't support this stream.
|
||||
*/
|
||||
if (best_bid < 1) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unrecognized archive format");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -369,8 +375,11 @@ choose_format(struct archive *a)
|
||||
* the last header started.
|
||||
*/
|
||||
int64_t
|
||||
archive_read_header_position(struct archive *a)
|
||||
archive_read_header_position(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
__archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_read_header_position");
|
||||
return (a->header_position);
|
||||
}
|
||||
|
||||
@ -386,8 +395,9 @@ archive_read_header_position(struct archive *a)
|
||||
* to read a single entry body.
|
||||
*/
|
||||
ssize_t
|
||||
archive_read_data(struct archive *a, void *buff, size_t s)
|
||||
archive_read_data(struct archive *_a, void *buff, size_t s)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
char *dest;
|
||||
size_t bytes_read;
|
||||
size_t len;
|
||||
@ -398,7 +408,7 @@ archive_read_data(struct archive *a, void *buff, size_t s)
|
||||
|
||||
while (s > 0) {
|
||||
if (a->read_data_remaining <= 0) {
|
||||
r = archive_read_data_block(a,
|
||||
r = archive_read_data_block(&a->archive,
|
||||
(const void **)&a->read_data_block,
|
||||
&a->read_data_remaining,
|
||||
&a->read_data_offset);
|
||||
@ -414,7 +424,7 @@ archive_read_data(struct archive *a, void *buff, size_t s)
|
||||
}
|
||||
|
||||
if (a->read_data_offset < a->read_data_output_offset) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Encountered out-of-order sparse blocks");
|
||||
return (ARCHIVE_RETRY);
|
||||
}
|
||||
@ -459,19 +469,22 @@ archive_read_data(struct archive *a, void *buff, size_t s)
|
||||
* Skip over all remaining data in this entry.
|
||||
*/
|
||||
int
|
||||
archive_read_data_skip(struct archive *a)
|
||||
archive_read_data_skip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_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");
|
||||
__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))
|
||||
while ((r = archive_read_data_block(&a->archive,
|
||||
&buff, &size, &offset))
|
||||
== ARCHIVE_OK)
|
||||
;
|
||||
}
|
||||
@ -479,7 +492,7 @@ archive_read_data_skip(struct archive *a)
|
||||
if (r == ARCHIVE_EOF)
|
||||
r = ARCHIVE_OK;
|
||||
|
||||
a->state = ARCHIVE_STATE_HEADER;
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
return (r);
|
||||
}
|
||||
|
||||
@ -492,13 +505,15 @@ archive_read_data_skip(struct archive *a)
|
||||
* the end of entry is encountered.
|
||||
*/
|
||||
int
|
||||
archive_read_data_block(struct archive *a,
|
||||
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");
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
__archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
||||
"archive_read_data_block");
|
||||
|
||||
if (a->format->read_data == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: "
|
||||
"No format_read_data_block function registered");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -515,12 +530,14 @@ archive_read_data_block(struct archive *a,
|
||||
* initialization.
|
||||
*/
|
||||
int
|
||||
archive_read_close(struct archive *a)
|
||||
archive_read_close(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_close");
|
||||
a->state = ARCHIVE_STATE_CLOSED;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_read_close");
|
||||
a->archive.state = ARCHIVE_STATE_CLOSED;
|
||||
|
||||
/* Call cleanup functions registered by optional components. */
|
||||
if (a->cleanup_archive_extract != NULL)
|
||||
@ -541,15 +558,23 @@ archive_read_close(struct archive *a)
|
||||
/*
|
||||
* 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
|
||||
archive_read_finish(struct archive *a)
|
||||
#endif
|
||||
archive_read_finish(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_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)
|
||||
archive_read_close(a);
|
||||
__archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY,
|
||||
"archive_read_finish");
|
||||
if (a->archive.state != ARCHIVE_STATE_CLOSED)
|
||||
r = archive_read_close(&a->archive);
|
||||
|
||||
/* Cleanup format-specific data. */
|
||||
slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
||||
@ -561,11 +586,14 @@ archive_read_finish(struct archive *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);
|
||||
archive_string_free(&a->archive.error_string);
|
||||
if (a->entry)
|
||||
archive_entry_free(a->entry);
|
||||
a->magic = 0;
|
||||
a->archive.magic = 0;
|
||||
free(a);
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
return (r);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -573,17 +601,19 @@ archive_read_finish(struct archive *a)
|
||||
* initialization functions.
|
||||
*/
|
||||
int
|
||||
__archive_read_register_format(struct archive *a,
|
||||
__archive_read_register_format(struct archive_read *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 (*bid)(struct archive_read *),
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
int (*cleanup)(struct archive_read *))
|
||||
{
|
||||
int i, number_slots;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "__archive_read_register_format");
|
||||
__archive_check_magic(&a->archive,
|
||||
ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"__archive_read_register_format");
|
||||
|
||||
number_slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
||||
|
||||
@ -610,13 +640,15 @@ __archive_read_register_format(struct archive *a,
|
||||
* initialization functions.
|
||||
*/
|
||||
int
|
||||
__archive_read_register_compression(struct archive *a,
|
||||
__archive_read_register_compression(struct archive_read *a,
|
||||
int (*bid)(const void *, size_t),
|
||||
int (*init)(struct archive *, const void *, size_t))
|
||||
int (*init)(struct archive_read *, const void *, size_t))
|
||||
{
|
||||
int i, number_slots;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "__archive_read_register_compression");
|
||||
__archive_check_magic(&a->archive,
|
||||
ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"__archive_read_register_compression");
|
||||
|
||||
number_slots = sizeof(a->decompressors) / sizeof(a->decompressors[0]);
|
||||
|
||||
|
@ -80,8 +80,6 @@ archive_read_data_into_fd(struct archive *a, int fd)
|
||||
total_written += bytes_written;
|
||||
p += bytes_written;
|
||||
size -= bytes_written;
|
||||
if (a->extract_progress != NULL)
|
||||
(*a->extract_progress)(a->extract_progress_user_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
188
lib/libarchive/archive_read_private.h
Normal file
188
lib/libarchive/archive_read_private.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_READ_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
struct archive_read {
|
||||
struct archive archive;
|
||||
|
||||
struct archive_entry *entry;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
struct {
|
||||
int (*bid)(const void *buff, size_t);
|
||||
int (*init)(struct archive_read *, 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_read *); /* Initialize. */
|
||||
int (*compression_finish)(struct archive_read *);
|
||||
int (*compression_write)(struct archive_read *, 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_read *,
|
||||
const void **, size_t request);
|
||||
ssize_t (*compression_read_consume)(struct archive_read *, size_t);
|
||||
off_t (*compression_skip)(struct archive_read *, off_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.
|
||||
*/
|
||||
|
||||
struct archive_format_descriptor {
|
||||
int (*bid)(struct archive_read *);
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *);
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *);
|
||||
int (*read_data_skip)(struct archive_read *);
|
||||
int (*cleanup)(struct archive_read *);
|
||||
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 guaranteed 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;
|
||||
int (*cleanup_archive_extract)(struct archive_read *);
|
||||
};
|
||||
|
||||
int __archive_read_register_format(struct archive_read *a,
|
||||
void *format_data,
|
||||
int (*bid)(struct archive_read *),
|
||||
int (*read_header)(struct archive_read *, struct archive_entry *),
|
||||
int (*read_data)(struct archive_read *, const void **, size_t *, off_t *),
|
||||
int (*read_data_skip)(struct archive_read *),
|
||||
int (*cleanup)(struct archive_read *));
|
||||
|
||||
int __archive_read_register_compression(struct archive_read *a,
|
||||
int (*bid)(const void *, size_t),
|
||||
int (*init)(struct archive_read *, const void *, size_t));
|
||||
|
||||
#endif
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#if HAVE_BZLIB_H
|
||||
struct private_data {
|
||||
@ -56,19 +57,20 @@ struct private_data {
|
||||
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 *);
|
||||
static int finish(struct archive_read *);
|
||||
static ssize_t read_ahead(struct archive_read *, const void **, size_t);
|
||||
static ssize_t read_consume(struct archive_read *, size_t);
|
||||
static int drive_decompressor(struct archive_read *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);
|
||||
static int init(struct archive_read *, const void *, size_t);
|
||||
|
||||
int
|
||||
archive_read_support_compression_bzip2(struct archive *a)
|
||||
archive_read_support_compression_bzip2(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
return (__archive_read_register_compression(a, bid, init));
|
||||
}
|
||||
|
||||
@ -152,19 +154,19 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
init(struct archive *a, const void *buff, size_t n)
|
||||
init(struct archive_read *a, const void *buff, size_t n)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
a->compression_name = "bzip2";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
a->archive.compression_name = "bzip2";
|
||||
|
||||
state = (struct private_data *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for %s decompression",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(state, 0, sizeof(*state));
|
||||
@ -176,9 +178,9 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
state->stream.avail_out = state->uncompressed_buffer_size;
|
||||
|
||||
if (state->uncompressed_buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate %s decompression buffers",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -215,25 +217,26 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
}
|
||||
|
||||
/* Library setup failed: Clean up. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing %s library", a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing %s library",
|
||||
a->archive.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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid setup parameter");
|
||||
break;
|
||||
case BZ_MEM_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
case BZ_CONFIG_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"mis-compiled library");
|
||||
break;
|
||||
@ -247,7 +250,7 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* as necessary.
|
||||
*/
|
||||
static ssize_t
|
||||
read_ahead(struct archive *a, const void **p, size_t min)
|
||||
read_ahead(struct archive_read *a, const void **p, size_t min)
|
||||
{
|
||||
struct private_data *state;
|
||||
int read_avail, was_avail, ret;
|
||||
@ -255,7 +258,7 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
state = (struct private_data *)a->compression_data;
|
||||
was_avail = -1;
|
||||
if (!a->client_reader) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No read callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -289,12 +292,12 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
* Mark a previously-returned block of data as read.
|
||||
*/
|
||||
static ssize_t
|
||||
read_consume(struct archive *a, size_t n)
|
||||
read_consume(struct archive_read *a, size_t n)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)a->compression_data;
|
||||
a->file_position += n;
|
||||
a->archive.file_position += n;
|
||||
state->read_next += n;
|
||||
if (state->read_next > state->stream.next_out)
|
||||
__archive_errx(1, "Request to consume too many "
|
||||
@ -306,7 +309,7 @@ read_consume(struct archive *a, size_t n)
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
finish(struct archive *a)
|
||||
finish(struct archive_read *a)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
@ -317,8 +320,9 @@ finish(struct archive *a)
|
||||
case BZ_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor", a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor",
|
||||
a->archive.compression_name);
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
@ -327,7 +331,7 @@ finish(struct archive *a)
|
||||
|
||||
a->compression_data = NULL;
|
||||
if (a->client_closer != NULL)
|
||||
(a->client_closer)(a, a->client_data);
|
||||
(a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -337,7 +341,7 @@ finish(struct archive *a)
|
||||
* blocks as necessary.
|
||||
*/
|
||||
static int
|
||||
drive_decompressor(struct archive *a, struct private_data *state)
|
||||
drive_decompressor(struct archive_read *a, struct private_data *state)
|
||||
{
|
||||
ssize_t ret;
|
||||
int decompressed, total_decompressed;
|
||||
@ -346,7 +350,7 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
total_decompressed = 0;
|
||||
for (;;) {
|
||||
if (state->stream.avail_in == 0) {
|
||||
ret = (a->client_reader)(a, a->client_data,
|
||||
ret = (a->client_reader)(&a->archive, a->client_data,
|
||||
(const void **)&state->stream.next_in);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
@ -356,12 +360,12 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
goto fatal;
|
||||
}
|
||||
if (ret == 0 && total_decompressed == 0) {
|
||||
archive_set_error(a, EIO,
|
||||
archive_set_error(&a->archive, EIO,
|
||||
"Premature end of %s compressed data",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
a->raw_position += ret;
|
||||
a->archive.raw_position += ret;
|
||||
state->stream.avail_in = ret;
|
||||
}
|
||||
|
||||
@ -393,8 +397,8 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
|
||||
/* Return a fatal error. */
|
||||
fatal:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC, "%s decompression failed",
|
||||
a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"%s decompression failed", a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/*
|
||||
* Because LZW decompression is pretty simple, I've just implemented
|
||||
@ -133,16 +134,17 @@ struct private_data {
|
||||
};
|
||||
|
||||
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);
|
||||
static int finish(struct archive_read *);
|
||||
static int init(struct archive_read *, const void *, size_t);
|
||||
static ssize_t read_ahead(struct archive_read *, const void **, size_t);
|
||||
static ssize_t read_consume(struct archive_read *, size_t);
|
||||
static int getbits(struct archive_read *, struct private_data *, int n);
|
||||
static int next_code(struct archive_read *a, struct private_data *state);
|
||||
|
||||
int
|
||||
archive_read_support_compression_compress(struct archive *a)
|
||||
archive_read_support_compression_compress(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
return (__archive_read_register_compression(a, bid, init));
|
||||
}
|
||||
|
||||
@ -187,13 +189,13 @@ bid(const void *buff, size_t len)
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
init(struct archive *a, const void *buff, size_t n)
|
||||
init(struct archive_read *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->archive.compression_code = ARCHIVE_COMPRESSION_COMPRESS;
|
||||
a->archive.compression_name = "compress (.Z)";
|
||||
|
||||
a->compression_read_ahead = read_ahead;
|
||||
a->compression_read_consume = read_consume;
|
||||
@ -202,9 +204,9 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
|
||||
state = (struct private_data *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for %s decompression",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(state, 0, sizeof(*state));
|
||||
@ -214,9 +216,9 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
state->uncompressed_buffer = malloc(state->uncompressed_buffer_size);
|
||||
|
||||
if (state->uncompressed_buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate %s decompression buffers",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
goto fatal;
|
||||
}
|
||||
|
||||
@ -235,7 +237,7 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Compress signature did not match.");
|
||||
goto fatal;
|
||||
}
|
||||
@ -270,7 +272,7 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* as necessary.
|
||||
*/
|
||||
static ssize_t
|
||||
read_ahead(struct archive *a, const void **p, size_t min)
|
||||
read_ahead(struct archive_read *a, const void **p, size_t min)
|
||||
{
|
||||
struct private_data *state;
|
||||
int read_avail, was_avail, ret;
|
||||
@ -278,7 +280,7 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
state = (struct private_data *)a->compression_data;
|
||||
was_avail = -1;
|
||||
if (!a->client_reader) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No read callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -325,12 +327,12 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
* Mark a previously-returned block of data as read.
|
||||
*/
|
||||
static ssize_t
|
||||
read_consume(struct archive *a, size_t n)
|
||||
read_consume(struct archive_read *a, size_t n)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)a->compression_data;
|
||||
a->file_position += n;
|
||||
a->archive.file_position += n;
|
||||
state->read_next += n;
|
||||
if (state->read_next > state->next_out)
|
||||
__archive_errx(1, "Request to consume too many "
|
||||
@ -342,7 +344,7 @@ read_consume(struct archive *a, size_t n)
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
finish(struct archive *a)
|
||||
finish(struct archive_read *a)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret = ARCHIVE_OK;
|
||||
@ -357,7 +359,7 @@ finish(struct archive *a)
|
||||
|
||||
a->compression_data = NULL;
|
||||
if (a->client_closer != NULL)
|
||||
ret = (a->client_closer)(a, a->client_data);
|
||||
ret = (a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -368,7 +370,7 @@ finish(struct archive *a)
|
||||
* format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise.
|
||||
*/
|
||||
static int
|
||||
next_code(struct archive *a, struct private_data *state)
|
||||
next_code(struct archive_read *a, struct private_data *state)
|
||||
{
|
||||
int code, newcode;
|
||||
|
||||
@ -412,7 +414,7 @@ next_code(struct archive *a, struct private_data *state)
|
||||
|
||||
if (code > state->free_ent) {
|
||||
/* An invalid code is a fatal error. */
|
||||
archive_set_error(a, -1, "Invalid compressed data");
|
||||
archive_set_error(&a->archive, -1, "Invalid compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@ -456,7 +458,7 @@ next_code(struct archive *a, struct private_data *state)
|
||||
* -1 indicates end of available data.
|
||||
*/
|
||||
static int
|
||||
getbits(struct archive *a, struct private_data *state, int n)
|
||||
getbits(struct archive_read *a, struct private_data *state, int n)
|
||||
{
|
||||
int code, ret;
|
||||
static const int mask[] = {
|
||||
@ -467,13 +469,13 @@ getbits(struct archive *a, struct private_data *state, int n)
|
||||
|
||||
while (state->bits_avail < n) {
|
||||
if (state->avail_in <= 0) {
|
||||
ret = (a->client_reader)(a, a->client_data,
|
||||
ret = (a->client_reader)(&a->archive, a->client_data,
|
||||
(const void **)&state->next_in);
|
||||
if (ret < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (ret == 0)
|
||||
return (ARCHIVE_EOF);
|
||||
a->raw_position += ret;
|
||||
a->archive.raw_position += ret;
|
||||
state->avail_in = ret;
|
||||
}
|
||||
state->bit_buffer |= *state->next_in++ << state->bits_avail;
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
struct private_data {
|
||||
@ -58,19 +59,20 @@ struct private_data {
|
||||
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 *);
|
||||
static int finish(struct archive_read *);
|
||||
static ssize_t read_ahead(struct archive_read *, const void **, size_t);
|
||||
static ssize_t read_consume(struct archive_read *, size_t);
|
||||
static int drive_decompressor(struct archive_read *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);
|
||||
static int init(struct archive_read *, const void *, size_t);
|
||||
|
||||
int
|
||||
archive_read_support_compression_gzip(struct archive *a)
|
||||
archive_read_support_compression_gzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
return (__archive_read_register_compression(a, bid, init));
|
||||
}
|
||||
|
||||
@ -135,7 +137,7 @@ bid(const void *buff, size_t len)
|
||||
* archives and emit a useful message.
|
||||
*/
|
||||
static int
|
||||
init(struct archive *a, const void *buff, size_t n)
|
||||
init(struct archive_read *a, const void *buff, size_t n)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)buff; /* UNUSED */
|
||||
@ -153,19 +155,19 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
init(struct archive *a, const void *buff, size_t n)
|
||||
init(struct archive_read *a, const void *buff, size_t n)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_GZIP;
|
||||
a->compression_name = "gzip";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_GZIP;
|
||||
a->archive.compression_name = "gzip";
|
||||
|
||||
state = (struct private_data *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for %s decompression",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(state, 0, sizeof(*state));
|
||||
@ -180,9 +182,9 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
state->stream.avail_out = state->uncompressed_buffer_size;
|
||||
|
||||
if (state->uncompressed_buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate %s decompression buffers",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -220,25 +222,26 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
}
|
||||
|
||||
/* Library setup failed: Clean up. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing %s library", a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing %s library",
|
||||
a->archive.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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid setup parameter");
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid library version");
|
||||
break;
|
||||
@ -252,7 +255,7 @@ init(struct archive *a, const void *buff, size_t n)
|
||||
* as necessary.
|
||||
*/
|
||||
static ssize_t
|
||||
read_ahead(struct archive *a, const void **p, size_t min)
|
||||
read_ahead(struct archive_read *a, const void **p, size_t min)
|
||||
{
|
||||
struct private_data *state;
|
||||
int read_avail, was_avail, ret;
|
||||
@ -260,7 +263,7 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
state = (struct private_data *)a->compression_data;
|
||||
was_avail = -1;
|
||||
if (!a->client_reader) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No read callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -294,12 +297,12 @@ read_ahead(struct archive *a, const void **p, size_t min)
|
||||
* Mark a previously-returned block of data as read.
|
||||
*/
|
||||
static ssize_t
|
||||
read_consume(struct archive *a, size_t n)
|
||||
read_consume(struct archive_read *a, size_t n)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)a->compression_data;
|
||||
a->file_position += n;
|
||||
a->archive.file_position += n;
|
||||
state->read_next += n;
|
||||
if (state->read_next > state->stream.next_out)
|
||||
__archive_errx(1, "Request to consume too many "
|
||||
@ -311,7 +314,7 @@ read_consume(struct archive *a, size_t n)
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
finish(struct archive *a)
|
||||
finish(struct archive_read *a)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
@ -322,8 +325,9 @@ finish(struct archive *a)
|
||||
case Z_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor", a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor",
|
||||
a->archive.compression_name);
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
@ -332,7 +336,7 @@ finish(struct archive *a)
|
||||
|
||||
a->compression_data = NULL;
|
||||
if (a->client_closer != NULL)
|
||||
(a->client_closer)(a, a->client_data);
|
||||
(a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -342,7 +346,7 @@ finish(struct archive *a)
|
||||
* blocks as necessary.
|
||||
*/
|
||||
static int
|
||||
drive_decompressor(struct archive *a, struct private_data *state)
|
||||
drive_decompressor(struct archive_read *a, struct private_data *state)
|
||||
{
|
||||
ssize_t ret;
|
||||
int decompressed, total_decompressed;
|
||||
@ -356,7 +360,7 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
total_decompressed = 0;
|
||||
for (;;) {
|
||||
if (state->stream.avail_in == 0) {
|
||||
ret = (a->client_reader)(a, a->client_data,
|
||||
ret = (a->client_reader)(&a->archive, a->client_data,
|
||||
(const void **)&state->stream.next_in);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
@ -366,12 +370,12 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
goto fatal;
|
||||
}
|
||||
if (ret == 0 && total_decompressed == 0) {
|
||||
archive_set_error(a, EIO,
|
||||
archive_set_error(&a->archive, EIO,
|
||||
"Premature end of %s compressed data",
|
||||
a->compression_name);
|
||||
a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
a->raw_position += ret;
|
||||
a->archive.raw_position += ret;
|
||||
state->stream.avail_in = ret;
|
||||
}
|
||||
|
||||
@ -520,7 +524,7 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
return (ARCHIVE_OK);
|
||||
default:
|
||||
/* Any other return value is an error. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"gzip decompression failed (%s)",
|
||||
state->stream.msg);
|
||||
goto fatal;
|
||||
@ -531,8 +535,8 @@ drive_decompressor(struct archive *a, struct private_data *state)
|
||||
|
||||
/* Return a fatal error. */
|
||||
fatal:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC, "%s decompression failed",
|
||||
a->compression_name);
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"%s decompression failed", a->archive.compression_name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
@ -45,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct archive_decompress_none {
|
||||
char *buffer;
|
||||
@ -75,18 +75,19 @@ struct archive_decompress_none {
|
||||
#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 *,
|
||||
static int archive_decompressor_none_finish(struct archive_read *);
|
||||
static int archive_decompressor_none_init(struct archive_read *,
|
||||
const void *, size_t);
|
||||
static ssize_t archive_decompressor_none_read_ahead(struct archive *,
|
||||
static ssize_t archive_decompressor_none_read_ahead(struct archive_read *,
|
||||
const void **, size_t);
|
||||
static ssize_t archive_decompressor_none_read_consume(struct archive *,
|
||||
static ssize_t archive_decompressor_none_read_consume(struct archive_read *,
|
||||
size_t);
|
||||
static off_t archive_decompressor_none_skip(struct archive *, off_t);
|
||||
static off_t archive_decompressor_none_skip(struct archive_read *, off_t);
|
||||
|
||||
int
|
||||
archive_read_support_compression_none(struct archive *a)
|
||||
archive_read_support_compression_none(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
return (__archive_read_register_compression(a,
|
||||
archive_decompressor_none_bid,
|
||||
archive_decompressor_none_init));
|
||||
@ -105,16 +106,16 @@ archive_decompressor_none_bid(const void *buff, size_t len)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_decompressor_none_init(struct archive *a, const void *buff, size_t n)
|
||||
archive_decompressor_none_init(struct archive_read *a, const void *buff, size_t n)
|
||||
{
|
||||
struct archive_decompress_none *state;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_NONE;
|
||||
a->compression_name = "none";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_NONE;
|
||||
a->archive.compression_name = "none";
|
||||
|
||||
state = (struct archive_decompress_none *)malloc(sizeof(*state));
|
||||
if (!state) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate input data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate input data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(state, 0, sizeof(*state));
|
||||
@ -124,7 +125,7 @@ archive_decompressor_none_init(struct archive *a, const void *buff, size_t n)
|
||||
state->next = state->buffer;
|
||||
if (state->buffer == NULL) {
|
||||
free(state);
|
||||
archive_set_error(a, ENOMEM, "Can't allocate input buffer");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate input buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@ -149,7 +150,7 @@ archive_decompressor_none_init(struct archive *a, const void *buff, size_t n)
|
||||
* buffer to combine reads.
|
||||
*/
|
||||
static ssize_t
|
||||
archive_decompressor_none_read_ahead(struct archive *a, const void **buff,
|
||||
archive_decompressor_none_read_ahead(struct archive_read *a, const void **buff,
|
||||
size_t min)
|
||||
{
|
||||
struct archive_decompress_none *state;
|
||||
@ -217,7 +218,8 @@ archive_decompressor_none_read_ahead(struct archive *a, const void **buff,
|
||||
* char ** should be compatible, but they
|
||||
* aren't, hence the cast.
|
||||
*/
|
||||
bytes_read = (a->client_reader)(a, a->client_data,
|
||||
bytes_read = (a->client_reader)(&a->archive,
|
||||
a->client_data,
|
||||
(const void **)&state->client_buff);
|
||||
if (bytes_read < 0) { /* Read error. */
|
||||
state->client_total = state->client_avail = 0;
|
||||
@ -231,7 +233,7 @@ archive_decompressor_none_read_ahead(struct archive *a, const void **buff,
|
||||
state->end_of_file = 1;
|
||||
break;
|
||||
}
|
||||
a->raw_position += bytes_read;
|
||||
a->archive.raw_position += bytes_read;
|
||||
state->client_total = bytes_read;
|
||||
state->client_avail = state->client_total;
|
||||
state->client_next = state->client_buff;
|
||||
@ -248,7 +250,7 @@ archive_decompressor_none_read_ahead(struct archive *a, const void **buff,
|
||||
* request.
|
||||
*/
|
||||
static ssize_t
|
||||
archive_decompressor_none_read_consume(struct archive *a, size_t request)
|
||||
archive_decompressor_none_read_consume(struct archive_read *a, size_t request)
|
||||
{
|
||||
struct archive_decompress_none *state;
|
||||
|
||||
@ -262,7 +264,7 @@ archive_decompressor_none_read_consume(struct archive *a, size_t request)
|
||||
state->client_next += request;
|
||||
state->client_avail -= request;
|
||||
}
|
||||
a->file_position += request;
|
||||
a->archive.file_position += request;
|
||||
return (request);
|
||||
}
|
||||
|
||||
@ -272,7 +274,7 @@ archive_decompressor_none_read_consume(struct archive *a, size_t request)
|
||||
* read_ahead, which does not guarantee a minimum count.
|
||||
*/
|
||||
static off_t
|
||||
archive_decompressor_none_skip(struct archive *a, off_t request)
|
||||
archive_decompressor_none_skip(struct archive_read *a, off_t request)
|
||||
{
|
||||
struct archive_decompress_none *state;
|
||||
off_t bytes_skipped, total_bytes_skipped = 0;
|
||||
@ -306,8 +308,8 @@ archive_decompressor_none_skip(struct archive *a, off_t request)
|
||||
#else
|
||||
if (a->client_skipper != NULL) {
|
||||
#endif
|
||||
bytes_skipped = (a->client_skipper)(a, a->client_data,
|
||||
request);
|
||||
bytes_skipped = (a->client_skipper)(&a->archive,
|
||||
a->client_data, request);
|
||||
if (bytes_skipped < 0) { /* error */
|
||||
state->client_total = state->client_avail = 0;
|
||||
state->client_next = state->client_buff = NULL;
|
||||
@ -315,10 +317,10 @@ archive_decompressor_none_skip(struct archive *a, off_t request)
|
||||
return (bytes_skipped);
|
||||
}
|
||||
total_bytes_skipped += bytes_skipped;
|
||||
a->file_position += bytes_skipped;
|
||||
a->archive.file_position += bytes_skipped;
|
||||
request -= bytes_skipped;
|
||||
state->client_next = state->client_buff;
|
||||
a->raw_position += bytes_skipped;
|
||||
a->archive.raw_position += bytes_skipped;
|
||||
state->client_avail = state->client_total = 0;
|
||||
}
|
||||
/*
|
||||
@ -336,23 +338,21 @@ archive_decompressor_none_skip(struct archive *a, off_t request)
|
||||
return (bytes_read);
|
||||
if (bytes_read == 0) {
|
||||
/* We hit EOF before we satisfied the skip request. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated input file (need to skip %jd bytes)",
|
||||
(intmax_t)request);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
assert(bytes_read >= 0); /* precondition for cast below */
|
||||
min = (size_t)(minimum(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)
|
||||
archive_decompressor_none_finish(struct archive_read *a)
|
||||
{
|
||||
struct archive_decompress_none *state;
|
||||
|
||||
@ -361,6 +361,6 @@ archive_decompressor_none_finish(struct archive *a)
|
||||
free(state);
|
||||
a->compression_data = NULL;
|
||||
if (a->client_closer != NULL)
|
||||
return ((a->client_closer)(a, a->client_data));
|
||||
return ((a->client_closer)(&a->archive, a->client_data));
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct cpio_bin_header {
|
||||
unsigned char c_magic[2];
|
||||
@ -108,7 +109,7 @@ struct links_entry {
|
||||
#define CPIO_MAGIC 0x13141516
|
||||
struct cpio {
|
||||
int magic;
|
||||
int (*read_header)(struct archive *, struct cpio *,
|
||||
int (*read_header)(struct archive_read *, struct cpio *,
|
||||
struct stat *, size_t *, size_t *);
|
||||
struct links_entry *links_head;
|
||||
struct archive_string entry_name;
|
||||
@ -120,34 +121,35 @@ struct cpio {
|
||||
|
||||
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 *,
|
||||
static int archive_read_format_cpio_bid(struct archive_read *);
|
||||
static int archive_read_format_cpio_cleanup(struct archive_read *);
|
||||
static int archive_read_format_cpio_read_data(struct archive_read *,
|
||||
const void **, size_t *, off_t *);
|
||||
static int archive_read_format_cpio_read_header(struct archive *,
|
||||
static int archive_read_format_cpio_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int be4(const unsigned char *);
|
||||
static int header_bin_be(struct archive *, struct cpio *, struct stat *,
|
||||
static int header_bin_be(struct archive_read *, struct cpio *, struct stat *,
|
||||
size_t *, size_t *);
|
||||
static int header_bin_le(struct archive *, struct cpio *, struct stat *,
|
||||
static int header_bin_le(struct archive_read *, struct cpio *, struct stat *,
|
||||
size_t *, size_t *);
|
||||
static int header_newc(struct archive *, struct cpio *, struct stat *,
|
||||
static int header_newc(struct archive_read *, struct cpio *, struct stat *,
|
||||
size_t *, size_t *);
|
||||
static int header_odc(struct archive *, struct cpio *, struct stat *,
|
||||
static int header_odc(struct archive_read *, 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)
|
||||
archive_read_support_format_cpio(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct cpio *cpio;
|
||||
int r;
|
||||
|
||||
cpio = (struct cpio *)malloc(sizeof(*cpio));
|
||||
if (cpio == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate cpio data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
@ -168,7 +170,7 @@ archive_read_support_format_cpio(struct archive *a)
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_cpio_bid(struct archive *a)
|
||||
archive_read_format_cpio_bid(struct archive_read *a)
|
||||
{
|
||||
int bid, bytes_read;
|
||||
const void *h;
|
||||
@ -227,7 +229,7 @@ archive_read_format_cpio_bid(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_cpio_read_header(struct archive *a,
|
||||
archive_read_format_cpio_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct stat st;
|
||||
@ -274,7 +276,7 @@ archive_read_format_cpio_read_header(struct archive *a,
|
||||
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
|
||||
if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
|
||||
/* TODO: Store file location of start of block. */
|
||||
archive_set_error(a, 0, NULL);
|
||||
archive_set_error(&a->archive, 0, NULL);
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
@ -285,7 +287,7 @@ archive_read_format_cpio_read_header(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_cpio_read_data(struct archive *a,
|
||||
archive_read_format_cpio_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
@ -322,7 +324,7 @@ archive_read_format_cpio_read_data(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
header_newc(struct archive_read *a, struct cpio *cpio, struct stat *st,
|
||||
size_t *namelength, size_t *name_pad)
|
||||
{
|
||||
const void *h;
|
||||
@ -339,11 +341,11 @@ header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
header = (const struct cpio_newc_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)";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
|
||||
a->archive.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)";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
|
||||
a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)";
|
||||
} else {
|
||||
/* TODO: Abort here? */
|
||||
}
|
||||
@ -379,15 +381,15 @@ header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
}
|
||||
|
||||
static int
|
||||
header_odc(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
header_odc(struct archive_read *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";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
|
||||
a->archive.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));
|
||||
@ -423,15 +425,15 @@ header_odc(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
}
|
||||
|
||||
static int
|
||||
header_bin_le(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
header_bin_le(struct archive_read *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)";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE;
|
||||
a->archive.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));
|
||||
@ -460,15 +462,15 @@ header_bin_le(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
}
|
||||
|
||||
static int
|
||||
header_bin_be(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
header_bin_be(struct archive_read *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)";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
|
||||
a->archive.archive_format_name = "cpio (big-endian binary)";
|
||||
|
||||
/* Read fixed-size portion of header. */
|
||||
bytes = (a->compression_read_ahead)(a, &h,
|
||||
@ -497,7 +499,7 @@ header_bin_be(struct archive *a, struct cpio *cpio, struct stat *st,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_cpio_cleanup(struct archive *a)
|
||||
archive_read_format_cpio_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
|
||||
|
@ -29,15 +29,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
static int archive_read_format_empty_bid(struct archive *);
|
||||
static int archive_read_format_empty_read_data(struct archive *,
|
||||
static int archive_read_format_empty_bid(struct archive_read *);
|
||||
static int archive_read_format_empty_read_data(struct archive_read *,
|
||||
const void **, size_t *, off_t *);
|
||||
static int archive_read_format_empty_read_header(struct archive *,
|
||||
static int archive_read_format_empty_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
int
|
||||
archive_read_support_format_empty(struct archive *a)
|
||||
archive_read_support_format_empty(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
@ -53,7 +55,7 @@ archive_read_support_format_empty(struct archive *a)
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_empty_bid(struct archive *a)
|
||||
archive_read_format_empty_bid(struct archive_read *a)
|
||||
{
|
||||
int bytes_read;
|
||||
const void *h;
|
||||
@ -65,20 +67,20 @@ archive_read_format_empty_bid(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_empty_read_header(struct archive *a,
|
||||
archive_read_format_empty_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)entry; /* UNUSED */
|
||||
|
||||
a->archive_format = ARCHIVE_FORMAT_EMPTY;
|
||||
a->archive_format_name = "Empty file";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_EMPTY;
|
||||
a->archive.archive_format_name = "Empty file";
|
||||
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_empty_read_data(struct archive *a,
|
||||
archive_read_format_empty_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
/*
|
||||
@ -222,12 +223,12 @@ struct iso9660 {
|
||||
};
|
||||
|
||||
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 *,
|
||||
static int archive_read_format_iso9660_bid(struct archive_read *);
|
||||
static int archive_read_format_iso9660_cleanup(struct archive_read *);
|
||||
static int archive_read_format_iso9660_read_data(struct archive_read *,
|
||||
const void **, size_t *, off_t *);
|
||||
static int archive_read_format_iso9660_read_data_skip(struct archive *);
|
||||
static int archive_read_format_iso9660_read_header(struct archive *,
|
||||
static int archive_read_format_iso9660_read_data_skip(struct archive_read *);
|
||||
static int archive_read_format_iso9660_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static const char *build_pathname(struct archive_string *, struct file_info *);
|
||||
static void dump_isodirrec(FILE *, const unsigned char *isodirrec);
|
||||
@ -236,7 +237,7 @@ static time_t isodate17(const unsigned char *);
|
||||
static time_t isodate7(const unsigned char *);
|
||||
static int isPVD(struct iso9660 *, const unsigned char *);
|
||||
static struct file_info *next_entry(struct iso9660 *);
|
||||
static int next_entry_seek(struct archive *a, struct iso9660 *iso9660,
|
||||
static int next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
|
||||
struct file_info **pfile);
|
||||
static struct file_info *
|
||||
parse_file_info(struct iso9660 *iso9660,
|
||||
@ -248,14 +249,15 @@ static void release_file(struct iso9660 *, struct file_info *);
|
||||
static unsigned toi(const void *p, int n);
|
||||
|
||||
int
|
||||
archive_read_support_format_iso9660(struct archive *a)
|
||||
archive_read_support_format_iso9660(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct iso9660 *iso9660;
|
||||
int r;
|
||||
|
||||
iso9660 = (struct iso9660 *)malloc(sizeof(*iso9660));
|
||||
if (iso9660 == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate iso9660 data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate iso9660 data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(iso9660, 0, sizeof(*iso9660));
|
||||
@ -279,7 +281,7 @@ archive_read_support_format_iso9660(struct archive *a)
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_bid(struct archive *a)
|
||||
archive_read_format_iso9660_bid(struct archive_read *a)
|
||||
{
|
||||
struct iso9660 *iso9660;
|
||||
ssize_t bytes_read;
|
||||
@ -338,7 +340,7 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_read_header(struct archive *a,
|
||||
archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct stat st;
|
||||
@ -349,9 +351,9 @@ archive_read_format_iso9660_read_header(struct archive *a,
|
||||
|
||||
iso9660 = (struct iso9660 *)*(a->pformat_data);
|
||||
|
||||
if (!a->archive_format) {
|
||||
a->archive_format = ARCHIVE_FORMAT_ISO9660;
|
||||
a->archive_format_name = "ISO9660";
|
||||
if (!a->archive.archive_format) {
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
|
||||
a->archive.archive_format_name = "ISO9660";
|
||||
}
|
||||
|
||||
/* Get the next entry that appears after the current offset. */
|
||||
@ -397,7 +399,7 @@ archive_read_format_iso9660_read_header(struct archive *a,
|
||||
/* 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order file");
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
@ -419,7 +421,7 @@ archive_read_format_iso9660_read_header(struct archive *a,
|
||||
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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to read full block when scanning ISO9660 directory list");
|
||||
release_file(iso9660, file);
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -445,9 +447,9 @@ archive_read_format_iso9660_read_header(struct archive *a,
|
||||
child = parse_file_info(iso9660, file, p);
|
||||
add_entry(iso9660, child);
|
||||
if (iso9660->seenRockridge) {
|
||||
a->archive_format =
|
||||
a->archive.archive_format =
|
||||
ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
|
||||
a->archive_format_name =
|
||||
a->archive.archive_format_name =
|
||||
"ISO9660 with Rockridge extensions";
|
||||
}
|
||||
}
|
||||
@ -459,7 +461,7 @@ archive_read_format_iso9660_read_header(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_read_data_skip(struct archive *a)
|
||||
archive_read_format_iso9660_read_data_skip(struct archive_read *a)
|
||||
{
|
||||
/* Because read_next_header always does an explicit skip
|
||||
* to the next entry, we don't need to do anything here. */
|
||||
@ -468,7 +470,7 @@ archive_read_format_iso9660_read_data_skip(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_read_data(struct archive *a,
|
||||
archive_read_format_iso9660_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
@ -484,7 +486,7 @@ archive_read_format_iso9660_read_data(struct archive *a,
|
||||
|
||||
bytes_read = (a->compression_read_ahead)(a, buff, 1);
|
||||
if (bytes_read == 0)
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated input file");
|
||||
if (bytes_read <= 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -500,7 +502,7 @@ archive_read_format_iso9660_read_data(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_iso9660_cleanup(struct archive *a)
|
||||
archive_read_format_iso9660_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct iso9660 *iso9660;
|
||||
struct file_info *file;
|
||||
@ -889,7 +891,7 @@ release_file(struct iso9660 *iso9660, struct file_info *file)
|
||||
}
|
||||
|
||||
static int
|
||||
next_entry_seek(struct archive *a, struct iso9660 *iso9660,
|
||||
next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
|
||||
struct file_info **pfile)
|
||||
{
|
||||
struct file_info *file;
|
||||
|
@ -83,6 +83,7 @@ static size_t wcslen(const wchar_t *s)
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/*
|
||||
* Layout of POSIX 'ustar' tar header.
|
||||
@ -174,50 +175,50 @@ struct tar {
|
||||
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 *,
|
||||
static int gnu_read_sparse_data(struct archive_read *, struct tar *,
|
||||
const struct archive_entry_header_gnutar *header);
|
||||
static void gnu_parse_sparse_data(struct archive *, struct tar *,
|
||||
static void gnu_parse_sparse_data(struct archive_read *, struct tar *,
|
||||
const struct gnu_sparse *sparse, int length);
|
||||
static int header_Solaris_ACL(struct archive *, struct tar *,
|
||||
static int header_Solaris_ACL(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *);
|
||||
static int header_common(struct archive *, struct tar *,
|
||||
static int header_common(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *);
|
||||
static int header_old_tar(struct archive *, struct tar *,
|
||||
static int header_old_tar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *);
|
||||
static int header_pax_extensions(struct archive *, struct tar *,
|
||||
static int header_pax_extensions(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *);
|
||||
static int header_pax_global(struct archive *, struct tar *,
|
||||
static int header_pax_global(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *h);
|
||||
static int header_longlink(struct archive *, struct tar *,
|
||||
static int header_longlink(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *h);
|
||||
static int header_longname(struct archive *, struct tar *,
|
||||
static int header_longname(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *h);
|
||||
static int header_volume(struct archive *, struct tar *,
|
||||
static int header_volume(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *h);
|
||||
static int header_ustar(struct archive *, struct tar *,
|
||||
static int header_ustar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *, const void *h);
|
||||
static int header_gnutar(struct archive *, struct tar *,
|
||||
static int header_gnutar(struct archive_read *, 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,
|
||||
static int archive_read_format_tar_bid(struct archive_read *);
|
||||
static int archive_read_format_tar_cleanup(struct archive_read *);
|
||||
static int archive_read_format_tar_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset);
|
||||
static int archive_read_format_tar_skip(struct archive *a);
|
||||
static int archive_read_format_tar_read_header(struct archive *,
|
||||
static int archive_read_format_tar_skip(struct archive_read *a);
|
||||
static int archive_read_format_tar_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int checksum(struct archive *, const void *);
|
||||
static int checksum(struct archive_read *, 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 *,
|
||||
static int pax_header(struct archive_read *, 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 *,
|
||||
static int read_body_to_string(struct archive_read *, 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 *,
|
||||
static int tar_read_header(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, struct stat *);
|
||||
static int tohex(int c);
|
||||
static char *url_decode(const char *);
|
||||
@ -254,14 +255,16 @@ archive_read_support_format_gnutar(struct archive *a)
|
||||
|
||||
|
||||
int
|
||||
archive_read_support_format_tar(struct archive *a)
|
||||
archive_read_support_format_tar(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct tar *tar;
|
||||
int r;
|
||||
|
||||
tar = (struct tar *)malloc(sizeof(*tar));
|
||||
if (tar == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate tar data");
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate tar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(tar, 0, sizeof(*tar));
|
||||
@ -279,7 +282,7 @@ archive_read_support_format_tar(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_tar_cleanup(struct archive *a)
|
||||
archive_read_format_tar_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct tar *tar;
|
||||
|
||||
@ -300,7 +303,7 @@ archive_read_format_tar_cleanup(struct archive *a)
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_tar_bid(struct archive *a)
|
||||
archive_read_format_tar_bid(struct archive_read *a)
|
||||
{
|
||||
int bid;
|
||||
ssize_t bytes_read;
|
||||
@ -311,8 +314,8 @@ archive_read_format_tar_bid(struct archive *a)
|
||||
* 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) !=
|
||||
if (a->archive.archive_format != 0 &&
|
||||
(a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) !=
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
return (0);
|
||||
bid = 0;
|
||||
@ -321,7 +324,7 @@ archive_read_format_tar_bid(struct archive *a)
|
||||
* If we're already reading a tar format, start the bid at 1 as
|
||||
* a failsafe.
|
||||
*/
|
||||
if ((a->archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
bid++;
|
||||
|
||||
@ -345,7 +348,7 @@ archive_read_format_tar_bid(struct archive *a)
|
||||
* If we already know this is a tar archive,
|
||||
* then we have a problem.
|
||||
*/
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated tar archive");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -353,7 +356,7 @@ archive_read_format_tar_bid(struct archive *a)
|
||||
/* If it's an end-of-archive mark, we can handle it. */
|
||||
if ((*(const char *)h) == 0 && archive_block_is_null((const unsigned char *)h)) {
|
||||
/* If it's a known tar file, end-of-archive is definite. */
|
||||
if ((a->archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
if ((a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) ==
|
||||
ARCHIVE_FORMAT_TAR)
|
||||
return (512);
|
||||
/* Empty archive? */
|
||||
@ -412,7 +415,7 @@ archive_read_format_tar_bid(struct archive *a)
|
||||
* tar_read_header() function below.
|
||||
*/
|
||||
static int
|
||||
archive_read_format_tar_read_header(struct archive *a,
|
||||
archive_read_format_tar_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
/*
|
||||
@ -472,7 +475,7 @@ archive_read_format_tar_read_header(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_tar_read_data(struct archive *a,
|
||||
archive_read_format_tar_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
@ -497,7 +500,7 @@ archive_read_format_tar_read_data(struct archive *a,
|
||||
if (tar->entry_bytes_remaining > 0) {
|
||||
bytes_read = (a->compression_read_ahead)(a, buff, 1);
|
||||
if (bytes_read == 0) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated tar archive");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -538,7 +541,7 @@ archive_read_format_tar_read_data(struct archive *a,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_tar_skip(struct archive *a)
|
||||
archive_read_format_tar_skip(struct archive_read *a)
|
||||
{
|
||||
off_t bytes_skipped;
|
||||
struct tar* tar;
|
||||
@ -584,7 +587,7 @@ archive_read_format_tar_skip(struct archive *a)
|
||||
* with a single entry.
|
||||
*/
|
||||
static int
|
||||
tar_read_header(struct archive *a, struct tar *tar,
|
||||
tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st)
|
||||
{
|
||||
ssize_t bytes;
|
||||
@ -610,7 +613,7 @@ tar_read_header(struct archive *a, struct tar *tar,
|
||||
bytes = (a->compression_read_ahead)(a, &h, 512);
|
||||
if (bytes > 0)
|
||||
(a->compression_read_consume)(a, bytes);
|
||||
archive_set_error(a, 0, NULL);
|
||||
archive_set_error(&a->archive, 0, NULL);
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
@ -622,12 +625,12 @@ tar_read_header(struct archive *a, struct tar *tar,
|
||||
* TODO: Improve this by implementing a real header scan.
|
||||
*/
|
||||
if (!checksum(a, h)) {
|
||||
archive_set_error(a, EINVAL, "Damaged tar archive");
|
||||
archive_set_error(&a->archive, 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");
|
||||
archive_set_error(&a->archive, EINVAL, "Too many special headers");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
@ -635,13 +638,13 @@ tar_read_header(struct archive *a, struct tar *tar,
|
||||
header = (const struct archive_entry_header_ustar *)h;
|
||||
switch(header->typeflag[0]) {
|
||||
case 'A': /* Solaris tar ACL */
|
||||
a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive_format_name = "Solaris tar";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive.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";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive.archive_format_name = "POSIX pax interchange format";
|
||||
err = header_pax_global(a, tar, entry, st, h);
|
||||
break;
|
||||
case 'K': /* Long link name (GNU tar, others) */
|
||||
@ -654,30 +657,30 @@ tar_read_header(struct archive *a, struct tar *tar,
|
||||
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 =
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive.archive_format_name =
|
||||
"POSIX pax interchange format (Sun variant)";
|
||||
err = header_pax_extensions(a, tar, entry, 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";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive.archive_format_name = "POSIX pax interchange format";
|
||||
err = header_pax_extensions(a, tar, entry, 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";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
||||
a->archive.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";
|
||||
if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) {
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
|
||||
a->archive.archive_format_name = "POSIX ustar format";
|
||||
}
|
||||
err = header_ustar(a, tar, entry, st, h);
|
||||
} else {
|
||||
a->archive_format = ARCHIVE_FORMAT_TAR;
|
||||
a->archive_format_name = "tar (non-POSIX)";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR;
|
||||
a->archive.archive_format_name = "tar (non-POSIX)";
|
||||
err = header_old_tar(a, tar, entry, st, h);
|
||||
}
|
||||
}
|
||||
@ -689,7 +692,7 @@ tar_read_header(struct archive *a, struct tar *tar,
|
||||
* Return true if block checksum is correct.
|
||||
*/
|
||||
static int
|
||||
checksum(struct archive *a, const void *h)
|
||||
checksum(struct archive_read *a, const void *h)
|
||||
{
|
||||
const unsigned char *bytes;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
@ -750,7 +753,7 @@ archive_block_is_null(const unsigned char *p)
|
||||
* Interpret 'A' Solaris ACL header
|
||||
*/
|
||||
static int
|
||||
header_Solaris_ACL(struct archive *a, struct tar *tar,
|
||||
header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
int err, err2;
|
||||
@ -786,7 +789,7 @@ header_Solaris_ACL(struct archive *a, struct tar *tar,
|
||||
* Interpret 'K' long linkname header.
|
||||
*/
|
||||
static int
|
||||
header_longlink(struct archive *a, struct tar *tar,
|
||||
header_longlink(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
int err, err2;
|
||||
@ -804,7 +807,7 @@ header_longlink(struct archive *a, struct tar *tar,
|
||||
* Interpret 'L' long filename header.
|
||||
*/
|
||||
static int
|
||||
header_longname(struct archive *a, struct tar *tar,
|
||||
header_longname(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
int err, err2;
|
||||
@ -822,7 +825,7 @@ header_longname(struct archive *a, struct tar *tar,
|
||||
* Interpret 'V' GNU tar volume header.
|
||||
*/
|
||||
static int
|
||||
header_volume(struct archive *a, struct tar *tar,
|
||||
header_volume(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
(void)h;
|
||||
@ -835,7 +838,7 @@ header_volume(struct archive *a, struct tar *tar,
|
||||
* Read body of an archive entry into an archive_string object.
|
||||
*/
|
||||
static int
|
||||
read_body_to_string(struct archive *a, struct tar *tar,
|
||||
read_body_to_string(struct archive_read *a, struct tar *tar,
|
||||
struct archive_string *as, const void *h)
|
||||
{
|
||||
off_t size, padded_size;
|
||||
@ -882,7 +885,7 @@ read_body_to_string(struct archive *a, struct tar *tar,
|
||||
* common parsing into one place.
|
||||
*/
|
||||
static int
|
||||
header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
header_common(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
struct stat *st, const void *h)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
@ -946,7 +949,7 @@ header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
* itself an uncompressed tar archive.
|
||||
*/
|
||||
if (st->st_size > 0 &&
|
||||
a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
|
||||
a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
|
||||
archive_read_format_tar_bid(a) > 50)
|
||||
st->st_size = 0;
|
||||
break;
|
||||
@ -1014,7 +1017,7 @@ header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
* Parse out header elements for "old-style" tar archives.
|
||||
*/
|
||||
static int
|
||||
header_old_tar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
header_old_tar(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
struct stat *st, const void *h)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
@ -1036,7 +1039,7 @@ header_old_tar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
* Parse a file header for a pax extended archive entry.
|
||||
*/
|
||||
static int
|
||||
header_pax_global(struct archive *a, struct tar *tar,
|
||||
header_pax_global(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
int err, err2;
|
||||
@ -1047,7 +1050,7 @@ header_pax_global(struct archive *a, struct tar *tar,
|
||||
}
|
||||
|
||||
static int
|
||||
header_pax_extensions(struct archive *a, struct tar *tar,
|
||||
header_pax_extensions(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, struct stat *st, const void *h)
|
||||
{
|
||||
int err, err2;
|
||||
@ -1080,7 +1083,7 @@ header_pax_extensions(struct archive *a, struct tar *tar,
|
||||
* handles "pax" or "extended ustar" entries.
|
||||
*/
|
||||
static int
|
||||
header_ustar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
struct stat *st, const void *h)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
@ -1132,7 +1135,7 @@ header_ustar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
* 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,
|
||||
pax_header(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
struct stat *st, char *attr)
|
||||
{
|
||||
size_t attr_length, l, line_length;
|
||||
@ -1158,7 +1161,7 @@ pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
line_length *= 10;
|
||||
line_length += *p - '0';
|
||||
if (line_length > 999999) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Rejecting pax extended attribute > 1MB");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
@ -1183,7 +1186,7 @@ pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
tar->pax_entry_length * sizeof(wchar_t));
|
||||
if (tar->pax_entry == NULL) {
|
||||
free(old_entry);
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -1192,7 +1195,7 @@ pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
/* 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid UTF8 character in pax extended attribute");
|
||||
err = err_combine(err, ARCHIVE_WARN);
|
||||
}
|
||||
@ -1204,7 +1207,7 @@ pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
while (*wp && *wp != L'=')
|
||||
++wp;
|
||||
if (*wp == L'\0' || wp == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid pax extended attributes");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
@ -1430,7 +1433,7 @@ pax_time(const wchar_t *p, int64_t *ps, long *pn)
|
||||
* Parse GNU tar header
|
||||
*/
|
||||
static int
|
||||
header_gnutar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
header_gnutar(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
|
||||
struct stat *st, const void *h)
|
||||
{
|
||||
const struct archive_entry_header_gnutar *header;
|
||||
@ -1495,7 +1498,7 @@ header_gnutar(struct archive *a, struct tar *tar, struct archive_entry *entry,
|
||||
}
|
||||
|
||||
static int
|
||||
gnu_read_sparse_data(struct archive *a, struct tar *tar,
|
||||
gnu_read_sparse_data(struct archive_read *a, struct tar *tar,
|
||||
const struct archive_entry_header_gnutar *header)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
@ -1516,7 +1519,7 @@ gnu_read_sparse_data(struct archive *a, struct tar *tar,
|
||||
if (bytes_read < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (bytes_read < 512) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated tar archive "
|
||||
"detected while reading sparse file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -1531,7 +1534,7 @@ gnu_read_sparse_data(struct archive *a, struct tar *tar,
|
||||
}
|
||||
|
||||
static void
|
||||
gnu_parse_sparse_data(struct archive *a, struct tar *tar,
|
||||
gnu_parse_sparse_data(struct archive_read *a, struct tar *tar,
|
||||
const struct gnu_sparse *sparse, int length)
|
||||
{
|
||||
struct sparse_block *last;
|
||||
|
@ -44,15 +44,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct zip {
|
||||
/* entry_bytes_remaining is the number of bytes we expect. */
|
||||
off_t entry_bytes_remaining;
|
||||
off_t entry_offset;
|
||||
int64_t entry_bytes_remaining;
|
||||
int64_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;
|
||||
int64_t entry_compressed_bytes_read;
|
||||
int64_t entry_uncompressed_bytes_read;
|
||||
|
||||
unsigned version;
|
||||
unsigned system;
|
||||
@ -74,8 +75,8 @@ struct zip {
|
||||
long crc32;
|
||||
ssize_t filename_length;
|
||||
ssize_t extra_length;
|
||||
off_t uncompressed_size;
|
||||
off_t compressed_size;
|
||||
int64_t uncompressed_size;
|
||||
int64_t compressed_size;
|
||||
|
||||
unsigned char *uncompressed_buffer;
|
||||
size_t uncompressed_buffer_size;
|
||||
@ -115,36 +116,40 @@ static const char *compression_names[] = {
|
||||
"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 *,
|
||||
static int archive_read_format_zip_bid(struct archive_read *);
|
||||
static int archive_read_format_zip_cleanup(struct archive_read *);
|
||||
static int archive_read_format_zip_read_data(struct archive_read *,
|
||||
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 *,
|
||||
static int archive_read_format_zip_read_data_skip(struct archive_read *a);
|
||||
static int archive_read_format_zip_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int i2(const char *);
|
||||
static int i4(const char *);
|
||||
static unsigned int u2(const char *);
|
||||
static unsigned int u4(const char *);
|
||||
static uint64_t u8(const char *);
|
||||
static int zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
static int zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, off_t *offset);
|
||||
static int zip_read_data_none(struct archive *a, const void **buff,
|
||||
static int zip_read_data_none(struct archive_read *a, const void **buff,
|
||||
size_t *size, off_t *offset);
|
||||
static int zip_read_file_header(struct archive *a,
|
||||
static int zip_read_file_header(struct archive_read *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);
|
||||
|
||||
/* Largest 32-bit unsigned value, stored in a 64-bit constant. */
|
||||
static const uint64_t max_uint32 = (((uint64_t)1) << 32) - 1;
|
||||
|
||||
int
|
||||
archive_read_support_format_zip(struct archive *a)
|
||||
archive_read_support_format_zip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct zip *zip;
|
||||
int r;
|
||||
|
||||
zip = (struct zip *)malloc(sizeof(*zip));
|
||||
if (zip == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate zip data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(zip, 0, sizeof(*zip));
|
||||
@ -164,14 +169,14 @@ archive_read_support_format_zip(struct archive *a)
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_zip_bid(struct archive *a)
|
||||
archive_read_format_zip_bid(struct archive_read *a)
|
||||
{
|
||||
int bytes_read;
|
||||
int bid = 0;
|
||||
const void *h;
|
||||
const char *p;
|
||||
|
||||
if (a->archive_format == ARCHIVE_FORMAT_ZIP)
|
||||
if (a->archive.archive_format == ARCHIVE_FORMAT_ZIP)
|
||||
bid += 1;
|
||||
|
||||
bytes_read = (a->compression_read_ahead)(a, &h, 4);
|
||||
@ -194,7 +199,7 @@ archive_read_format_zip_bid(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_zip_read_header(struct archive *a,
|
||||
archive_read_format_zip_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
int bytes_read;
|
||||
@ -202,9 +207,9 @@ archive_read_format_zip_read_header(struct archive *a,
|
||||
const char *signature;
|
||||
struct zip *zip;
|
||||
|
||||
a->archive_format = ARCHIVE_FORMAT_ZIP;
|
||||
if (a->archive_format_name == NULL)
|
||||
a->archive_format_name = "ZIP";
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
|
||||
if (a->archive.archive_format_name == NULL)
|
||||
a->archive.archive_format_name = "ZIP";
|
||||
|
||||
zip = (struct zip *)*(a->pformat_data);
|
||||
zip->decompress_init = 0;
|
||||
@ -218,7 +223,7 @@ archive_read_format_zip_read_header(struct archive *a,
|
||||
|
||||
signature = (const char *)h;
|
||||
if (signature[0] != 'P' || signature[1] != 'K') {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad ZIP file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -243,19 +248,19 @@ archive_read_format_zip_read_header(struct archive *a,
|
||||
* We should never encounter this record here;
|
||||
* see ZIP_LENGTH_AT_END handling below for details.
|
||||
*/
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Bad ZIP file: Unexpected end-of-entry record");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, 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,
|
||||
zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
struct zip *zip)
|
||||
{
|
||||
const struct zip_file_header *p;
|
||||
@ -266,7 +271,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry,
|
||||
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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -299,7 +304,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry,
|
||||
/* 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -316,7 +321,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry,
|
||||
/* 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -341,7 +346,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry,
|
||||
sprintf(zip->format_name, "ZIP %d.%d (%s)",
|
||||
zip->version / 10, zip->version % 10,
|
||||
zip->compression_name);
|
||||
a->archive_format_name = zip->format_name;
|
||||
a->archive.archive_format_name = zip->format_name;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -368,7 +373,7 @@ zip_time(const char *p)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_zip_read_data(struct archive *a,
|
||||
archive_read_format_zip_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, off_t *offset)
|
||||
{
|
||||
int r;
|
||||
@ -388,7 +393,7 @@ archive_read_format_zip_read_data(struct archive *a,
|
||||
int bytes_read =
|
||||
(a->compression_read_ahead)(a, &h, 16);
|
||||
if (bytes_read < 16) {
|
||||
archive_set_error(a,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP end-of-file record");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -402,19 +407,21 @@ archive_read_format_zip_read_data(struct archive *a,
|
||||
|
||||
/* Check file size, CRC against these values. */
|
||||
if (zip->compressed_size != zip->entry_compressed_bytes_read) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, 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,
|
||||
/* Size field only stores the lower 32 bits of the actual size. */
|
||||
if ((zip->uncompressed_size & max_uint32)
|
||||
!= (zip->entry_uncompressed_bytes_read & max_uint32)) {
|
||||
archive_set_error(&a->archive, 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,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"ZIP data CRC error");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
@ -437,7 +444,7 @@ archive_read_format_zip_read_data(struct archive *a,
|
||||
*size = 0;
|
||||
*offset = 0;
|
||||
/* Return a warning. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported ZIP compression method (%s)",
|
||||
zip->compression_name);
|
||||
if (zip->flags & ZIP_LENGTH_AT_END) {
|
||||
@ -472,7 +479,7 @@ archive_read_format_zip_read_data(struct archive *a,
|
||||
* zip->end_of_entry if it consumes all of the data.
|
||||
*/
|
||||
static int
|
||||
zip_read_data_none(struct archive *a, const void **buff,
|
||||
zip_read_data_none(struct archive_read *a, const void **buff,
|
||||
size_t *size, off_t *offset)
|
||||
{
|
||||
struct zip *zip;
|
||||
@ -495,7 +502,7 @@ zip_read_data_none(struct archive *a, const void **buff,
|
||||
*/
|
||||
bytes_avail = (a->compression_read_ahead)(a, buff, 1);
|
||||
if (bytes_avail <= 0) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -513,7 +520,7 @@ zip_read_data_none(struct archive *a, const void **buff,
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
static int
|
||||
zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, off_t *offset)
|
||||
{
|
||||
struct zip *zip;
|
||||
@ -529,7 +536,7 @@ zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
zip->uncompressed_buffer
|
||||
= (unsigned char *)malloc(zip->uncompressed_buffer_size);
|
||||
if (zip->uncompressed_buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory for ZIP decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -540,7 +547,7 @@ zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
r = inflateInit2(&zip->stream,
|
||||
-15 /* Don't check for zlib header */);
|
||||
if (r != Z_OK) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't initialize ZIP decompression.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -555,7 +562,7 @@ zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
*/
|
||||
bytes_avail = (a->compression_read_ahead)(a, &compressed_buff, 1);
|
||||
if (bytes_avail <= 0) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file body");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -581,11 +588,11 @@ zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
zip->end_of_entry = 1;
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Out of memory for ZIP decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"ZIP decompression failed (%d)", r);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -605,20 +612,20 @@ zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
}
|
||||
#else
|
||||
static int
|
||||
zip_read_data_deflate(struct archive *a, const void **buff,
|
||||
zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, off_t *offset)
|
||||
{
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = 0;
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, 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)
|
||||
archive_read_format_zip_read_data_skip(struct archive_read *a)
|
||||
{
|
||||
struct zip *zip;
|
||||
const void *buff = NULL;
|
||||
@ -648,7 +655,8 @@ archive_read_format_zip_read_data_skip(struct archive *a)
|
||||
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,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file body");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -663,7 +671,7 @@ archive_read_format_zip_read_data_skip(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_zip_cleanup(struct archive *a)
|
||||
archive_read_format_zip_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct zip *zip;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
.Dt archive_util 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_clear_error ,
|
||||
.Nm archive_compression ,
|
||||
.Nm archive_compression_name ,
|
||||
.Nm archive_errno ,
|
||||
@ -38,6 +39,8 @@
|
||||
.Nd libarchive utility functions
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft void
|
||||
.Fn archive_clear_error "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_compression "struct archive *"
|
||||
.Ft const char *
|
||||
@ -59,6 +62,9 @@ object used in the
|
||||
.Xr libarchive 3
|
||||
library.
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_clear_error
|
||||
Clears any error information left over from a previous call.
|
||||
Not generally used in client code.
|
||||
.It Fn archive_compression
|
||||
Returns a numeric code indicating the current compression.
|
||||
This value is set by
|
||||
|
@ -118,6 +118,12 @@ archive_position_uncompressed(struct archive *a)
|
||||
return (a->file_position);
|
||||
}
|
||||
|
||||
void
|
||||
archive_clear_error(struct archive *a)
|
||||
{
|
||||
archive_string_empty(&a->error_string);
|
||||
a->error = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
archive_set_error(struct archive *a, int error_number, const char *fmt, ...)
|
||||
|
81
lib/libarchive/archive_virtual.c
Normal file
81
lib/libarchive/archive_virtual.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
int
|
||||
archive_write_close(struct archive *a)
|
||||
{
|
||||
return ((a->vtable->archive_write_close)(a));
|
||||
}
|
||||
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
int
|
||||
archive_write_finish(struct archive *a)
|
||||
{
|
||||
return ((a->vtable->archive_write_finish)(a));
|
||||
}
|
||||
#else
|
||||
/* Temporarily allow library to compile with either 1.x or 2.0 API. */
|
||||
void
|
||||
archive_write_finish(struct archive *a)
|
||||
{
|
||||
(void)(a->vtable->archive_write_finish)(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_write_header(struct archive *a, struct archive_entry *entry)
|
||||
{
|
||||
return ((a->vtable->archive_write_header)(a, entry));
|
||||
}
|
||||
|
||||
int
|
||||
archive_write_finish_entry(struct archive *a)
|
||||
{
|
||||
return ((a->vtable->archive_write_finish_entry)(a));
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
return ((a->vtable->archive_write_data)(a, buff, s));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
archive_write_data_block(struct archive *a, const void *buff, size_t s, off_t o)
|
||||
{
|
||||
return ((a->vtable->archive_write_data_block)(a, buff, s, o));
|
||||
}
|
@ -89,13 +89,13 @@
|
||||
.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 int
|
||||
.Ft ssize_t
|
||||
.Fn archive_write_data "struct archive *" "const void *" "size_t"
|
||||
.Ft int
|
||||
.Fn archive_write_finish_entry "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_write_close "struct archive *"
|
||||
.Ft void
|
||||
.Ft int
|
||||
.Fn archive_write_finish "struct archive *"
|
||||
.Sh DESCRIPTION
|
||||
These functions provide a complete API for creating streaming
|
||||
@ -260,6 +260,12 @@ Complete the archive and invoke the close callback.
|
||||
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
|
||||
@ -457,8 +463,9 @@ 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_close .
|
||||
.Fn archive_write_finish .
|
||||
The client callback can call
|
||||
.Fn archive_set_error
|
||||
to provide values that can then be retrieved by
|
||||
|
@ -55,6 +55,31 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
static struct archive_vtable *archive_write_vtable(void);
|
||||
|
||||
static int _archive_write_close(struct archive *);
|
||||
static int _archive_write_finish(struct archive *);
|
||||
static int _archive_write_header(struct archive *, struct archive_entry *);
|
||||
static int _archive_write_finish_entry(struct archive *);
|
||||
static ssize_t _archive_write_data(struct archive *, const void *, size_t);
|
||||
|
||||
static struct archive_vtable *
|
||||
archive_write_vtable(void)
|
||||
{
|
||||
static struct archive_vtable av;
|
||||
static int inited = 0;
|
||||
|
||||
if (!inited) {
|
||||
av.archive_write_close = _archive_write_close;
|
||||
av.archive_write_finish = _archive_write_finish;
|
||||
av.archive_write_header = _archive_write_header;
|
||||
av.archive_write_finish_entry = _archive_write_finish_entry;
|
||||
av.archive_write_data = _archive_write_data;
|
||||
}
|
||||
return (&av);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate, initialize and return an archive object.
|
||||
@ -62,18 +87,18 @@ __FBSDID("$FreeBSD$");
|
||||
struct archive *
|
||||
archive_write_new(void)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_write *a;
|
||||
unsigned char *nulls;
|
||||
|
||||
a = (struct archive *)malloc(sizeof(*a));
|
||||
a = (struct archive_write *)malloc(sizeof(*a));
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->magic = ARCHIVE_WRITE_MAGIC;
|
||||
a->user_uid = geteuid();
|
||||
a->archive.magic = ARCHIVE_WRITE_MAGIC;
|
||||
a->archive.state = ARCHIVE_STATE_NEW;
|
||||
a->archive.vtable = archive_write_vtable();
|
||||
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. */
|
||||
@ -91,17 +116,19 @@ archive_write_new(void)
|
||||
* client to link in support for that format, even if they didn't
|
||||
* ever use it.
|
||||
*/
|
||||
archive_write_set_compression_none(a);
|
||||
return (a);
|
||||
archive_write_set_compression_none(&a->archive);
|
||||
return (&a->archive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the block size. Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
archive_write_set_bytes_per_block(struct archive *a, int bytes_per_block)
|
||||
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");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_set_bytes_per_block");
|
||||
a->bytes_per_block = bytes_per_block;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -110,9 +137,11 @@ archive_write_set_bytes_per_block(struct archive *a, int bytes_per_block)
|
||||
* Get the current block size. -1 if it has never been set.
|
||||
*/
|
||||
int
|
||||
archive_write_get_bytes_per_block(struct archive *a)
|
||||
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");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_get_bytes_per_block");
|
||||
return (a->bytes_per_block);
|
||||
}
|
||||
|
||||
@ -121,9 +150,11 @@ archive_write_get_bytes_per_block(struct archive *a)
|
||||
* Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
archive_write_set_bytes_in_last_block(struct archive *a, int bytes)
|
||||
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");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_set_bytes_in_last_block");
|
||||
a->bytes_in_last_block = bytes;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -132,9 +163,11 @@ archive_write_set_bytes_in_last_block(struct archive *a, int bytes)
|
||||
* Return the value set above. -1 indicates it has not been set.
|
||||
*/
|
||||
int
|
||||
archive_write_get_bytes_in_last_block(struct archive *a)
|
||||
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");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_get_bytes_in_last_block");
|
||||
return (a->bytes_in_last_block);
|
||||
}
|
||||
|
||||
@ -144,9 +177,11 @@ archive_write_get_bytes_in_last_block(struct archive *a)
|
||||
* an archive to itself recursively.
|
||||
*/
|
||||
int
|
||||
archive_write_set_skip_file(struct archive *a, dev_t d, ino_t i)
|
||||
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");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_set_skip_file");
|
||||
a->skip_file_dev = d;
|
||||
a->skip_file_ino = i;
|
||||
return (ARCHIVE_OK);
|
||||
@ -157,16 +192,18 @@ archive_write_set_skip_file(struct archive *a, dev_t d, ino_t i)
|
||||
* Open the archive using the current settings.
|
||||
*/
|
||||
int
|
||||
archive_write_open(struct archive *a, void *client_data,
|
||||
archive_write_open(struct archive *_a, void *client_data,
|
||||
archive_open_callback *opener, archive_write_callback *writer,
|
||||
archive_close_callback *closer)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
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;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_write_open");
|
||||
archive_clear_error(&a->archive);
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
a->client_data = client_data;
|
||||
a->client_writer = writer;
|
||||
a->client_opener = opener;
|
||||
@ -185,15 +222,17 @@ archive_write_open(struct archive *a, void *client_data,
|
||||
* Don't assume we actually wrote anything or performed any non-trivial
|
||||
* initialization.
|
||||
*/
|
||||
int
|
||||
archive_write_close(struct archive *a)
|
||||
static int
|
||||
_archive_write_close(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_close");
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_close");
|
||||
|
||||
/* Finish the last entry. */
|
||||
if (a->state & ARCHIVE_STATE_DATA)
|
||||
if (a->archive.state & ARCHIVE_STATE_DATA)
|
||||
r = ((a->format_finish_entry)(a));
|
||||
|
||||
/* Finish off the archive. */
|
||||
@ -203,6 +242,13 @@ archive_write_close(struct archive *a)
|
||||
r = r1;
|
||||
}
|
||||
|
||||
/* Release resources. */
|
||||
if (a->format_destroy != NULL) {
|
||||
r1 = (a->format_destroy)(a);
|
||||
if (r1 < r)
|
||||
r = r1;
|
||||
}
|
||||
|
||||
/* Finish the compression and close the stream. */
|
||||
if (a->compression_finish != NULL) {
|
||||
r1 = (a->compression_finish)(a);
|
||||
@ -210,41 +256,47 @@ archive_write_close(struct archive *a)
|
||||
r = r1;
|
||||
}
|
||||
|
||||
a->state = ARCHIVE_STATE_CLOSED;
|
||||
a->archive.state = ARCHIVE_STATE_CLOSED;
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the archive structure.
|
||||
*/
|
||||
void
|
||||
archive_write_finish(struct archive *a)
|
||||
static int
|
||||
_archive_write_finish(struct archive *_a)
|
||||
{
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_finish");
|
||||
if (a->state != ARCHIVE_STATE_CLOSED)
|
||||
archive_write_close(a);
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
int r = ARCHIVE_OK;
|
||||
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_ANY, "archive_write_finish");
|
||||
if (a->archive.state != ARCHIVE_STATE_CLOSED)
|
||||
r = archive_write_close(&a->archive);
|
||||
|
||||
/* Release various dynamic buffers. */
|
||||
free((void *)(uintptr_t)(const void *)a->nulls);
|
||||
archive_string_free(&a->error_string);
|
||||
a->magic = 0;
|
||||
archive_string_free(&a->archive.error_string);
|
||||
a->archive.magic = 0;
|
||||
free(a);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the appropriate header.
|
||||
*/
|
||||
int
|
||||
archive_write_header(struct archive *a, struct archive_entry *entry)
|
||||
static int
|
||||
_archive_write_header(struct archive *_a, struct archive_entry *entry)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
int ret, r2;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_DATA | ARCHIVE_STATE_HEADER, "archive_write_header");
|
||||
archive_string_empty(&a->error_string);
|
||||
archive_clear_error(&a->archive);
|
||||
|
||||
/* In particular, "retry" and "fatal" get returned immediately. */
|
||||
ret = archive_write_finish_entry(a);
|
||||
ret = archive_write_finish_entry(&a->archive);
|
||||
if (ret < ARCHIVE_OK && ret != ARCHIVE_WARN)
|
||||
return (ret);
|
||||
|
||||
@ -252,7 +304,8 @@ archive_write_header(struct archive *a, struct archive_entry *entry)
|
||||
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");
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Can't add archive to itself");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
@ -261,33 +314,34 @@ archive_write_header(struct archive *a, struct archive_entry *entry)
|
||||
if (r2 < ret)
|
||||
ret = r2;
|
||||
|
||||
a->state = ARCHIVE_STATE_DATA;
|
||||
a->archive.state = ARCHIVE_STATE_DATA;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
archive_write_finish_entry(struct archive * a)
|
||||
static int
|
||||
_archive_write_finish_entry(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
||||
"archive_write_finish_entry");
|
||||
if (a->state & ARCHIVE_STATE_DATA)
|
||||
if (a->archive.state & ARCHIVE_STATE_DATA)
|
||||
ret = (a->format_finish_entry)(a);
|
||||
a->state = ARCHIVE_STATE_HEADER;
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the compressor is responsible for blocking.
|
||||
*/
|
||||
/* Should be "ssize_t", but that breaks the ABI. <sigh> */
|
||||
int
|
||||
archive_write_data(struct archive *a, const void *buff, size_t s)
|
||||
static ssize_t
|
||||
_archive_write_data(struct archive *_a, const void *buff, size_t s)
|
||||
{
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
ARCHIVE_STATE_DATA, "archive_write_data");
|
||||
archive_string_empty(&a->error_string);
|
||||
archive_clear_error(&a->archive);
|
||||
return ((a->format_write_data)(a, buff, s));
|
||||
}
|
||||
|
358
lib/libarchive/archive_write_disk.3
Normal file
358
lib/libarchive/archive_write_disk.3
Normal file
@ -0,0 +1,358 @@
|
||||
.\" Copyright (c) 2003-2007 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$
|
||||
.\"
|
||||
.Dd March 2, 2007
|
||||
.Dt archive_write_disk 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_write_disk_new ,
|
||||
.Nm archive_write_disk_set_options ,
|
||||
.Nm archive_write_disk_set_skip_file ,
|
||||
.Nm archive_write_disk_set_group_lookup ,
|
||||
.Nm archive_write_disk_set_standard_lookup ,
|
||||
.Nm archive_write_disk_set_user_lookup ,
|
||||
.Nm archive_write_header ,
|
||||
.Nm archive_write_data ,
|
||||
.Nm archive_write_finish_entry ,
|
||||
.Nm archive_write_close ,
|
||||
.Nm archive_write_finish
|
||||
.Nd functions for creating objects on disk
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft struct archive *
|
||||
.Fn archive_write_disk_new "void"
|
||||
.Ft int
|
||||
.Fn archive_write_disk_set_options "struct archive *" "int flags"
|
||||
.Ft int
|
||||
.Fn archive_write_disk_set_skip_file "struct archive *" "dev_t" "ino_t"
|
||||
.Ft int
|
||||
.Fn archive_write_disk_set_group_lookup "struct archive *" "void *" "gid_t (*)(void *, const char *gname, gid_t gid)" "void (*cleanup)(void *)"
|
||||
.Ft int
|
||||
.Fn archive_write_disk_set_standard_lookup "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_write_disk_set_user_lookup "struct archive *" "void *" "uid_t (*)(void *, const char *uname, uid_t uid)" "void (*cleanup)(void *)"
|
||||
.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_finish_entry "struct archive *"
|
||||
.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 objects on
|
||||
disk from
|
||||
.Tn struct archive_entry
|
||||
descriptions.
|
||||
They are most naturally used when extracting objects from an archive
|
||||
using the
|
||||
.Fn archive_read
|
||||
interface.
|
||||
The general process is to read
|
||||
.Tn struct archive_entry
|
||||
objects from an archive, then write those objects to a
|
||||
.Tn struct archive
|
||||
object created using the
|
||||
.Fn archive_write_disk
|
||||
family functions.
|
||||
This interface is deliberately very similar to the
|
||||
.Fn archive_write
|
||||
interface used to write objects to a streaming archive.
|
||||
.Bl -tag -width indent
|
||||
.It Fn archive_write_disk_new
|
||||
Allocates and initializes a
|
||||
.Tn struct archive
|
||||
object suitable for writing objects to disk.
|
||||
.It Fn archive_write_disk_set_skip_file
|
||||
Records the device and inode numbers of a file that should not be
|
||||
overwritten.
|
||||
This is typically used to ensure that an extraction process does not
|
||||
overwrite the archive from which objects are being read.
|
||||
This capability is technically unnecessary but can be a significant
|
||||
performance optimization in practice.
|
||||
.It Fn archive_write_disk_set_options
|
||||
The options field 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
|
||||
Full permissions (including SGID, SUID, and sticky bits) should
|
||||
be restored exactly as specified, without obeying the
|
||||
current umask.
|
||||
Note that SUID and SGID bits can only be restored if the
|
||||
user and group ID of the object on disk are correct.
|
||||
If
|
||||
.Cm ARCHIVE_EXTRACT_OWNER
|
||||
is not specified, then SUID and SGID bits will only be restored
|
||||
if the default user and group IDs of newly-created objects on disk
|
||||
happen to match those specified in the archive entry.
|
||||
By default, only basic permissions are restored, and umask is obeyed.
|
||||
.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 before any attempt to
|
||||
create them.
|
||||
In some cases, this can prove to be a significant performance improvement.
|
||||
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.
|
||||
.It Cm ARCHIVE_EXTRACT_XATTR
|
||||
Attempt to restore POSIX.1e extended attributes.
|
||||
By default, they are ignored.
|
||||
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
|
||||
Refuse to extract any object whose final location would be altered
|
||||
by a symlink on disk.
|
||||
This is intended to help guard against a variety of mischief
|
||||
caused by archives that (deliberately or otherwise) extract
|
||||
files outside of the current directory.
|
||||
The default is not to perform this check.
|
||||
If
|
||||
.Cm ARCHIVE_EXTRACT_UNLINK
|
||||
is specified together with this option, the library will
|
||||
remove any intermediate symlinks it finds and return an
|
||||
error only if such symlink could not be removed.
|
||||
.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT
|
||||
Refuse to extract a path that contains a
|
||||
.Pa ..
|
||||
element anywhere within it.
|
||||
The default is to not refuse such paths.
|
||||
Note that paths ending in
|
||||
.Pa ..
|
||||
always cause an error, regardless of this flag.
|
||||
.El
|
||||
.It Fn archive_write_disk_set_group_lookup , Fn archive_write_disk_set_user_lookup
|
||||
The
|
||||
.Tn struct archive_entry
|
||||
objects contain both names and ids that can be used to identify users
|
||||
and groups.
|
||||
These names and ids describe the ownership of the file itself and
|
||||
also appear in ACL lists.
|
||||
By default, the library uses the ids and ignores the names, but
|
||||
this can be overridden by registering user and group lookup functions.
|
||||
To register, you must provide a lookup function which
|
||||
accepts both a name and id and returns a suitable id.
|
||||
You may also provide a
|
||||
.Tn void *
|
||||
pointer to a private data structure and a cleanup function for
|
||||
that data.
|
||||
The cleanup function will be invoked when the
|
||||
.Tn struct archive
|
||||
object is destroyed.
|
||||
.It Fn archive_write_disk_set_standard_lookup
|
||||
This convenience function installs a standard set of user
|
||||
and group lookup functions.
|
||||
These functions use
|
||||
.Xr getpwnam 3
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
to convert names to ids, defaulting to the ids if the names cannot
|
||||
be looked up.
|
||||
These functions also implement a simple memory cache to reduce
|
||||
the number of calls to
|
||||
.Xr getpwnam 3
|
||||
and
|
||||
.Xr getgrnam 3 .
|
||||
.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_finish_entry
|
||||
Close out the entry just written.
|
||||
Ordinarily, clients never need to call this, as it
|
||||
is called automatically by
|
||||
.Fn archive_write_next_header
|
||||
and
|
||||
.Fn archive_write_close
|
||||
as needed.
|
||||
.It Fn archive_write_close
|
||||
Set any attributes that could not be set during the initial restore.
|
||||
For example, directory timestamps are not restored initially because
|
||||
restoring a subsequent file would alter that timestamp.
|
||||
Similarly, non-writable directories are initially created with
|
||||
write permissions (so that their contents can be restored).
|
||||
The
|
||||
.Nm
|
||||
library maintains a list of all such deferred attributes and
|
||||
sets them when this function is invoked.
|
||||
.It Fn archive_write_finish
|
||||
Invokes
|
||||
.Fn archive_write_close
|
||||
if it was not invoked manually, then releases all resources.
|
||||
.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.
|
||||
Many of these functions are also documented under
|
||||
.Xr archive_write 3 .
|
||||
.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_disk_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.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_write 3 ,
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm libarchive
|
||||
library first appeared in
|
||||
.Fx 5.3 .
|
||||
The
|
||||
.Nm archive_write_disk
|
||||
interface was added to
|
||||
.Nm libarchive 2.0
|
||||
and first appeared in
|
||||
.Fx 6.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_write_header ,
|
||||
but final permissions are not set until
|
||||
.Fn archive_write_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.
|
||||
.Pp
|
||||
The library attempts to create objects with filenames longer than
|
||||
.Cm PATH_MAX
|
||||
by creating prefixes of the full path and changing the current directory.
|
||||
Currently, this logic is limited in scope; the fixup pass does
|
||||
not work correctly for such objects and the symlink security check
|
||||
option disables the support for very long pathnames.
|
||||
.Pp
|
||||
Restoring the path
|
||||
.Pa aa/../bb
|
||||
does create each intermediate directory.
|
||||
In particular, the directory
|
||||
.Pa aa
|
||||
is created as well as the final object
|
||||
.Pa bb .
|
||||
In theory, this can be exploited to create an entire directory heirarchy
|
||||
with a single request.
|
||||
Of course, this does not work if the
|
||||
.Cm ARCHIVE_EXTRACT_NODOTDOT
|
||||
option is specified.
|
||||
.Pp
|
||||
Implicit directories are always created obeying the current umask.
|
||||
Explicit objects are created obeying the current umask unless
|
||||
.Cm ARCHIVE_EXTRACT_PERM
|
||||
is specified, in which case they current umask is ignored.
|
||||
.Pp
|
||||
SGID and SUID bits are restored only if the correct user and
|
||||
group could be set.
|
||||
If
|
||||
.Cm ARCHIVE_EXTRACT_OWNER
|
||||
is not specified, then no attempt is made to set the ownership.
|
||||
In this case, SGID and SUID bits are restored only if the
|
||||
user and group of the final object happen to match those specified
|
||||
in the entry.
|
||||
.Pp
|
||||
The
|
||||
.Dq standard
|
||||
user-id and group-id lookup functions are not the defaults because
|
||||
.Xr getgrnam 3
|
||||
and
|
||||
.Xr getpwnam 3
|
||||
are sometimes too large for particular applications.
|
||||
The current design allows the application author to use a more
|
||||
compact implementation when appropriate.
|
||||
.Pp
|
||||
There should be a corresponding
|
||||
.Nm archive_read_disk
|
||||
interface that walks a directory heirarchy and returns archive
|
||||
entry objects.
|
1929
lib/libarchive/archive_write_disk.c
Normal file
1929
lib/libarchive/archive_write_disk.c
Normal file
File diff suppressed because it is too large
Load Diff
34
lib/libarchive/archive_write_disk_private.h
Normal file
34
lib/libarchive/archive_write_disk_private.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
|
||||
|
||||
struct archive_write_disk;
|
||||
|
||||
#endif
|
212
lib/libarchive/archive_write_disk_set_standard_lookup.c
Normal file
212
lib/libarchive/archive_write_disk_set_standard_lookup.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ACL_H
|
||||
#include <sys/acl.h>
|
||||
#endif
|
||||
#ifdef HAVE_ATTR_XATTR_H
|
||||
#include <attr/xattr.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_write_disk_private.h"
|
||||
|
||||
struct bucket {
|
||||
char *name;
|
||||
int hash;
|
||||
id_t id;
|
||||
};
|
||||
|
||||
static unsigned int hash(const char *);
|
||||
static gid_t lookup_gid(void *, const char *uname, gid_t);
|
||||
static uid_t lookup_uid(void *, const char *uname, uid_t);
|
||||
static void cleanup(void *);
|
||||
|
||||
/*
|
||||
* Installs functions that use getpwnam()/getgrnam()---along with
|
||||
* a simple cache to accelerate such lookups---into the archive_write_disk
|
||||
* object. This is in a separate file because getpwnam()/getgrnam()
|
||||
* can pull in a LOT of library code (including NIS/LDAP functions, which
|
||||
* pull in DNS resolveers, etc). This can easily top 500kB, which makes
|
||||
* it inappropriate for some space-constrained applications.
|
||||
*
|
||||
* Applications that are size-sensitive may want to just use the
|
||||
* real default functions (defined in archive_write_disk.c) that just
|
||||
* use the uid/gid without the lookup. Or define your own custom functions
|
||||
* if you prefer.
|
||||
*
|
||||
* TODO: Replace these hash tables with simpler move-to-front LRU
|
||||
* lists with a bounded size (128 items?). The hash is a bit faster,
|
||||
* but has a bad pathology in which it thrashes a single bucket. Even
|
||||
* walking a list of 128 items is a lot faster than calling
|
||||
* getpwnam()!
|
||||
*/
|
||||
int
|
||||
archive_write_disk_set_standard_lookup(struct archive *a)
|
||||
{
|
||||
struct bucket *ucache = malloc(sizeof(struct bucket[127]));
|
||||
struct bucket *gcache = malloc(sizeof(struct bucket[127]));
|
||||
memset(ucache, 0, sizeof(struct bucket[127]));
|
||||
memset(gcache, 0, sizeof(struct bucket[127]));
|
||||
archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
|
||||
archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static gid_t
|
||||
lookup_gid(void *private_data, const char *gname, gid_t gid)
|
||||
{
|
||||
int h;
|
||||
struct bucket *b;
|
||||
int cache_size;
|
||||
struct bucket *gcache = (struct bucket *)private_data;
|
||||
|
||||
cache_size = 127;
|
||||
|
||||
/* If no gname, just use the gid provided. */
|
||||
if (gname == NULL || *gname == '\0')
|
||||
return (gid);
|
||||
|
||||
/* Try to find gname in the cache. */
|
||||
h = hash(gname);
|
||||
b = &gcache[h % cache_size ];
|
||||
if (b->name != NULL && b->hash == h && strcmp(gname, b->name) == 0)
|
||||
return ((gid_t)b->id);
|
||||
|
||||
/* Free the cache slot for a new entry. */
|
||||
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;
|
||||
#if HAVE_GRP_H
|
||||
{
|
||||
struct group *grent = getgrnam(gname);
|
||||
if (grent != NULL)
|
||||
gid = grent->gr_gid;
|
||||
}
|
||||
#elif _WIN32
|
||||
/* TODO: do a gname->gid lookup for Windows. */
|
||||
#endif
|
||||
b->id = gid;
|
||||
|
||||
return (gid);
|
||||
}
|
||||
|
||||
static uid_t
|
||||
lookup_uid(void *private_data, const char *uname, uid_t uid)
|
||||
{
|
||||
int h;
|
||||
struct bucket *b;
|
||||
int cache_size;
|
||||
struct bucket *ucache = (struct bucket *)private_data;
|
||||
|
||||
cache_size = 127;
|
||||
|
||||
/* If no uname, just use the uid provided. */
|
||||
if (uname == NULL || *uname == '\0')
|
||||
return (uid);
|
||||
|
||||
/* Try to find uname in the cache. */
|
||||
h = hash(uname);
|
||||
b = &ucache[h % cache_size ];
|
||||
if (b->name != NULL && b->hash == h && strcmp(uname, b->name) == 0)
|
||||
return ((uid_t)b->id);
|
||||
|
||||
/* Free the cache slot for a new entry. */
|
||||
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;
|
||||
#if HAVE_PWD_H
|
||||
{
|
||||
struct passwd *pwent = getpwnam(uname);
|
||||
if (pwent != NULL)
|
||||
uid = pwent->pw_uid;
|
||||
}
|
||||
#elif _WIN32
|
||||
/* TODO: do a uname->uid lookup for Windows. */
|
||||
#endif
|
||||
b->id = uid;
|
||||
|
||||
return (uid);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(void *private)
|
||||
{
|
||||
free(private);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
177
lib/libarchive/archive_write_private.h
Normal file
177
lib/libarchive/archive_write_private.h
Normal file
@ -0,0 +1,177 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_WRITE_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_WRITE_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
struct archive_write {
|
||||
struct archive archive;
|
||||
|
||||
struct archive_entry *entry;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/*
|
||||
* On write, the client just invokes an archive_write_set function
|
||||
* which sets up the data here directly.
|
||||
*/
|
||||
void *compression_data; /* Data for (de)compressor. */
|
||||
int (*compression_init)(struct archive_write *); /* Initialize. */
|
||||
int (*compression_finish)(struct archive_write *);
|
||||
int (*compression_write)(struct archive_write *, 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);
|
||||
off_t (*compression_skip)(struct archive *, off_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 guaranteed 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_write *);
|
||||
int (*format_finish)(struct archive_write *);
|
||||
int (*format_destroy)(struct archive_write *);
|
||||
int (*format_finish_entry)(struct archive_write *);
|
||||
int (*format_write_header)(struct archive_write *,
|
||||
struct archive_entry *);
|
||||
ssize_t (*format_write_data)(struct archive_write *,
|
||||
const void *buff, size_t);
|
||||
|
||||
/*
|
||||
* Various information needed by archive_extract.
|
||||
*/
|
||||
struct extract *extract;
|
||||
int (*cleanup_archive_extract)(struct archive *);
|
||||
};
|
||||
|
||||
/*
|
||||
* Utility function to format a USTAR header into a buffer. If
|
||||
* "strict" is set, this tries to create the absolutely most portable
|
||||
* version of a ustar header. If "strict" is set to 0, then it will
|
||||
* relax certain requirements.
|
||||
*
|
||||
* Generally, format-specific declarations don't belong in this
|
||||
* header; this is a rare example of a function that is shared by
|
||||
* two very similar formats (ustar and pax).
|
||||
*/
|
||||
int
|
||||
__archive_write_format_header_ustar(struct archive_write *, char buff[512],
|
||||
struct archive_entry *, int tartype, int strict);
|
||||
|
||||
#endif
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct private_data {
|
||||
bz_stream stream;
|
||||
@ -62,23 +63,23 @@ struct private_data {
|
||||
#define SET_NEXT_IN(st,src) \
|
||||
(st)->stream.next_in = (char *)(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 *,
|
||||
static int archive_compressor_bzip2_finish(struct archive_write *);
|
||||
static int archive_compressor_bzip2_init(struct archive_write *);
|
||||
static int archive_compressor_bzip2_write(struct archive_write *,
|
||||
const void *, size_t);
|
||||
static int drive_compressor(struct archive_write *, struct private_data *,
|
||||
int finishing);
|
||||
|
||||
/*
|
||||
* Allocate, initialize and return an archive object.
|
||||
*/
|
||||
int
|
||||
archive_write_set_compression_bzip2(struct archive *a)
|
||||
archive_write_set_compression_bzip2(struct archive *_a)
|
||||
{
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_bzip2");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, 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);
|
||||
}
|
||||
|
||||
@ -86,23 +87,23 @@ archive_write_set_compression_bzip2(struct archive *a)
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_bzip2_init(struct archive *a)
|
||||
archive_compressor_bzip2_init(struct archive_write *a)
|
||||
{
|
||||
int ret;
|
||||
struct private_data *state;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
a->compression_name = "bzip2";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
a->archive.compression_name = "bzip2";
|
||||
|
||||
if (a->client_opener != NULL) {
|
||||
ret = (a->client_opener)(a, a->client_data);
|
||||
ret = (a->client_opener)(&a->archive, a->client_data);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
state = (struct private_data *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for compression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -112,7 +113,7 @@ archive_compressor_bzip2_init(struct archive *a)
|
||||
state->compressed = (char *)malloc(state->compressed_buffer_size);
|
||||
|
||||
if (state->compressed == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for compression buffer");
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -131,7 +132,7 @@ archive_compressor_bzip2_init(struct archive *a)
|
||||
}
|
||||
|
||||
/* Library setup failed: clean up. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library");
|
||||
free(state->compressed);
|
||||
free(state);
|
||||
@ -139,17 +140,17 @@ archive_compressor_bzip2_init(struct archive *a)
|
||||
/* Override the error message if we know what really went wrong. */
|
||||
switch (ret) {
|
||||
case BZ_PARAM_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid setup parameter");
|
||||
break;
|
||||
case BZ_MEM_ERROR:
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
case BZ_CONFIG_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"mis-compiled library");
|
||||
break;
|
||||
@ -165,14 +166,14 @@ archive_compressor_bzip2_init(struct archive *a)
|
||||
* Returns ARCHIVE_OK if all data written, error otherwise.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_bzip2_write(struct archive *a, const void *buff,
|
||||
archive_compressor_bzip2_write(struct archive_write *a, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)a->compression_data;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -186,7 +187,7 @@ archive_compressor_bzip2_write(struct archive *a, const void *buff,
|
||||
state->stream.avail_in = length;
|
||||
if (drive_compressor(a, state, 0))
|
||||
return (ARCHIVE_FATAL);
|
||||
a->file_position += length;
|
||||
a->archive.file_position += length;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -195,7 +196,7 @@ archive_compressor_bzip2_write(struct archive *a, const void *buff,
|
||||
* Finish the compression.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_bzip2_finish(struct archive *a)
|
||||
archive_compressor_bzip2_finish(struct archive_write *a)
|
||||
{
|
||||
ssize_t block_length;
|
||||
int ret;
|
||||
@ -207,7 +208,7 @@ archive_compressor_bzip2_finish(struct archive *a)
|
||||
state = (struct private_data *)a->compression_data;
|
||||
ret = ARCHIVE_OK;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered?\n"
|
||||
"This is probably an internal programming error.");
|
||||
ret = ARCHIVE_FATAL;
|
||||
@ -257,14 +258,14 @@ archive_compressor_bzip2_finish(struct archive *a)
|
||||
}
|
||||
|
||||
/* Write the last block */
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
bytes_written = (a->client_writer)(&a->archive, 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;
|
||||
a->archive.raw_position += ret;
|
||||
ret = ARCHIVE_OK;
|
||||
}
|
||||
|
||||
@ -274,7 +275,7 @@ archive_compressor_bzip2_finish(struct archive *a)
|
||||
case BZ_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Failed to clean up compressor");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
@ -284,7 +285,7 @@ archive_compressor_bzip2_finish(struct archive *a)
|
||||
|
||||
/* Close the output */
|
||||
if (a->client_closer != NULL)
|
||||
(a->client_closer)(a, a->client_data);
|
||||
(a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -297,15 +298,16 @@ archive_compressor_bzip2_finish(struct archive *a)
|
||||
* false) and the end-of-archive case (finishing == true).
|
||||
*/
|
||||
static int
|
||||
drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
drive_compressor(struct archive_write *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);
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, state->compressed,
|
||||
state->compressed_buffer_size);
|
||||
if (bytes_written <= 0) {
|
||||
/* TODO: Handle this write failure */
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -317,7 +319,7 @@ drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
state->compressed_buffer_size - bytes_written);
|
||||
}
|
||||
|
||||
a->raw_position += bytes_written;
|
||||
a->archive.raw_position += bytes_written;
|
||||
state->stream.next_out = state->compressed +
|
||||
state->compressed_buffer_size - bytes_written;
|
||||
state->stream.avail_out = bytes_written;
|
||||
@ -340,7 +342,8 @@ drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
return (ARCHIVE_OK);
|
||||
default:
|
||||
/* Any other return value indicates an error */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Bzip2 compression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct private_data {
|
||||
z_stream stream;
|
||||
@ -63,11 +64,11 @@ struct private_data {
|
||||
#define SET_NEXT_IN(st,src) \
|
||||
(st)->stream.next_in = (Bytef *)(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 *,
|
||||
static int archive_compressor_gzip_finish(struct archive_write *);
|
||||
static int archive_compressor_gzip_init(struct archive_write *);
|
||||
static int archive_compressor_gzip_write(struct archive_write *,
|
||||
const void *, size_t);
|
||||
static int drive_compressor(struct archive_write *, struct private_data *,
|
||||
int finishing);
|
||||
|
||||
|
||||
@ -75,12 +76,14 @@ static int drive_compressor(struct archive *, struct private_data *,
|
||||
* Allocate, initialize and return a archive object.
|
||||
*/
|
||||
int
|
||||
archive_write_set_compression_gzip(struct archive *a)
|
||||
archive_write_set_compression_gzip(struct archive *_a)
|
||||
{
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_gzip");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, 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";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_GZIP;
|
||||
a->archive.compression_name = "gzip";
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -88,24 +91,24 @@ archive_write_set_compression_gzip(struct archive *a)
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_init(struct archive *a)
|
||||
archive_compressor_gzip_init(struct archive_write *a)
|
||||
{
|
||||
int ret;
|
||||
struct private_data *state;
|
||||
time_t t;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_GZIP;
|
||||
a->compression_name = "gzip";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_GZIP;
|
||||
a->archive.compression_name = "gzip";
|
||||
|
||||
if (a->client_opener != NULL) {
|
||||
ret = (a->client_opener)(a, a->client_data);
|
||||
ret = (a->client_opener)(&a->archive, a->client_data);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
state = (struct private_data *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for compression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -116,7 +119,7 @@ archive_compressor_gzip_init(struct archive *a)
|
||||
state->crc = crc32(0L, NULL, 0);
|
||||
|
||||
if (state->compressed == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for compression buffer");
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -157,7 +160,7 @@ archive_compressor_gzip_init(struct archive *a)
|
||||
}
|
||||
|
||||
/* Library setup failed: clean up. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC, "Internal error "
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal error "
|
||||
"initializing compression library");
|
||||
free(state->compressed);
|
||||
free(state);
|
||||
@ -165,16 +168,16 @@ archive_compressor_gzip_init(struct archive *a)
|
||||
/* Override the error message if we know what really went wrong. */
|
||||
switch (ret) {
|
||||
case Z_STREAM_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing "
|
||||
"compression library: invalid setup parameter");
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(a, ENOMEM, "Internal error initializing "
|
||||
archive_set_error(&a->archive, ENOMEM, "Internal error initializing "
|
||||
"compression library");
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing "
|
||||
"compression library: invalid library version");
|
||||
break;
|
||||
@ -187,7 +190,7 @@ archive_compressor_gzip_init(struct archive *a)
|
||||
* Write data to the compressed stream.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_write(struct archive *a, const void *buff,
|
||||
archive_compressor_gzip_write(struct archive_write *a, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct private_data *state;
|
||||
@ -195,7 +198,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
|
||||
|
||||
state = (struct private_data *)a->compression_data;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -211,7 +214,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
|
||||
if ((ret = drive_compressor(a, state, 0)) != ARCHIVE_OK)
|
||||
return (ret);
|
||||
|
||||
a->file_position += length;
|
||||
a->archive.file_position += length;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -220,7 +223,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
|
||||
* Finish the compression...
|
||||
*/
|
||||
static int
|
||||
archive_compressor_gzip_finish(struct archive *a)
|
||||
archive_compressor_gzip_finish(struct archive_write *a)
|
||||
{
|
||||
ssize_t block_length, target_block_length, bytes_written;
|
||||
int ret;
|
||||
@ -231,7 +234,7 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
state = (struct private_data *)a->compression_data;
|
||||
ret = 0;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
ret = ARCHIVE_FATAL;
|
||||
@ -280,13 +283,13 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
|
||||
/* If it overflowed, flush and start a new block. */
|
||||
if (tocopy < 8) {
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
bytes_written = (a->client_writer)(&a->archive, a->client_data,
|
||||
state->compressed, state->compressed_buffer_size);
|
||||
if (bytes_written <= 0) {
|
||||
ret = ARCHIVE_FATAL;
|
||||
goto cleanup;
|
||||
}
|
||||
a->raw_position += bytes_written;
|
||||
a->archive.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);
|
||||
@ -317,13 +320,13 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
}
|
||||
|
||||
/* Write the last block */
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
bytes_written = (a->client_writer)(&a->archive, a->client_data,
|
||||
state->compressed, block_length);
|
||||
if (bytes_written <= 0) {
|
||||
ret = ARCHIVE_FATAL;
|
||||
goto cleanup;
|
||||
}
|
||||
a->raw_position += bytes_written;
|
||||
a->archive.raw_position += bytes_written;
|
||||
|
||||
/* Cleanup: shut down compressor, release memory, etc. */
|
||||
cleanup:
|
||||
@ -331,7 +334,7 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
case Z_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up compressor");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
@ -340,7 +343,7 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
|
||||
/* Close the output */
|
||||
if (a->client_closer != NULL)
|
||||
(a->client_closer)(a, a->client_data);
|
||||
(a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -353,15 +356,16 @@ archive_compressor_gzip_finish(struct archive *a)
|
||||
* false) and the end-of-archive case (finishing == true).
|
||||
*/
|
||||
static int
|
||||
drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
drive_compressor(struct archive_write *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);
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, state->compressed,
|
||||
state->compressed_buffer_size);
|
||||
if (bytes_written <= 0) {
|
||||
/* TODO: Handle this write failure */
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -372,7 +376,7 @@ drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
state->compressed + bytes_written,
|
||||
state->compressed_buffer_size - bytes_written);
|
||||
}
|
||||
a->raw_position += bytes_written;
|
||||
a->archive.raw_position += bytes_written;
|
||||
state->stream.next_out
|
||||
= state->compressed +
|
||||
state->compressed_buffer_size - bytes_written;
|
||||
@ -396,7 +400,7 @@ drive_compressor(struct archive *a, struct private_data *state, int finishing)
|
||||
return (ARCHIVE_OK);
|
||||
default:
|
||||
/* Any other return value indicates an error. */
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"GZip compression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
@ -38,11 +38,12 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_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);
|
||||
static int archive_compressor_none_finish(struct archive_write *a);
|
||||
static int archive_compressor_none_init(struct archive_write *);
|
||||
static int archive_compressor_none_write(struct archive_write *,
|
||||
const void *, size_t);
|
||||
|
||||
struct archive_none {
|
||||
char *buffer;
|
||||
@ -52,12 +53,12 @@ struct archive_none {
|
||||
};
|
||||
|
||||
int
|
||||
archive_write_set_compression_none(struct archive *a)
|
||||
archive_write_set_compression_none(struct archive *_a)
|
||||
{
|
||||
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_none");
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
__archive_check_magic(&a->archive, 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);
|
||||
}
|
||||
|
||||
@ -65,23 +66,23 @@ archive_write_set_compression_none(struct archive *a)
|
||||
* Setup callback.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_none_init(struct archive *a)
|
||||
archive_compressor_none_init(struct archive_write *a)
|
||||
{
|
||||
int ret;
|
||||
struct archive_none *state;
|
||||
|
||||
a->compression_code = ARCHIVE_COMPRESSION_NONE;
|
||||
a->compression_name = "none";
|
||||
a->archive.compression_code = ARCHIVE_COMPRESSION_NONE;
|
||||
a->archive.compression_name = "none";
|
||||
|
||||
if (a->client_opener != NULL) {
|
||||
ret = (a->client_opener)(a, a->client_data);
|
||||
ret = (a->client_opener)(&a->archive, a->client_data);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
state = (struct archive_none *)malloc(sizeof(*state));
|
||||
if (state == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate data for output buffering");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -91,7 +92,7 @@ archive_compressor_none_init(struct archive *a)
|
||||
if (state->buffer_size != 0) {
|
||||
state->buffer = (char *)malloc(state->buffer_size);
|
||||
if (state->buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate output buffer");
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -111,7 +112,7 @@ archive_compressor_none_init(struct archive *a)
|
||||
* Write data to the stream.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
archive_compressor_none_write(struct archive_write *a, const void *vbuff,
|
||||
size_t length)
|
||||
{
|
||||
const char *buff;
|
||||
@ -122,7 +123,7 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
state = (struct archive_none *)a->compression_data;
|
||||
buff = (const char *)vbuff;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -138,14 +139,14 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
*/
|
||||
if (state->buffer_size == 0) {
|
||||
while (remaining > 0) {
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
buff, remaining);
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, buff, remaining);
|
||||
if (bytes_written <= 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
remaining -= bytes_written;
|
||||
buff += bytes_written;
|
||||
}
|
||||
a->file_position += length;
|
||||
a->archive.file_position += length;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -155,12 +156,12 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
* output buffer.
|
||||
*/
|
||||
if (state->avail == 0) {
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
state->buffer, state->buffer_size);
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
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;
|
||||
a->archive.raw_position += bytes_written;
|
||||
state->next = state->buffer;
|
||||
state->avail = state->buffer_size;
|
||||
}
|
||||
@ -174,7 +175,7 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
buff += to_copy;
|
||||
remaining -= to_copy;
|
||||
}
|
||||
a->file_position += length;
|
||||
a->archive.file_position += length;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -183,7 +184,7 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
|
||||
* Finish the compression.
|
||||
*/
|
||||
static int
|
||||
archive_compressor_none_finish(struct archive *a)
|
||||
archive_compressor_none_finish(struct archive_write *a)
|
||||
{
|
||||
ssize_t block_length;
|
||||
ssize_t target_block_length;
|
||||
@ -195,7 +196,7 @@ archive_compressor_none_finish(struct archive *a)
|
||||
state = (struct archive_none *)a->compression_data;
|
||||
ret = ret2 = ARCHIVE_OK;
|
||||
if (a->client_writer == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"No write callback is registered? "
|
||||
"This is probably an internal programming error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -222,19 +223,19 @@ archive_compressor_none_finish(struct archive *a)
|
||||
target_block_length - block_length);
|
||||
block_length = target_block_length;
|
||||
}
|
||||
bytes_written = (a->client_writer)(a, a->client_data,
|
||||
state->buffer, block_length);
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, state->buffer, block_length);
|
||||
if (bytes_written <= 0)
|
||||
ret = ARCHIVE_FATAL;
|
||||
else {
|
||||
a->raw_position += bytes_written;
|
||||
a->archive.raw_position += bytes_written;
|
||||
ret = ARCHIVE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the output */
|
||||
if (a->client_closer != NULL)
|
||||
ret2 = (a->client_closer)(a, a->client_data);
|
||||
ret2 = (a->client_closer)(&a->archive, a->client_data);
|
||||
|
||||
free(state->buffer);
|
||||
free(state);
|
||||
|
@ -43,12 +43,14 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_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 *,
|
||||
static ssize_t archive_write_cpio_data(struct archive_write *,
|
||||
const void *buff, size_t s);
|
||||
static int archive_write_cpio_finish(struct archive_write *);
|
||||
static int archive_write_cpio_destroy(struct archive_write *);
|
||||
static int archive_write_cpio_finish_entry(struct archive_write *);
|
||||
static int archive_write_cpio_header(struct archive_write *,
|
||||
struct archive_entry *);
|
||||
static int format_octal(int64_t, void *, int);
|
||||
static int64_t format_octal_recursive(int64_t, char *, int);
|
||||
@ -75,17 +77,18 @@ struct cpio_header {
|
||||
* Set output format to 'cpio' format.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_cpio(struct archive *a)
|
||||
archive_write_set_format_cpio(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct cpio *cpio;
|
||||
|
||||
/* If someone else was already registered, unregister them. */
|
||||
if (a->format_finish != NULL)
|
||||
(a->format_finish)(a);
|
||||
if (a->format_destroy != NULL)
|
||||
(a->format_destroy)(a);
|
||||
|
||||
cpio = (struct cpio *)malloc(sizeof(*cpio));
|
||||
if (cpio == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate cpio data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
@ -96,13 +99,14 @@ archive_write_set_format_cpio(struct archive *a)
|
||||
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->format_destroy = archive_write_cpio_destroy;
|
||||
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)
|
||||
archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
const char *p, *path;
|
||||
@ -126,7 +130,7 @@ archive_write_cpio_header(struct archive *a, struct archive_entry *entry)
|
||||
* field only limits the number of files in the archive.
|
||||
*/
|
||||
if (st->st_ino > 0777777) {
|
||||
archive_set_error(a, ERANGE, "large inode number truncated");
|
||||
archive_set_error(&a->archive, ERANGE, "large inode number truncated");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
@ -167,7 +171,7 @@ archive_write_cpio_header(struct archive *a, struct archive_entry *entry)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
archive_write_cpio_data(struct archive *a, const void *buff, size_t s)
|
||||
archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
int ret;
|
||||
@ -215,7 +219,7 @@ format_octal_recursive(int64_t v, char *p, int s)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_cpio_finish(struct archive *a)
|
||||
archive_write_cpio_finish(struct archive_write *a)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
struct stat st;
|
||||
@ -230,14 +234,22 @@ archive_write_cpio_finish(struct archive *a)
|
||||
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)
|
||||
archive_write_cpio_destroy(struct archive_write *a)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
|
||||
cpio = (struct cpio *)a->format_data;
|
||||
free(cpio);
|
||||
a->format_data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_cpio_finish_entry(struct archive_write *a)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
int to_write, ret;
|
||||
|
@ -52,12 +52,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_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,
|
||||
@ -69,11 +69,12 @@ static void add_pax_attr_time(struct archive_string *,
|
||||
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 *,
|
||||
static ssize_t archive_write_pax_data(struct archive_write *,
|
||||
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 *,
|
||||
static int archive_write_pax_finish(struct archive_write *);
|
||||
static int archive_write_pax_destroy(struct archive_write *);
|
||||
static int archive_write_pax_finish_entry(struct archive_write *);
|
||||
static int archive_write_pax_header(struct archive_write *,
|
||||
struct archive_entry *);
|
||||
static char *base64_encode(const char *src, size_t len);
|
||||
static char *build_pax_attribute_name(char *dest, const char *src);
|
||||
@ -82,7 +83,7 @@ static char *build_ustar_entry_name(char *dest, const char *src,
|
||||
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);
|
||||
static int write_nulls(struct archive_write *, size_t);
|
||||
|
||||
/*
|
||||
* Set output format to 'restricted pax' format.
|
||||
@ -92,10 +93,11 @@ static int write_nulls(struct archive *, size_t);
|
||||
* bsdtar, for instance.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_pax_restricted(struct archive *a)
|
||||
archive_write_set_format_pax_restricted(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
int r;
|
||||
r = archive_write_set_format_pax(a);
|
||||
r = archive_write_set_format_pax(&a->archive);
|
||||
a->archive_format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
|
||||
a->archive_format_name = "restricted POSIX pax interchange";
|
||||
return (r);
|
||||
@ -105,16 +107,17 @@ archive_write_set_format_pax_restricted(struct archive *a)
|
||||
* Set output format to 'pax' format.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_pax(struct archive *a)
|
||||
archive_write_set_format_pax(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct pax *pax;
|
||||
|
||||
if (a->format_finish != NULL)
|
||||
(a->format_finish)(a);
|
||||
if (a->format_destroy != NULL)
|
||||
(a->format_destroy)(a);
|
||||
|
||||
pax = (struct pax *)malloc(sizeof(*pax));
|
||||
if (pax == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate pax data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate pax data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(pax, 0, sizeof(*pax));
|
||||
@ -124,6 +127,7 @@ archive_write_set_format_pax(struct archive *a)
|
||||
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_destroy = archive_write_pax_destroy;
|
||||
a->format_finish_entry = archive_write_pax_finish_entry;
|
||||
a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
a->archive_format_name = "POSIX pax interchange";
|
||||
@ -388,7 +392,7 @@ archive_write_pax_header_xattrs(struct pax *pax, struct archive_entry *entry)
|
||||
* key/value data.
|
||||
*/
|
||||
static int
|
||||
archive_write_pax_header(struct archive *a,
|
||||
archive_write_pax_header(struct archive_write *a,
|
||||
struct archive_entry *entry_original)
|
||||
{
|
||||
struct archive_entry *entry_main;
|
||||
@ -407,7 +411,6 @@ archive_write_pax_header(struct archive *a,
|
||||
|
||||
need_extension = 0;
|
||||
pax = (struct pax *)a->format_data;
|
||||
pax->written = 1;
|
||||
|
||||
st_original = archive_entry_stat(entry_original);
|
||||
|
||||
@ -424,11 +427,11 @@ archive_write_pax_header(struct archive *a,
|
||||
case S_IFIFO:
|
||||
break;
|
||||
case S_IFSOCK:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"tar format cannot archive socket");
|
||||
return (ARCHIVE_WARN);
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"tar format cannot archive this (mode=0%lo)",
|
||||
(unsigned long)st_original->st_mode);
|
||||
return (ARCHIVE_WARN);
|
||||
@ -1038,23 +1041,33 @@ build_pax_attribute_name(char *dest, const char *src)
|
||||
|
||||
/* Write two null blocks for the end of archive */
|
||||
static int
|
||||
archive_write_pax_finish(struct archive *a)
|
||||
archive_write_pax_finish(struct archive_write *a)
|
||||
{
|
||||
struct pax *pax;
|
||||
int r;
|
||||
|
||||
r = ARCHIVE_OK;
|
||||
if (a->compression_write == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
pax = (struct 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;
|
||||
r = write_nulls(a, 512 * 2);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_pax_finish_entry(struct archive *a)
|
||||
archive_write_pax_destroy(struct archive_write *a)
|
||||
{
|
||||
struct pax *pax;
|
||||
|
||||
pax = (struct pax *)a->format_data;
|
||||
archive_string_free(&pax->pax_header);
|
||||
free(pax);
|
||||
a->format_data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_pax_finish_entry(struct archive_write *a)
|
||||
{
|
||||
struct pax *pax;
|
||||
int ret;
|
||||
@ -1066,7 +1079,7 @@ archive_write_pax_finish_entry(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
write_nulls(struct archive *a, size_t padding)
|
||||
write_nulls(struct archive_write *a, size_t padding)
|
||||
{
|
||||
int ret, to_write;
|
||||
|
||||
@ -1081,13 +1094,12 @@ write_nulls(struct archive *a, size_t padding)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
archive_write_pax_data(struct archive *a, const void *buff, size_t s)
|
||||
archive_write_pax_data(struct archive_write *a, const void *buff, size_t s)
|
||||
{
|
||||
struct pax *pax;
|
||||
int ret;
|
||||
|
||||
pax = (struct pax *)a->format_data;
|
||||
pax->written = 1;
|
||||
if (s > pax->entry_bytes_remaining)
|
||||
s = pax->entry_bytes_remaining;
|
||||
|
||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct shar {
|
||||
int dump;
|
||||
@ -60,19 +61,20 @@ struct shar {
|
||||
struct archive_string work;
|
||||
};
|
||||
|
||||
static int archive_write_shar_finish(struct archive *);
|
||||
static int archive_write_shar_header(struct archive *,
|
||||
static int archive_write_shar_finish(struct archive_write *);
|
||||
static int archive_write_shar_destroy(struct archive_write *);
|
||||
static int archive_write_shar_header(struct archive_write *,
|
||||
struct archive_entry *);
|
||||
static ssize_t archive_write_shar_data_sed(struct archive *,
|
||||
static ssize_t archive_write_shar_data_sed(struct archive_write *,
|
||||
const void * buff, size_t);
|
||||
static ssize_t archive_write_shar_data_uuencode(struct archive *,
|
||||
static ssize_t archive_write_shar_data_uuencode(struct archive_write *,
|
||||
const void * buff, size_t);
|
||||
static int archive_write_shar_finish_entry(struct archive *);
|
||||
static int shar_printf(struct archive *, const char *fmt, ...);
|
||||
static int archive_write_shar_finish_entry(struct archive_write *);
|
||||
static int shar_printf(struct archive_write *, const char *fmt, ...);
|
||||
static void uuencode_group(struct shar *);
|
||||
|
||||
static int
|
||||
shar_printf(struct archive *a, const char *fmt, ...)
|
||||
shar_printf(struct archive_write *a, const char *fmt, ...)
|
||||
{
|
||||
struct shar *shar;
|
||||
va_list ap;
|
||||
@ -91,17 +93,18 @@ shar_printf(struct archive *a, const char *fmt, ...)
|
||||
* Set output format to 'shar' format.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_shar(struct archive *a)
|
||||
archive_write_set_format_shar(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct shar *shar;
|
||||
|
||||
/* If someone else was already registered, unregister them. */
|
||||
if (a->format_finish != NULL)
|
||||
(a->format_finish)(a);
|
||||
if (a->format_destroy != NULL)
|
||||
(a->format_destroy)(a);
|
||||
|
||||
shar = (struct shar *)malloc(sizeof(*shar));
|
||||
if (shar == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate shar data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(shar, 0, sizeof(*shar));
|
||||
@ -110,6 +113,7 @@ archive_write_set_format_shar(struct archive *a)
|
||||
a->pad_uncompressed = 0;
|
||||
a->format_write_header = archive_write_shar_header;
|
||||
a->format_finish = archive_write_shar_finish;
|
||||
a->format_destroy = archive_write_shar_destroy;
|
||||
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;
|
||||
@ -124,11 +128,12 @@ archive_write_set_format_shar(struct archive *a)
|
||||
* and other extended file information.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_shar_dump(struct archive *a)
|
||||
archive_write_set_format_shar_dump(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct shar *shar;
|
||||
|
||||
archive_write_set_format_shar(a);
|
||||
archive_write_set_format_shar(&a->archive);
|
||||
shar = (struct shar *)a->format_data;
|
||||
shar->dump = 1;
|
||||
a->format_write_data = archive_write_shar_data_uuencode;
|
||||
@ -138,7 +143,7 @@ archive_write_set_format_shar_dump(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_shar_header(struct archive *a, struct archive_entry *entry)
|
||||
archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
{
|
||||
const char *linkname;
|
||||
const char *name;
|
||||
@ -186,7 +191,7 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
|
||||
archive_entry_set_size(entry, 0);
|
||||
if (archive_entry_hardlink(entry) == NULL &&
|
||||
archive_entry_symlink(entry) == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"shar format cannot archive this");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
@ -323,7 +328,7 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
|
||||
|
||||
/* 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)
|
||||
archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n)
|
||||
{
|
||||
struct shar *shar;
|
||||
const char *src;
|
||||
@ -387,7 +392,7 @@ uuencode_group(struct shar *shar)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
archive_write_shar_data_uuencode(struct archive *a, const void *buff,
|
||||
archive_write_shar_data_uuencode(struct archive_write *a, const void *buff,
|
||||
size_t length)
|
||||
{
|
||||
struct shar *shar;
|
||||
@ -419,7 +424,7 @@ archive_write_shar_data_uuencode(struct archive *a, const void *buff,
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_shar_finish_entry(struct archive *a)
|
||||
archive_write_shar_finish_entry(struct archive_write *a)
|
||||
{
|
||||
const char *g, *p, *u;
|
||||
struct shar *shar;
|
||||
@ -504,7 +509,7 @@ archive_write_shar_finish_entry(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_shar_finish(struct archive *a)
|
||||
archive_write_shar_finish(struct archive_write *a)
|
||||
{
|
||||
struct shar *shar;
|
||||
int ret;
|
||||
@ -527,12 +532,21 @@ archive_write_shar_finish(struct archive *a)
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
/* Shar output is never padded. */
|
||||
archive_write_set_bytes_in_last_block(a, 1);
|
||||
archive_write_set_bytes_in_last_block(&a->archive, 1);
|
||||
/*
|
||||
* TODO: shar should also suppress padding of
|
||||
* uncompressed data within gzip/bzip2 streams.
|
||||
*/
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_shar_destroy(struct archive_write *a)
|
||||
{
|
||||
struct shar *shar;
|
||||
|
||||
shar = (struct shar *)a->format_data;
|
||||
if (shar->entry != NULL)
|
||||
archive_entry_free(shar->entry);
|
||||
if (shar->last_dir != NULL)
|
||||
|
@ -50,11 +50,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
|
||||
struct ustar {
|
||||
uint64_t entry_bytes_remaining;
|
||||
uint64_t entry_padding;
|
||||
char written;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -150,38 +150,40 @@ static const char template_header[] = {
|
||||
0,0,0,0,0,0,0,0, 0,0,0,0
|
||||
};
|
||||
|
||||
static ssize_t archive_write_ustar_data(struct archive *a, const void *buff,
|
||||
static ssize_t archive_write_ustar_data(struct archive_write *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 *,
|
||||
static int archive_write_ustar_destroy(struct archive_write *);
|
||||
static int archive_write_ustar_finish(struct archive_write *);
|
||||
static int archive_write_ustar_finish_entry(struct archive_write *);
|
||||
static int archive_write_ustar_header(struct archive_write *,
|
||||
struct archive_entry *entry);
|
||||
static int 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);
|
||||
static int write_nulls(struct archive_write *a, size_t);
|
||||
|
||||
/*
|
||||
* Set output format to 'ustar' format.
|
||||
*/
|
||||
int
|
||||
archive_write_set_format_ustar(struct archive *a)
|
||||
archive_write_set_format_ustar(struct archive *_a)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct ustar *ustar;
|
||||
|
||||
/* If someone else was already registered, unregister them. */
|
||||
if (a->format_finish != NULL)
|
||||
(a->format_finish)(a);
|
||||
if (a->format_destroy != NULL)
|
||||
(a->format_destroy)(a);
|
||||
|
||||
/* Basic internal sanity test. */
|
||||
if (sizeof(template_header) != 512) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header));
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header));
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
ustar = (struct ustar *)malloc(sizeof(*ustar));
|
||||
if (ustar == NULL) {
|
||||
archive_set_error(a, ENOMEM, "Can't allocate ustar data");
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ustar, 0, sizeof(*ustar));
|
||||
@ -191,6 +193,7 @@ archive_write_set_format_ustar(struct archive *a)
|
||||
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_destroy = archive_write_ustar_destroy;
|
||||
a->format_finish_entry = archive_write_ustar_finish_entry;
|
||||
a->archive_format = ARCHIVE_FORMAT_TAR_USTAR;
|
||||
a->archive_format_name = "POSIX ustar";
|
||||
@ -198,14 +201,13 @@ archive_write_set_format_ustar(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
|
||||
archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
{
|
||||
char buff[512];
|
||||
int ret;
|
||||
struct ustar *ustar;
|
||||
|
||||
ustar = (struct ustar *)a->format_data;
|
||||
ustar->written = 1;
|
||||
|
||||
/* Only regular files (not hardlinks) have data. */
|
||||
if (archive_entry_hardlink(entry) != NULL ||
|
||||
@ -236,7 +238,7 @@ archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
|
||||
* This is exported so that other 'tar' formats can use it.
|
||||
*/
|
||||
int
|
||||
__archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
__archive_write_format_header_ustar(struct archive_write *a, char h[512],
|
||||
struct archive_entry *entry, int tartype, int strict)
|
||||
{
|
||||
unsigned int checksum;
|
||||
@ -272,11 +274,11 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
* remaining name are too large, return an error.
|
||||
*/
|
||||
if (!p) {
|
||||
archive_set_error(a, ENAMETOOLONG,
|
||||
archive_set_error(&a->archive, ENAMETOOLONG,
|
||||
"Pathname too long");
|
||||
ret = ARCHIVE_WARN;
|
||||
} else if (p > pp + USTAR_prefix_size) {
|
||||
archive_set_error(a, ENAMETOOLONG,
|
||||
archive_set_error(&a->archive, ENAMETOOLONG,
|
||||
"Pathname too long");
|
||||
ret = ARCHIVE_WARN;
|
||||
} else {
|
||||
@ -294,7 +296,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
if (p != NULL && p[0] != '\0') {
|
||||
copy_length = strlen(p);
|
||||
if (copy_length > USTAR_linkname_size) {
|
||||
archive_set_error(a, ENAMETOOLONG,
|
||||
archive_set_error(&a->archive, ENAMETOOLONG,
|
||||
"Link contents too long");
|
||||
ret = ARCHIVE_WARN;
|
||||
copy_length = USTAR_linkname_size;
|
||||
@ -306,7 +308,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
if (p != NULL && p[0] != '\0') {
|
||||
copy_length = strlen(p);
|
||||
if (copy_length > USTAR_uname_size) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Username too long");
|
||||
ret = ARCHIVE_WARN;
|
||||
copy_length = USTAR_uname_size;
|
||||
@ -318,7 +320,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
if (p != NULL && p[0] != '\0') {
|
||||
copy_length = strlen(p);
|
||||
if (strlen(p) > USTAR_gname_size) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Group name too long");
|
||||
ret = ARCHIVE_WARN;
|
||||
copy_length = USTAR_gname_size;
|
||||
@ -329,27 +331,27 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
st = archive_entry_stat(entry);
|
||||
|
||||
if (format_number(st->st_mode & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE, "Numeric mode too large");
|
||||
archive_set_error(&a->archive, ERANGE, "Numeric mode too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
if (format_number(st->st_uid, h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE, "Numeric user ID too large");
|
||||
archive_set_error(&a->archive, ERANGE, "Numeric user ID too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
if (format_number(st->st_gid, h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE, "Numeric group ID too large");
|
||||
archive_set_error(&a->archive, ERANGE, "Numeric group ID too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
if (format_number(st->st_size, h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE, "File size out of range");
|
||||
archive_set_error(&a->archive, ERANGE, "File size out of range");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
if (format_number(st->st_mtime, h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE,
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"File modification time too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
@ -357,14 +359,14 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) {
|
||||
if (format_number(major(st->st_rdev), h + USTAR_rdevmajor_offset,
|
||||
USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE,
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Major device number too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
|
||||
if (format_number(minor(st->st_rdev), h + USTAR_rdevminor_offset,
|
||||
USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) {
|
||||
archive_set_error(a, ERANGE,
|
||||
archive_set_error(&a->archive, ERANGE,
|
||||
"Minor device number too large");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
@ -383,12 +385,12 @@ __archive_write_format_header_ustar(struct archive *a, char h[512],
|
||||
case S_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
|
||||
case S_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
|
||||
case S_IFSOCK:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"tar format cannot archive socket");
|
||||
ret = ARCHIVE_WARN;
|
||||
break;
|
||||
default:
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"tar format cannot archive this (mode=0%lo)",
|
||||
(unsigned long)st->st_mode);
|
||||
ret = ARCHIVE_WARN;
|
||||
@ -486,27 +488,32 @@ format_octal(int64_t v, char *p, int s)
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_ustar_finish(struct archive *a)
|
||||
archive_write_ustar_finish(struct archive_write *a)
|
||||
{
|
||||
struct ustar *ustar;
|
||||
int r;
|
||||
|
||||
r = ARCHIVE_OK;
|
||||
if (a->compression_write == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
ustar = (struct 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;
|
||||
r = write_nulls(a, 512*2);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_ustar_finish_entry(struct archive *a)
|
||||
archive_write_ustar_destroy(struct archive_write *a)
|
||||
{
|
||||
struct ustar *ustar;
|
||||
|
||||
ustar = (struct ustar *)a->format_data;
|
||||
free(ustar);
|
||||
a->format_data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_ustar_finish_entry(struct archive_write *a)
|
||||
{
|
||||
struct ustar *ustar;
|
||||
int ret;
|
||||
@ -519,7 +526,7 @@ archive_write_ustar_finish_entry(struct archive *a)
|
||||
}
|
||||
|
||||
static int
|
||||
write_nulls(struct archive *a, size_t padding)
|
||||
write_nulls(struct archive_write *a, size_t padding)
|
||||
{
|
||||
int ret, to_write;
|
||||
|
||||
@ -534,7 +541,7 @@ write_nulls(struct archive *a, size_t padding)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
archive_write_ustar_data(struct archive *a, const void *buff, size_t s)
|
||||
archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
|
||||
{
|
||||
struct ustar *ustar;
|
||||
int ret;
|
||||
|
67
lib/libarchive/test/Makefile
Normal file
67
lib/libarchive/test/Makefile
Normal file
@ -0,0 +1,67 @@
|
||||
# $FreeBSD$
|
||||
|
||||
TESTS= \
|
||||
test_archive_api_feature.c \
|
||||
test_bad_fd.c \
|
||||
test_read_data_large.c \
|
||||
test_read_extract.c \
|
||||
test_read_format_cpio_bin.c \
|
||||
test_read_format_cpio_bin_Z.c \
|
||||
test_read_format_cpio_bin_bz2.c \
|
||||
test_read_format_cpio_bin_gz.c \
|
||||
test_read_format_cpio_odc.c \
|
||||
test_read_format_cpio_svr4_gzip.c \
|
||||
test_read_format_cpio_svr4c_Z.c \
|
||||
test_read_format_empty.c \
|
||||
test_read_format_gtar_gz.c \
|
||||
test_read_format_iso_gz.c \
|
||||
test_read_format_isorr_bz2.c \
|
||||
test_read_format_pax_bz2.c \
|
||||
test_read_format_tar.c \
|
||||
test_read_format_tbz.c \
|
||||
test_read_format_tgz.c \
|
||||
test_read_format_tz.c \
|
||||
test_read_format_zip.c \
|
||||
test_read_large.c \
|
||||
test_read_position.c \
|
||||
test_read_truncated.c \
|
||||
test_write_disk.c \
|
||||
test_write_disk_perms.c \
|
||||
test_write_disk_secure.c \
|
||||
test_write_format_cpio_empty.c \
|
||||
test_write_format_shar_empty.c \
|
||||
test_write_format_tar.c \
|
||||
test_write_format_tar_empty.c \
|
||||
test_write_open_memory.c
|
||||
|
||||
SRCS= ${TESTS} \
|
||||
list.h \
|
||||
main.c
|
||||
|
||||
CLEANFILES+= list.h
|
||||
|
||||
MK_MAN=no
|
||||
NO_MAN=yes
|
||||
|
||||
PROG=libarchive_test
|
||||
DPADD=${LIBARCHIVE} ${LIBBZ2} ${LIBZ}
|
||||
LDADD= -larchive -lz -lbz2
|
||||
CFLAGS+= -static -g
|
||||
CFLAGS+= -I${.OBJDIR}
|
||||
|
||||
test: libarchive_test
|
||||
./libarchive_test
|
||||
|
||||
list.h: ${TESTS} Makefile
|
||||
(cd ${.CURDIR}; cat ${TESTS}) | grep DEFINE_TEST > list.h
|
||||
|
||||
clean:
|
||||
rm -f *.out
|
||||
rm -f *.o
|
||||
rm -f *.core
|
||||
rm -f *~
|
||||
rm -f list.h
|
||||
-chmod -R +w /tmp/libarchive_test.*
|
||||
rm -rf /tmp/libarchive_test.*
|
||||
|
||||
.include <bsd.prog.mk>
|
46
lib/libarchive/test/README
Normal file
46
lib/libarchive/test/README
Normal file
@ -0,0 +1,46 @@
|
||||
$FreeBSD$
|
||||
|
||||
This is the test harness for libarchive.
|
||||
|
||||
It compiles into a single program "libarchive_test" that is intended
|
||||
to exercise as much of the library as possible. It is, of course,
|
||||
very much a work in progress.
|
||||
|
||||
Each test is a function named test_foo in a file named test_foo.c.
|
||||
Note that the file name is the same as the function name.
|
||||
Each file must start with this line:
|
||||
|
||||
#include "test.h"
|
||||
|
||||
The test function must be declared with a line of this form
|
||||
|
||||
DEFINE_TEST(test_foo)
|
||||
|
||||
Nothing else should appear on that line.
|
||||
|
||||
When you add a test, please update the Makefile to add your
|
||||
file to the list of tests. The Makefile and main.c use various
|
||||
macro trickery to automatically collect a list of test functions
|
||||
to be invoked.
|
||||
|
||||
Each test function can rely on the following:
|
||||
|
||||
* The current directory will be a freshly-created empty directory
|
||||
suitable for that test. (The top-level main() creates a
|
||||
directory for each separate test and chdir()s to that directory
|
||||
before running the test.)
|
||||
|
||||
* The test function should use assert(), assertA() and similar macros
|
||||
defined in test.h. If you need to add new macros of this form, feel
|
||||
free to do so.
|
||||
|
||||
* You are encouraged to document each assertion with a failure() call
|
||||
just before the assert. The failure() function is a printf-like
|
||||
function whose text is displayed only if the assertion fails. It
|
||||
can be used to display additional information relevant to the failure:
|
||||
|
||||
failure("The data read from file %s did not match the data written to that file.", filename);
|
||||
assert(strcmp(buff1, buff2) == 0);
|
||||
|
||||
* Tests are encouraged to be economical with their memory and disk usage,
|
||||
though this is not essential.
|
168
lib/libarchive/test/main.c
Normal file
168
lib/libarchive/test/main.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Various utility routines useful for test programs.
|
||||
* Each test program is linked against this file.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* My own implementation of the standard assert() macro emits the
|
||||
* message in the same format as GCC (file:line: message).
|
||||
* It also includes some additional useful information.
|
||||
* This makes it a lot easier to skim through test failures in
|
||||
* Emacs. ;-)
|
||||
*
|
||||
* It also supports a few special features specifically to simplify
|
||||
* libarchive test harnesses:
|
||||
* failure(fmt, args) -- Stores a text string that gets
|
||||
* printed if the following assertion fails, good for
|
||||
* explaining subtle tests.
|
||||
* assertA(a, cond) -- If the test fails, also prints out any error
|
||||
* message stored in archive object 'a'.
|
||||
*/
|
||||
static char msg[4096];
|
||||
|
||||
void
|
||||
failure(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsprintf(msg, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
test_assert(const char *file, int line, int value, const char *condition, struct archive *a)
|
||||
{
|
||||
if (value) {
|
||||
msg[0] = '\0';
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
|
||||
fprintf(stderr, " Condition: %s\n", condition);
|
||||
if (msg[0] != '\0') {
|
||||
fprintf(stderr, " Description: %s\n", msg);
|
||||
msg[0] = '\0';
|
||||
}
|
||||
if (a != NULL) {
|
||||
fprintf(stderr, " archive error: %s\n", archive_error_string(a));
|
||||
}
|
||||
*(char *)(NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
test_assert_equal_int(const char *file, int line,
|
||||
int v1, const char *e1, int v2, const char *e2, struct archive *a)
|
||||
{
|
||||
if (v1 == v2) {
|
||||
msg[0] = '\0';
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s:%d: Assertion failed\n", file, line);
|
||||
fprintf(stderr, " Condition: %s==%s\n", e1, e2);
|
||||
fprintf(stderr, " %s=%d\n", e1, v1);
|
||||
fprintf(stderr, " %s=%d\n", e2, v2);
|
||||
if (msg[0] != '\0') {
|
||||
fprintf(stderr, " Description: %s\n", msg);
|
||||
msg[0] = '\0';
|
||||
}
|
||||
if (a != NULL) {
|
||||
fprintf(stderr, " archive error: %s\n", archive_error_string(a));
|
||||
}
|
||||
*(char *)(NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* "list.h" is automatically generated; it just has a lot of lines like:
|
||||
* DEFINE_TEST(function_name)
|
||||
* The common "test.h" includes it to declare all of the test functions.
|
||||
* We reuse it here to define a list of all tests to run.
|
||||
*/
|
||||
#undef DEFINE_TEST
|
||||
#define DEFINE_TEST(n) n, #n,
|
||||
struct { void (*func)(void); char *name; } tests[] = {
|
||||
#include "list.h"
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void (*f)(void);
|
||||
int limit = sizeof(tests) / sizeof(tests[0]);
|
||||
int i;
|
||||
time_t now;
|
||||
char tmpdir[256];
|
||||
int tmpdirHandle;
|
||||
|
||||
/*
|
||||
* Create a temp directory for the following tests.
|
||||
* Include the time the tests started as part of the name,
|
||||
* to make it easier to track the results of multiple tests.
|
||||
*/
|
||||
now = time(NULL);
|
||||
strftime(tmpdir, sizeof(tmpdir),
|
||||
"/tmp/libarchive_test.%Y-%m-%dT%H.%M.%S.XXXXXX",
|
||||
localtime(&now));
|
||||
if (mkdtemp(tmpdir) == NULL) {
|
||||
fprintf(stderr, "ERROR: Unable to create temp directory %s\n",
|
||||
tmpdir);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Running libarchive tests in: %s\n", tmpdir);
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
printf("%d: %s\n", i, tests[i].name);
|
||||
if (chdir(tmpdir)) {
|
||||
fprintf(stderr,
|
||||
"ERROR: Couldn't chdir to temp dir %s\n",
|
||||
tmpdir);
|
||||
exit(1);
|
||||
}
|
||||
/* Create a temp directory for this specific test. */
|
||||
if (mkdir(tests[i].name, 0755)) {
|
||||
fprintf(stderr,
|
||||
"ERROR: Couldn't create temp dir ``%s''\n",
|
||||
tests[i].name);
|
||||
exit(1);
|
||||
}
|
||||
if (chdir(tests[i].name)) {
|
||||
fprintf(stderr,
|
||||
"ERROR: Couldn't chdir to temp dir ``%s''\n",
|
||||
tests[i].name);
|
||||
exit(1);
|
||||
}
|
||||
(*tests[i].func)();
|
||||
}
|
||||
printf("%d tests succeeded.\n", limit);
|
||||
return (0);
|
||||
}
|
89
lib/libarchive/test/test.h
Normal file
89
lib/libarchive/test/test.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* Every test program should #include "test.h" as the first thing. */
|
||||
|
||||
/*
|
||||
* The goal of this file (and the matching test.c) is to
|
||||
* simplify the very repetitive test-*.c test programs.
|
||||
*/
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
/* Most POSIX platforms use the 'configure' script to build config.h */
|
||||
#include "../../config.h"
|
||||
#elif defined(__FreeBSD__)
|
||||
/* Building as part of FreeBSD system requires a pre-built config.h. */
|
||||
#include "../config_freebsd.h"
|
||||
#elif defined(_WIN32)
|
||||
/* Win32 can't run the 'configure' script. */
|
||||
#include "../config_windows.h"
|
||||
#else
|
||||
/* Warn if the library hasn't been (automatically or manually) configured. */
|
||||
#error Oops: No config.h and no pre-built configuration in test.h.
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* "list.h" is simply created by "grep DEFINE_TEST"; it has
|
||||
* a line like
|
||||
* DEFINE_TEST(test_function)
|
||||
* for each test.
|
||||
* Include it here with a suitable DEFINE_TEST to declare all of the
|
||||
* test functions.
|
||||
*/
|
||||
#define DEFINE_TEST(name) void name(void);
|
||||
#include "list.h"
|
||||
/*
|
||||
* Redefine DEFINE_TEST for use in defining the test functions.
|
||||
*/
|
||||
#undef DEFINE_TEST
|
||||
#define DEFINE_TEST(name) void name(void)
|
||||
|
||||
/* An implementation of the standard assert() macro */
|
||||
#define assert(e) test_assert(__FILE__, __LINE__, (e), #e, NULL)
|
||||
/* As above, but reports any archive_error found in variable 'a' */
|
||||
#define assertA(e) test_assert(__FILE__, __LINE__, (e), #e, (a))
|
||||
/* Asserts that two values are the same. Reports value of each one if not. */
|
||||
#define assertEqualIntA(a,v1,v2) \
|
||||
test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
|
||||
/* Asserts that two values are the same. Reports value of each one if not. */
|
||||
#define assertEqualInt(v1,v2) \
|
||||
test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
|
||||
/* Function declarations. These are defined in test_utility.c. */
|
||||
void failure(const char *fmt, ...);
|
||||
void test_assert(const char *, int, int, const char *, struct archive *);
|
||||
void test_assert_equal_int(const char *, int, int, const char *, int, const char *, struct archive *);
|
||||
|
33
lib/libarchive/test/test_archive_api_feature.c
Normal file
33
lib/libarchive/test/test_archive_api_feature.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_archive_api_feature)
|
||||
{
|
||||
assert(ARCHIVE_API_FEATURE == archive_api_feature());
|
||||
assert(ARCHIVE_API_VERSION == archive_api_version());
|
||||
assert(0 == (strcmp(ARCHIVE_LIBRARY_VERSION, archive_version())));
|
||||
}
|
41
lib/libarchive/test/test_bad_fd.c
Normal file
41
lib/libarchive/test/test_bad_fd.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Verify that attempting to open an invalid fd returns correct error. */
|
||||
DEFINE_TEST(test_bad_fd)
|
||||
{
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(ARCHIVE_FATAL == archive_read_open_fd(a, -1, 1024));
|
||||
assertA(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
116
lib/libarchive/test/test_read_data_large.c
Normal file
116
lib/libarchive/test/test_read_data_large.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Test read/write of a 10M block of data in a single operation.
|
||||
* Uses an in-memory archive with a single 10M entry. Exercises
|
||||
* archive_read_data() to ensure it can handle large blocks like
|
||||
* this and also exercises archive_read_data_into_fd() (which
|
||||
* had a bug relating to this, fixed in Nov 2006).
|
||||
*/
|
||||
|
||||
char buff1[11000000];
|
||||
char buff2[10000000];
|
||||
char buff3[10000000];
|
||||
|
||||
DEFINE_TEST(test_read_data_large)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
char tmpfilename[] = "largefile";
|
||||
int tmpfile;
|
||||
int i;
|
||||
size_t used;
|
||||
|
||||
/* Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_open_memory(a, buff1, sizeof(buff1), &used));
|
||||
|
||||
/*
|
||||
* Write a file (with random contents) to it.
|
||||
*/
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0755);
|
||||
for (i = 0; i < sizeof(buff2); i++)
|
||||
buff2[i] = (unsigned char)rand();
|
||||
archive_entry_set_size(ae, sizeof(buff2));
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(sizeof(buff2) == archive_write_data(a, buff2, sizeof(buff2)));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
/* Check that archive_read_data can handle 10*10^6 at a pop. */
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
failure("Wrote 10MB, but didn't read the same amount");
|
||||
assertEqualIntA(a, sizeof(buff2),archive_read_data(a, buff3, sizeof(buff3)));
|
||||
failure("Read expected 10MB, but data read didn't match what was written");
|
||||
assert(0 == memcmp(buff2, buff3, sizeof(buff3)));
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
|
||||
/* Check archive_read_data_into_fd */
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
tmpfile = open(tmpfilename, O_WRONLY | O_CREAT, 0777);
|
||||
assert(tmpfile != 0);
|
||||
assertEqualIntA(a, 0, archive_read_data_into_fd(a, tmpfile));
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
close(tmpfile);
|
||||
|
||||
tmpfile = open(tmpfilename, O_RDONLY);
|
||||
assert(tmpfile != 0);
|
||||
assertEqualIntA(NULL, sizeof(buff3), read(tmpfile, buff3, sizeof(buff3)));
|
||||
close(tmpfile);
|
||||
assert(0 == memcmp(buff2, buff3, sizeof(buff3)));
|
||||
|
||||
unlink(tmpfilename);
|
||||
}
|
177
lib/libarchive/test/test_read_extract.c
Normal file
177
lib/libarchive/test/test_read_extract.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define BUFF_SIZE 1000000
|
||||
#define FILE_BUFF_SIZE 100000
|
||||
|
||||
DEFINE_TEST(test_read_extract)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
struct stat st;
|
||||
ssize_t used;
|
||||
int i;
|
||||
char *buff, *file_buff;
|
||||
int fd;
|
||||
ssize_t bytes_read;
|
||||
|
||||
buff = malloc(BUFF_SIZE);
|
||||
file_buff = malloc(FILE_BUFF_SIZE);
|
||||
|
||||
/* Force the umask to something predictable. */
|
||||
umask(022);
|
||||
|
||||
/* Create a new archive in memory containing various types of entries. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_open_memory(a, buff, BUFF_SIZE, &used));
|
||||
/* A directory to be restored with EXTRACT_PERM. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir_0775");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0775);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* A regular file. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0755);
|
||||
for (i = 0; i < FILE_BUFF_SIZE; i++)
|
||||
file_buff[i] = (unsigned char)rand();
|
||||
archive_entry_set_size(ae, FILE_BUFF_SIZE);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(FILE_BUFF_SIZE == archive_write_data(a, file_buff, FILE_BUFF_SIZE));
|
||||
archive_entry_free(ae);
|
||||
/* A directory that should obey umask when restored. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0777);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* A file in the directory. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir/file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0700);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* A file in a dir that is not already in the archive. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir2/file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0000);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* A dir with a trailing /. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir3/.");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0710);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* Multiple dirs with a single entry. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir4/a/../b/../c/");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0711);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* A symlink. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "symlink");
|
||||
archive_entry_set_mode(ae, S_IFLNK | 0755);
|
||||
archive_entry_set_symlink(ae, "file");
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
/* Extract the entries to disk. */
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE));
|
||||
/* Restore first entry with _EXTRACT_PERM. */
|
||||
failure("Error reading first entry", i);
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM));
|
||||
/* Rest of entries get restored with no flags. */
|
||||
for (i = 0; i < 7; i++) {
|
||||
failure("Error reading entry %d", i+1);
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(0 == archive_read_extract(a, ae, 0));
|
||||
}
|
||||
assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
|
||||
/* Test the entries on disk. */
|
||||
assert(0 == stat("dir_0775", &st));
|
||||
failure("This was 0775 in archive, and should be 0775 on disk");
|
||||
assert(st.st_mode == (S_IFDIR | 0775));
|
||||
assert(0 == stat("file", &st));
|
||||
failure("st.st_mode=%o should be %o", st.st_mode, S_IFREG | 0755);
|
||||
assert(st.st_mode == (S_IFREG | 0755));
|
||||
failure("The file extracted to disk is the wrong size.");
|
||||
assert(st.st_size == FILE_BUFF_SIZE);
|
||||
fd = open("file", O_RDONLY);
|
||||
failure("The file on disk could not be opened.");
|
||||
assert(fd != 0);
|
||||
bytes_read = read(fd, buff, FILE_BUFF_SIZE);
|
||||
failure("The file contents read from disk are the wrong size");
|
||||
assert(bytes_read == FILE_BUFF_SIZE);
|
||||
failure("The file contents on disk do not match the file contents that were put into the archive.");
|
||||
assert(memcmp(buff, file_buff, FILE_BUFF_SIZE) == 0);
|
||||
assert(0 == stat("dir", &st));
|
||||
failure("This was 0777 in archive, but umask should make it 0755");
|
||||
assert(st.st_mode == (S_IFDIR | 0755));
|
||||
assert(0 == stat("dir/file", &st));
|
||||
assert(st.st_mode == (S_IFREG | 0700));
|
||||
assert(0 == stat("dir2", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0755));
|
||||
assert(0 == stat("dir2/file", &st));
|
||||
assert(st.st_mode == (S_IFREG | 0000));
|
||||
assert(0 == stat("dir3", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0710));
|
||||
assert(0 == stat("dir4", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0755));
|
||||
assert(0 == stat("dir4/a", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0755));
|
||||
assert(0 == stat("dir4/b", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0755));
|
||||
assert(0 == stat("dir4/c", &st));
|
||||
assert(st.st_mode == (S_IFDIR | 0711));
|
||||
assert(0 == lstat("symlink", &st));
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
#if HAVE_LCHMOD
|
||||
/* Systems that lack lchmod() can't set symlink perms, so skip this. */
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
#endif
|
||||
assert(0 == stat("symlink", &st));
|
||||
assert(st.st_mode == (S_IFREG | 0755));
|
||||
|
||||
free(buff);
|
||||
free(file_buff);
|
||||
}
|
64
lib/libarchive/test/test_read_format_cpio_bin.c
Normal file
64
lib/libarchive/test/test_read_format_cpio_bin.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
199,'q',21,4,177,'y',237,'A',232,3,232,3,2,0,0,0,'p','C',244,'M',2,0,0,0,
|
||||
0,0,'.',0,199,'q',0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,0,0,'T','R',
|
||||
'A','I','L','E','R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_bin)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
53
lib/libarchive/test/test_read_format_cpio_bin_Z.c
Normal file
53
lib/libarchive/test/test_read_format_cpio_bin_Z.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,157,144,199,226,'T',' ',16,'+','O',187,' ',232,6,'$',20,0,160,'!',156,
|
||||
'!',244,154,'0','l',216,208,5,128,128,20,'3','R',12,160,177,225,2,141,'T',
|
||||
164,4,'I',194,164,136,148,16,'(',';',170,'\\',201,178,165,203,151,'0','c',
|
||||
202,156,'I',179,166,205,155,'8','s',234,220,201,179,167,207,159,'@',127,2};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_bin_Z)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_COMPRESS);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
54
lib/libarchive/test/test_read_format_cpio_bin_bz2.c
Normal file
54
lib/libarchive/test/test_read_format_cpio_bin_bz2.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'B','Z','h','9','1','A','Y','&','S','Y',134,'J',208,'4',0,0,30,246,141,253,
|
||||
8,2,0,' ',1,'*','&',20,0,'`',' ',' ',2,0,128,0,'B',4,8,' ',0,'T','P',0,'4',
|
||||
0,13,6,137,168,245,27,'Q',160,'a',25,169,5,'I',187,'(',10,'d','E',177,177,
|
||||
142,218,232,'r',130,'4','D',247,'<','Z',190,'U',237,236,'d',227,31,' ','z',
|
||||
192,'E','_',23,'r','E','8','P',144,134,'J',208,'4'};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_bin_bz2)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_BZIP2);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
53
lib/libarchive/test/test_read_format_cpio_bin_gz.c
Normal file
53
lib/libarchive/test/test_read_format_cpio_bin_gz.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,139,8,0,244,'M','p','C',0,3,';','^','(',202,178,177,242,173,227,11,230,
|
||||
23,204,'L',12,12,12,5,206,'_','|','A','4',3,131,30,195,241,'B',6,'8','`',
|
||||
132,210,220,'`','2','$',200,209,211,199,'5','H','Q','Q',145,'a',20,12,'i',
|
||||
0,0,170,199,228,195,0,2,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_bin_gz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_GZIP);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
68
lib/libarchive/test/test_read_format_cpio_odc.c
Normal file
68
lib/libarchive/test/test_read_format_cpio_odc.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'0','7','0','7','0','7','0','0','2','0','2','5','0','7','4','6','6','1','0',
|
||||
'4','0','7','5','5','0','0','1','7','5','0','0','0','1','7','5','0','0','0',
|
||||
'0','0','0','2','0','0','0','0','0','0','1','0','3','3','4','0','5','0','0',
|
||||
'5','3','0','0','0','0','0','2','0','0','0','0','0','0','0','0','0','0','0',
|
||||
'.',0,'0','7','0','7','0','7','0','0','0','0','0','0','0','0','0','0','0',
|
||||
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0',
|
||||
'0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0',
|
||||
'0','0','0','0','0','0','0','0','1','3','0','0','0','0','0','0','0','0','0',
|
||||
'0','0','T','R','A','I','L','E','R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_odc)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_POSIX);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
54
lib/libarchive/test/test_read_format_cpio_svr4_gzip.c
Normal file
54
lib/libarchive/test/test_read_format_cpio_svr4_gzip.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,139,8,0,236,'c',217,'D',0,3,'3','0','7','0','7','0','4','0','0',181,'0',
|
||||
183,'L',2,210,6,6,'&',134,169,')',' ',218,192,'8',213,2,133,'6','0','0','2',
|
||||
'1','6','7','0','5','0','N','6','@',5,'&',16,202,208,212,0,';','0',130,'1',
|
||||
244,24,12,160,246,17,5,136,'U',135,14,146,'`',140,144,' ','G','O',31,215,
|
||||
' ','E','E','E',134,'Q',128,21,0,0,'%',215,202,221,0,2,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_svr4_gzip)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_GZIP);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
56
lib/libarchive/test/test_read_format_cpio_svr4c_Z.c
Normal file
56
lib/libarchive/test/test_read_format_cpio_svr4c_Z.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,157,144,'0','n',4,132,'!',3,6,140,26,'8','n',228,16,19,195,160,'A',26,
|
||||
'1',202,144,'q','h','p','F',25,28,20,'a','X',196,152,145,' ',141,25,2,'k',
|
||||
192,160,'A',163,163,201,135,29,'c',136,'<',201,'2','c','A',147,'.',0,12,20,
|
||||
248,178,165,205,155,20,27,226,220,201,243,166,152,147,'T',164,4,'I',194,164,
|
||||
136,148,16,'H',1,'(',']',202,180,169,211,167,'P',163,'J',157,'J',181,170,
|
||||
213,171,'X',179,'j',221,202,181,171,215,175,'L',1};
|
||||
|
||||
DEFINE_TEST(test_read_format_cpio_svr4c_Z)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
/* printf("Archive address: start=%X, end=%X\n", archive, archive+sizeof(archive)); */
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_COMPRESS);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_SVR4_CRC);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
49
lib/libarchive/test/test_read_format_empty.c
Normal file
49
lib/libarchive/test/test_read_format_empty.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = { };
|
||||
|
||||
DEFINE_TEST(test_read_format_empty)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_EMPTY);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
54
lib/libarchive/test/test_read_format_gtar_gz.c
Normal file
54
lib/libarchive/test/test_read_format_gtar_gz.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,139,8,0,'+','e',217,'D',0,3,211,211,'g',160,'9','0',0,2,'s','S','S',16,
|
||||
'm','h','n','j',128,'L',195,0,131,161,129,177,177,137,129,137,185,185,161,
|
||||
'!',131,129,161,129,153,161,'9',131,130,')',237,157,198,192,'P','Z','\\',
|
||||
146,'X',164,160,192,'P',146,153,139,'W',29,'!','y',152,'G','`',244,'(',24,
|
||||
5,163,'`',20,12,'r',0,0,226,234,'6',162,0,6,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_gtar_gz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_GZIP);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_TAR_GNUTAR);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
73
lib/libarchive/test/test_read_format_iso_gz.c
Normal file
73
lib/libarchive/test/test_read_format_iso_gz.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,139,8,8,201,'R','p','C',0,3,'t','e','s','t','-','r','e','a','d','_','f',
|
||||
'o','r','m','a','t','.','i','s','o',0,237,219,223,'k',211,'@',28,0,240,212,
|
||||
23,'K','}',20,169,143,135,15,162,224,218,180,']','W',186,183,173,'I',183,
|
||||
206,254,144,'d',19,246,'$',5,';',24,'2',11,235,240,239,221,127,162,233,'f',
|
||||
17,29,219,24,12,'\'',243,243,'!',185,187,220,']',146,';',8,9,223,131,'D',
|
||||
17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'P',234,
|
||||
'%','q',220,'(','E',253,211,217,'l',';','O',194,'u','z','I','6',25,']',219,
|
||||
26,194,234,'z',241,'o',217,13,247,'-',182,229,30,149,203,'Q',229,178,170,
|
||||
242,252,'W',243,139,'e',242,'*',170,'^',30,'U',163,242,'2','+','G',199,207,
|
||||
158,'V','_',190,';',127,178,':',255,134,1,241,23,140,222,15,242,'I','?',15,
|
||||
'E',26,186,27,27,'q','}',183,'8',232,15,134,'i','~',152,239,167,163,176,'}',
|
||||
'0',24,'&','i',22,'^','/',159,159,180,'7',201,146,162,176,150,213,147,143,
|
||||
'E','!','K',183,246,'\'','Y','x',211,'{',27,26,221,'n','+',164,181,195,201,
|
||||
193,'x','\'',217,26,166,171,202,'N',216,171,'}','H',183,178,'|','2',174,239,
|
||||
213,242,222,238,'`','8',28,140,'w',30,'j',186,205,'8','n','7',26,'q',167,
|
||||
217,'j',174,183,';','q','|','~',165,'"',254,'C','t',165,'G',')','z',168,209,
|
||||
243,'o',184,143,215,'6',220,139,239,'?',191,255,0,192,255,163,136,224,194,
|
||||
'h',254,'5',140,231,223,'B',232,132,'f','k',179,185,190,217,238,'\\',132,
|
||||
':',149,147,'/',199,139,249,209,'"','4','k','q',173,21,214,230,225,'l',182,
|
||||
'8','[',';',157,'M','?',127,':',154,159,158,'L',207,'j','E','{',152,'>',244,
|
||||
28,0,128,187,')',']',172,177,139,255,1,0,0,224,'1',187,136,252,171,22,0,0,
|
||||
0,0,224,'1',187,253,31,187,'[','{','X',';',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,206,
|
||||
'~',0,137,'#',195,182,0,128,1,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_iso_gz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_GZIP);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_ISO9660);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
180
lib/libarchive/test/test_read_format_isorr_bz2.c
Normal file
180
lib/libarchive/test/test_read_format_isorr_bz2.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
Execute the following to rebuild the data for this program:
|
||||
tail -n +5 test-read_format-isorr_bz2.c | /bin/sh
|
||||
|
||||
rm -rf /tmp/iso
|
||||
mkdir /tmp/iso
|
||||
mkdir /tmp/iso/dir
|
||||
echo "hello" >/tmp/iso/file
|
||||
ln /tmp/iso/file /tmp/iso/hardlink
|
||||
(cd /tmp/iso; ln -s file symlink)
|
||||
TZ=utc touch -afhm -t 197001010000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir
|
||||
TZ=utc touch -afhm -t 196912312359.58 /tmp/iso/symlink
|
||||
mkhybrid -R -uid 1 -gid 2 /tmp/iso | bzip2 > data.iso.bz2
|
||||
cat data.iso.bz2 | ./maketest.pl > data.c
|
||||
exit 1
|
||||
*/
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'B','Z','h','9','1','A','Y','&','S','Y','G',11,4,'c',0,0,199,255,221,255,
|
||||
255,203,252,221,'c',251,248,'?',255,223,224,167,255,222,'&','!',234,'$',0,
|
||||
'0',1,' ',0,'D',2,129,8,192,3,14,'2','3','$',19,184,'J',' ','F',168,244,201,
|
||||
149,'6','Q',226,155,'S',212,209,160,'h','4','i',160,26,13,0,244,134,212,0,
|
||||
218,'O',212,153,1,144,244,128,148,' ',147,13,' ',213,'=','1','\'',169,166,
|
||||
128,'=','!',233,0,208,0,26,0,0,30,160,'h',0,'4','z',130,180,163,'@',0,0,4,
|
||||
211,0,0,0,2,'b','`',0,0,0,0,0,8,146,133,'F',154,'y','A',163,'A',161,163,'@',
|
||||
'z',134,'C','C','F',131,'F','@',0,0,0,0,6,154,26,'Q',24,234,180,'P',172,251,
|
||||
'=',2,'P','H','&','Y','o',130,28,'"',229,210,247,227,248,200,'?','6',161,
|
||||
'?',170,'H',172,'"','H','I',16,'2','"','&',148,'G',133,'T','z',224,1,215,
|
||||
' ',0,191,184,10,160,24,248,180,183,244,156,'K',202,133,208,'U',5,'6','C',
|
||||
26,144,'H',168,'H','H','(','"',151,'@','m',223,'(','P',169,'e',145,148,'6',
|
||||
237,235,7,227,204,']','k','{',241,187,227,244,251,':','a','L',138,'#','R',
|
||||
'"',221,'_',239,')',140,'*','*',172,'Q',16,1,16,207,166,251,233,'Z',169,'4',
|
||||
'_',195,'a',14,18,231,'}',14,139,137,'e',213,185,'T',194,'D','`',25,'$',187,
|
||||
208,'%','c',162,'~',181,'@',204,'2',238,'P',161,213,127,'I',169,3,' ','o',
|
||||
6,161,16,128,'F',214,'S','m',6,244,11,229,'Z','y','.',176,'q',' ',248,167,
|
||||
204,26,193,'q',211,241,214,133,221,212,'I','`',28,244,'N','N','f','H','9',
|
||||
'w',245,209,'*',20,26,208,'h','(',194,156,192,'l',';',192,'X','T',151,177,
|
||||
209,'0',156,16,'=',20,'k',184,144,'z',26,'j',133,194,'9',227,'<','[','^',
|
||||
17,'w','p',225,220,248,'>',205,'>','[',19,'5',155,17,175,28,28,168,175,'n',
|
||||
'\'','c','w',27,222,204,'k','n','x','I',23,237,'c',145,11,184,'A','(',1,169,
|
||||
'0',180,189,134,'\\','Y','x',187,'C',151,'d','k','y','-','L',218,138,'s',
|
||||
'*','(',12,'h',242,'*',17,'E','L',202,146,138,'l','0',217,160,'9','.','S',
|
||||
214,198,143,'3','&',237,'=','t','P',168,214,210,'`','p','J',181,'H',138,149,
|
||||
'1','B',206,22,164,'[','O','A',172,134,224,179,219,166,184,'X',185,'W',154,
|
||||
219,19,161,'Y',184,220,237,147,'9',191,237,'&','i','_',226,146,205,160,'@',
|
||||
'b',182,';',3,'!',183,'J','t',161,160,178,173,'S',235,':','2',159,':',245,
|
||||
'{','U',174,'P',142,'G','(',')',9,168,185,'A','U',231,193,'g',213,'e',12,
|
||||
'X',223,22,249,')',152,237,'G',150,156,3,201,245,212,'2',218,209,177,196,
|
||||
235,'_','~',137,24,31,196,232,'B',172,'w',159,24,'n',156,150,225,'1','y',
|
||||
22,'#',138,193,227,232,169,170,166,179,1,11,182,'i',')',160,180,198,175,128,
|
||||
249,167,5,194,142,183,'f',134,206,180,'&','E','!','[',31,195,':',192,'s',
|
||||
232,187,'N',131,'Y',137,243,15,'y',12,'J',163,'-',242,'5',197,151,130,163,
|
||||
240,220,'T',161,'L',159,141,159,152,'4',18,128,'.','^',250,168,200,163,'P',
|
||||
231,'Y','w','F','U',186,'x',190,16,'0',228,22,'9','F','t',168,157,'i',190,
|
||||
'+',246,141,142,18,' ','M',174,197,'O',165,'m',224,27,'b',150,'|','W','H',
|
||||
196,'.','*','Q','$',225,'I','-',148,169,'F',7,197,'m','-',130,153,0,158,21,
|
||||
'(',221,221,226,206,'g',13,159,163,'y',176,'~',158,'k','4','q','d','s',177,
|
||||
'7',14,217,'1',173,206,228,'t',250,200,170,162,'d','2','Z','$','e',168,224,
|
||||
223,129,174,229,165,187,252,203,'-',28,'`',207,183,'-','/',127,196,230,131,
|
||||
'B',30,237,' ',8,26,194,'O',132,'L','K','\\',144,'L','c',1,10,176,192,'c',
|
||||
0,244,2,168,3,0,'+',233,186,16,17,'P',17,129,252,'2',0,2,154,247,255,166,
|
||||
'.',228,138,'p',161,' ',142,22,8,198};
|
||||
|
||||
DEFINE_TEST(test_read_format_isorr_bz2)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
const void *p;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
|
||||
/* First entry is '.' root directory. */
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(0 == strcmp(".", archive_entry_pathname(ae)));
|
||||
assert(S_ISDIR(archive_entry_stat(ae)->st_mode));
|
||||
assert(2048 == archive_entry_size(ae));
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
assert(0 == archive_entry_mtime_nsec(ae));
|
||||
assert(1 == archive_entry_ctime(ae));
|
||||
assert(0 == archive_entry_stat(ae)->st_nlink);
|
||||
assert(0 == archive_entry_uid(ae));
|
||||
|
||||
/* A directory. */
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(0 == strcmp("dir", archive_entry_pathname(ae)));
|
||||
assert(S_ISDIR(archive_entry_stat(ae)->st_mode));
|
||||
assert(2048 == archive_entry_size(ae));
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
assert(1 == archive_entry_atime(ae));
|
||||
assert(2 == archive_entry_stat(ae)->st_nlink);
|
||||
assert(1 == archive_entry_uid(ae));
|
||||
assert(2 == archive_entry_gid(ae));
|
||||
|
||||
/* A regular file. */
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(0 == strcmp("file", archive_entry_pathname(ae)));
|
||||
assert(S_ISREG(archive_entry_stat(ae)->st_mode));
|
||||
assert(6 == archive_entry_size(ae));
|
||||
assert(0 == archive_read_data_block(a, &p, &size, &offset));
|
||||
assert(6 == size);
|
||||
assert(0 == offset);
|
||||
assert(0 == memcmp(p, "hello\n", 6));
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
assert(1 == archive_entry_atime(ae));
|
||||
assert(2 == archive_entry_stat(ae)->st_nlink);
|
||||
assert(1 == archive_entry_uid(ae));
|
||||
assert(2 == archive_entry_gid(ae));
|
||||
|
||||
/* A hardlink to the regular file. */
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(0 == strcmp("hardlink", archive_entry_pathname(ae)));
|
||||
assert(S_ISREG(archive_entry_stat(ae)->st_mode));
|
||||
assert(0 == strcmp("file", archive_entry_hardlink(ae)));
|
||||
assert(6 == archive_entry_size(ae));
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
assert(1 == archive_entry_atime(ae));
|
||||
assert(2 == archive_entry_stat(ae)->st_nlink);
|
||||
assert(1 == archive_entry_uid(ae));
|
||||
assert(2 == archive_entry_gid(ae));
|
||||
|
||||
/* A symlink to the regular file. */
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(0 == strcmp("symlink", archive_entry_pathname(ae)));
|
||||
assert(S_ISLNK(archive_entry_stat(ae)->st_mode));
|
||||
assert(0 == strcmp("file", archive_entry_symlink(ae)));
|
||||
assert(0 == archive_entry_size(ae));
|
||||
assert(-2 == archive_entry_mtime(ae));
|
||||
assert(-2 == archive_entry_atime(ae));
|
||||
assert(1 == archive_entry_stat(ae)->st_nlink);
|
||||
assert(1 == archive_entry_uid(ae));
|
||||
assert(2 == archive_entry_gid(ae));
|
||||
|
||||
/* End of archive. */
|
||||
assert(ARCHIVE_EOF == archive_read_next_header(a, &ae));
|
||||
|
||||
/* Verify archive format. */
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_BZIP2);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);
|
||||
|
||||
/* Close the archive. */
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
62
lib/libarchive/test/test_read_format_pax_bz2.c
Normal file
62
lib/libarchive/test/test_read_format_pax_bz2.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'B','Z','h','9','1','A','Y','&','S','Y',152,180,30,185,0,0,140,127,176,212,
|
||||
144,0,' ','@',1,255,226,8,'d','H',' ',238,'/',159,'@',0,16,4,'@',0,8,'0',
|
||||
0,216,'A',164,167,147,'Q',147,'!',180,'#',0,'L',153,162,'i',181,'?','P',192,
|
||||
26,'h','h',209,136,200,6,128,13,12,18,132,202,'5','O',209,'5','=',26,'2',
|
||||
154,7,168,12,2,'d',252,13,254,29,'4',247,181,'l','T','i',130,5,195,1,'2',
|
||||
'@',146,18,251,245,'c','J',130,224,172,'$','l','4',235,170,186,'c','1',255,
|
||||
179,'K',188,136,18,208,152,192,149,153,10,'{','|','0','8',166,3,6,9,128,172,
|
||||
'(',164,220,244,149,6,' ',243,212,'B',25,17,'6',237,13,'I',152,'L',129,209,
|
||||
'G','J','<',137,'Y',16,'b',21,18,'a','Y','l','t','r',160,128,147,'l','f',
|
||||
'~',219,206,'=','?','S',233,'3',251,'L','~',17,176,169,'%',23,'_',225,'M',
|
||||
'C','u','k',218,8,'q',216,'(',22,235,'K',131,136,146,136,147,202,0,158,134,
|
||||
'F',23,160,184,'s','0','a',246,'*','P',7,2,238,'H',167,10,18,19,22,131,215,
|
||||
' '};
|
||||
|
||||
DEFINE_TEST(test_read_format_pax_bz2)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_BZIP2);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
93
lib/libarchive/test/test_read_format_tar.c
Normal file
93
lib/libarchive/test/test_read_format_tar.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'.',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0','7','5',
|
||||
'5',' ',0,'0','0','1','7','5','0',' ',0,'0','0','1','7','5','0',' ',0,'0',
|
||||
'0','0','0','0','0','0','0','0','0','0',' ','1','0','3','3','4','0','4','1',
|
||||
'7','3','6',' ','0','1','0','5','6','1',0,' ','5',0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,'0','0','t','i','m',0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'t','i','m',0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0','0','0','0',
|
||||
' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_tar)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_TAR_USTAR);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
55
lib/libarchive/test/test_read_format_tbz.c
Normal file
55
lib/libarchive/test/test_read_format_tbz.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'B','Z','h','9','1','A','Y','&','S','Y',237,7,140,'W',0,0,27,251,144,208,
|
||||
128,0,' ','@',1,'o',128,0,0,224,'"',30,0,0,'@',0,8,' ',0,'T','2',26,163,'&',
|
||||
129,160,211,212,18,'I',169,234,13,168,26,6,150,'1',155,134,'p',8,173,3,183,
|
||||
'J','S',26,20,'2',222,'b',240,160,'a','>',205,'f',29,170,227,'[',179,139,
|
||||
'\'','L','o',211,':',178,'0',162,134,'*','>','8',24,153,230,147,'R','?',23,
|
||||
'r','E','8','P',144,237,7,140,'W'};
|
||||
|
||||
DEFINE_TEST(test_read_format_tbz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_BZIP2);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_TAR_USTAR);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
54
lib/libarchive/test/test_read_format_tgz.c
Normal file
54
lib/libarchive/test/test_read_format_tgz.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,139,8,0,222,'C','p','C',0,3,211,'c',160,'=','0','0','0','0','7','5','U',
|
||||
0,210,134,230,166,6,200,'4',28,'(',24,26,24,27,155,24,152,24,154,27,155,')',
|
||||
24,24,26,152,154,25,'2','(',152,210,193,'m',12,165,197,'%',137,'E','@',167,
|
||||
148,'d',230,226,'U','G','H',30,234,15,'8','=',10,'F',193,'(',24,5,131,28,
|
||||
0,0,29,172,5,240,0,6,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_tgz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assert(0 == archive_read_support_compression_all(a));
|
||||
assert(0 == archive_read_support_format_all(a));
|
||||
assert(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assert(0 == archive_read_next_header(a, &ae));
|
||||
assert(archive_compression(a) == ARCHIVE_COMPRESSION_GZIP);
|
||||
assert(archive_format(a) == ARCHIVE_FORMAT_TAR_USTAR);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
56
lib/libarchive/test/test_read_format_tz.c
Normal file
56
lib/libarchive/test/test_read_format_tz.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
31,157,144,'.',0,8,28,'H',176,160,193,131,8,19,'*','\\',200,176,'!','B',24,
|
||||
16,'o',212,168,1,2,0,196,24,18,'a','T',188,152,'q','#',196,143,' ','5',198,
|
||||
128,'1','c',6,13,24,'4','0',206,176,1,2,198,200,26,'6','b',0,0,'Q',195,161,
|
||||
205,155,'8','s',234,4,'P','g',14,157,'0','r',',',194,160,147,166,205,206,
|
||||
132,'D',141,30,'=',24,'R',163,'P',144,21,151,'J',157,'J',181,170,213,171,
|
||||
'X',179,'j',221,202,181,171,215,175,'`',195,138,29,'K',182,172,217,179,'h',
|
||||
211,170,']',203,182,173,219,183,'g',1};
|
||||
|
||||
DEFINE_TEST(test_read_format_tz)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_COMPRESS);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_TAR_USTAR);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
54
lib/libarchive/test/test_read_format_zip.c
Normal file
54
lib/libarchive/test/test_read_format_zip.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char archive[] = {
|
||||
'P','K',3,4,10,0,0,0,0,0,162,186,'g','3',0,0,0,0,0,0,0,0,0,0,0,0,1,0,21,0,
|
||||
'a','U','T',9,0,3,224,'Q','p','C',224,'Q','p','C','U','x',4,0,232,3,232,3,
|
||||
'P','K',1,2,23,3,10,0,0,0,0,0,162,186,'g','3',0,0,0,0,0,0,0,0,0,0,0,0,1,0,
|
||||
13,0,0,0,0,0,0,0,0,0,164,129,0,0,0,0,'a','U','T',5,0,3,224,'Q','p','C','U',
|
||||
'x',0,0,'P','K',5,6,0,0,0,0,1,0,1,0,'<',0,0,0,'4',0,0,0,0,0};
|
||||
|
||||
DEFINE_TEST(test_read_format_zip)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
|
||||
assertA(archive_format(a) == ARCHIVE_FORMAT_ZIP);
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
93
lib/libarchive/test/test_read_large.c
Normal file
93
lib/libarchive/test/test_read_large.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char testdata[10 * 1024 * 1024];
|
||||
static unsigned char testdatacopy[10 * 1024 * 1024];
|
||||
static unsigned char buff[11 * 1024 * 1024];
|
||||
|
||||
/* Check correct behavior on large reads. */
|
||||
DEFINE_TEST(test_read_large)
|
||||
{
|
||||
int i;
|
||||
int tmpfile;
|
||||
char tmpfilename[] = "/tmp/test-read_large.XXXXXX";
|
||||
size_t used;
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
|
||||
for (i = 0; i < sizeof(testdata); i++)
|
||||
testdata[i] = (unsigned char)(rand());
|
||||
|
||||
assert(NULL != (a = archive_write_new()));
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
assert(NULL != (entry = archive_entry_new()));
|
||||
archive_entry_set_size(entry, sizeof(testdata));
|
||||
archive_entry_set_mode(entry, S_IFREG | 0777);
|
||||
archive_entry_set_pathname(entry, "test");
|
||||
assertA(0 == archive_write_header(a, entry));
|
||||
assertA(sizeof(testdata) == archive_write_data(a, testdata, sizeof(testdata)));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
assert(NULL != (a = archive_read_new()));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, sizeof(buff)));
|
||||
assertA(0 == archive_read_next_header(a, &entry));
|
||||
assertA(0 == archive_read_data_into_buffer(a, testdatacopy, sizeof(testdatacopy)));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
assert(0 == memcmp(testdata, testdatacopy, sizeof(testdata)));
|
||||
|
||||
|
||||
assert(NULL != (a = archive_read_new()));
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, sizeof(buff)));
|
||||
assertA(0 == archive_read_next_header(a, &entry));
|
||||
assert(0 < (tmpfile = mkstemp(tmpfilename)));
|
||||
assertA(0 == archive_read_data_into_fd(a, tmpfile));
|
||||
close(tmpfile);
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
tmpfile = open(tmpfilename, O_RDONLY);
|
||||
read(tmpfile, testdatacopy, sizeof(testdatacopy));
|
||||
close(tmpfile);
|
||||
assert(0 == memcmp(testdata, testdatacopy, sizeof(testdata)));
|
||||
|
||||
unlink(tmpfilename);
|
||||
}
|
74
lib/libarchive/test/test_read_position.c
Normal file
74
lib/libarchive/test/test_read_position.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static unsigned char nulls[10000000];
|
||||
static unsigned char buff[10000000];
|
||||
|
||||
/* Check that header_position tracks correctly on read. */
|
||||
DEFINE_TEST(test_read_position)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
size_t write_pos;
|
||||
const size_t data_size = 1000000;
|
||||
|
||||
/* Create a simple archive_entry. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_pathname(ae, "testfile");
|
||||
archive_entry_set_mode(ae, S_IFREG);
|
||||
archive_entry_set_size(ae, data_size);
|
||||
|
||||
assert(NULL != (a = archive_write_new()));
|
||||
assertA(0 == archive_write_set_format_pax_restricted(a));
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, 512));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &write_pos));
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(data_size == archive_write_data(a, nulls, sizeof(nulls)));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
assertA(0 == archive_write_close(a));
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
/* 512-byte header + data_size (rounded up) + 1024 end-of-archive */
|
||||
assert(write_pos == ((512 + data_size + 1024 + 511)/512)*512);
|
||||
|
||||
/* Read the archive back. */
|
||||
assert(NULL != (a = archive_read_new()));
|
||||
assertA(0 == archive_read_support_format_tar(a));
|
||||
assertA(0 == archive_read_open_memory2(a, buff, sizeof(buff), 512));
|
||||
assert((intmax_t)0 == (intmax_t)archive_read_header_position(a));
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assert((intmax_t)0 == (intmax_t)archive_read_header_position(a));
|
||||
assertA(0 == archive_read_data_skip(a));
|
||||
assert((intmax_t)0 == (intmax_t)archive_read_header_position(a));
|
||||
assertA(1 == archive_read_next_header(a, &ae));
|
||||
assert((intmax_t)((data_size + 511 + 512)/512)*512 == (intmax_t)archive_read_header_position(a));
|
||||
assertA(0 == archive_read_close(a));
|
||||
assert((intmax_t)((data_size + 511 + 512)/512)*512 == (intmax_t)archive_read_header_position(a));
|
||||
archive_read_finish(a);
|
||||
}
|
148
lib/libarchive/test/test_read_truncated.c
Normal file
148
lib/libarchive/test/test_read_truncated.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
char buff[1000000];
|
||||
char buff2[100000];
|
||||
|
||||
DEFINE_TEST(test_read_truncated)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
int i;
|
||||
size_t used;
|
||||
|
||||
/* Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/*
|
||||
* Write a file to it.
|
||||
*/
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0755);
|
||||
for (i = 0; i < sizeof(buff2); i++)
|
||||
buff2[i] = (unsigned char)rand();
|
||||
archive_entry_set_size(ae, sizeof(buff2));
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(sizeof(buff2) == archive_write_data(a, buff2, sizeof(buff2)));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
/* Now, read back a truncated version of the archive and
|
||||
* verify that we get an appropriate error. */
|
||||
for (i = 1; i < used + 100; i += 100) {
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, i));
|
||||
|
||||
if (i < 512) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
|
||||
goto wrap_up;
|
||||
} else {
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
}
|
||||
|
||||
if (i < 512 + sizeof(buff2)) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_data(a, buff2, sizeof(buff2)));
|
||||
goto wrap_up;
|
||||
} else {
|
||||
assertA(sizeof(buff2) == archive_read_data(a, buff2, sizeof(buff2)));
|
||||
}
|
||||
|
||||
/* Verify the end of the archive. */
|
||||
/* Archive must be long enough to capture a 512-byte
|
||||
* block of zeroes after the entry. (POSIX requires a
|
||||
* second block of zeros to be written but libarchive
|
||||
* does not return an error if it can't consume
|
||||
* it.) */
|
||||
if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
|
||||
} else {
|
||||
assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
|
||||
}
|
||||
wrap_up:
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Same as above, except skip the body instead of reading it. */
|
||||
for (i = 1; i < used + 100; i += 100) {
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, i));
|
||||
|
||||
if (i < 512) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
|
||||
goto wrap_up2;
|
||||
} else {
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
}
|
||||
|
||||
if (i < 512 + 512*((sizeof(buff2)+511)/512)) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_data_skip(a));
|
||||
goto wrap_up2;
|
||||
} else {
|
||||
assertA(ARCHIVE_OK == archive_read_data_skip(a));
|
||||
}
|
||||
|
||||
/* Verify the end of the archive. */
|
||||
/* Archive must be long enough to capture a 512-byte
|
||||
* block of zeroes after the entry. (POSIX requires a
|
||||
* second block of zeros to be written but libarchive
|
||||
* does not return an error if it can't consume
|
||||
* it.) */
|
||||
if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) {
|
||||
assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
|
||||
} else {
|
||||
assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
|
||||
}
|
||||
wrap_up2:
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
}
|
92
lib/libarchive/test/test_write_disk.c
Normal file
92
lib/libarchive/test/test_write_disk.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define UMASK 022
|
||||
|
||||
static void create(struct archive_entry *ae)
|
||||
{
|
||||
struct archive *ad;
|
||||
struct stat st;
|
||||
|
||||
/* Write the entry to disk. */
|
||||
assert((ad = archive_write_disk_new()) != NULL);
|
||||
assert(0 == archive_write_header(ad, ae));
|
||||
assert(0 == archive_write_finish_entry(ad));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_write_finish(ad));
|
||||
#else
|
||||
archive_write_finish(ad);
|
||||
#endif
|
||||
/* Test the entries on disk. */
|
||||
assert(0 == stat(archive_entry_pathname(ae), &st));
|
||||
failure("st.st_mode=%o archive_entry_mode(ae)=%o",
|
||||
st.st_mode, archive_entry_mode(ae));
|
||||
assert(st.st_mode == (archive_entry_mode(ae) & ~UMASK));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_write_disk)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
|
||||
/* Force the umask to something predictable. */
|
||||
umask(UMASK);
|
||||
|
||||
/* A regular file. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0755);
|
||||
create(ae);
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* A regular file over an existing file */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0724);
|
||||
create(ae);
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* A directory. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0555);
|
||||
create(ae);
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* A directory over an existing file. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0742);
|
||||
create(ae);
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* A file over an existing dir. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0744);
|
||||
create(ae);
|
||||
archive_entry_free(ae);
|
||||
}
|
324
lib/libarchive/test/test_write_disk_perms.c
Normal file
324
lib/libarchive/test/test_write_disk_perms.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define UMASK 022
|
||||
|
||||
static gid_t _default_gid = 0;
|
||||
static gid_t _invalid_gid = 0;
|
||||
static gid_t _alt_gid = 0;
|
||||
|
||||
/*
|
||||
* To fully test SGID restores, we need three distinct GIDs to work
|
||||
* with:
|
||||
* * the GID that files are created with by default (for the
|
||||
* current user in the current directory)
|
||||
* * An "alt gid" that this user can create files with
|
||||
* * An "invalid gid" that this user is not permitted to create
|
||||
* files with.
|
||||
* The second fails if this user doesn't belong to at least two groups;
|
||||
* the third fails if the current user is root.
|
||||
*/
|
||||
static int
|
||||
searchgid(void)
|
||||
{
|
||||
static int _searched = 0;
|
||||
uid_t uid = getuid();
|
||||
gid_t gid = 0;
|
||||
int n;
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
/* If we've already looked this up, we're done. */
|
||||
if (_searched)
|
||||
return;
|
||||
_searched = 1;
|
||||
|
||||
/* Create a file on disk. */
|
||||
fd = open("test_gid", O_CREAT, 0664);
|
||||
failure("Couldn't create a file for gid testing.");
|
||||
assert(fd > 0);
|
||||
|
||||
/* See what GID it ended up with. This is our "valid" GID. */
|
||||
assert(fstat(fd, &st) == 0);
|
||||
_default_gid = st.st_gid;
|
||||
|
||||
/* Find a GID for which fchown() fails. This is our "invalid" GID. */
|
||||
_invalid_gid = 0;
|
||||
/* This loop stops when we wrap the gid or examine 10,000 gids. */
|
||||
for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
|
||||
if (fchown(fd, uid, gid) != 0) {
|
||||
_invalid_gid = gid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a GID for which fchown() succeeds, but which isn't the
|
||||
* default. This is the "alternate" gid.
|
||||
*/
|
||||
_alt_gid = 0;
|
||||
for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
|
||||
/* _alt_gid must be different than _default_gid */
|
||||
if (gid == _default_gid)
|
||||
continue;
|
||||
if (fchown(fd, uid, gid) == 0) {
|
||||
_alt_gid = gid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int
|
||||
altgid(void)
|
||||
{
|
||||
searchgid();
|
||||
return (_alt_gid);
|
||||
}
|
||||
|
||||
static int
|
||||
invalidgid(void)
|
||||
{
|
||||
searchgid();
|
||||
return (_invalid_gid);
|
||||
}
|
||||
|
||||
static int
|
||||
defaultgid(void)
|
||||
{
|
||||
searchgid();
|
||||
return (_default_gid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exercise permission and ownership restores.
|
||||
* In particular, try to exercise a bunch of border cases related
|
||||
* to files/dirs that already exist, SUID/SGID bits, etc.
|
||||
*/
|
||||
|
||||
DEFINE_TEST(test_write_disk_perms)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
struct stat st;
|
||||
|
||||
/* Create an archive_write_disk object. */
|
||||
assert((a = archive_write_disk_new()) != NULL);
|
||||
|
||||
/* Write a regular file to it. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_0755");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_no_suid");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
|
||||
archive_write_disk_set_options(a, 0);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular file with ARCHIVE_EXTRACT_PERM. */
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_0777");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_4742");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
|
||||
archive_entry_set_uid(ae, getuid());
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/*
|
||||
* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
|
||||
* but wrong uid. POSIX says you shouldn't restore SUID bit
|
||||
* unless the UID could be restored.
|
||||
*/
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_bad_suid");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
|
||||
archive_entry_set_uid(ae, getuid() + 1);
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(ARCHIVE_WARN == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_perm_sgid");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
|
||||
archive_entry_set_gid(ae, defaultgid());
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
failure("Setting SGID bit should succeed here.");
|
||||
assertEqualIntA(a, 0, archive_write_finish_entry(a));
|
||||
|
||||
if (altgid() == 0) {
|
||||
/*
|
||||
* Current user must belong to at least two groups or
|
||||
* else we can't test setting the GID to another group.
|
||||
*/
|
||||
printf("Current user can't test gid restore: must belong to more than one group.\n");
|
||||
} else {
|
||||
/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
|
||||
/*
|
||||
* This is a weird case: The user has asked for permissions to
|
||||
* be restored but not asked for ownership to be restored. As
|
||||
* a result, the default file creation will create a file with
|
||||
* the wrong group. There are two reasonable behaviors: warn
|
||||
* and drop the SGID bit (the current libarchive behavior) or
|
||||
* try to set the group. It is completely wrong to set the
|
||||
* SGID bit with the wrong group (which is, incidentally,
|
||||
* exactly what gtar 1.15 does).
|
||||
*/
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_alt_sgid");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
|
||||
archive_entry_set_uid(ae, getuid());
|
||||
archive_entry_set_gid(ae, altgid());
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
failure("Setting SGID bit should not succeed here.");
|
||||
assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
|
||||
|
||||
/* As above, but add _EXTRACT_OWNER. */
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
|
||||
archive_entry_set_uid(ae, getuid());
|
||||
archive_entry_set_gid(ae, altgid());
|
||||
archive_write_disk_set_options(a,
|
||||
ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
failure("Setting SGID bit should succeed here.");
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
|
||||
* but wrong GID. POSIX says you shouldn't restore SGID bit
|
||||
* unless the GID could be restored.
|
||||
*/
|
||||
if (invalidgid() == 0) {
|
||||
/* This test always fails for root. */
|
||||
printf("Running as root: Can't test SGID failures.\n");
|
||||
} else {
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_bad_sgid");
|
||||
archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
|
||||
archive_entry_set_gid(ae, invalidgid());
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
failure("This SGID restore should fail.");
|
||||
assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
|
||||
}
|
||||
|
||||
/* Set ownership should fail if we're not root. */
|
||||
if (getuid() == 0) {
|
||||
printf("Running as root: Can't test setuid failures.\n");
|
||||
} else {
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_bad_owner");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0744);
|
||||
archive_entry_set_uid(ae, getuid() + 1);
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
|
||||
}
|
||||
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
/* Test the entries on disk. */
|
||||
assert(0 == stat("file_0755", &st));
|
||||
failure("file_0755: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
assert(0 == stat("file_no_suid", &st));
|
||||
failure("file_0755: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
assert(0 == stat("file_0777", &st));
|
||||
failure("file_0777: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0777);
|
||||
|
||||
/* SUID bit should get set here. */
|
||||
assert(0 == stat("file_4742", &st));
|
||||
failure("file_4742: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (S_ISUID | 0742));
|
||||
|
||||
/* SUID bit should NOT have been set here. */
|
||||
assert(0 == stat("file_bad_suid", &st));
|
||||
failure("file_bad_suid: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (0742));
|
||||
|
||||
/* SGID should be set here. */
|
||||
assert(0 == stat("file_perm_sgid", &st));
|
||||
failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (S_ISGID | 0742));
|
||||
|
||||
if (altgid() != 0) {
|
||||
/* SGID should not be set here. */
|
||||
assert(0 == stat("file_alt_sgid", &st));
|
||||
failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (0742));
|
||||
|
||||
/* SGID should be set here. */
|
||||
assert(0 == stat("file_alt_sgid_owner", &st));
|
||||
failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (S_ISGID | 0742));
|
||||
}
|
||||
|
||||
if (invalidgid() != 0) {
|
||||
/* SGID should NOT be set here. */
|
||||
assert(0 == stat("file_bad_sgid", &st));
|
||||
failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (0742));
|
||||
}
|
||||
|
||||
if (getuid() != 0) {
|
||||
assert(0 == stat("file_bad_owner", &st));
|
||||
failure("file_bad_owner: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == (0744));
|
||||
failure("file_bad_owner: st.st_uid=%d getuid()=%d",
|
||||
st.st_uid, getuid());
|
||||
/* The entry had getuid()+1, but because we're
|
||||
* not root, we should not have been able to set that. */
|
||||
assert(st.st_uid == getuid());
|
||||
}
|
||||
|
||||
}
|
140
lib/libarchive/test/test_write_disk_secure.c
Normal file
140
lib/libarchive/test/test_write_disk_secure.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define UMASK 022
|
||||
|
||||
/*
|
||||
* Exercise security checks that should prevent certain
|
||||
* writes.
|
||||
*/
|
||||
|
||||
DEFINE_TEST(test_write_disk_secure)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
struct stat st;
|
||||
|
||||
/* Start with a known umask. */
|
||||
umask(UMASK);
|
||||
|
||||
/* Create an archive_write_disk object. */
|
||||
assert((a = archive_write_disk_new()) != NULL);
|
||||
|
||||
/* Write a regular dir to it. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0777);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a symlink to the dir above. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "link_to_dir");
|
||||
archive_entry_set_mode(ae, S_IFLNK | 0777);
|
||||
archive_entry_set_symlink(ae, "dir");
|
||||
archive_write_disk_set_options(a, 0);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/*
|
||||
* Without security checks, we should be able to
|
||||
* extract a file through the link.
|
||||
*/
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "link_to_dir/filea");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* But with security checks enabled, this should fail. */
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "link_to_dir/fileb");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
|
||||
failure("Extracting a file through a symlink should fail here.");
|
||||
assertEqualInt(ARCHIVE_WARN, archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Create another link. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "link_to_dir2");
|
||||
archive_entry_set_mode(ae, S_IFLNK | 0777);
|
||||
archive_entry_set_symlink(ae, "dir");
|
||||
archive_write_disk_set_options(a, 0);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/*
|
||||
* With symlink check and unlink option, it should remove
|
||||
* the link and create the dir.
|
||||
*/
|
||||
assert(archive_entry_clear(ae) != NULL);
|
||||
archive_entry_copy_pathname(ae, "link_to_dir2/filec");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_UNLINK);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
/* Test the entries on disk. */
|
||||
assert(0 == lstat("dir", &st));
|
||||
failure("dir: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
assert(0 == lstat("link_to_dir", &st));
|
||||
failure("link_to_dir: st.st_mode=%o", st.st_mode);
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
#if HAVE_LCHMOD
|
||||
/* Systems that lack lchmod() can't set symlink perms, so skip this. */
|
||||
failure("link_to_dir: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
#endif
|
||||
|
||||
assert(0 == lstat("dir/filea", &st));
|
||||
failure("dir/filea: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
failure("dir/fileb: This file should not have been created");
|
||||
assert(0 != lstat("dir/fileb", &st));
|
||||
|
||||
assert(0 == lstat("link_to_dir2", &st));
|
||||
failure("link_to_dir2 should have been re-created as a true dir");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
failure("link_to_dir2: Implicit dir creation should obey umask, but st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
assert(0 == lstat("link_to_dir2/filec", &st));
|
||||
assert(S_ISREG(st.st_mode));
|
||||
failure("link_to_dir2/filec: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
}
|
76
lib/libarchive/test/test_write_format_cpio_empty.c
Normal file
76
lib/libarchive/test/test_write_format_cpio_empty.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Check that an "empty" cpio archive is correctly created.
|
||||
*/
|
||||
|
||||
/* Here's what an empty cpio archive should look like. */
|
||||
static char ref[] =
|
||||
"070707" /* Magic number */
|
||||
"000000" /* Dev = 0 */
|
||||
"000000" /* ino = 0 */
|
||||
"000000" /* mode = 0 */
|
||||
"000000" /* uid = 0 */
|
||||
"000000" /* gid = 0 */
|
||||
"000001" /* nlink = 1 */
|
||||
"000000" /* rdev = 0 */
|
||||
"00000000000" /* mtime = 0 */
|
||||
"000013" /* Namesize = 11 */
|
||||
"00000000000" /* filesize = 0 */
|
||||
"TRAILER!!!\0"; /* Name */
|
||||
|
||||
DEFINE_TEST(test_write_format_cpio_empty)
|
||||
{
|
||||
struct archive *a;
|
||||
char buff[2048];
|
||||
size_t used;
|
||||
int i;
|
||||
|
||||
/* Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_cpio(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
/* 1-byte block size ensures we see only the required bytes. */
|
||||
/* We're not testing the padding here. */
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, 1));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
failure("Empty cpio archive should be exactly 87 bytes, was %d.", used);
|
||||
assert(used == 87);
|
||||
failure("Empty cpio archive is incorrectly formatted.");
|
||||
assert(memcmp(buff, ref, 87) == 0);
|
||||
}
|
59
lib/libarchive/test/test_write_format_shar_empty.c
Normal file
59
lib/libarchive/test/test_write_format_shar_empty.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Check that an "empty" shar archive is correctly created as an empty file.
|
||||
*/
|
||||
|
||||
DEFINE_TEST(test_write_format_shar_empty)
|
||||
{
|
||||
struct archive *a;
|
||||
char buff[2048];
|
||||
size_t used;
|
||||
int i;
|
||||
|
||||
/* Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_shar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
/* 1-byte block size ensures we see only the required bytes. */
|
||||
/* We're not testing the padding here. */
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, 1));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
failure("Empty shar archive should be exactly 0 bytes, was %d.", used);
|
||||
assert(used == 0);
|
||||
}
|
111
lib/libarchive/test/test_write_format_tar.c
Normal file
111
lib/libarchive/test/test_write_format_tar.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
char buff[1000000];
|
||||
char buff2[64];
|
||||
|
||||
DEFINE_TEST(test_write_format_tar)
|
||||
{
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
char *p;
|
||||
size_t used;
|
||||
int blocksize;
|
||||
|
||||
/* Repeat the following for a variety of odd blocksizes. */
|
||||
for (blocksize = 1; blocksize < 100000; blocksize += blocksize + 3) {
|
||||
/* Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, blocksize));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, blocksize));
|
||||
assertA(blocksize == archive_write_get_bytes_in_last_block(a));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
assertA(blocksize == archive_write_get_bytes_in_last_block(a));
|
||||
|
||||
/*
|
||||
* Write a file to it.
|
||||
*/
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_mtime(ae, 1, 10);
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
assert(10 == archive_entry_mtime_nsec(ae));
|
||||
p = strdup("file");
|
||||
archive_entry_copy_pathname(ae, p);
|
||||
strcpy(p, "XXXX");
|
||||
free(p);
|
||||
assert(0 == strcmp("file", archive_entry_pathname(ae)));
|
||||
archive_entry_set_mode(ae, S_IFREG | 0755);
|
||||
assert((S_IFREG | 0755) == archive_entry_mode(ae));
|
||||
archive_entry_set_size(ae, 8);
|
||||
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
assertA(8 == archive_write_data(a, "12345678", 9));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
/* This calculation gives "the smallest multiple of
|
||||
* the block size that is at least 2048 bytes". */
|
||||
assert(((2048 - 1)/blocksize+1)*blocksize == used);
|
||||
|
||||
/*
|
||||
* Now, read the data back.
|
||||
*/
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertA(0 == archive_read_support_format_all(a));
|
||||
assertA(0 == archive_read_support_compression_all(a));
|
||||
assertA(0 == archive_read_open_memory(a, buff, used));
|
||||
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
|
||||
assert(1 == archive_entry_mtime(ae));
|
||||
/* Not the same as above: ustar doesn't store hi-res timestamps. */
|
||||
assert(0 == archive_entry_mtime_nsec(ae));
|
||||
assert(0 == archive_entry_atime(ae));
|
||||
assert(0 == archive_entry_ctime(ae));
|
||||
assert(0 == strcmp("file", archive_entry_pathname(ae)));
|
||||
assert((S_IFREG | 0755) == archive_entry_mode(ae));
|
||||
assert(8 == archive_entry_size(ae));
|
||||
assertA(8 == archive_read_data(a, buff2, 10));
|
||||
assert(0 == memcmp(buff2, "12345678", 8));
|
||||
|
||||
/* Verify the end of the archive. */
|
||||
assert(1 == archive_read_next_header(a, &ae));
|
||||
assert(0 == archive_read_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_read_finish(a));
|
||||
#else
|
||||
archive_read_finish(a);
|
||||
#endif
|
||||
}
|
||||
}
|
84
lib/libarchive/test/test_write_format_tar_empty.c
Normal file
84
lib/libarchive/test/test_write_format_tar_empty.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Check that an "empty" tar archive is correctly created.
|
||||
*/
|
||||
|
||||
DEFINE_TEST(test_write_format_tar_empty)
|
||||
{
|
||||
struct archive *a;
|
||||
char buff[2048];
|
||||
size_t used;
|
||||
int i;
|
||||
|
||||
/* USTAR format: Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, 512));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, 512));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
failure("Empty tar archive should be exactly 1024 bytes, was %d.", used);
|
||||
assert(used == 1024);
|
||||
for (i = 0; i < used; i++) {
|
||||
failure("Empty tar archive should be all nulls.");
|
||||
assert(buff[i] == 0);
|
||||
}
|
||||
|
||||
/* PAX format: Create a new archive in memory. */
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_pax(a));
|
||||
assertA(0 == archive_write_set_compression_none(a));
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, 512));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, 512));
|
||||
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
|
||||
|
||||
/* Close out the archive. */
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assertA(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
|
||||
failure("Empty tar archive should be exactly 1024 bytes, was %d.", used);
|
||||
assert(used == 1024);
|
||||
for (i = 0; i < used; i++) {
|
||||
failure("Empty tar archive should be all nulls.");
|
||||
assert(buff[i] == 0);
|
||||
}
|
||||
}
|
75
lib/libarchive/test/test_write_open_memory.c
Normal file
75
lib/libarchive/test/test_write_open_memory.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Try to force archive_write_open_memory.c to write past the end of an array. */
|
||||
static unsigned char buff[16384];
|
||||
|
||||
DEFINE_TEST(test_write_open_memory)
|
||||
{
|
||||
int i;
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
const char *name="/tmp/test";
|
||||
|
||||
/* Create a simple archive_entry. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_pathname(ae, name);
|
||||
archive_entry_set_mode(ae, S_IFREG);
|
||||
assert(0 == strcmp(archive_entry_pathname(ae), name));
|
||||
|
||||
/* Try writing with different buffer sizes. */
|
||||
/* Make sure that we get failure on too-small buffers, success on
|
||||
* large enough ones. */
|
||||
for (i = 100; i < 1600; i++) {
|
||||
size_t s;
|
||||
size_t blocksize = 94;
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertA(0 == archive_write_set_format_ustar(a));
|
||||
assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
|
||||
assertA(0 == archive_write_set_bytes_per_block(a, blocksize));
|
||||
buff[i] = 0xAE;
|
||||
assertA(0 == archive_write_open_memory(a, buff, i, &s));
|
||||
/* If buffer is smaller than a tar header, this should fail. */
|
||||
if (i < (511/blocksize)*blocksize)
|
||||
assertA(ARCHIVE_FATAL == archive_write_header(a,ae));
|
||||
else
|
||||
assertA(0 == archive_write_header(a, ae));
|
||||
/* If buffer is smaller than a tar header plus 1024 byte
|
||||
* end-of-archive marker, then this should fail. */
|
||||
if (i < 1536)
|
||||
assertA(ARCHIVE_FATAL == archive_write_close(a));
|
||||
else
|
||||
assertA(0 == archive_write_close(a));
|
||||
#if ARCHIVE_API_VERSION > 1
|
||||
assert(0 == archive_write_finish(a));
|
||||
#else
|
||||
archive_write_finish(a);
|
||||
#endif
|
||||
assert(buff[i] == 0xAE);
|
||||
assert(s <= i);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user