MFV r309299:
Sync libarchive with vendor. Important vendor bugfixes (relevant to FreeBSD): #821: tar -P cannot extract hardlinks through symlinks #825: Add sanity check of tar "uid, "gid" and "mtime" fields PR: 213255 Reported by: Tijl Coosemans <tilj@FreeBSD.org> MFC after: 1 week
This commit is contained in:
commit
d5d08d297d
@ -1,3 +1,5 @@
|
||||
Oct 26, 2016: Remove liblzmadec support
|
||||
|
||||
Oct 23, 2016: libarchive 3.2.2 released
|
||||
Security release
|
||||
|
||||
|
@ -94,6 +94,7 @@ archive_acl_clear(struct archive_acl *acl)
|
||||
acl->acl_text = NULL;
|
||||
}
|
||||
acl->acl_p = NULL;
|
||||
acl->acl_types = 0;
|
||||
acl->acl_state = 0; /* Not counting. */
|
||||
}
|
||||
|
||||
@ -284,8 +285,11 @@ acl_new_entry(struct archive_acl *acl,
|
||||
aq = NULL;
|
||||
while (ap != NULL) {
|
||||
if (ap->type == type && ap->tag == tag && ap->id == id) {
|
||||
ap->permset = permset;
|
||||
return (ap);
|
||||
if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
|
||||
tag != ARCHIVE_ENTRY_ACL_GROUP)) {
|
||||
ap->permset = permset;
|
||||
return (ap);
|
||||
}
|
||||
}
|
||||
aq = ap;
|
||||
ap = ap->next;
|
||||
|
@ -1441,6 +1441,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
|
||||
type, permset, tag, id, name, wcslen(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a bitmask of ACL types in an archive entry ACL list
|
||||
*/
|
||||
int
|
||||
archive_entry_acl_types(struct archive_entry *entry)
|
||||
{
|
||||
return ((&entry->acl)->acl_types);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a count of entries matching "want_type".
|
||||
*/
|
||||
|
@ -508,6 +508,9 @@ __LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
|
||||
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
|
||||
int /* flags */);
|
||||
|
||||
/* Return bitmask of ACL types in an archive entry */
|
||||
__LA_DECL int archive_entry_acl_types(struct archive_entry *);
|
||||
|
||||
/* Return a count of entries matching 'want_type' */
|
||||
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
|
||||
|
||||
|
@ -33,7 +33,8 @@
|
||||
.Nm archive_entry_acl_next ,
|
||||
.Nm archive_entry_acl_next_w ,
|
||||
.Nm archive_entry_acl_reset ,
|
||||
.Nm archive_entry_acl_text_w
|
||||
.Nm archive_entry_acl_text_w ,
|
||||
.Nm archive_entry_acl_types
|
||||
.Nd functions for manipulating Access Control Lists in archive entry descriptions
|
||||
.Sh LIBRARY
|
||||
Streaming Archive Library (libarchive, -larchive)
|
||||
@ -85,6 +86,8 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_types "struct archive_entry *a"
|
||||
.\" enum?
|
||||
.Sh DESCRIPTION
|
||||
An
|
||||
@ -192,6 +195,11 @@ The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_types
|
||||
get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
|
||||
ACL entries cannot be mixed, this function is a very efficient way to detect if
|
||||
an ACL already contains POSIX.1e or NFSv4 ACL entries.
|
||||
.Sh RETURN VALUES
|
||||
.Fn archive_entry_acl_count
|
||||
and
|
||||
@ -225,6 +233,9 @@ The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_types
|
||||
returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_entry 3
|
||||
.Xr libarchive 3 ,
|
||||
|
@ -125,6 +125,10 @@ static int setup_xattrs(struct archive_read_disk *,
|
||||
struct archive_entry *, int *fd);
|
||||
static int setup_sparse(struct archive_read_disk *,
|
||||
struct archive_entry *, int *fd);
|
||||
#if defined(HAVE_LINUX_FIEMAP_H)
|
||||
static int setup_sparse_fiemap(struct archive_read_disk *,
|
||||
struct archive_entry *, int *fd);
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_disk_entry_from_file(struct archive *_a,
|
||||
@ -1124,7 +1128,7 @@ setup_xattrs(struct archive_read_disk *a,
|
||||
#if defined(HAVE_LINUX_FIEMAP_H)
|
||||
|
||||
/*
|
||||
* Linux sparse interface.
|
||||
* Linux FIEMAP sparse interface.
|
||||
*
|
||||
* The FIEMAP ioctl returns an "extent" for each physical allocation
|
||||
* on disk. We need to process those to generate a more compact list
|
||||
@ -1139,7 +1143,7 @@ setup_xattrs(struct archive_read_disk *a,
|
||||
*/
|
||||
|
||||
static int
|
||||
setup_sparse(struct archive_read_disk *a,
|
||||
setup_sparse_fiemap(struct archive_read_disk *a,
|
||||
struct archive_entry *entry, int *fd)
|
||||
{
|
||||
char buff[4096];
|
||||
@ -1191,7 +1195,7 @@ setup_sparse(struct archive_read_disk *a,
|
||||
/* When something error happens, it is better we
|
||||
* should return ARCHIVE_OK because an earlier
|
||||
* version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
|
||||
goto exit_setup_sparse;
|
||||
goto exit_setup_sparse_fiemap;
|
||||
}
|
||||
if (fm->fm_mapped_extents == 0) {
|
||||
if (iters == 0) {
|
||||
@ -1226,14 +1230,24 @@ setup_sparse(struct archive_read_disk *a,
|
||||
} else
|
||||
break;
|
||||
}
|
||||
exit_setup_sparse:
|
||||
exit_setup_sparse_fiemap:
|
||||
return (exit_sts);
|
||||
}
|
||||
|
||||
#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
|
||||
#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
|
||||
static int
|
||||
setup_sparse(struct archive_read_disk *a,
|
||||
struct archive_entry *entry, int *fd)
|
||||
{
|
||||
return setup_sparse_fiemap(a, entry, fd);
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(HAVE_LINUX_FIEMAP_H) */
|
||||
|
||||
#if defined(SEEK_HOLE) && defined(SEEK_DATA)
|
||||
|
||||
/*
|
||||
* FreeBSD and Solaris sparse interface.
|
||||
* SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
|
||||
*/
|
||||
|
||||
static int
|
||||
@ -1241,8 +1255,8 @@ setup_sparse(struct archive_read_disk *a,
|
||||
struct archive_entry *entry, int *fd)
|
||||
{
|
||||
int64_t size;
|
||||
off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
|
||||
off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
|
||||
off_t initial_off;
|
||||
off_t off_s, off_e;
|
||||
int exit_sts = ARCHIVE_OK;
|
||||
int check_fully_sparse = 0;
|
||||
|
||||
@ -1268,8 +1282,10 @@ setup_sparse(struct archive_read_disk *a,
|
||||
}
|
||||
|
||||
if (*fd >= 0) {
|
||||
#ifdef _PC_MIN_HOLE_SIZE
|
||||
if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
|
||||
return (ARCHIVE_OK);
|
||||
#endif
|
||||
initial_off = lseek(*fd, 0, SEEK_CUR);
|
||||
if (initial_off != 0)
|
||||
lseek(*fd, 0, SEEK_SET);
|
||||
@ -1280,8 +1296,10 @@ setup_sparse(struct archive_read_disk *a,
|
||||
if (path == NULL)
|
||||
path = archive_entry_pathname(entry);
|
||||
|
||||
#ifdef _PC_MIN_HOLE_SIZE
|
||||
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
|
||||
return (ARCHIVE_OK);
|
||||
#endif
|
||||
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (*fd < 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
@ -1292,6 +1310,19 @@ setup_sparse(struct archive_read_disk *a,
|
||||
initial_off = 0;
|
||||
}
|
||||
|
||||
#ifndef _PC_MIN_HOLE_SIZE
|
||||
/* Check if the underlying filesystem supports seek hole */
|
||||
off_s = lseek(*fd, 0, SEEK_HOLE);
|
||||
if (off_s < 0)
|
||||
#if defined(HAVE_LINUX_FIEMAP_H)
|
||||
return setup_sparse_fiemap(a, entry, fd);
|
||||
#else
|
||||
goto exit_setup_sparse;
|
||||
#endif
|
||||
else if (off_s > 0)
|
||||
lseek(*fd, 0, SEEK_SET);
|
||||
#endif
|
||||
|
||||
off_s = 0;
|
||||
size = archive_entry_size(entry);
|
||||
while (off_s < size) {
|
||||
@ -1341,7 +1372,7 @@ setup_sparse(struct archive_read_disk *a,
|
||||
return (exit_sts);
|
||||
}
|
||||
|
||||
#else
|
||||
#elif !defined(HAVE_LINUX_FIEMAP_H)
|
||||
|
||||
/*
|
||||
* Generic (stub) sparse support.
|
||||
|
@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#if HAVE_LZMA_H
|
||||
#include <lzma.h>
|
||||
#elif HAVE_LZMADEC_H
|
||||
#include <lzmadec.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **);
|
||||
static int xz_filter_close(struct archive_read_filter *);
|
||||
static int xz_lzma_bidder_init(struct archive_read_filter *);
|
||||
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
struct private_data {
|
||||
lzmadec_stream stream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Lzma-only filter */
|
||||
static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
|
||||
static int lzma_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a)
|
||||
bidder->free = NULL;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return (ARCHIVE_OK);
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lzma program for lzma decompression");
|
||||
@ -763,175 +746,6 @@ xz_filter_close(struct archive_read_filter *self)
|
||||
|
||||
#else
|
||||
|
||||
#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
/*
|
||||
* If we have the older liblzmadec library, then we can handle
|
||||
* LZMA streams but not XZ streams.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
ssize_t ret, avail_in;
|
||||
|
||||
self->code = ARCHIVE_FILTER_LZMA;
|
||||
self->name = "lzma";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for lzma decompression");
|
||||
free(out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = lzma_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = lzma_filter_close;
|
||||
|
||||
/* Prime the lzma library with 18 bytes of input. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 18, &avail_in);
|
||||
if (state->stream.next_in == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
state->stream.avail_in = avail_in;
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Initialize compression library. */
|
||||
ret = lzmadec_init(&(state->stream));
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
if (ret == LZMADEC_OK)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* Library setup failed: Clean up. */
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing lzma library");
|
||||
|
||||
/* Override the error message if we know what really went wrong. */
|
||||
switch (ret) {
|
||||
case LZMADEC_HEADER_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid header");
|
||||
break;
|
||||
case LZMADEC_MEM_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
self->data = NULL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next block of decompressed data.
|
||||
*/
|
||||
static ssize_t
|
||||
lzma_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in, ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (state->stream.next_in == NULL && avail_in < 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated lzma input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
|
||||
/* Decompress as much as we can in one pass. */
|
||||
ret = lzmadec_decode(&(state->stream), avail_in == 0);
|
||||
switch (ret) {
|
||||
case LZMADEC_STREAM_END: /* Found end of stream. */
|
||||
state->eof = 1;
|
||||
/* FALL THROUGH */
|
||||
case LZMADEC_OK: /* Decompressor made some progress. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
break;
|
||||
case LZMADEC_BUF_ERROR: /* Insufficient input data? */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
default:
|
||||
/* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma decompression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
decompressed = state->stream.next_out - state->out_block;
|
||||
state->total_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else
|
||||
*p = state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
lzma_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
ret = ARCHIVE_OK;
|
||||
switch (lzmadec_end(&(state->stream))) {
|
||||
case LZMADEC_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor",
|
||||
self->archive->archive.compression_name);
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
*
|
||||
* If we have no suitable library on this system, we can't actually do
|
||||
@ -953,9 +767,6 @@ lzma_bidder_init(struct archive_read_filter *self)
|
||||
return (r);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LZMADEC_H */
|
||||
|
||||
|
||||
static int
|
||||
xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
@ -984,5 +795,4 @@ lzip_bidder_init(struct archive_read_filter *self)
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_LZMA_H */
|
||||
|
@ -294,6 +294,46 @@ archive_read_format_tar_cleanup(struct archive_read *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
validate_number_field(const char* p_field, size_t i_size)
|
||||
{
|
||||
unsigned char marker = (unsigned char)p_field[0];
|
||||
/* octal? */
|
||||
if ((marker >= '0' && marker <= '7') || marker == ' ') {
|
||||
size_t i = 0;
|
||||
int octal_found = 0;
|
||||
for (i = 0; i < i_size; ++i) {
|
||||
switch (p_field[i])
|
||||
{
|
||||
case ' ': /* skip any leading spaces and trailing space*/
|
||||
if (octal_found == 0 || i == i_size - 1) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case '\0': /* null is allowed only at the end */
|
||||
if (i != i_size - 1) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
/* rest must be octal digits */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
++octal_found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return octal_found > 0;
|
||||
}
|
||||
/* base 256 (i.e. binary number) */
|
||||
else if (marker == 128 || marker == 255 || marker == 0) {
|
||||
/* nothing to check */
|
||||
return 1;
|
||||
}
|
||||
/* not a number field */
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
||||
@ -346,23 +386,23 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
||||
return (0);
|
||||
bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */
|
||||
|
||||
/* Sanity check: Look at first byte of mode field. */
|
||||
switch (255 & (unsigned)header->mode[0]) {
|
||||
case 0: case 255:
|
||||
/* Base-256 value: No further verification possible! */
|
||||
break;
|
||||
case ' ': /* Not recommended, but not illegal, either. */
|
||||
break;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
/* Octal Value. */
|
||||
/* TODO: Check format of remainder of this field. */
|
||||
break;
|
||||
default:
|
||||
/* Not a valid mode; bail out here. */
|
||||
return (0);
|
||||
/*
|
||||
* Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
|
||||
* These are usually octal numbers but GNU tar encodes "big" values as
|
||||
* base256 and leading zeroes are sometimes replaced by spaces.
|
||||
* Even the null terminator is sometimes omitted. Anyway, must be checked
|
||||
* to avoid false positives.
|
||||
*/
|
||||
if (bid > 0 &&
|
||||
(validate_number_field(header->mode, sizeof(header->mode)) == 0 ||
|
||||
validate_number_field(header->uid, sizeof(header->uid)) == 0 ||
|
||||
validate_number_field(header->gid, sizeof(header->gid)) == 0 ||
|
||||
validate_number_field(header->mtime, sizeof(header->mtime)) == 0 ||
|
||||
validate_number_field(header->size, sizeof(header->size)) == 0 ||
|
||||
validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 ||
|
||||
validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
|
||||
bid = 0;
|
||||
}
|
||||
/* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
|
||||
|
||||
return (bid);
|
||||
}
|
||||
|
@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#if HAVE_LZMA_H
|
||||
#include <lzma.h>
|
||||
#elif HAVE_LZMADEC_H
|
||||
#include <lzmadec.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
@ -334,9 +332,6 @@ struct xar {
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
lzma_stream lzstream;
|
||||
int lzstream_valid;
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
lzmadec_stream lzstream;
|
||||
int lzstream_valid;
|
||||
#endif
|
||||
/*
|
||||
* For Checksum data.
|
||||
@ -1526,34 +1521,6 @@ decompression_init(struct archive_read *a, enum enctype encoding)
|
||||
xar->lzstream.total_in = 0;
|
||||
xar->lzstream.total_out = 0;
|
||||
break;
|
||||
#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
if (xar->lzstream_valid)
|
||||
lzmadec_end(&(xar->lzstream));
|
||||
r = lzmadec_init(&(xar->lzstream));
|
||||
if (r != LZMADEC_OK) {
|
||||
switch (r) {
|
||||
case LZMADEC_HEADER_ERROR:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing "
|
||||
"compression library: "
|
||||
"invalid header");
|
||||
break;
|
||||
case LZMADEC_MEM_ERROR:
|
||||
archive_set_error(&a->archive,
|
||||
ENOMEM,
|
||||
"Internal error initializing "
|
||||
"compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
xar->lzstream_valid = 1;
|
||||
xar->lzstream.total_in = 0;
|
||||
xar->lzstream.total_out = 0;
|
||||
break;
|
||||
#endif
|
||||
/*
|
||||
* Unsupported compression.
|
||||
@ -1563,9 +1530,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
|
||||
case BZIP2:
|
||||
#endif
|
||||
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
|
||||
#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
#endif
|
||||
case XZ:
|
||||
#endif
|
||||
switch (xar->entry_encoding) {
|
||||
@ -1685,46 +1650,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
|
||||
*used = avail_in - xar->lzstream.avail_in;
|
||||
*outbytes = avail_out - xar->lzstream.avail_out;
|
||||
break;
|
||||
#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
|
||||
xar->lzstream.avail_in = avail_in;
|
||||
xar->lzstream.next_out = (unsigned char *)outbuff;
|
||||
xar->lzstream.avail_out = avail_out;
|
||||
r = lzmadec_decode(&(xar->lzstream), 0);
|
||||
switch (r) {
|
||||
case LZMADEC_STREAM_END: /* Found end of stream. */
|
||||
switch (lzmadec_end(&(xar->lzstream))) {
|
||||
case LZMADEC_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up lzmadec decompressor");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
xar->lzstream_valid = 0;
|
||||
/* FALLTHROUGH */
|
||||
case LZMADEC_OK: /* Decompressor made some progress. */
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"lzmadec decompression failed(%d)",
|
||||
r);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
*used = avail_in - xar->lzstream.avail_in;
|
||||
*outbytes = avail_out - xar->lzstream.avail_out;
|
||||
break;
|
||||
#endif
|
||||
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
|
||||
case BZIP2:
|
||||
#endif
|
||||
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
|
||||
#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
#endif
|
||||
case XZ:
|
||||
#endif
|
||||
case NONE:
|
||||
|
@ -336,14 +336,19 @@ struct archive_write_disk {
|
||||
|
||||
#define HFS_BLOCKS(s) ((s) >> 12)
|
||||
|
||||
static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
|
||||
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
||||
const char *);
|
||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||
int);
|
||||
static int check_symlinks(struct archive_write_disk *);
|
||||
static int create_filesystem_object(struct archive_write_disk *);
|
||||
static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
|
||||
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
||||
const char *pathname);
|
||||
#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
|
||||
static void edit_deep_directories(struct archive_write_disk *ad);
|
||||
#endif
|
||||
static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
|
||||
static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
|
||||
int);
|
||||
static int cleanup_pathname(struct archive_write_disk *);
|
||||
static int create_dir(struct archive_write_disk *, char *);
|
||||
static int create_parent_dir(struct archive_write_disk *, char *);
|
||||
@ -374,11 +379,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
|
||||
|
||||
static int _archive_write_disk_close(struct archive *);
|
||||
static int _archive_write_disk_free(struct archive *);
|
||||
static int _archive_write_disk_header(struct archive *, struct archive_entry *);
|
||||
static int _archive_write_disk_header(struct archive *,
|
||||
struct archive_entry *);
|
||||
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
|
||||
static int _archive_write_disk_finish_entry(struct archive *);
|
||||
static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
|
||||
static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
|
||||
static ssize_t _archive_write_disk_data(struct archive *, const void *,
|
||||
size_t);
|
||||
static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
|
||||
size_t, int64_t);
|
||||
|
||||
static int
|
||||
lazy_stat(struct archive_write_disk *a)
|
||||
@ -649,7 +657,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
if (a->restore_pwd >= 0) {
|
||||
r = fchdir(a->restore_pwd);
|
||||
if (r != 0) {
|
||||
archive_set_error(&a->archive, errno, "chdir() failure");
|
||||
archive_set_error(&a->archive, errno,
|
||||
"chdir() failure");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
close(a->restore_pwd);
|
||||
@ -697,7 +706,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
}
|
||||
if (archive_entry_birthtime_is_set(entry)) {
|
||||
fe->birthtime = archive_entry_birthtime(entry);
|
||||
fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
|
||||
fe->birthtime_nanos = archive_entry_birthtime_nsec(
|
||||
entry);
|
||||
} else {
|
||||
/* If birthtime is unset, use mtime. */
|
||||
fe->birthtime = fe->mtime;
|
||||
@ -723,7 +733,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->mac_metadata = malloc(metadata_size);
|
||||
if (fe->mac_metadata != NULL) {
|
||||
memcpy(fe->mac_metadata, metadata, metadata_size);
|
||||
memcpy(fe->mac_metadata, metadata,
|
||||
metadata_size);
|
||||
fe->mac_metadata_size = metadata_size;
|
||||
fe->fixup |= TODO_MAC_METADATA;
|
||||
}
|
||||
@ -1480,7 +1491,8 @@ _archive_write_disk_data_block(struct archive *_a,
|
||||
return (r);
|
||||
if ((size_t)r < size) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize);
|
||||
"Too much data: Truncating file at %ju bytes",
|
||||
(uintmax_t)a->filesize);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
#if ARCHIVE_VERSION_NUMBER < 3999000
|
||||
@ -2005,8 +2017,9 @@ restore_entry(struct archive_write_disk *a)
|
||||
|
||||
if (en) {
|
||||
/* Everything failed; give up here. */
|
||||
archive_set_error(&a->archive, en, "Can't create '%s'",
|
||||
a->name);
|
||||
if ((&a->archive)->error == NULL)
|
||||
archive_set_error(&a->archive, en, "Can't create '%s'",
|
||||
a->name);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2043,19 +2056,32 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
if (linkname_copy == NULL) {
|
||||
return (EPERM);
|
||||
}
|
||||
/* TODO: consider using the cleaned-up path as the link target? */
|
||||
r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags);
|
||||
/*
|
||||
* TODO: consider using the cleaned-up path as the link
|
||||
* target?
|
||||
*/
|
||||
r = cleanup_pathname_fsobj(linkname_copy, &error_number,
|
||||
&error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
free(linkname_copy);
|
||||
/* EPERM is more appropriate than error_number for our callers */
|
||||
/*
|
||||
* EPERM is more appropriate than error_number for our
|
||||
* callers
|
||||
*/
|
||||
return (EPERM);
|
||||
}
|
||||
r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags);
|
||||
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
||||
&error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
free(linkname_copy);
|
||||
/* EPERM is more appropriate than error_number for our callers */
|
||||
/*
|
||||
* EPERM is more appropriate than error_number for our
|
||||
* callers
|
||||
*/
|
||||
return (EPERM);
|
||||
}
|
||||
free(linkname_copy);
|
||||
@ -2076,8 +2102,8 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
a->todo = 0;
|
||||
a->deferred = 0;
|
||||
} else if (r == 0 && a->filesize > 0) {
|
||||
a->fd = open(a->name,
|
||||
O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
|
||||
a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY
|
||||
| O_CLOEXEC | O_NOFOLLOW);
|
||||
__archive_ensure_cloexec_flag(a->fd);
|
||||
if (a->fd < 0)
|
||||
r = errno;
|
||||
@ -2388,6 +2414,17 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
return (a->current_fixup);
|
||||
}
|
||||
|
||||
/* Error helper for new *_fsobj functions */
|
||||
static void
|
||||
fsobj_error(int *a_eno, struct archive_string *a_estr,
|
||||
int err, const char *errstr, const char *path)
|
||||
{
|
||||
if (a_eno)
|
||||
*a_eno = err;
|
||||
if (a_estr)
|
||||
archive_string_sprintf(a_estr, errstr, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Someday, integrate this with the deep dir support; they both
|
||||
* scan the path and both can be optimized by comparing against other
|
||||
@ -2400,7 +2437,8 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
* ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
|
||||
*/
|
||||
static int
|
||||
check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
|
||||
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
int flags)
|
||||
{
|
||||
#if !defined(HAVE_LSTAT)
|
||||
/* Platform doesn't have lstat, so we can't look for symlinks. */
|
||||
@ -2433,7 +2471,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
* - if it's a directory and it's not the last chunk, cd into it
|
||||
* As we go:
|
||||
* head points to the current (relative) path
|
||||
* tail points to the temporary \0 terminating the segment we're currently examining
|
||||
* tail points to the temporary \0 terminating the segment we're
|
||||
* currently examining
|
||||
* c holds what used to be in *tail
|
||||
* last is 1 if this is the last tail
|
||||
*/
|
||||
@ -2455,7 +2494,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
* Exiting the loop with break is okay; continue is not.
|
||||
*/
|
||||
while (!last) {
|
||||
/* Skip the separator we just consumed, plus any adjacent ones */
|
||||
/*
|
||||
* Skip the separator we just consumed, plus any adjacent ones
|
||||
*/
|
||||
while (*tail == '/')
|
||||
++tail;
|
||||
/* Skip the next path element. */
|
||||
@ -2474,19 +2515,20 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
/* Treat any other error as fatal - best to be paranoid here
|
||||
* Note: This effectively disables deep directory
|
||||
* support when security checks are enabled.
|
||||
* Otherwise, very long pathnames that trigger
|
||||
* an error here could evade the sandbox.
|
||||
* TODO: We could do better, but it would probably
|
||||
* require merging the symlink checks with the
|
||||
* deep-directory editing. */
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not stat %s",
|
||||
path);
|
||||
/*
|
||||
* Treat any other error as fatal - best to be
|
||||
* paranoid here.
|
||||
* Note: This effectively disables deep
|
||||
* directory support when security checks are
|
||||
* enabled. Otherwise, very long pathnames that
|
||||
* trigger an error here could evade the
|
||||
* sandbox.
|
||||
* TODO: We could do better, but it would
|
||||
* probably require merging the symlink checks
|
||||
* with the deep-directory editing.
|
||||
*/
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not stat %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
@ -2494,11 +2536,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
if (!last) {
|
||||
if (chdir(head) != 0) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not chdir %s",
|
||||
path);
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not chdir %s", path);
|
||||
res = (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
@ -2514,11 +2553,9 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
*/
|
||||
if (unlink(head)) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not remove symlink %s",
|
||||
path);
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not remove symlink %s",
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
@ -2529,13 +2566,14 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
* symlink with another symlink.
|
||||
*/
|
||||
tail[0] = c;
|
||||
/* FIXME: not sure how important this is to restore
|
||||
/*
|
||||
* FIXME: not sure how important this is to
|
||||
* restore
|
||||
*/
|
||||
/*
|
||||
if (!S_ISLNK(path)) {
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Removing symlink %s",
|
||||
path);
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Removing symlink %s", path);
|
||||
}
|
||||
*/
|
||||
/* Symlink gone. No more problem! */
|
||||
@ -2545,22 +2583,60 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
/* User asked us to remove problems. */
|
||||
if (unlink(head) != 0) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Cannot remove intervening symlink %s",
|
||||
path);
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot remove intervening "
|
||||
"symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
tail[0] = c;
|
||||
} else if ((flags &
|
||||
ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
|
||||
/*
|
||||
* We are not the last element and we want to
|
||||
* follow symlinks if they are a directory.
|
||||
*
|
||||
* This is needed to extract hardlinks over
|
||||
* symlinks.
|
||||
*/
|
||||
r = stat(head, &st);
|
||||
if (r != 0) {
|
||||
tail[0] = c;
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
fsobj_error(a_eno, a_estr,
|
||||
errno,
|
||||
"Could not stat %s", path);
|
||||
res = (ARCHIVE_FAILED);
|
||||
break;
|
||||
}
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
if (chdir(head) != 0) {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr,
|
||||
errno,
|
||||
"Could not chdir %s", path);
|
||||
res = (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Our view is now from inside
|
||||
* this dir:
|
||||
*/
|
||||
head = tail + 1;
|
||||
} else {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot extract through "
|
||||
"symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Cannot extract through symlink %s",
|
||||
path);
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot extract through symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
@ -2577,10 +2653,8 @@ check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error
|
||||
if (restore_pwd >= 0) {
|
||||
r = fchdir(restore_pwd);
|
||||
if (r != 0) {
|
||||
if(error_number) *error_number = errno;
|
||||
if(error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"chdir() failure");
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"chdir() failure", "");
|
||||
}
|
||||
close(restore_pwd);
|
||||
restore_pwd = -1;
|
||||
@ -2605,9 +2679,11 @@ check_symlinks(struct archive_write_disk *a)
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string, a->flags);
|
||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
||||
a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
a->pst = NULL; /* to be safe */
|
||||
@ -2688,17 +2764,16 @@ cleanup_pathname_win(struct archive_write_disk *a)
|
||||
* is set) if the path is absolute.
|
||||
*/
|
||||
static int
|
||||
cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
|
||||
cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
int flags)
|
||||
{
|
||||
char *dest, *src;
|
||||
char separator = '\0';
|
||||
|
||||
dest = src = path;
|
||||
if (*src == '\0') {
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Invalid empty pathname");
|
||||
fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid empty ", "pathname");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2708,10 +2783,8 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err
|
||||
/* Skip leading '/'. */
|
||||
if (*src == '/') {
|
||||
if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Path is absolute");
|
||||
fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
|
||||
"Path is ", "absolute");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2738,11 +2811,11 @@ cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *err
|
||||
} else if (src[1] == '.') {
|
||||
if (src[2] == '/' || src[2] == '\0') {
|
||||
/* Conditionally warn about '..' */
|
||||
if (flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Path contains '..'");
|
||||
if (flags
|
||||
& ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
fsobj_error(a_eno, a_estr,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Path contains ", "'..'");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
@ -2795,9 +2868,11 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, a->flags);
|
||||
rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
|
||||
a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
return rc;
|
||||
@ -2881,7 +2956,8 @@ create_dir(struct archive_write_disk *a, char *path)
|
||||
}
|
||||
} else if (errno != ENOENT && errno != ENOTDIR) {
|
||||
/* Stat failed? */
|
||||
archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't test directory '%s'", path);
|
||||
return (ARCHIVE_FAILED);
|
||||
} else if (slash != NULL) {
|
||||
*slash = '\0';
|
||||
@ -3406,7 +3482,8 @@ clear_nochange_fflags(struct archive_write_disk *a)
|
||||
nochange_flags |= EXT2_IMMUTABLE_FL;
|
||||
#endif
|
||||
|
||||
return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags));
|
||||
return (set_fflags_platform(a, a->fd, a->name, mode, 0,
|
||||
nochange_flags));
|
||||
}
|
||||
|
||||
|
||||
@ -3931,7 +4008,8 @@ set_xattrs(struct archive_write_disk *a)
|
||||
if (errno == ENOTSUP || errno == ENOSYS) {
|
||||
if (!warning_done) {
|
||||
warning_done = 1;
|
||||
archive_set_error(&a->archive, errno,
|
||||
archive_set_error(&a->archive,
|
||||
errno,
|
||||
"Cannot restore extended "
|
||||
"attributes on this file "
|
||||
"system");
|
||||
@ -3942,7 +4020,8 @@ set_xattrs(struct archive_write_disk *a)
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid extended attribute encountered");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
@ -3986,19 +4065,22 @@ set_xattrs(struct archive_write_disk *a)
|
||||
errno = 0;
|
||||
#if HAVE_EXTATTR_SET_FD
|
||||
if (a->fd >= 0)
|
||||
e = extattr_set_fd(a->fd, namespace, name, value, size);
|
||||
e = extattr_set_fd(a->fd, namespace, name,
|
||||
value, size);
|
||||
else
|
||||
#endif
|
||||
/* TODO: should we use extattr_set_link() instead? */
|
||||
{
|
||||
e = extattr_set_file(archive_entry_pathname(entry),
|
||||
namespace, name, value, size);
|
||||
e = extattr_set_file(
|
||||
archive_entry_pathname(entry), namespace,
|
||||
name, value, size);
|
||||
}
|
||||
if (e != (ssize_t)size) {
|
||||
if (errno == ENOTSUP || errno == ENOSYS) {
|
||||
if (!warning_done) {
|
||||
warning_done = 1;
|
||||
archive_set_error(&a->archive, errno,
|
||||
archive_set_error(&a->archive,
|
||||
errno,
|
||||
"Cannot restore extended "
|
||||
"attributes on this file "
|
||||
"system");
|
||||
|
@ -106,10 +106,48 @@ test_compat_gtar_1(void)
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* test_compat_gtar_2.tar exercises reading of UID = 2097152 as base256
|
||||
* and GID = 2097152 as octal without null terminator.
|
||||
*/
|
||||
static void
|
||||
test_compat_gtar_2(void)
|
||||
{
|
||||
char name[] = "test_compat_gtar_2.tar";
|
||||
struct archive_entry *ae;
|
||||
struct archive *a;
|
||||
int r;
|
||||
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
extract_reference_file(name);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
|
||||
|
||||
/* Read first entry. */
|
||||
assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check UID and GID */
|
||||
assertEqualInt(2097152, archive_entry_uid(ae));
|
||||
assertEqualInt(2097152, archive_entry_gid(ae));
|
||||
|
||||
/* Verify the end-of-archive. */
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
|
||||
/* Verify that the format detection worked. */
|
||||
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
|
||||
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);
|
||||
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_compat_gtar)
|
||||
{
|
||||
test_compat_gtar_1();
|
||||
test_compat_gtar_2();
|
||||
}
|
||||
|
||||
|
||||
|
49
contrib/libarchive/libarchive/test/test_compat_gtar_2.tar.uu
Normal file
49
contrib/libarchive/libarchive/test/test_compat_gtar_2.tar.uu
Normal file
@ -0,0 +1,49 @@
|
||||
begin 660 test_compat_gtar_2.tar.uu
|
||||
M9FEL95]W:71H7V)I9U]U:61?9VED````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````#`P,#`V-C8`@``````@```Q,#`P,#`P,#`P,#`P,#`P,38W
|
||||
M`#$S,#$T-C<R,38W`#`Q,S,U,``@,```````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````!U<W1A<B`@`'1E<W0`
|
||||
M````````````````````````````````````8FEG````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````!4:&ES(&9I;&4@:&%S($=)1#TR,#DW,34R('=H
|
||||
M:6-H(&ES(&]N92!O=F5R('1H92!L:6UI="!O9B!T87(@=BXW(&%N9"!'3E4@
|
||||
M=&%R('-T;W)E<R!I="!A<R!B87-E(#(U-B!N=6UB97(@*&YO="!O8W1A;"DN
|
||||
M"@``````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
7````````````````````````````````
|
||||
`
|
||||
end
|
@ -0,0 +1,215 @@
|
||||
/*-
|
||||
* 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 reading entries with POSIX.1e ACLs from archives created by star
|
||||
*
|
||||
* This should work on all systems, regardless of whether local filesystems
|
||||
* support ACLs or not.
|
||||
*/
|
||||
|
||||
struct acl_t {
|
||||
int type; /* Type of ACL: "access" or "default" */
|
||||
int permset; /* Permissions for this class of users. */
|
||||
int tag; /* Owner, User, Owning group, group, other, etc. */
|
||||
const char *name; /* Name of user/group, depending on tag. */
|
||||
};
|
||||
|
||||
static struct acl_t acls0[] = {
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_USER, "user77" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_MASK, ""},
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
|
||||
ARCHIVE_ENTRY_ACL_OTHER, "" },
|
||||
};
|
||||
|
||||
static struct acl_t acls1[] = {
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_USER, "user77" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
|
||||
ARCHIVE_ENTRY_ACL_USER, "user78" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
|
||||
ARCHIVE_ENTRY_ACL_GROUP, "group78" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
|
||||
ARCHIVE_ENTRY_ACL_MASK, ""},
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_OTHER, "" },
|
||||
};
|
||||
|
||||
static struct acl_t acls2[] = {
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_USER, "user77" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
|
||||
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_GROUP, "group78" },
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
|
||||
ARCHIVE_ENTRY_ACL_MASK, ""},
|
||||
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_WRITE,
|
||||
ARCHIVE_ENTRY_ACL_OTHER, "" },
|
||||
};
|
||||
|
||||
static int
|
||||
acl_match(struct acl_t *acl, int type, int permset, int tag, const char *name)
|
||||
{
|
||||
if (type != acl->type)
|
||||
return (0);
|
||||
if (permset != acl->permset)
|
||||
return (0);
|
||||
if (tag != acl->tag)
|
||||
return (0);
|
||||
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
|
||||
return (1);
|
||||
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
|
||||
return (1);
|
||||
if (tag == ARCHIVE_ENTRY_ACL_OTHER)
|
||||
return (1);
|
||||
if (tag == ARCHIVE_ENTRY_ACL_MASK)
|
||||
return (1);
|
||||
if (name == NULL)
|
||||
return (acl->name == NULL || acl->name[0] == '\0');
|
||||
if (acl->name == NULL)
|
||||
return (name == NULL || name[0] == '\0');
|
||||
return (0 == strcmp(name, acl->name));
|
||||
}
|
||||
|
||||
static void
|
||||
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode,
|
||||
int want_type)
|
||||
{
|
||||
int *marker = malloc(sizeof(marker[0]) * n);
|
||||
int i;
|
||||
int r;
|
||||
int type, permset, tag, qual;
|
||||
int matched;
|
||||
const char *name;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
marker[i] = i;
|
||||
|
||||
while (0 == (r = archive_entry_acl_next(ae, want_type,
|
||||
&type, &permset, &tag, &qual, &name))) {
|
||||
for (i = 0, matched = 0; i < n && !matched; i++) {
|
||||
if (acl_match(&acls[marker[i]], type, permset,
|
||||
tag, name)) {
|
||||
/* We found a match; remove it. */
|
||||
marker[i] = marker[n - 1];
|
||||
n--;
|
||||
matched = 1;
|
||||
}
|
||||
}
|
||||
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
|
||||
if (!matched) printf("No match for user_obj perm\n");
|
||||
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
|
||||
failure("USER_OBJ permset (%02o) != user mode (%02o)",
|
||||
permset, 07 & (mode >> 6));
|
||||
assert((permset << 6) == (mode & 0700));
|
||||
}
|
||||
} else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
|
||||
if (!matched) printf("No match for group_obj perm\n");
|
||||
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
|
||||
failure("GROUP_OBJ permset %02o != group mode %02o",
|
||||
permset, 07 & (mode >> 3));
|
||||
assert((permset << 3) == (mode & 0070));
|
||||
}
|
||||
} else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
|
||||
if (!matched) printf("No match for other perm\n");
|
||||
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
|
||||
failure("OTHER permset (%02o) != other mode (%02o)",
|
||||
permset, mode & 07);
|
||||
assert((permset << 0) == (mode & 0007));
|
||||
}
|
||||
} else if (tag != ARCHIVE_ENTRY_ACL_MASK) {
|
||||
failure("Could not find match for ACL "
|
||||
"(type=%d,permset=%d,tag=%d,name=``%s'')",
|
||||
type, permset, tag, name);
|
||||
assert(matched == 1);
|
||||
}
|
||||
}
|
||||
assertEqualInt(ARCHIVE_EOF, r);
|
||||
assert((mode_t)(mode & 0777) == (archive_entry_mode(ae) & 0777));
|
||||
failure("Could not find match for ACL "
|
||||
"(type=%d,permset=%d,tag=%d,name=``%s'')",
|
||||
acls[marker[0]].type, acls[marker[0]].permset,
|
||||
acls[marker[0]].tag, acls[marker[0]].name);
|
||||
assert(n == 0); /* Number of ACLs not matched should == 0 */
|
||||
free(marker);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_compat_star_acl_posix1e)
|
||||
{
|
||||
char name[] = "test_compat_star_acl_posix1e.tar";
|
||||
struct archive *a;
|
||||
struct archive_entry *ae;
|
||||
|
||||
/* Read archive file */
|
||||
assert(NULL != (a = archive_read_new()));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
extract_reference_file(name);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
|
||||
|
||||
/* First item has a few ACLs */
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
failure("One extended ACL should flag all ACLs to be returned.");
|
||||
assertEqualInt(5, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), 0142, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Second item has pretty extensive ACLs */
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualInt(7, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
|
||||
compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0543, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
failure("Basic ACLs should set mode to 0543, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0543);
|
||||
|
||||
/* Third item has default ACLs */
|
||||
assertA(0 == archive_read_next_header(a, &ae));
|
||||
assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
|
||||
compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0142, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
|
||||
failure("Basic ACLs should set mode to 0142, not %04o",
|
||||
archive_entry_mode(ae)&0777);
|
||||
assert((archive_entry_mode(ae) & 0777) == 0142);
|
||||
|
||||
/* Close the archive. */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
begin 644 test_compat_star_acl_posix1e.tar
|
||||
M+B\N+T!087A(96%D97(`````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````#`P,#`V,#`@,#`P,#`P,"`P,#`P,#`P(#`P,#`P,#`P,C<R
|
||||
M(#`P,#`P,#`P,#`P(#`P,38P-S0@9P``````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````!U<W1A<@`P,')O;W0`
|
||||
M````````````````````````````````````=VAE96P`````````````````
|
||||
M```````````````````P,#`P,#`P(#`P,#`P,#`@````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M```````````````````````````````````P,#`P,#`P,#`P,"`P,#`P,#`P
|
||||
M,#`P,"`````````````````U-R!30TA)3%DN<F5L96%S93US=&%R(#$N-2XS
|
||||
M("AA;60V-"UU;FMN;W=N+69R965B<V0Q,2XP*0HR-R!30TA)3%DN87)C:'1Y
|
||||
M<&4]97AU<W1A<@HT-R!30TA)3%DN=F]L:&1R+F1U;7!D871E/3$T-SDQ,CDY
|
||||
M-30N,#4X-S<R-SDS"C(U(%-#2$E,62YV;VQH9'(N=F]L;F\],0HS,"!30TA)
|
||||
M3%DN=F]L:&1R+F)L;V-K<VEZ93TR,`H`````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````````````````````````````````"XO+B]`4&%X2&5A
|
||||
M9&5R````````````````````````````````````````````````````````
|
||||
M```````````````````````````````````````````````````````````P
|
||||
M,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#(U,2`P,#`P,#`P,#`P
|
||||
M,"`P,#$V,3$R('@`````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````=7-T87(`,#!R;V]T````````````````
|
||||
M`````````````````````'=H965L````````````````````````````````
|
||||
M````,#`P,#`P,"`P,#`P,#`P(```````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````,#`P,#`P,#`P,#`@,#`P,#`P,#`P,#`@````````
|
||||
M````````,S`@871I;64],30W.3$R,34Y-BXT.#4W,30P,#`*,S`@8W1I;64]
|
||||
M,30W.3$R.3<V-RXQ,#@Y.#8P,#`*,S`@;71I;64],30W.3$R,34Y-BXT.#4W
|
||||
M,30P,#`*-SD@4T-(24Q9+F%C;"YA8V-E<W,]=7-E<CHZ+2UX+'5S97(Z=7-E
|
||||
M<C<W.G(M+2QG<F]U<#HZ<BTM+&UA<VLZ.G(M+2QO=&AE<CHZ+7<M"@``````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````!F:6QE,0``````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````,#`P,#$T,B`P,#`P
|
||||
M,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,34R-S0@,#`Q-#8W,2`P
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````'5S=&%R`#`P<F]O=```````````````````````````````
|
||||
M``````!W:&5E;````````````````````````````````````#`P,#`P,#`@
|
||||
M,#`P,#`P,"``````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````#$S,#$R,S$U,C<T(#$S,#$R,S,U,C0W(````````````````"XO+B]`
|
||||
M4&%X2&5A9&5R````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M```````P,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#,Q-"`P,#`P
|
||||
M,#`P,#`P,"`P,#$V,3$R('@`````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````=7-T87(`,#!R;V]T````````
|
||||
M`````````````````````````````'=H965L````````````````````````
|
||||
M````````````,#`P,#`P,"`P,#`P,#`P(```````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````,#`P,#`P,#`P,#`@,#`P,#`P,#`P,#`@
|
||||
M````````````````,S`@871I;64],30W.3$R,38P,2XP-C`X-C8P,#`*,S`@
|
||||
M8W1I;64],30W.3$R.3<V-RXQ,#@Y-S0P,#`*,S`@;71I;64],30W.3$R,38P
|
||||
M,2XP-C`X-C8P,#`*,3$T(%-#2$E,62YA8VPN86-C97-S/75S97(Z.G(M>"QU
|
||||
M<V5R.G5S97(W-SIR+2TL=7-E<CIU<V5R-S@Z+2TM+&=R;W5P.CIR+2TL9W)O
|
||||
M=7`Z9W)O=7`W.#IR=W@L;6%S:SHZ<G=X+&]T:&5R.CHM=W@*````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````!F:6QE,@``````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````,#`P,#4W
|
||||
M,R`P,#`P,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,34S,#$@,#`Q
|
||||
M-#8V,"`P````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````````'5S=&%R`#`P<F]O=```````````````````````
|
||||
M``````````````!W:&5E;````````````````````````````````````#`P
|
||||
M,#`P,#`@,#`P,#`P,"``````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````#$S,#$R,S$U,S`Q(#$S,#$R,S,U,C0W(```````````````
|
||||
M`"XO+B]`4&%X2&5A9&5R````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M```````````````P,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#,W
|
||||
M,R`P,#`P,#`P,#`P,"`P,#$V,3$W('@`````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````=7-T87(`,#!R;V]T
|
||||
M`````````````````````````````````````'=H965L````````````````
|
||||
M````````````````````,#`P,#`P,"`P,#`P,#`P(```````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````,#`P,#`P,#`P,#`@,#`P,#`P
|
||||
M,#`P,#`@````````````````,S`@871I;64],30W.3$R,3<R-BXX,3<T-3`P
|
||||
M,#`*,S`@8W1I;64],30W.3$R,3@S,2XU.#,U-3(P,#`*,S`@;71I;64],30W
|
||||
M.3$R,3<R-BXX,3<T-3`P,#`*-C,@4T-(24Q9+F%C;"YA8V-E<W,]=7-E<CHZ
|
||||
M+2UX+&=R;W5P.CIR+2TL;6%S:SHZ<BTM+&]T:&5R.CHM=RT*.3@@4T-(24Q9
|
||||
M+F%C;"YD969A=6QT/75S97(Z.BTM>"QU<V5R.G5S97(W-SIR+2TL9W)O=7`Z
|
||||
M.G(M+2QG<F]U<#IG<F]U<#<X.BTM>"QM87-K.CIR+7@L;W1H97(Z.BUW+0H`
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````````!D:7(Q+P``````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M,#`P,#$T,B`P,#`P,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,34T
|
||||
M-S8@,#`Q-#8R-B`U````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````````````````'5S=&%R`#`P<F]O=```````````````
|
||||
M``````````````````````!W:&5E;```````````````````````````````
|
||||
M`````#`P,#`P,#`@,#`P,#`P,"``````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````````#$S,#$R,S$U-#<V(#$S,#$R,S$U-C0W(```````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
9````````````````````````````````````
|
||||
`
|
||||
end
|
@ -0,0 +1,95 @@
|
||||
begin 660 test_read_format_raw.bufr.uu
|
||||
M,#`P-S0T.3@P,`$-#0HP,#`-#0I)15%8,#$@155-4"`P-S`U,#`-#0I"5492
|
||||
M`2+?!```%@``_@`````#_]T0``?@"P<$.P````D``'C`Z`@!(K0``,``_@!N
|
||||
M@#T!^`"P!P"!`````"JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ@#=]]]]]
|
||||
M]]]]]]]]]]@`````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````0AS@
|
||||
M/.`\X#S@//M\^WS[?/M]%ET6719=%ETQ/3$],3TQ(```````````&V`;8!M@
|
||||
M&V`V0#9`-D`V0%&`48!1@%&`;&!L8&Q@;&"'0(=`AT"'0*(@HB"B(*(@O8"]
|
||||
M@+V`O8#80-A`V$#80/.@\Z#SH/.A#H$.@0Z!#H$I82EA*6$I843!1,%$P43!
|
||||
M7X%?@5^!7X%Z87IA>F%Z897!E<&5P97!L*&PH;"AL*',`<P!S`',`>;AYN'F
|
||||
MX>;B`B("(@(B`B(<@AR"'((<@C?B-^(WXC?B4L)2PE+"4L)N(FXB;B)N(HCB
|
||||
MB.*(XHCBH\*CPJ/"H\BZQK3$>Z`M3P```96P=EB)(F#:0C*.B=E8YJH8[61W
|
||||
MV+Z)DM;2)*Q8Z4V[T6O1*GO&@Y3UWQHV$QNX==:0U"G4XC@H"!]-(J(@'D/?
|
||||
M@(SYTVUR+"E#9NEU?4F/)3&DAC2@Z%6S^G>N30VJGI%L62FLU1@^LI27SAJ\
|
||||
MAE7)"Z[IC/VMTH6><,,*6=1B_>=>!,RS3:UOL>+6(/[321O:>SY39A-MM<W-
|
||||
MRC7A%J!DXUZ=ZKM_#FX=3KN![XZY_(<B@/0)X">;Q$AVID_52A79OI7GLR$&
|
||||
MSF*I)!#&@`%Q#EY!`,.RR%*'&\:EF1QI5(J]<GHB=*+)O?D-%S2?J38<U/^7
|
||||
MI50TKK;FT6L)]PU4'>X(-6,[J'"6>D\2[%OX:S*/?P46S?=U=PV5MOW^%-?Q
|
||||
M"-,Z'1F[U]*D5IJX<+]WA,(L9NKCB>[D-C</1[P"M>3H[!`U7VI[+9C9M9:A
|
||||
M3'3YOJJE-5E\Z$7102[J,RG1VXIIC',\]YQ3C.:890?))T[97M[+-*8XQY&W
|
||||
MIH_F5(+RXB"?$"!HHBA%2^8,)-!3&H29["AH7VT*^HIG\Y^_U;GAW,\!)WGV
|
||||
M&],S7-,TY;['3(@ZG`VXB\VVM&^?"X!RVCO\T02FIP`U;[V.JPQGC64RBRT4
|
||||
MUY0&N\%%_CDP*E%B_.L)Q%IB\M:L5+[&I0_%2T.JE&DSJ\F.HTZ_HGFV49Y:
|
||||
MC`"$AQ,D=<3^/R?B54&T*A&33@,V;Q7#IJ$==HB_(T7H(#)O*9>_":$02^K"
|
||||
MF*F5#21OUT-KRQ]\L0"FP^9B'>[1/3**.N@"OB````7M\#3O$=.;64K*60;(
|
||||
M,]2>I1YH\R)I$TL26+"'A#Q(8D+O!W@^'?#M86L+?5OJO77KL:6-2E)2DKC5
|
||||
MQHT4:*6!+"=3.IGX3\1=8NN9D,R$7"+A.DG2+C%R#<!N`6L+:'X#[@```P(8
|
||||
M$("2!*@$P!P@<00%]"]C?QP`O07D3V)[D:B-)G(SF7E+R'[S]YV$[`EN2W(W
|
||||
MT;RO%7BIA4P,>&/"^9?*X#<"-<&M[Y5\L[_=_1,(F$):$K+4EJR-I&M(FD3/
|
||||
MDGR64K*=:6M(.$Q](FI95+*I%-(>I9E++I$-(4I9U+,I"](+I:=+1I!](`I;
|
||||
M-+6I`E'RI;]+;H^U'CI==+FH]%'1I?=+TH[%&WIAU,$HX%&8IEE,?HTE%NIK
|
||||
MU-)HO]$GIU=.(HHE"HJ(-/[H<4]LJX=3^H!L:<OTUC(F6Q$]"Z@``+20XM$K
|
||||
M@BJ'9XU0%(0H!&Q8SQ%68J2&B`RN%=`K5&8(R0%C`L,&3PQU%F0LJ&/XQ?%H
|
||||
M@L^&,XQ-%J`M-&*@P]%K`M6&(8PO%KHM;&&@PA%KXM?&$XP5%L`MAP'%K
|
||||
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
|
||||
!20``
|
||||
`
|
||||
end
|
@ -35,6 +35,7 @@ DEFINE_TEST(test_read_format_raw)
|
||||
struct archive *a;
|
||||
const char *reffile1 = "test_read_format_raw.data";
|
||||
const char *reffile2 = "test_read_format_raw.data.Z";
|
||||
const char *reffile3 = "test_read_format_raw.bufr";
|
||||
|
||||
/* First, try pulling data out of an uninterpretable file. */
|
||||
extract_reference_file(reffile1);
|
||||
@ -90,4 +91,30 @@ DEFINE_TEST(test_read_format_raw)
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
|
||||
|
||||
/* Third, try with file which fooled us in past - appeared to be tar. */
|
||||
extract_reference_file(reffile3);
|
||||
assert((a = archive_read_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_read_open_filename(a, reffile3, 1));
|
||||
|
||||
/* First (and only!) Entry */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
assertEqualString("data", archive_entry_pathname(ae));
|
||||
assertEqualInt(archive_entry_is_encrypted(ae), 0);
|
||||
assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
|
||||
/* Most fields should be unset (unknown) */
|
||||
assert(!archive_entry_size_is_set(ae));
|
||||
assert(!archive_entry_atime_is_set(ae));
|
||||
assert(!archive_entry_ctime_is_set(ae));
|
||||
assert(!archive_entry_mtime_is_set(ae));
|
||||
|
||||
/* Test EOF */
|
||||
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
||||
|
@ -146,28 +146,14 @@ create_sparse_file(const char *path, const struct sparse *s)
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_PC_MIN_HOLE_SIZE)
|
||||
|
||||
/*
|
||||
* FreeBSD and Solaris can detect 'hole' of a sparse file
|
||||
* through lseek(HOLE) on ZFS. (UFS does not support yet)
|
||||
*/
|
||||
|
||||
static int
|
||||
is_sparse_supported(const char *path)
|
||||
{
|
||||
return (pathconf(path, _PC_MIN_HOLE_SIZE) > 0);
|
||||
}
|
||||
|
||||
#elif defined(__linux__)&& defined(HAVE_LINUX_FIEMAP_H)
|
||||
|
||||
#if defined(HAVE_LINUX_FIEMAP_H)
|
||||
/*
|
||||
* FIEMAP, which can detect 'hole' of a sparse file, has
|
||||
* been supported from 2.6.28
|
||||
*/
|
||||
|
||||
static int
|
||||
is_sparse_supported(const char *path)
|
||||
is_sparse_supported_fiemap(const char *path)
|
||||
{
|
||||
const struct sparse sparse_file[] = {
|
||||
/* This hole size is too small to create a sparse
|
||||
@ -198,7 +184,58 @@ is_sparse_supported(const char *path)
|
||||
return (r >= 0);
|
||||
}
|
||||
|
||||
#else
|
||||
#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
|
||||
static int
|
||||
is_sparse_supported(const char *path)
|
||||
{
|
||||
return is_sparse_supported_fiemap(path);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_PC_MIN_HOLE_SIZE)
|
||||
|
||||
/*
|
||||
* FreeBSD and Solaris can detect 'hole' of a sparse file
|
||||
* through lseek(HOLE) on ZFS. (UFS does not support yet)
|
||||
*/
|
||||
|
||||
static int
|
||||
is_sparse_supported(const char *path)
|
||||
{
|
||||
return (pathconf(path, _PC_MIN_HOLE_SIZE) > 0);
|
||||
}
|
||||
|
||||
#elif defined(SEEK_HOLE) && defined(SEEK_DATA)
|
||||
|
||||
static int
|
||||
is_sparse_supported(const char *path)
|
||||
{
|
||||
const struct sparse sparse_file[] = {
|
||||
/* This hole size is too small to create a sparse
|
||||
* files for almost filesystem. */
|
||||
{ HOLE, 1024 }, { DATA, 10240 },
|
||||
{ END, 0 }
|
||||
};
|
||||
int fd, r;
|
||||
const char *testfile = "can_sparse";
|
||||
|
||||
(void)path; /* UNUSED */
|
||||
create_sparse_file(testfile, sparse_file);
|
||||
fd = open(testfile, O_RDWR);
|
||||
if (fd < 0)
|
||||
return (0);
|
||||
r = lseek(fd, 0, SEEK_HOLE);
|
||||
close(fd);
|
||||
unlink(testfile);
|
||||
#if defined(HAVE_LINUX_FIEMAP_H)
|
||||
if (r < 0)
|
||||
return (is_sparse_supported_fiemap(path));
|
||||
#endif
|
||||
return (r >= 0);
|
||||
}
|
||||
|
||||
#elif !defined(HAVE_LINUX_FIEMAP_H)
|
||||
|
||||
/*
|
||||
* Other system may do not have the API such as lseek(HOLE),
|
||||
|
@ -47,11 +47,18 @@ DEFINE_TEST(test_symlink_dir)
|
||||
assertMakeDir("source/dir3", 0755);
|
||||
assertMakeDir("source/dir3/d3", 0755);
|
||||
assertMakeFile("source/dir3/f3", 0755, "abcde");
|
||||
assertMakeDir("source/dir4", 0755);
|
||||
assertMakeFile("source/dir4/file3", 0755, "abcdef");
|
||||
assertMakeHardlink("source/dir4/file4", "source/dir4/file3");
|
||||
|
||||
assertEqualInt(0,
|
||||
systemf("%s -cf test.tar -C source dir dir2 dir3 file file2",
|
||||
testprog));
|
||||
|
||||
/* Second archive with hardlinks */
|
||||
assertEqualInt(0,
|
||||
systemf("%s -cf test2.tar -C source dir4", testprog));
|
||||
|
||||
/*
|
||||
* Extract with -x and without -P.
|
||||
*/
|
||||
@ -118,9 +125,15 @@ DEFINE_TEST(test_symlink_dir)
|
||||
assertMakeSymlink("dest2/file2", "real_file2");
|
||||
assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
|
||||
|
||||
/* dest2/dir symlink should be followed */
|
||||
/* "dir4" is a symlink to existing "real_dir" */
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/dir4", "real_dir");
|
||||
assertEqualInt(0, systemf("%s -xPf test2.tar -C dest2", testprog));
|
||||
|
||||
/* dest2/dir and dest2/dir4 symlinks should be followed */
|
||||
if (canSymlink()) {
|
||||
assertIsSymlink("dest2/dir", "real_dir");
|
||||
assertIsSymlink("dest2/dir4", "real_dir");
|
||||
assertIsDir("dest2/real_dir", -1);
|
||||
}
|
||||
|
||||
@ -141,4 +154,7 @@ DEFINE_TEST(test_symlink_dir)
|
||||
/* dest2/file2 symlink should be removed */
|
||||
failure("Symlink to non-existing file should be removed");
|
||||
assertIsReg("dest2/file2", -1);
|
||||
|
||||
/* dest2/dir4/file3 and dest2/dir4/file4 should be hard links */
|
||||
assertIsHardlink("dest2/dir4/file3", "dest2/dir4/file4");
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ TESTS_SRCS= \
|
||||
test_compat_pax_libarchive_2x.c \
|
||||
test_compat_solaris_tar_acl.c \
|
||||
test_compat_solaris_pax_sparse.c \
|
||||
test_compat_star_acl_posix1e.c \
|
||||
test_compat_tar_hardlink.c \
|
||||
test_compat_uudecode.c \
|
||||
test_compat_uudecode_large.c \
|
||||
@ -321,6 +322,7 @@ ${PACKAGE}FILES+= test_compat_bzip2_1.tbz.uu
|
||||
${PACKAGE}FILES+= test_compat_bzip2_2.tbz.uu
|
||||
${PACKAGE}FILES+= test_compat_cpio_1.cpio.uu
|
||||
${PACKAGE}FILES+= test_compat_gtar_1.tar.uu
|
||||
${PACKAGE}FILES+= test_compat_gtar_2.tar.uu
|
||||
${PACKAGE}FILES+= test_compat_gzip_1.tgz.uu
|
||||
${PACKAGE}FILES+= test_compat_gzip_2.tgz.uu
|
||||
${PACKAGE}FILES+= test_compat_lz4_1.tar.lz4.uu
|
||||
@ -349,6 +351,7 @@ ${PACKAGE}FILES+= test_compat_pax_libarchive_2x.tar.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_1.pax.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_2.pax.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_solaris_tar_acl.tar.uu
|
||||
${PACKAGE}FILES+= test_compat_star_acl_posix1e.tar.uu
|
||||
${PACKAGE}FILES+= test_compat_tar_hardlink_1.tar.uu
|
||||
${PACKAGE}FILES+= test_compat_uudecode_large.tar.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_xz_1.txz.uu
|
||||
@ -490,6 +493,7 @@ ${PACKAGE}FILES+= test_read_format_rar_sfx.exe.uu
|
||||
${PACKAGE}FILES+= test_read_format_rar_subblock.rar.uu
|
||||
${PACKAGE}FILES+= test_read_format_rar_unicode.rar.uu
|
||||
${PACKAGE}FILES+= test_read_format_rar_windows.rar.uu
|
||||
${PACKAGE}FILES+= test_read_format_raw.bufr.uu
|
||||
${PACKAGE}FILES+= test_read_format_raw.data.Z.uu
|
||||
${PACKAGE}FILES+= test_read_format_raw.data.uu
|
||||
${PACKAGE}FILES+= test_read_format_tar_concatenated.tar.uu
|
||||
|
Loading…
Reference in New Issue
Block a user