MFC r309362:
Sync libarchive with vendor. Small improvements, style fixes, bugfixes. Restores compatibility with tar archives created with Perl Archive::Tar (1) MFC after: 1 week Reported by: Matthew Seaman <matthew@freebsd.org> (1)
This commit is contained in:
commit
007dbc1f18
@ -562,7 +562,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *);
|
||||
* we cannot say whether there are encrypted entries, then
|
||||
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
|
||||
* In general, this function will return values below zero when the
|
||||
* reader is uncertain or totally uncapable of encryption support.
|
||||
* reader is uncertain or totally incapable of encryption support.
|
||||
* When this function returns 0 you can be sure that the reader
|
||||
* supports encryption detection but no encrypted entries have
|
||||
* been found yet.
|
||||
@ -984,12 +984,12 @@ __LA_DECL int archive_read_disk_can_descend(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
|
||||
/* Request that the access time of the entry visited by travesal be restored. */
|
||||
/* Request that the access time of the entry visited by traversal be restored. */
|
||||
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
|
||||
/*
|
||||
* Set behavior. The "flags" argument selects optional behavior.
|
||||
*/
|
||||
/* Request that the access time of the entry visited by travesal be restored.
|
||||
/* Request that the access time of the entry visited by traversal be restored.
|
||||
* This is the same as archive_read_disk_set_atime_restored. */
|
||||
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
|
||||
/* Default: Do not skip an entry which has nodump flags. */
|
||||
@ -1124,7 +1124,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *,
|
||||
|
||||
/*
|
||||
* Flags to tell a matching type of time stamps. These are used for
|
||||
* following functinos.
|
||||
* following functions.
|
||||
*/
|
||||
/* Time flag: mtime to be tested. */
|
||||
#define ARCHIVE_MATCH_MTIME (0x0100)
|
||||
@ -1144,7 +1144,7 @@ __LA_DECL int archive_match_include_date(struct archive *, int _flag,
|
||||
const char *_datestr);
|
||||
__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
|
||||
const wchar_t *_datestr);
|
||||
/* Set inclusion time by a particluar file. */
|
||||
/* Set inclusion time by a particular file. */
|
||||
__LA_DECL int archive_match_include_file_time(struct archive *,
|
||||
int _flag, const char *_pathname);
|
||||
__LA_DECL int archive_match_include_file_time_w(struct archive *,
|
||||
|
@ -75,6 +75,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define MTREE_HAS_OPTIONAL 0x0800
|
||||
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
|
||||
|
||||
#define MTREE_HASHTABLE_SIZE 1024
|
||||
|
||||
struct mtree_option {
|
||||
struct mtree_option *next;
|
||||
char *value;
|
||||
@ -86,6 +88,8 @@ struct mtree_entry {
|
||||
char *name;
|
||||
char full;
|
||||
char used;
|
||||
unsigned int name_hash;
|
||||
struct mtree_entry *hashtable_next;
|
||||
};
|
||||
|
||||
struct mtree {
|
||||
@ -98,6 +102,7 @@ struct mtree {
|
||||
const char *archive_format_name;
|
||||
struct mtree_entry *entries;
|
||||
struct mtree_entry *this_entry;
|
||||
struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
|
||||
struct archive_string current_dir;
|
||||
struct archive_string contents_name;
|
||||
|
||||
@ -110,6 +115,7 @@ struct mtree {
|
||||
static int bid_keycmp(const char *, const char *, ssize_t);
|
||||
static int cleanup(struct archive_read *);
|
||||
static int detect_form(struct archive_read *, int *);
|
||||
static unsigned int hash(const char *);
|
||||
static int mtree_bid(struct archive_read *, int);
|
||||
static int parse_file(struct archive_read *, struct archive_entry *,
|
||||
struct mtree *, struct mtree_entry *, int *);
|
||||
@ -862,11 +868,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
struct mtree_option **global, const char *line, ssize_t line_len,
|
||||
struct mtree_entry **last_entry, int is_form_d)
|
||||
{
|
||||
struct mtree_entry *entry;
|
||||
struct mtree_entry *entry, *ht_iter;
|
||||
struct mtree_option *iter;
|
||||
const char *next, *eq, *name, *end;
|
||||
size_t name_len, len;
|
||||
int r, i;
|
||||
unsigned int ht_idx;
|
||||
|
||||
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
||||
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
||||
@ -877,6 +884,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
entry->name = NULL;
|
||||
entry->used = 0;
|
||||
entry->full = 0;
|
||||
entry->name_hash = 0;
|
||||
entry->hashtable_next = NULL;
|
||||
|
||||
/* Add this entry to list. */
|
||||
if (*last_entry == NULL)
|
||||
@ -929,6 +938,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
memcpy(entry->name, name, name_len);
|
||||
entry->name[name_len] = '\0';
|
||||
parse_escapes(entry->name, entry);
|
||||
entry->name_hash = hash(entry->name);
|
||||
|
||||
ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
|
||||
if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
|
||||
while (ht_iter->hashtable_next)
|
||||
ht_iter = ht_iter->hashtable_next;
|
||||
ht_iter->hashtable_next = entry;
|
||||
} else {
|
||||
mtree->entry_hashtable[ht_idx] = entry;
|
||||
}
|
||||
|
||||
for (iter = *global; iter != NULL; iter = iter->next) {
|
||||
r = add_option(a, &entry->options, iter->value,
|
||||
@ -1122,8 +1141,9 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
||||
* with pathname canonicalization, which is a very
|
||||
* tricky subject.)
|
||||
*/
|
||||
for (mp = mentry->next; mp != NULL; mp = mp->next) {
|
||||
for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
|
||||
if (mp->full && !mp->used
|
||||
&& mentry->name_hash == mp->name_hash
|
||||
&& strcmp(mentry->name, mp->name) == 0) {
|
||||
/* Later lines override earlier ones. */
|
||||
mp->used = 1;
|
||||
@ -2000,3 +2020,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
|
||||
find_off = u - mtree->line.s;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash(const char *p)
|
||||
{
|
||||
/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
|
||||
as used by ELF for hashing function names. */
|
||||
unsigned g, h = 0;
|
||||
while (*p != '\0') {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = h & 0xF0000000) != 0) {
|
||||
h ^= g >> 24;
|
||||
h &= 0x0FFFFFFF;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
@ -294,8 +294,14 @@ archive_read_format_tar_cleanup(struct archive_read *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate number field
|
||||
*
|
||||
* Flags:
|
||||
* 1 - allow double \0 at field end
|
||||
*/
|
||||
static int
|
||||
validate_number_field(const char* p_field, size_t i_size)
|
||||
validate_number_field(const char* p_field, size_t i_size, int flags)
|
||||
{
|
||||
unsigned char marker = (unsigned char)p_field[0];
|
||||
/* octal? */
|
||||
@ -305,13 +311,23 @@ validate_number_field(const char* p_field, size_t i_size)
|
||||
for (i = 0; i < i_size; ++i) {
|
||||
switch (p_field[i])
|
||||
{
|
||||
case ' ': /* skip any leading spaces and trailing space*/
|
||||
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 */
|
||||
case '\0':
|
||||
/*
|
||||
* null should be allowed only at the end
|
||||
*
|
||||
* Perl Archive::Tar terminates some fields
|
||||
* with two nulls. We must allow this to stay
|
||||
* compatible.
|
||||
*/
|
||||
if (i != i_size - 1) {
|
||||
if (((flags & 1) == 0)
|
||||
|| i != i_size - 2)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@ -390,17 +406,24 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
||||
* 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.
|
||||
* Even the null terminator is sometimes omitted. Anyway, must be
|
||||
* checked to avoid false positives.
|
||||
*
|
||||
* Perl Archive::Tar does not follow the spec and terminates mode, uid,
|
||||
* gid, rdevmajor and rdevminor with a double \0. For compatibility
|
||||
* reasons we allow this deviation.
|
||||
*/
|
||||
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)) {
|
||||
if (bid > 0 && (
|
||||
validate_number_field(header->mode, sizeof(header->mode), 1) == 0
|
||||
|| validate_number_field(header->uid, sizeof(header->uid), 1) == 0
|
||||
|| validate_number_field(header->gid, sizeof(header->gid), 1) == 0
|
||||
|| validate_number_field(header->mtime, sizeof(header->mtime),
|
||||
0) == 0
|
||||
|| validate_number_field(header->size, sizeof(header->size), 0) == 0
|
||||
|| validate_number_field(header->rdevmajor,
|
||||
sizeof(header->rdevmajor), 1) == 0
|
||||
|| validate_number_field(header->rdevminor,
|
||||
sizeof(header->rdevminor), 1) == 0)) {
|
||||
bid = 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Martin Matuska
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD");
|
||||
|
||||
/*
|
||||
* Verify our ability to read sample files created by Perl module Archive::Tar
|
||||
*/
|
||||
|
||||
DEFINE_TEST(test_compat_perl_archive_tar)
|
||||
{
|
||||
char name[] = "test_compat_perl_archive_tar.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;
|
||||
}
|
||||
assertEqualString("file1", archive_entry_pathname(ae));
|
||||
assertEqualInt(1480603099, archive_entry_mtime(ae));
|
||||
assertEqualInt(1000, archive_entry_uid(ae));
|
||||
assertEqualString("john", archive_entry_uname(ae));
|
||||
assertEqualInt(1000, archive_entry_gid(ae));
|
||||
assertEqualString("john", archive_entry_gname(ae));
|
||||
assertEqualInt(0100644, archive_entry_mode(ae));
|
||||
|
||||
/* Verify that the format detection worked. */
|
||||
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
|
||||
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
|
||||
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
begin 644 test_compat_perl_archive_tar.tar
|
||||
M9FEL93$`````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````#`P,#8T-```,#`Q-S4P```P,#$W-3```"`@("`@("`@("`U
|
||||
M`#$S,#(P,#,R-S,S`"`Q,3$R,P`@,```````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````````````````````````!U<W1A<@`P,&IO:&X`
|
||||
M````````````````````````````````````:F]H;@``````````````````
|
||||
M```````````````````P,#`P,#```#`P,#`P,```````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M``````````````````````!A8F-D"@``````````````````````````````
|
||||
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````````````````````````````````````````````````````````````
|
||||
7````````````````````````````````
|
||||
`
|
||||
end
|
@ -295,7 +295,7 @@ cset_auto_compress(struct creation_set *cset, const char *filename)
|
||||
struct filter_set *v;
|
||||
int i, r;
|
||||
|
||||
/* Release previos filters. */
|
||||
/* Release previous filters. */
|
||||
_cleanup_filters(old_filters, old_filter_count);
|
||||
|
||||
v = malloc(sizeof(*v) * cset->filter_count);
|
||||
@ -308,7 +308,7 @@ cset_auto_compress(struct creation_set *cset, const char *filename)
|
||||
cset->filters = v;
|
||||
return (1);
|
||||
} else {
|
||||
/* Put previos filters back. */
|
||||
/* Put previous filters back. */
|
||||
cset->filters = old_filters;
|
||||
cset->filter_count = old_filter_count;
|
||||
return (0);
|
||||
|
@ -521,7 +521,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
return (0); /* Standard: return 0 for end-of-string. */
|
||||
cnt = utf8_count[ch];
|
||||
|
||||
/* Invalide sequence or there are not plenty bytes. */
|
||||
/* Invalid sequence or there are not plenty bytes. */
|
||||
if (n < (size_t)cnt)
|
||||
return (-1);
|
||||
|
||||
@ -560,7 +560,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* The code point larger than 0x10FFFF is not leagal
|
||||
/* The code point larger than 0x10FFFF is not legal
|
||||
* Unicode values. */
|
||||
if (wc > 0x10FFFF)
|
||||
return (-1);
|
||||
|
@ -285,7 +285,7 @@ copy_basic(void)
|
||||
|
||||
/* NOTE: for proper operation on cygwin-1.5 and windows, the
|
||||
* length of the name of the directory below, "plain", must be
|
||||
* less than or equal to the lengthe of the name of the original
|
||||
* less than or equal to the length of the name of the original
|
||||
* directory, "original" This restriction derives from the
|
||||
* extremely limited pathname lengths on those platforms.
|
||||
*/
|
||||
@ -327,7 +327,7 @@ copy_ustar(void)
|
||||
|
||||
/* NOTE: for proper operation on cygwin-1.5 and windows, the
|
||||
* length of the name of the directory below, "ustar", must be
|
||||
* less than or equal to the lengthe of the name of the original
|
||||
* less than or equal to the length of the name of the original
|
||||
* directory, "original" This restriction derives from the
|
||||
* extremely limited pathname lengths on those platforms.
|
||||
*/
|
||||
|
@ -527,7 +527,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
|
||||
struct archive *disk = bsdtar->diskreader;
|
||||
|
||||
/*
|
||||
* This tricky code here is to correctly read the cotents
|
||||
* This tricky code here is to correctly read the contents
|
||||
* of the entry because the disk reader bsdtar->diskreader
|
||||
* is pointing at does not have any information about the
|
||||
* entry by this time and using archive_read_data_block()
|
||||
|
@ -71,6 +71,7 @@ TESTS_SRCS= \
|
||||
test_compat_lzop.c \
|
||||
test_compat_mac.c \
|
||||
test_compat_pax_libarchive_2x.c \
|
||||
test_compat_perl_archive_tar.c \
|
||||
test_compat_solaris_tar_acl.c \
|
||||
test_compat_solaris_pax_sparse.c \
|
||||
test_compat_star_acl_posix1e.c \
|
||||
@ -348,6 +349,7 @@ ${PACKAGE}FILES+= test_compat_lzop_3.tar.lzo.uu
|
||||
${PACKAGE}FILES+= test_compat_mac-1.tar.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_mac-2.tar.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_pax_libarchive_2x.tar.Z.uu
|
||||
${PACKAGE}FILES+= test_compat_perl_archive_tar.tar.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
|
||||
|
Loading…
Reference in New Issue
Block a user