MFV r347989:

Sync libarchive with vendor.

Relevant vendor changes:
  Issue #795: XAR - do not try to add xattrs without an allocated name
  PR #812: non-recursive option for extract and list
  PR #958: support reading metadata from compressed files
  PR #999: add --exclude-vcs option to bsdtar
  Issue #1062: treat empty archives with a GNU volume header as valid
  PR #1074: Handle ZIP files with trailing 0s in the extra fields
            (Android APK archives)
  PR #1109: Ignore padding in Zip extra field data (Android APK archives)
  PR #1167: fix problems related to unreadable directories
  Issue #1168: fix handling of strtol() and strtoul()
  PR #1172: RAR5 - fix invalid window buffer read in E8E9 filter
  PR #1174: ZIP reader - fix of MSZIP signature parsing
  PR #1175: gzip filter - fix reading files larger than 4GB from memory
  PR #1177: gzip filter - fix memory leak with repeated header reads
  PR #1180: ZIP reader - add support for Info-ZIP Unicode Path Extra Field
  PR #1181: RAR5 - fix merge_block() recursion
            (OSS-Fuzz 12999, 13029, 13144, 13478, 13490)
  PR #1183: fix memory leak when decompressing ZIP files with LZMA
  PR #1184: fix RAR5 OSS-Fuzz issues 12466, 14490, 14491, 12817
    OSS-Fuzz 12466: RAR5 - fix buffer overflow when parsing huffman tables
    OSS-Fuzz 14490, 14491: RAR5 - fix bad shift-left operations
    OSS-Fuzz 12817: RAR5 - handle a case with truncated huffman tables
  PR #1186: RAR5 - fix invalid type used for dictionary size mask
            (OSS-Fuzz 14537)
  PR #1187: RAR5 - fix integer overflow (OSS-Fuzz 14555)
  PR #1190: RAR5 - RAR5 don't try to unpack entries marked as directories
            (OSS-Fuzz 14574)
  PR #1196: RAR5 - fix a potential SIGSEGV on 32-bit builds
  OSS-Fuzz 2582: RAR - fix use after free if there is an invalid entry
  OSS-Fuzz 14331: RAR5 - fix maximum owner name length
  OSS-Fuzz 13965: RAR5 - use unsigned int for volume number + range check

  Additional RAR5 reader changes:
    - support symlinks, hardlinks, file owner, file group, versioned files
    - change ARCHIVE_FORMAT_RAR_V5 to 0x100000
    - set correct mode for readonly directories
    - support readonly, hidden and system Windows file attributes

MFC after:	2 weeks
This commit is contained in:
Martin Matuska 2019-05-20 12:57:39 +00:00
commit 52c2bb7516
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=347990
89 changed files with 6648 additions and 3302 deletions

View file

@ -1,3 +1,13 @@
Apr 16, 2019: Support for non-recursive list and extract
Apr 14, 2019: New tar option: --exclude-vcs
Mar 27, 2019: Support for file and directory symlinks on Windows
Mar 12, 2019: Important fixes for storing file attributes and flags
Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 compression in zip archives
Oct 06, 2018: RAR 5.0 reader
Sep 03, 2018: libarchive 3.3.3 released

View file

@ -46,7 +46,7 @@ verify_files(const char *msg)
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
/* Another file with 1 link and different permissions. */
failure(msg);
@ -173,7 +173,7 @@ DEFINE_TEST(test_basic)
/* Symlink to above file. */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
if (is_LargeInode("symlink")) {
strncat(result,

View file

@ -114,7 +114,7 @@ DEFINE_TEST(test_format_newc)
/* "symlink" */
if (canSymlink()) {
assertMakeSymlink("symlink", "file1");
assertMakeSymlink("symlink", "file1", 0);
fprintf(list, "symlink\n");
}
@ -233,7 +233,12 @@ DEFINE_TEST(test_format_newc)
assert(is_hex(e, 110));
assertEqualMem(e + 0, "070701", 6); /* Magic */
assert(is_hex(e + 6, 8)); /* ino */
#if defined(_WIN32) && !defined(CYGWIN)
/* Mode: Group members bits and others bits do not work. */
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
#else
assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */
#endif
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000001", 8); /* nlink */

View file

@ -71,7 +71,7 @@ unpack_test(const char *from, const char *options, const char *se)
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
/* dir */
assertIsDir("dir", 0775);

View file

@ -30,8 +30,10 @@ __FBSDID("$FreeBSD$");
* tests won't run on Windows. */
#if defined(_WIN32) && !defined(__CYGWIN__)
#define CAT "type"
#define SEP "\\"
#else
#define CAT "cat"
#define SEP "/"
#endif
DEFINE_TEST(test_option_L_upper)
@ -51,7 +53,7 @@ DEFINE_TEST(test_option_L_upper)
fprintf(filelist, "file\n");
/* Symlink to above file. */
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
fclose(filelist);
@ -61,7 +63,7 @@ DEFINE_TEST(test_option_L_upper)
assertTextFileContents("1 block\n", "copy.err");
failure("Regular -p without -L should preserve symlinks.");
assertIsSymlink("copy/symlink", NULL);
assertIsSymlink("copy/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
assertEqualInt(r, 0);
@ -77,13 +79,14 @@ DEFINE_TEST(test_option_L_upper)
assertMakeDir("unpack", 0755);
assertChdir("unpack");
r = systemf(CAT " ../archive.out | %s -i >unpack.out 2>unpack.err", testprog);
r = systemf(CAT " .." SEP "archive.out | %s -i >unpack.out 2>unpack.err", testprog);
failure("Error invoking %s -i", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "unpack.err");
assertChdir("..");
assertIsSymlink("unpack/symlink", NULL);
assertIsSymlink("unpack/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
failure("Error invoking %s -oL", testprog);
@ -92,7 +95,8 @@ DEFINE_TEST(test_option_L_upper)
assertMakeDir("unpack-L", 0755);
assertChdir("unpack-L");
r = systemf(CAT " ../archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
r = systemf(CAT " .." SEP "archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
failure("Error invoking %s -i < archive-L.out", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "unpack-L.err");

View file

@ -71,8 +71,13 @@ test_create(void)
* #ifdef this section out. Most of the test below is
* still valid. */
memset(&times, 0, sizeof(times));
#if defined(_WIN32) && !defined(CYGWIN)
times.actime = 86400;
times.modtime = 86400;
#else
times.actime = 1;
times.modtime = 3;
#endif
assertEqualInt(0, utime(files[i].name, &times));
/* Record whatever atime the file ended up with. */

View file

@ -85,7 +85,7 @@ DEFINE_TEST(test_option_c)
/* "symlink" */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
}

View file

@ -338,9 +338,9 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FORMAT_LHA 0xB0000
#define ARCHIVE_FORMAT_CAB 0xC0000
#define ARCHIVE_FORMAT_RAR 0xD0000
#define ARCHIVE_FORMAT_RAR_V5 (ARCHIVE_FORMAT_RAR | 1)
#define ARCHIVE_FORMAT_7ZIP 0xE0000
#define ARCHIVE_FORMAT_WARC 0xF0000
#define ARCHIVE_FORMAT_RAR_V5 0x100000
/*
* Codes returned by archive_read_format_capabilities().
@ -1095,6 +1095,8 @@ __LA_DECL int archive_match_excluded(struct archive *,
*/
__LA_DECL int archive_match_path_excluded(struct archive *,
struct archive_entry *);
/* Control recursive inclusion of directory content when directory is included. Default on. */
__LA_DECL int archive_match_set_inclusion_recursion(struct archive *, int);
/* Add exclusion pathname pattern. */
__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
__LA_DECL int archive_match_exclude_pattern_w(struct archive *,

View file

@ -168,6 +168,7 @@ archive_entry_clear(struct archive_entry *entry)
archive_entry_xattr_clear(entry);
archive_entry_sparse_clear(entry);
free(entry->stat);
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
memset(entry, 0, sizeof(*entry));
return entry;
}
@ -202,6 +203,9 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy symlink type */
entry2->ae_symlink_type = entry->ae_symlink_type;
/* Copy encryption status */
entry2->encryption = entry->encryption;
@ -253,6 +257,7 @@ archive_entry_new2(struct archive *a)
if (entry == NULL)
return (NULL);
entry->archive = a;
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
return (entry);
}
@ -675,6 +680,12 @@ archive_entry_symlink(struct archive_entry *entry)
return (NULL);
}
int
archive_entry_symlink_type(struct archive_entry *entry)
{
return (entry->ae_symlink_type);
}
const char *
archive_entry_symlink_utf8(struct archive_entry *entry)
{
@ -1245,6 +1256,12 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
entry->ae_set &= ~AE_SET_SYMLINK;
}
void
archive_entry_set_symlink_type(struct archive_entry *entry, int type)
{
entry->ae_symlink_type = type;
}
void
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
{
@ -1749,6 +1766,10 @@ static const struct flag {
{ "nohidden", L"nohidden", UF_HIDDEN, 0},
{ "nouhidden", L"nouhidden", UF_HIDDEN, 0},
#endif
#ifdef FILE_ATTRIBUTE_HIDDEN
{ "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0},
{ "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0},
#endif
#ifdef UF_OFFLINE
{ "nooffline", L"nooffline", UF_OFFLINE, 0},
{ "nouoffline", L"nouoffline", UF_OFFLINE, 0},
@ -1758,6 +1779,11 @@ static const struct flag {
{ "nourdonly", L"nourdonly", UF_READONLY, 0},
{ "noreadonly", L"noreadonly", UF_READONLY, 0},
#endif
#ifdef FILE_ATTRIBUTE_READONLY
{ "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0},
{ "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0},
{ "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0},
#endif
#ifdef UF_SPARSE
{ "nosparse", L"nosparse", UF_SPARSE, 0},
{ "nousparse", L"nousparse", UF_SPARSE, 0},
@ -1770,6 +1796,10 @@ static const struct flag {
{ "nosystem", L"nosystem", UF_SYSTEM, 0},
{ "nousystem", L"nousystem", UF_SYSTEM, 0},
#endif
#ifdef FILE_ATTRIBUTE_SYSTEM
{ "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0},
{ "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0},
#endif
#if defined(FS_UNRM_FL) /* 'u' */
{ "noundel", L"noundel", FS_UNRM_FL, 0},
#elif defined(EXT2_UNRM_FL)

View file

@ -190,6 +190,13 @@ struct archive_entry;
#define AE_IFDIR ((__LA_MODE_T)0040000)
#define AE_IFIFO ((__LA_MODE_T)0010000)
/*
* Symlink types
*/
#define AE_SYMLINK_TYPE_UNDEFINED 0
#define AE_SYMLINK_TYPE_FILE 1
#define AE_SYMLINK_TYPE_DIRECTORY 2
/*
* Basic object manipulation
*/
@ -275,6 +282,7 @@ __LA_DECL int archive_entry_size_is_set(struct archive_entry *);
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *);
__LA_DECL int archive_entry_symlink_type(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
@ -350,6 +358,7 @@ __LA_DECL void archive_entry_unset_size(struct archive_entry *);
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int);
__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
@ -692,7 +701,6 @@ __LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
struct archive_entry **, struct archive_entry **);
__LA_DECL struct archive_entry *archive_entry_partial_links(
struct archive_entry_linkresolver *res, unsigned int *links);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,62 @@
.\" Copyright (c) 2019 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 AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 15, 2019
.Dt ARCHIVE_ENTRY_MISC 3
.Os
.Sh NAME
.Nm archive_entry_symlink_type ,
.Nm archive_entry_set_symlink_type
.Nd miscellaneous functions for manipulating properties of archive_entry.
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft int
.Fn archive_entry_symlink_type "struct archive_entry *a"
.Ft void
.Fn archive_entry_set_symlink_type "struct archive_entry *a" "int"
.Sh DESCRIPTION
The function
.Fn archive_entry_symlink_type
returns and the function
.Fn archive_entry_set_symlink_type
sets the type of the symbolic link stored in an archive entry. These functions
have special meaning on operating systems that support multiple symbolic link
types (e.g. Microsoft Windows).
.Pp
Supported values are:
.Bl -tag -width "AE_SYMLINK_TYPE_DIRECTORY" -compact
.It AE_SYMLINK_TYPE_UNDEFINED
Symbolic link target type is not defined (default on unix systems)
.It AE_SYMLINK_TYPE_FILE
Symbolic link points to a file
.It AE_SYMLINK_TYPE_DIRECTORY
Symbolic link points to a directory
.El
.Sh SEE ALSO
.Xr archive_entry 3 ,
.Xr archive_entry_paths 3 ,
.Xr archive_entry_stat 3 ,
.Xr libarchive 3

View file

@ -176,6 +176,9 @@ struct archive_entry {
/* Miscellaneous. */
char strmode[12];
/* Symlink type support */
int ae_symlink_type;
};
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */

View file

@ -83,6 +83,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
#pragma GCC diagnostic ignored "-Wcast-qual"
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_HASH_HANDLE hHash;
DWORD hash_len;

View file

@ -93,6 +93,9 @@ struct archive_match {
/* exclusion/inclusion set flag. */
int setflag;
/* Recursively include directory content? */
int recursive_include;
/*
* Matching filename patterns.
*/
@ -223,6 +226,7 @@ archive_match_new(void)
return (NULL);
a->archive.magic = ARCHIVE_MATCH_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->recursive_include = 1;
match_list_init(&(a->inclusions));
match_list_init(&(a->exclusions));
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
@ -470,6 +474,28 @@ archive_match_path_excluded(struct archive *_a,
#endif
}
/*
* When recursive inclusion of directory content is enabled,
* an inclusion pattern that matches a directory will also
* include everything beneath that directory. Enabled by default.
*
* For compatibility with GNU tar, exclusion patterns always
* match if a subset of the full patch matches (i.e., they are
* are not rooted at the beginning of the path) and thus there
* is no corresponding non-recursive exclusion mode.
*/
int
archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
{
struct archive_match *a;
archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
a = (struct archive_match *)_a;
a->recursive_include = enabled;
return (ARCHIVE_OK);
}
/*
* Utility functions to get statistic information for inclusion patterns.
*/
@ -781,7 +807,10 @@ static int
match_path_inclusion(struct archive_match *a, struct match *m,
int mbs, const void *pn)
{
int flag = PATHMATCH_NO_ANCHOR_END;
/* Recursive operation requires only a prefix match. */
int flag = a->recursive_include ?
PATHMATCH_NO_ANCHOR_END :
0;
int r;
if (mbs) {
@ -1232,7 +1261,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
archive_set_error(&(a->archive), EINVAL, "pathname is empty");
return (ARCHIVE_FAILED);
}
if (stat(path, &st) != 0) {
if (la_stat(path, &st) != 0) {
archive_set_error(&(a->archive), errno, "Failed to stat()");
return (ARCHIVE_FAILED);
}

View file

@ -69,6 +69,8 @@
* either Windows or Posix APIs. */
#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
#include "archive_windows.h"
#else
#define la_stat(path,stref) stat(path,stref)
#endif
/*

View file

@ -611,6 +611,15 @@ choose_filters(struct archive_read *a)
return (ARCHIVE_FATAL);
}
int
__archive_read_header(struct archive_read *a, struct archive_entry *entry)
{
if (a->filter->read_header)
return a->filter->read_header(a->filter, entry);
else
return (ARCHIVE_OK);
}
/*
* Read header of next entry.
*/

View file

@ -191,7 +191,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
} else
#endif
if (stat(path, &s) != 0) {
if (la_stat(path, &s) != 0) {
archive_set_error(&a->archive, errno,
"Can't stat %s", path);
return (ARCHIVE_FAILED);

View file

@ -909,7 +909,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
}
break;
}
}
} while (lst == NULL);
#ifdef __APPLE__
@ -1295,10 +1295,23 @@ archive_read_disk_descend(struct archive *_a)
if (t->visit_type != TREE_REGULAR || !t->descend)
return (ARCHIVE_OK);
/*
* We must not treat the initial specified path as a physical dir,
* because if we do then we will try and ascend out of it by opening
* ".." which is (a) wrong and (b) causes spurious permissions errors
* if ".." is not readable by us. Instead, treat it as if it were a
* symlink. (This uses an extra fd, but it can only happen once at the
* top level of a traverse.) But we can't necessarily assume t->st is
* valid here (though t->lst is), which complicates the logic a
* little.
*/
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
t->lst.st_dev, t->lst.st_ino, &t->restore_time);
t->stack->flags |= isDir;
if (t->stack->parent->parent != NULL)
t->stack->flags |= isDir;
else
t->stack->flags |= isDirLink;
} else if (tree_current_is_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
t->st.st_dev, t->st.st_ino, &t->restore_time);
@ -2151,6 +2164,17 @@ tree_open(const char *path, int symlink_mode, int restore_time)
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
#if defined(O_PATH)
/* Linux */
const int o_flag = O_PATH;
#elif defined(O_SEARCH)
/* SunOS */
const int o_flag = O_SEARCH;
#elif defined(O_EXEC)
/* FreeBSD */
const int o_flag = O_EXEC;
#endif
t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
@ -2172,6 +2196,15 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
t->stack->flags = needsFirstVisit;
t->maxOpenCount = t->openCount = 1;
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC)
/*
* Most likely reason to fail opening "." is that it's not readable,
* so try again for execute. The consequences of not opening this are
* unhelpful and unnecessary errors later.
*/
if (t->initial_dir_fd < 0)
t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
#endif
__archive_ensure_cloexec_flag(t->initial_dir_fd);
t->working_dir_fd = tree_dup(t->initial_dir_fd);
return (t);
@ -2479,7 +2512,7 @@ tree_current_stat(struct tree *t)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
if (stat(tree_current_access_path(t), &t->st) != 0)
if (la_stat(tree_current_access_path(t), &t->st) != 0)
#endif
return NULL;
t->flags |= hasStat;

View file

@ -98,6 +98,8 @@ struct archive_read_filter {
int (*close)(struct archive_read_filter *self);
/* Function that handles switching from reading one block to the next/prev */
int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
/* Read any header metadata if available. */
int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
/* My private data. */
void *data;
@ -250,6 +252,7 @@ int64_t __archive_read_seek(struct archive_read*, int64_t, int);
int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_header(struct archive_read *, struct archive_entry *);
int __archive_read_program(struct archive_read_filter *, const char *);
void __archive_read_free_filters(struct archive_read *);
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);

View file

@ -73,6 +73,9 @@ archive_read_set_format(struct archive *_a, int code)
case ARCHIVE_FORMAT_RAR:
strcpy(str, "rar");
break;
case ARCHIVE_FORMAT_RAR_V5:
strcpy(str, "rar5");
break;
case ARCHIVE_FORMAT_TAR:
strcpy(str, "tar");
break;

View file

@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -45,6 +48,8 @@ __FBSDID("$FreeBSD$");
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_endian.h"
#include "archive_private.h"
#include "archive_read_private.h"
@ -56,6 +61,8 @@ struct private_data {
size_t out_block_size;
int64_t total_out;
unsigned long crc;
uint32_t mtime;
char *name;
char eof; /* True = found end of compressed data. */
};
@ -123,7 +130,8 @@ archive_read_support_filter_gzip(struct archive *_a)
* count of bits verified, suitable for use by bidder.
*/
static ssize_t
peek_at_header(struct archive_read_filter *filter, int *pbits)
peek_at_header(struct archive_read_filter *filter, int *pbits,
struct private_data *state)
{
const unsigned char *p;
ssize_t avail, len;
@ -144,7 +152,9 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
return (0);
bits += 3;
header_flags = p[3];
/* Bytes 4-7 are mod time. */
/* Bytes 4-7 are mod time in little endian. */
if (state)
state->mtime = archive_le32dec(p + 4);
/* Byte 8 is deflate flags. */
/* XXXX TODO: return deflate flags back to consume_header for use
in initializing the decompressor. */
@ -161,6 +171,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
/* Null-terminated optional filename. */
if (header_flags & 8) {
ssize_t file_start = len;
do {
++len;
if (avail < len)
@ -169,6 +180,12 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
if (p == NULL)
return (0);
} while (p[len - 1] != 0);
if (state) {
/* Reset the name in case of repeat header reads. */
free(state->name);
state->name = strdup((const char *)&p[file_start]);
}
}
/* Null-terminated optional comment. */
@ -214,11 +231,28 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
(void)self; /* UNUSED */
if (peek_at_header(filter, &bits_checked))
if (peek_at_header(filter, &bits_checked, NULL))
return (bits_checked);
return (0);
}
static int
gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry)
{
struct private_data *state;
state = (struct private_data *)self->data;
/* A mtime of 0 is considered invalid/missing. */
if (state->mtime != 0)
archive_entry_set_mtime(entry, state->mtime, 0);
/* If the name is available, extract it. */
if (state->name)
archive_entry_set_pathname(entry, state->name);
return (ARCHIVE_OK);
}
#ifndef HAVE_ZLIB_H
@ -272,6 +306,7 @@ gzip_bidder_init(struct archive_read_filter *self)
self->read = gzip_filter_read;
self->skip = NULL; /* not supported */
self->close = gzip_filter_close;
self->read_header = gzip_read_header;
state->in_stream = 0; /* We're not actually within a stream yet. */
@ -289,7 +324,7 @@ consume_header(struct archive_read_filter *self)
state = (struct private_data *)self->data;
/* If this is a real header, consume it. */
len = peek_at_header(self->upstream, NULL);
len = peek_at_header(self->upstream, NULL, state);
if (len == 0)
return (ARCHIVE_EOF);
__archive_read_filter_consume(self->upstream, len);
@ -374,7 +409,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
{
struct private_data *state;
size_t decompressed;
ssize_t avail_in;
ssize_t avail_in, max_in;
int ret;
state = (struct private_data *)self->data;
@ -408,6 +443,12 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
"truncated gzip input");
return (ARCHIVE_FATAL);
}
if (UINT_MAX >= SSIZE_MAX)
max_in = SSIZE_MAX;
else
max_in = UINT_MAX;
if (avail_in > max_in)
avail_in = max_in;
state->stream.avail_in = (uInt)avail_in;
/* Decompress and consume some of that data. */
@ -469,6 +510,7 @@ gzip_filter_close(struct archive_read_filter *self)
}
}
free(state->name);
free(state->out_block);
free(state);
return (ret);

View file

@ -1509,8 +1509,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
}
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
goto nomszip;
else if (cab->stream.next_in[0] != 0x43 ||
cab->stream.next_in[1] != 0x4b)
else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 ||
cab->stream.next_in[1] != 0x4b))
goto nomszip;
cab->stream.next_in += mszip;
cab->stream.avail_in -= mszip;

View file

@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#include "archive.h"
#include "archive_entry.h"
@ -1011,7 +1014,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
{
ssize_t len;
uintmax_t counter;
char *p;
char *p, *s;
struct mtree_option *global;
struct mtree_entry *last_entry;
int r, is_form_d;
@ -1025,6 +1028,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
(void)detect_form(a, &is_form_d);
for (counter = 1; ; ++counter) {
r = ARCHIVE_OK;
len = readline(a, mtree, &p, 65536);
if (len == 0) {
mtree->this_entry = mtree->entries;
@ -1045,6 +1049,15 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
if (!isprint(*s)) {
r = ARCHIVE_FATAL;
break;
}
}
if (r != ARCHIVE_OK)
break;
if (*p != '/') {
r = process_add_entry(a, mtree, &global, p, len,
&last_entry, is_form_d);

View file

@ -1024,8 +1024,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_GOOD:
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->start_new_table = 1;
}
break;
default:

View file

@ -120,7 +120,9 @@ archive_read_format_raw_read_header(struct archive_read *a,
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, 0644);
/* I'm deliberately leaving most fields unset here. */
return (ARCHIVE_OK);
/* Let the filter fill out any fields it might have. */
return __archive_read_header(a, entry);
}
static int

View file

@ -694,11 +694,13 @@ tar_read_header(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, size_t *unconsumed)
{
ssize_t bytes;
int err;
int err, eof_vol_header;
const char *h;
const struct archive_entry_header_ustar *header;
const struct archive_entry_header_gnutar *gnuheader;
eof_vol_header = 0;
/* Loop until we find a workable header record. */
for (;;) {
tar_flush_unconsumed(a, unconsumed);
@ -788,6 +790,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
break;
case 'V': /* GNU volume header */
err = header_volume(a, tar, entry, h, unconsumed);
if (err == ARCHIVE_EOF)
eof_vol_header = 1;
break;
case 'X': /* Used by SUN tar; same as 'x'. */
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
@ -862,9 +866,17 @@ tar_read_header(struct archive_read *a, struct tar *tar,
}
return (err);
}
if (err == ARCHIVE_EOF)
/* EOF when recursively reading a header is bad. */
archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
if (err == ARCHIVE_EOF) {
if (!eof_vol_header) {
/* EOF when recursively reading a header is bad. */
archive_set_error(&a->archive, EINVAL,
"Damaged tar archive");
} else {
/* If we encounter just a GNU volume header treat
* this situation as an empty archive */
return (ARCHIVE_EOF);
}
}
return (ARCHIVE_FATAL);
}
@ -1944,6 +1956,15 @@ pax_attribute(struct archive_read *a, struct tar *tar,
pax_time(value, &s, &n);
archive_entry_set_birthtime(entry, s, n);
}
if (strcmp(key, "LIBARCHIVE.symlinktype") == 0) {
if (strcmp(value, "file") == 0) {
archive_entry_set_symlink_type(entry,
AE_SYMLINK_TYPE_FILE);
} else if (strcmp(value, "dir") == 0) {
archive_entry_set_symlink_type(entry,
AE_SYMLINK_TYPE_DIRECTORY);
}
}
if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0)
pax_attribute_xattr(entry, key, value);
break;

View file

@ -744,8 +744,9 @@ _warc_rdlen(const char *buf, size_t bsz)
/* there must be at least one digit */
if (!isdigit((unsigned char)*val))
return -1;
errno = 0;
len = strtol(val, &on, 10);
if (on != eol) {
if (errno != 0 || on != eol) {
/* line must end here */
return -1;
}

View file

@ -798,7 +798,8 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
xattr = file->xattr_list;
while (xattr != NULL) {
const void *d;
size_t outbytes, used;
size_t outbytes = 0;
size_t used = 0;
r = move_reading_point(a, xattr->offset);
if (r != ARCHIVE_OK)
@ -820,8 +821,18 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
r = checksum_final(a,
xattr->a_sum.val, xattr->a_sum.len,
xattr->e_sum.val, xattr->e_sum.len);
if (r != ARCHIVE_OK)
if (r != ARCHIVE_OK) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr checksum error");
r = ARCHIVE_WARN;
break;
}
if (xattr->name.s == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr name error");
r = ARCHIVE_WARN;
break;
}
archive_entry_xattr_add_entry(entry,
xattr->name.s, d, outbytes);
xattr = xattr->next;
@ -847,7 +858,7 @@ xar_read_data(struct archive_read *a,
const void **buff, size_t *size, int64_t *offset)
{
struct xar *xar;
size_t used;
size_t used = 0;
int r;
xar = (struct xar *)(a->format->data);

View file

@ -472,27 +472,49 @@ zip_time(const char *p)
* triplets. id and size are 2 bytes each.
*/
static int
process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
process_extra(struct archive_read *a, struct archive_entry *entry,
const char *p, size_t extra_length, struct zip_entry* zip_entry)
{
unsigned offset = 0;
struct zip *zip = (struct zip *)(a->format->data);
if (extra_length == 0) {
return ARCHIVE_OK;
}
if (extra_length < 4) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
return ARCHIVE_FAILED;
size_t i = 0;
/* Some ZIP files may have trailing 0 bytes. Let's check they
* are all 0 and ignore them instead of returning an error.
*
* This is not techincally correct, but some ZIP files look
* like this and other tools support those files - so let's
* also support them.
*/
for (; i < extra_length; i++) {
if (p[i] != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Too-small extra data: "
"Need at least 4 bytes, "
"but only found %d bytes",
(int)extra_length);
return ARCHIVE_FAILED;
}
}
return ARCHIVE_OK;
}
while (offset <= extra_length - 4) {
unsigned short headerid = archive_le16dec(p + offset);
unsigned short datasize = archive_le16dec(p + offset + 2);
offset += 4;
if (offset + datasize > extra_length) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Extra data overflow: Need %d bytes but only found %d bytes",
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Extra data overflow: "
"Need %d bytes but only found %d bytes",
(int)datasize, (int)(extra_length - offset));
return ARCHIVE_FAILED;
}
@ -507,9 +529,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->uncompressed_size == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit uncompressed size");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"uncompressed size");
return ARCHIVE_FAILED;
}
zip_entry->uncompressed_size = t;
@ -519,9 +544,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->compressed_size == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit compressed size");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"compressed size");
return ARCHIVE_FAILED;
}
zip_entry->compressed_size = t;
@ -531,9 +559,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->local_header_offset == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit local header offset");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"local header offset");
return ARCHIVE_FAILED;
}
zip_entry->local_header_offset = t;
@ -566,7 +597,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
/* Extended time field "UT". */
int flags;
if (datasize == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Incomplete extended time field");
return ARCHIVE_FAILED;
}
@ -648,7 +680,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
* if bitmap & 1, 2 byte "version made by"
* if bitmap & 2, 2 byte "internal file attributes"
* if bitmap & 4, 4 byte "external file attributes"
* if bitmap & 8, 2 byte comment length + n byte comment
* if bitmap & 8, 2 byte comment length + n byte
* comment
*/
int bitmap, bitmap_last;
@ -699,13 +732,18 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
= external_attributes >> 16;
} else if (zip_entry->system == 0) {
// Interpret MSDOS directory bit
if (0x10 == (external_attributes & 0x10)) {
zip_entry->mode = AE_IFDIR | 0775;
if (0x10 == (external_attributes &
0x10)) {
zip_entry->mode =
AE_IFDIR | 0775;
} else {
zip_entry->mode = AE_IFREG | 0664;
zip_entry->mode =
AE_IFREG | 0664;
}
if (0x01 == (external_attributes & 0x01)) {
// Read-only bit; strip write permissions
if (0x01 == (external_attributes &
0x01)) {
/* Read-only bit;
* strip write permissions */
zip_entry->mode &= 0555;
}
} else {
@ -732,6 +770,59 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
break;
}
case 0x7075:
{
/* Info-ZIP Unicode Path Extra Field. */
if (datasize < 5 || entry == NULL)
break;
offset += 5;
datasize -= 5;
/* The path name in this field is always encoded
* in UTF-8. */
if (zip->sconv_utf8 == NULL) {
zip->sconv_utf8 =
archive_string_conversion_from_charset(
&a->archive, "UTF-8", 1);
/* If the converter from UTF-8 is not
* available, then the path name from the main
* field will more likely be correct. */
if (zip->sconv_utf8 == NULL)
break;
}
/* Make sure the CRC32 of the filename matches. */
if (!zip->ignore_crc32) {
const char *cp = archive_entry_pathname(entry);
if (cp) {
unsigned long file_crc =
zip->crc32func(0, cp, strlen(cp));
unsigned long utf_crc =
archive_le32dec(p + offset - 4);
if (file_crc != utf_crc) {
#ifdef DEBUG
fprintf(stderr,
"CRC filename mismatch; "
"CDE is %lx, but UTF8 "
"is outdated with %lx\n",
file_crc, utf_crc);
#endif
break;
}
}
}
if (archive_entry_copy_pathname_l(entry,
p + offset, datasize, zip->sconv_utf8) != 0) {
/* Ignore the error, and fallback to the path
* name from the main field. */
#ifdef DEBUG
fprintf(stderr, "Failed to read the ZIP "
"0x7075 extra field path.\n");
#endif
}
break;
}
case 0x7855:
/* Info-ZIP Unix Extra Field (type 2) "Ux". */
#ifdef DEBUG
@ -766,7 +857,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
if (datasize >= (2 + uidsize + 3)) {
/* get a gid size. */
gidsize = 0xff & (int)p[offset+2+uidsize];
gidsize = 0xff &
(int)p[offset+2+uidsize];
if (gidsize == 2)
zip_entry->gid =
archive_le16dec(
@ -783,7 +875,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
case 0x9901:
/* WinZip AES extra data field. */
if (datasize < 6) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Incomplete AES field");
return ARCHIVE_FAILED;
}
@ -803,12 +896,6 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
offset += datasize;
}
if (offset != extra_length) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed extra data: Consumed %d bytes of %d bytes",
(int)offset, (int)extra_length);
return ARCHIVE_FAILED;
}
return ARCHIVE_OK;
}
@ -928,7 +1015,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
if (ARCHIVE_OK != process_extra(a, entry, h, extra_length,
zip_entry)) {
return ARCHIVE_FATAL;
}
__archive_read_consume(a, extra_length);
@ -945,8 +1033,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= 0664;
}
/* Windows archivers sometimes use backslash as the directory separator.
Normalize to slash. */
/* Windows archivers sometimes use backslash as the directory
* separator. Normalize to slash. */
if (zip_entry->system == 0 &&
(wp = archive_entry_pathname_w(entry)) != NULL) {
if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
@ -1255,7 +1343,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
zip->entry->crc32 = archive_le32dec(p + 4);
compressed = archive_le64dec(p + 8);
uncompressed = archive_le64dec(p + 16);
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
if (compressed > INT64_MAX || uncompressed >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Overflow of 64-bit file sizes");
@ -1372,7 +1461,8 @@ consume_optional_marker(struct archive_read *a, struct zip *zip)
zip->entry->crc32 = archive_le32dec(p);
compressed = archive_le64dec(p + 4);
uncompressed = archive_le64dec(p + 12);
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
if (compressed > INT64_MAX ||
uncompressed > INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Overflow of 64-bit file sizes");
@ -1444,12 +1534,16 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
} alone_header;
#pragma pack(pop)
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma that
* is a part of XZ Utils. The stream format stored inside ZIPX file is a
* modified "lzma alone" file format, that was used by the `lzma` utility
* which was later deprecated in favour of `xz` utility. Since those
* formats are nearly the same, we can use a standard "lzma alone" decoder
* from XZ Utils. */
if(zip->zipx_lzma_valid) {
lzma_end(&zip->zipx_lzma_stream);
zip->zipx_lzma_valid = 0;
}
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
* that is a part of XZ Utils. The stream format stored inside ZIPX
* file is a modified "lzma alone" file format, that was used by the
* `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard
* "lzma alone" decoder from XZ Utils. */
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX);
@ -1477,8 +1571,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
* lzma_params is a 5-byte blob that has to be decoded to extract
* parameters of this LZMA stream. The uncompressed_size field is an
* uint64_t value that contains information about the size of the
* uncompressed file, or UINT64_MAX if this value is unknown. The <data...>
* part is the actual lzma-compressed data stream.
* uncompressed file, or UINT64_MAX if this value is unknown.
* The <data...> part is the actual lzma-compressed data stream.
*
* Now here's the structure of the stream inside the ZIPX file:
*
@ -1488,17 +1582,17 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
* 2byte 2byte 5 bytes n bytes
* <magic1><magic2><lzma_params><data...>
*
* This means that the ZIPX file contains an additional magic1 and magic2
* headers, the lzma_params field contains the same parameter set as in the
* "lzma alone" format, and the <data...> field is the same as in the "lzma
* alone" format as well. Note that also the zipx format is missing the
* uncompressed_size field.
* This means that the ZIPX file contains an additional magic1 and
* magic2 headers, the lzma_params field contains the same parameter
* set as in the "lzma alone" format, and the <data...> field is the
* same as in the "lzma alone" format as well. Note that also the zipx
* format is missing the uncompressed_size field.
*
* So, in order to use the "lzma alone" decoder for the zipx lzma stream,
* we simply need to shuffle around some fields, prepare a new lzma alone
* header, feed it into lzma alone decoder so it will initialize itself
* properly, and then we can start feeding normal zipx lzma stream into the
* decoder.
* So, in order to use the "lzma alone" decoder for the zipx lzma
* stream, we simply need to shuffle around some fields, prepare a new
* lzma alone header, feed it into lzma alone decoder so it will
* initialize itself properly, and then we can start feeding normal
* zipx lzma stream into the decoder.
*/
/* Read magic1,magic2,lzma_params from the ZIPX stream. */
@ -1514,8 +1608,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
return (ARCHIVE_FATAL);
}
/* Prepare an lzma alone header: copy the lzma_params blob into a proper
* place into the lzma alone header. */
/* Prepare an lzma alone header: copy the lzma_params blob into
* a proper place into the lzma alone header. */
memcpy(&alone_header.bytes[0], p + 4, 5);
/* Initialize the 'uncompressed size' field to unknown; we'll manually
@ -1541,8 +1635,9 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
zip->zipx_lzma_stream.total_out = 0;
/* Feed only the header into the lzma alone decoder. This will effectively
* initialize the decoder, and will not produce any output bytes yet. */
/* Feed only the header into the lzma alone decoder. This will
* effectively initialize the decoder, and will not produce any
* output bytes yet. */
r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
if (r != LZMA_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
@ -1617,7 +1712,8 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
if((int64_t) zip->zipx_lzma_stream.total_in !=
zip->entry_bytes_remaining)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"xz premature end of stream");
return (ARCHIVE_FATAL);
}
@ -1662,12 +1758,13 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
return (ret);
}
/* Fetch more compressed data. The same note as in deflate handler applies
* here as well:
/* Fetch more compressed data. The same note as in deflate handler
* applies here as well:
*
* Note: '1' here is a performance optimization. Recall that the
* decompression layer returns a count of available bytes; asking for more
* than that forces the decompressor to combine reads by copying data.
* decompression layer returns a count of available bytes; asking for
* more than that forces the decompressor to combine reads by copying
* data.
*/
compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail < 0) {
@ -1684,8 +1781,9 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
zip->zipx_lzma_stream.total_in = 0;
zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
zip->zipx_lzma_stream.avail_out =
/* These lzma_alone streams lack end of stream marker, so let's make
* sure the unpacker won't try to unpack more than it's supposed to. */
/* These lzma_alone streams lack end of stream marker, so let's
* make sure the unpacker won't try to unpack more than it's
* supposed to. */
zipmin((int64_t) zip->uncompressed_buffer_size,
zip->entry->uncompressed_size -
zip->entry_uncompressed_bytes_read);
@ -1810,7 +1908,8 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
return (ARCHIVE_FATAL);
}
__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order, restore_method);
__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order,
restore_method);
/* Allocate the buffer that will hold uncompressed data. */
free(zip->uncompressed_buffer);
@ -1856,8 +1955,8 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
return ret;
}
/* Fetch for more data. We're reading 1 byte here, but libarchive should
* prefetch more bytes. */
/* Fetch for more data. We're reading 1 byte here, but libarchive
* should prefetch more bytes. */
(void) __archive_read_ahead(a, 1, &bytes_avail);
if(bytes_avail < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@ -1871,7 +1970,8 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
/* Decompression loop. */
do {
int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(&zip->ppmd8);
int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(
&zip->ppmd8);
if(sym < 0) {
zip->end_of_entry = 1;
break;
@ -1880,8 +1980,9 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
/* This field is set by ppmd_read() when there was no more data
* to be read. */
if(zip->ppmd8_stream_failed) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated PPMd8 file body");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated PPMd8 file body");
return (ARCHIVE_FATAL);
}
@ -1985,9 +2086,10 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
if(in_bytes < 1) {
/* libbz2 doesn't complain when caller feeds avail_in == 0. It will
* actually return success in this case, which is undesirable. This is
* why we need to make this check manually. */
/* libbz2 doesn't complain when caller feeds avail_in == 0.
* It will actually return success in this case, which is
* undesirable. This is why we need to make this check
* manually. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated bzip2 file body");
@ -2014,16 +2116,18 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
case BZ_OK:
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to clean up bzip2 decompressor");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Failed to clean up bzip2 "
"decompressor");
return ARCHIVE_FATAL;
}
zip->end_of_entry = 1;
break;
case BZ_OK:
/* The decompressor has successfully decoded this chunk of
* data, but more data is still in queue. */
/* The decompressor has successfully decoded this
* chunk of data, but more data is still in queue. */
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -2131,8 +2235,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
if (zip->tctx_valid || zip->cctx_valid) {
if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) {
size_t buff_remaining =
(zip->decrypted_buffer + zip->decrypted_buffer_size)
- (zip->decrypted_ptr + zip->decrypted_bytes_remaining);
(zip->decrypted_buffer +
zip->decrypted_buffer_size)
- (zip->decrypted_ptr +
zip->decrypted_bytes_remaining);
if (buff_remaining > (size_t)bytes_avail)
buff_remaining = (size_t)bytes_avail;
@ -2143,12 +2249,12 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
+ buff_remaining)
> zip->entry_bytes_remaining) {
if (zip->entry_bytes_remaining <
(int64_t)zip->decrypted_bytes_remaining)
(int64_t)zip->decrypted_bytes_remaining)
buff_remaining = 0;
else
buff_remaining =
(size_t)zip->entry_bytes_remaining
- zip->decrypted_bytes_remaining;
- zip->decrypted_bytes_remaining;
}
}
if (buff_remaining > 0) {
@ -2167,7 +2273,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
+ zip->decrypted_bytes_remaining,
&dsize);
}
zip->decrypted_bytes_remaining += buff_remaining;
zip->decrypted_bytes_remaining +=
buff_remaining;
}
}
bytes_avail = zip->decrypted_bytes_remaining;
@ -2751,7 +2858,7 @@ archive_read_format_zip_cleanup(struct archive_read *a)
inflateEnd(&zip->stream);
#endif
#if HAVA_LZMA_H && HAVE_LIBLZMA
#if HAVE_LZMA_H && HAVE_LIBLZMA
if (zip->zipx_lzma_valid) {
lzma_end(&zip->zipx_lzma_stream);
}
@ -3391,7 +3498,8 @@ expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
}
static int
slurp_central_directory(struct archive_read *a, struct zip *zip)
slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
struct zip *zip)
{
ssize_t i;
unsigned found;
@ -3501,8 +3609,10 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
filename_length = archive_le16dec(p + 28);
extra_length = archive_le16dec(p + 30);
comment_length = archive_le16dec(p + 32);
/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
/* disk_start = archive_le16dec(p + 34);
* Better be zero.
* internal_attributes = archive_le16dec(p + 36);
* text bit */
external_attributes = archive_le32dec(p + 38);
zip_entry->local_header_offset =
archive_le32dec(p + 42) + correction;
@ -3538,7 +3648,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
"Truncated ZIP file header");
return ARCHIVE_FATAL;
}
if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
extra_length, zip_entry)) {
return ARCHIVE_FATAL;
}
@ -3560,7 +3671,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
* a directory. We should treat it as a non
* resource fork file to expose it. */
if (name[filename_length-1] != '/' &&
(r - name < 3 || r[0] != '.' || r[1] != '_')) {
(r - name < 3 || r[0] != '.' ||
r[1] != '_')) {
__archive_rb_tree_insert_node(
&zip->tree, &zip_entry->node);
/* Expose its parent directories. */
@ -3637,8 +3749,10 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
switch(rsrc->compression) {
case 0: /* No compression. */
if (rsrc->uncompressed_size != rsrc->compressed_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed OS X metadata entry: inconsistent size");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed OS X metadata entry: "
"inconsistent size");
return (ARCHIVE_FATAL);
}
#ifdef HAVE_ZLIB_H
@ -3797,7 +3911,7 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
a->archive.archive_format_name = "ZIP";
if (zip->zip_entries == NULL) {
r = slurp_central_directory(a, zip);
r = slurp_central_directory(a, entry, zip);
if (r != ARCHIVE_OK)
return r;
/* Get first entry whose local header offset is lower than
@ -3827,8 +3941,8 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
__archive_read_reset_passphrase(a);
/* File entries are sorted by the header offset, we should mostly
* use __archive_read_consume to advance a read point to avoid redundant
* data reading. */
* use __archive_read_consume to advance a read point to avoid
* redundant data reading. */
offset = archive_filter_bytes(&a->archive, 0);
if (offset < zip->entry->local_header_offset)
__archive_read_consume(a,

View file

@ -449,7 +449,7 @@ __archive_mktemp(const char *tmpdir)
temp_name.s[temp_name.length-1] = '\0';
temp_name.length --;
}
if (stat(temp_name.s, &st) < 0)
if (la_stat(temp_name.s, &st) < 0)
goto exit_tmpfile;
if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;

View file

@ -390,10 +390,13 @@ archive_compressor_xz_options(struct archive_write_filter *f,
data->compression_level = 6;
return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) {
char *endptr;
if (value == NULL)
return (ARCHIVE_WARN);
data->threads = (int)strtoul(value, NULL, 10);
if (data->threads == 0 && errno != 0) {
errno = 0;
data->threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
data->threads = 1;
return (ARCHIVE_WARN);
}

View file

@ -2032,7 +2032,7 @@ restore_entry(struct archive_write_disk *a)
* follow the symlink if we're creating a dir.
*/
if (S_ISDIR(a->mode))
r = stat(a->name, &a->st);
r = la_stat(a->name, &a->st);
/*
* If it's not a dir (or it's a broken symlink),
* then don't follow it.
@ -2198,7 +2198,7 @@ create_filesystem_object(struct archive_write_disk *a)
#ifdef HAVE_LSTAT
r = lstat(a->name, &st);
#else
r = stat(a->name, &st);
r = la_stat(a->name, &st);
#endif
if (r != 0)
r = errno;
@ -2712,7 +2712,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
* This is needed to extract hardlinks over
* symlinks.
*/
r = stat(head, &st);
r = la_stat(head, &st);
if (r != 0) {
tail[0] = c;
if (errno == ENOENT) {
@ -3052,7 +3052,7 @@ create_dir(struct archive_write_disk *a, char *path)
* here loses the ability to extract through symlinks. Also note
* that this should not use the a->st cache.
*/
if (stat(path, &st) == 0) {
if (la_stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
return (ARCHIVE_OK);
if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
@ -3110,7 +3110,7 @@ create_dir(struct archive_write_disk *a, char *path)
* don't add it to the fixup list here, as it's already been
* added.
*/
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
return (ARCHIVE_OK);
archive_set_error(&a->archive, errno, "Failed to create dir '%s'",

View file

@ -1114,6 +1114,10 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && acl_types != 0)
need_extension = 1;
/* If the symlink type is defined, we need an extension */
if (!need_extension && archive_entry_symlink_type(entry_main) > 0)
need_extension = 1;
/*
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
@ -1247,6 +1251,17 @@ archive_write_pax_header(struct archive_write *a,
archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
}
/* Store extended symlink information */
if (archive_entry_symlink_type(entry_main) ==
AE_SYMLINK_TYPE_FILE) {
add_pax_attr(&(pax->pax_header),
"LIBARCHIVE.symlinktype", "file");
} else if (archive_entry_symlink_type(entry_main) ==
AE_SYMLINK_TYPE_DIRECTORY) {
add_pax_attr(&(pax->pax_header),
"LIBARCHIVE.symlinktype", "dir");
}
}
/* Only regular files have data. */

View file

@ -496,10 +496,13 @@ xar_options(struct archive_write *a, const char *key, const char *value)
return (ARCHIVE_OK);
}
if (strcmp(key, "threads") == 0) {
char *endptr;
if (value == NULL)
return (ARCHIVE_FAILED);
xar->opt_threads = (int)strtoul(value, NULL, 10);
if (xar->opt_threads == 0 && errno != 0) {
errno = 0;
xar->opt_threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
xar->opt_threads = 1;
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,

View file

@ -27,6 +27,10 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h> /* for Linux file flags */
#endif
#ifndef HAVE_WCSCPY
static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
{
@ -337,16 +341,37 @@ DEFINE_TEST(test_entry)
/* TODO: Make this system-independent. */
assertEqualString(archive_entry_fflags_text(e),
"uappnd,nouchg,nodump,noopaque,uunlnk,nosystem");
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
/* Test archive_entry_copy_fflags_text_w() */
archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,uunlnk");
archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,hidden");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(16, set);
assertEqualInt(7, clear);
assertEqualInt(UF_HIDDEN, set);
assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
/* Test archive_entry_copy_fflags_text() */
archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,uunlnk");
archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,hidden");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(16, set);
assertEqualInt(7, clear);
assertEqualInt(UF_HIDDEN, set);
assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
#elif defined(_WIN32) && !defined(CYGWIN)
archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
archive_entry_copy_fflags_text(e, "rdonly,hidden,nosystem");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
#elif defined FS_IOC_GETFLAGS /* Linux */
archive_entry_copy_fflags_text_w(e, L"sappnd,schg,dump,noundel");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
archive_entry_copy_fflags_text(e, "sappnd,schg,dump,noundel");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
#endif
/* See test_acl_basic.c for tests of ACL set/get consistency. */

View file

@ -58,6 +58,14 @@ test_fuzz(const struct files *filesets)
size_t blk_size;
int64_t blk_offset;
int n;
const char *skip_fuzz_tests;
skip_fuzz_tests = getenv("SKIP_TEST_FUZZ");
if (skip_fuzz_tests != NULL) {
skipping("Skipping fuzz tests due to SKIP_TEST_FUZZ "
"environment variable");
return;
}
for (n = 0; filesets[n].names != NULL; ++n) {
const size_t buffsize = 30000000;

View file

@ -40,7 +40,30 @@ atimeIsUpdated(void)
{
const char *fn = "fs_noatime";
struct stat st;
#if defined(_WIN32) && !defined(CYGWIN)
char *buff = NULL;
char *ptr;
int r;
r = systemf("fsutil behavior query disableLastAccess > query_atime");
if (r == 0) {
buff = slurpfile(NULL, "query_atime");
if (buff != NULL) {
ptr = buff;
while(*ptr != '\0' && !isdigit(*ptr)) {
ptr++;
}
if (*ptr == '0') {
free(buff);
return(1);
} else if (*ptr == '1' || *ptr == '2') {
free(buff);
return(0);
}
free(buff);
}
}
#endif
if (!assertMakeFile(fn, 0666, "a"))
return (0);
if (!assertUtimes(fn, 1, 0, 1, 0))
@ -570,13 +593,13 @@ test_symlink_hybrid(void)
assertMakeDir("h", 0755);
assertChdir("h");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
assert((ae = archive_entry_new()) != NULL);
@ -727,13 +750,13 @@ test_symlink_logical(void)
assertMakeDir("l", 0755);
assertChdir("l");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Note: this test uses archive_read_next_header()
@ -961,8 +984,8 @@ test_symlink_logical_loop(void)
assertMakeDir("d1/d2/d3", 0755);
assertMakeDir("d2", 0755);
assertMakeFile("d2/file1", 0644, "d2/file1");
assertMakeSymlink("d1/d2/ld1", "../../d1");
assertMakeSymlink("d1/d2/ld2", "../../d2");
assertMakeSymlink("d1/d2/ld1", "../../d1", 1);
assertMakeSymlink("d1/d2/ld2", "../../d2", 1);
assertChdir("..");
assert((ae = archive_entry_new()) != NULL);
@ -1567,6 +1590,254 @@ test_nodump(void)
archive_entry_free(ae);
}
static void
test_parent(void)
{
struct archive *a;
struct archive_entry *ae;
const void *p;
size_t size;
int64_t offset;
int file_count;
int match_count;
int r;
assertMakeDir("lock", 0311);
assertMakeDir("lock/dir1", 0755);
assertMakeFile("lock/dir1/f1", 0644, "0123456789");
assertMakeDir("lock/lock2", 0311);
assertMakeDir("lock/lock2/dir1", 0755);
assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
assert((ae = archive_entry_new()) != NULL);
assert((a = archive_read_disk_new()) != NULL);
/*
* Test1: Traverse lock/dir1 as .
*/
assertChdir("lock/dir1");
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), ".") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertChdir("../..");
/*
* Test2: Traverse lock/dir1 directly
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
* Test3: Traverse lock/dir1/.
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
* Test4: Traverse lock/lock2/dir1 from inside lock.
*
* This test is expected to fail on platforms with no O_EXEC or
* equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
* the current traversal code can't handle the case where it can't
* obtain an open fd for the initial current directory. We need to
* check that condition here, because if O_EXEC _does_ exist, we don't
* want to overlook any failure.
*/
assertChdir("lock");
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
archive_entry_clear(ae);
r = archive_read_next_header2(a, ae);
if (r == ARCHIVE_FAILED) {
#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC)
assertEqualIntA(a, ARCHIVE_OK, r);
#endif
/* Close the disk object. */
archive_read_close(a);
} else {
file_count = 2;
match_count = 0;
while (file_count--) {
if (file_count == 0)
assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae),
"lock2/dir1") == 0) {
assertEqualInt(archive_entry_filetype(ae),
AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae),
"lock2/dir1/f1") == 0) {
assertEqualInt(archive_entry_filetype(ae),
AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size,
&offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size,
&offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory
* traverse tries to ascend past the initial directory, since
* it lacks permission to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF,
archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
}
assertChdir("..");
/* Destroy the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
archive_entry_free(ae);
}
DEFINE_TEST(test_read_disk_directory_traversals)
{
/* Basic test. */
@ -1583,4 +1854,6 @@ DEFINE_TEST(test_read_disk_directory_traversals)
test_callbacks();
/* Test nodump. */
test_nodump();
/* Test parent overshoot. */
test_parent();
}

View file

@ -161,7 +161,7 @@ DEFINE_TEST(test_read_extract)
assertIsDir("dir4/b", 0755);
assertIsDir("dir4/c", 0711);
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
free(buff);
free(file_buff);

View file

@ -717,4 +717,28 @@ DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
/*
* Check mtree file with non-printable ascii characters
*/
DEFINE_TEST(test_read_format_mtree_noprint)
{
const char reffile[] = "test_read_format_mtree_noprint.mtree";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(reffile);
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));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_filename(a, reffile, 11));
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualString("Can't parse line 3", archive_error_string(a));
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View file

@ -0,0 +1,4 @@
begin 644 test_read_format_mtree_noprint.mtree
K(VUT<F5E"F1I<E]O:R!T>7!E/61I<@ID:7)?P[;%H<2'('1Y<&4]9&ER"@``
`
end

View file

@ -28,6 +28,22 @@
#include <locale.h>
DEFINE_TEST(test_read_format_rar_set_format)
{
struct archive *a;
struct archive_entry *ae;
const char reffile[] = "test_read_format_rar.rar";
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_RAR));
assertA(0 == archive_read_open_filename(a, reffile, 10240));
assertA(0 == archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_basic)
{
char buff[64];
@ -3740,3 +3756,26 @@ DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_ppmd_use_after_free)
{
uint8_t buf[16];
const char* reffile = "test_read_format_rar_ppmd_use_after_free.rar";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_support_format_all(a));
assertA(0 == archive_read_open_filename(a, reffile, 10240));
assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_distance_overflow.rar
M4F%R(1H'`0"-[P+2``(''/\@("`@_R4``B`@("`@("`@("`@(/__("`@("`@
M(/\@("`@("`@((9ML63,PX"&AK%:S+?_(/\@_R#_(/\@_R#_(/\@`"``!R`@
MR<G)``#_(,G)R?___R#___\@____(/___R#___\@____R4#)R<G___\@____
M(/\@____("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(/__________
M____________________________________________________("`@("`@
.("`@("`@("`@("#_("``
`
end

View file

@ -0,0 +1,10 @@
begin 644 test_read_format_rar5_extra_field_version.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"BNGU4(0(#!%D&7^V#`I?:-URW@4'R
M@`,!"&)I;B\R=&\S`P0``<7)5B550C]U!#WY13&:5TJ$=$IZ(*3`C\#F0%O\
M)$)*@]X[RK.Z.G*HUT;V5FO&;:X/FDW,W`95I8T%@@C:DD="_8Z.9+CQH^IG
M8!ZF0N)JSY2?R(W@25K`U&W)Q1X"`MD`!M\`[8,"E]HW7+>!0?*``P$(8FEN
M+S)T;S/%R58E54(_=00]^44QFE=*A'1*>B"DP(_`YD!;_"1"2H/>.\JSNCIR
MJ-=&]E9KQFVN#YI-S-P&5:6-!8((VI)'0OV.CF2X\:/J9V`>ID+B:L^4G\B-
,X$E:P!UW5E$#!00`
`
end

View file

@ -0,0 +1,13 @@
begin 640 test_read_format_rar5_fileattr.rar
M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``-$;*1"@"`PN+``2+`"&+W8Z;@```
M#')E861O;FQY+G1X=`H#`J*C5`BE!M4!,3(S-#4V-S@@#0JYZ,#-)@(#"XL`
M!(L`(F^$/86````*:&ED9&5N+G1X=`H#`G(Q.0^E!M4!,C,T-38W.#D@#0H>
M%_EV)@(#"XL`!(L`)"V,TBB````*<WES=&5M+G1X=`H#`F:K01.E!M4!,S0U
M-C<X.3`@#0HQ>$42*0(#"XL`!(L`(RZ?$!V````-<F]?:&ED9&5N+G1X=`H#
M`JIEBD2M!M4!-C<X.3`Q,C,@#0HQAL?6)@(#"P`%`!$`````@```#&1I<E]R
M96%D;VYL>0H#`HS,%ABE!M4!Q!O^+"0"`PL`!0`2`````(````ID:7)?:&ED
M9&5N"@,">JRV&:4&U0'&L*8=)`(#"P`%`!0`````@```"F1I<E]S>7-T96T*
M`P(@+D4;I0;5`2YJ1$0F`@,+``4`$P````"````,9&ER7W)O:&ED9&5N"@,"
0CW7S@JT&U0$==U91`P4$````
`
end

View file

@ -0,0 +1,6 @@
begin 644 test_read_format_rar5_hardlink.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!KI,1X'@("A0`&A0"D@P(XC;=<(1>3
M?8```0AF:6QE+G1X=#$R,S0*[8@"T2X"`PT`!@6D@P(XC;=<`````(```0QH
@87)D;&EN:RYT>'0,!00`"&9I;&4N='AT'7=640,%!```
`
end

View file

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_invalid_dict_reference.rar
M4F%R(1H'`0"-[P+2``+#!QR`!P`F^P#_^_O[^_O[^R4``B$<`0(`#@```0``
M`"#2````_____QH(`/__^P#_W5)04(#_`(:&;;%DS+?,L0```````````+%D
MS+*RLK*R/@``____Y`"R````XP```````!4``````.X`````````````````
M%5<M;&@W;3$W"2!S;'$2C5L`_____@D0````$"('``"8F)@+````/__?````
M@```2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$@S2(``2$A(2$A(
>2$A(2$A(2$A(2$A(2$A(2$Q(2$A(2$A(2$A(2)](
`
end

View file

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_leftshift1.rar
M4F%R(1H'`0"-[P+2``(''(`'`"``_R4``B$<`0(`#@```0```"#2````____
M_P`(`/__^P#_W0`"(8#_`(:&;;%DS+?,L=:NL0#(3`$`````````````````
M``"``````````+!DS+*RL[*RL@```-P``````````````````(``````````
ML&3,LK*RLK*R````W`````#X____````````````````````````%5H>;&@T
M+3HW"2!SB^)_<Z3_`````?40'Q\?'Q\?'Q\?'Q\?'Q\?'Q\?'Q\?'Q\`````
5`````````````````/H`>@``````
`
end

View file

@ -0,0 +1,6 @@
begin 644 test_read_format_rar5_leftshift2.rar
M4F%R(1H'`0"-[P+2``(''(`'`2``_RL``B'+`0(`,O__````-WJ\KR<<)0`"
M(;<*`BY*`!```&;%T#%24%"`_R4`[@K+(2Y*`&$``'__`/\E``(N2@`0`0(`
0(?__`%N&?Q2UH.CHZ.CHZ```
`
end

View file

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_nonempty_dir_stream.rar
M4F%R(1H'`0"-[P+2``(''($'$7\`_R4``BP<`0(`(0#_Y@```"#2````____
M_P`(`/__^P#_W0`"(8#_`(:&;;%DS+?,L8```!;(&P#>``#__^_P```4```&
M`````````````+`!`@`A`/_F````(-(```#_____``@`___[`/_=``(A``++
M``"`]/^`!P!#^_____\"(2$!`@`A````_R4``B$A`0(`@````0```"#&`/_=
M``(A@/\`AH9ML63,M\R`_P```,@;`````!@`````_0`````````!87(A&@<`
5`(WO`M(``O8'&X`'`#C[_X`E``(A
`
end

View file

@ -0,0 +1,8 @@
begin 644 test_read_format_rar5_owner.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!W:E-^+0(##H4`!H4`I(,"_8VW7"$7
MDWV```$(<F]O="YT>'0-!@,$<F]O=`5W:&5E;#$R,S0*2J"P0S,"`Q*%``:%
M`*2#`FZ-MUQFP<VL@``!"FYO8F]D>2YT>'01!@,&;F]B;V1Y!VYO9W)O=7`U
M-C<X"L=81/8I`@,'A0`&A0"D@P)LD[=<>B#;(H```0MN=6UE<FEC+G1X=`8&
2#(].N$4Y.3DY"AUW5E$#!00`
`
end

View file

@ -0,0 +1,15 @@
begin 644 test_read_format_rar5_readtables_overflow.rar
M4F%R(1H'`0"-[P+2`)3+'_4`C>\"T@`"T@"4RQ_5]0#O0````,L?Q_T``(`"
MT@"4RQ_=V-C8`)3+']W=]0"-\`+2`)3+']WU`(WO`M(``M(`E,L?U?4`[P+2
M`)3+'\?]``"``M(`E,L?W=C8V`"4RQ_=]0#V`(WO`M'UV,?8V-C8$=C8V-C8
MV(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V-C8!]C8V-C8V-C8V-C8V-C8V-C8
MV-C8V-C8V-C(V-C8V-C2`)3+']W8V-C8V-C8V-C8V-C8V-C8@-C8V-C8V-C8
MV/+8V-C8V-C8V-C8`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8!-C8
MV-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8`(`"V`7V`(WO`M'U`]L?
MW?4`C>\"T@`"T@"4'__U`(WO`N``E,L?W84`C0`0T@"4RQ_=V-C8V-C8V`"4
MR_\R]0#V`(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8
MV-C8V-C8V-C8V-C8R-C8V-C8T@"4RQ_=V-C8V-C8V-C8V-C8V-C8V(#8V-C8
MV-C8````9-C8V-C8V!'8V-C8V-C8]]C8V-C8V-C8V-C8V/+8V-C8V-C8V-C8
=`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-@`
`
end

View file

@ -0,0 +1,8 @@
begin 644 test_read_format_rar5_symlink.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"$O8RN'@("A0`&A0"D@P(XC;=<(1>3
M?8!``0AF:6QE+G1X=#$R,S0*8QI3.2T"`PT`!@CMPP)7C;=<`````(!``0MS
M>6UL:6YK+G1X=`P%`0`(9FEL92YT>'2.NOQU)`(#"``&`^W#`DF6MUP`````
M@$`!!V1I<FQI;FL'!0$!`V1I<J/_?\87`@(`!P#M@P%&EK=<`````(```0-D
*:7(==U91`P4$````
`
end

View file

@ -0,0 +1,7 @@
begin 644 test_read_format_rar5_truncated_huff.rar
M4F%R(1H'`0"-[P+2``'#]#P\7P$'`0"-[P+2``+2`!;#M#Q::7!)2?__'`!I
M?_O_0B\*0RX-,'%O.\(#!-'^T#4````0`P1_``!#(3`P,./H`P```*^OKZ^O
MKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ\0`*^OKZ^A``KZ``$`2^\#
9T>WMNP$+-5H*^@`!`$OOB]$````0"S5:*@``
`
end

View file

@ -1,68 +1,69 @@
begin 644 test_read_format_rar5_win32.rar
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
;0];M1^11#SKD/'L0\&IZ_]!^T!UW5E$#!00`
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
KJ,`Z/SC^]Q#CZ_LA]/M(_0T0][6AZ>"'E94/$R(?'_N'S0`==U91`P4$````
`
end

View file

@ -0,0 +1,10 @@
begin 644 test_read_format_rar_ppmd_use_after_free.rar
M4F%R(1H'``1G=$Q26`!W````>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)"
M+W5N<V5T"6=I9`UD#1T+``!"`````````&%R(1H'``1G>TQ26`!W=&@`[E!+
M`P0Q`'#_(````"`@(+<@!/T`("`@("`@("`@("`@("`@("`@("`@("`@("`@
M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@
M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(`1G=$Q26`!W````
M>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)"+W5N<V5T"6=I9`UD#1T+``!"
@`````````&%R(1H'``1G>TQ26`!W=&@`[E!+`P0Q`'``
`
end

View file

@ -36,6 +36,7 @@ DEFINE_TEST(test_read_format_raw)
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";
const char *reffile4 = "test_read_format_raw.data.gz";
/* First, try pulling data out of an uninterpretable file. */
extract_reference_file(reffile1);
@ -117,4 +118,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));
/* Fourth, try with gzip which has metadata. */
extract_reference_file(reffile4);
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, reffile4, 1));
/* First (and only!) Entry */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("test-file-name.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);
assert(archive_entry_mtime_is_set(ae));
assertEqualIntA(a, archive_entry_mtime(ae), 0x5cbafd25);
/* 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));
/* 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));
}

View file

@ -0,0 +1,4 @@
begin 644 test_read_format_raw.data.gz
L'XL(""7]NEP``W1E<W0M9FEL92UN86UE+F1A=&$`2\O/YP(`J&4R?@0`````
`
end

View file

@ -0,0 +1,53 @@
/*-
* Copyright (c) 2019 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$");
/*
* Tar archives with with just a GNU label (or ending with one) should
* be treated as valid (empty) archives
*/
DEFINE_TEST(test_read_format_tar_empty_with_gnulabel)
{
char name[] = "test_read_format_tar_empty_with_gnulabel.tar";
struct archive_entry *ae;
struct archive *a;
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_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);
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View file

@ -0,0 +1,231 @@
begin 664 test_read_format_tar_empty_with_gnulabel.tar
M;&%B96P`````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`#$S-#8W-S,V,C`S`#`P,C8R,``@5@``````````````````````````````
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````````````````````````````````````````````````````````````
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````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
9````````````````````````````````````
`
end

View file

@ -32,29 +32,29 @@ __FBSDID("$FreeBSD$");
static
int extract_one(struct archive* a, struct archive_entry* ae, uint32_t crc)
{
la_ssize_t fsize, bytes_read;
uint8_t* buf;
int ret = 1;
uint32_t computed_crc;
la_ssize_t fsize, bytes_read;
uint8_t* buf;
int ret = 1;
uint32_t computed_crc;
fsize = (la_ssize_t) archive_entry_size(ae);
buf = malloc(fsize);
if(buf == NULL)
return 1;
fsize = (la_ssize_t) archive_entry_size(ae);
buf = malloc(fsize);
if(buf == NULL)
return 1;
bytes_read = archive_read_data(a, buf, fsize);
if(bytes_read != fsize) {
assertEqualInt(bytes_read, fsize);
goto fn_exit;
}
bytes_read = archive_read_data(a, buf, fsize);
if(bytes_read != fsize) {
assertEqualInt(bytes_read, fsize);
goto fn_exit;
}
computed_crc = crc32(0, buf, fsize);
assertEqualInt(computed_crc, crc);
ret = 0;
computed_crc = crc32(0, buf, fsize);
assertEqualInt(computed_crc, crc);
ret = 0;
fn_exit:
free(buf);
return ret;
free(buf);
return ret;
}
static
@ -111,7 +111,7 @@ verify_basic(struct archive *a, int seek_checks)
int64_t o;
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("ZIP 1.0 (uncompressed)", archive_format_name(a));
assertEqualString("ZIP 1.0 (uncompressed)", archive_format_name(a));
assertEqualString("dir/", archive_entry_pathname(ae));
assertEqualInt(1179604249, archive_entry_mtime(ae));
assertEqualInt(0, archive_entry_size(ae));
@ -124,7 +124,7 @@ verify_basic(struct archive *a, int seek_checks)
assertEqualInt((int)s, 0);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
assertEqualString("file1", archive_entry_pathname(ae));
assertEqualInt(1179604289, archive_entry_mtime(ae));
if (seek_checks)
@ -144,7 +144,7 @@ verify_basic(struct archive *a, int seek_checks)
}
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
assertEqualString("file2", archive_entry_pathname(ae));
assertEqualInt(1179605932, archive_entry_mtime(ae));
assertEqualInt(archive_entry_is_encrypted(ae), 0);
@ -166,7 +166,7 @@ verify_basic(struct archive *a, int seek_checks)
assert(archive_errno(a) != 0);
}
assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
/* Verify the number of files read. */
failure("the archive file has three files");
assertEqualInt(3, archive_file_count(a));
@ -493,9 +493,14 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@ -513,9 +518,14 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@ -533,9 +543,14 @@ DEFINE_TEST(test_read_format_zip_lzma_multi)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -565,9 +580,14 @@ DEFINE_TEST(test_read_format_zip_lzma_multi_blockread)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -598,9 +618,14 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
skipping("bzip2 is not fully supported on this platform");
archive_read_close(a);
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@ -618,9 +643,14 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
skipping("bzip2 is not fully supported on this platform");
archive_read_close(a);
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@ -638,9 +668,14 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
skipping("bzip2 is not fully supported on this platform");
archive_read_close(a);
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -670,9 +705,14 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
skipping("bzip2 is not fully supported on this platform");
archive_read_close(a);
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -702,9 +742,14 @@ DEFINE_TEST(test_read_format_zip_xz_multi)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -734,9 +779,14 @@ DEFINE_TEST(test_read_format_zip_xz_multi_blockread)
struct archive *a;
struct archive_entry *ae;
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
@ -789,9 +839,14 @@ DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid)
struct archive_entry *ae;
char buf[8];
assert((a = archive_read_new()) != NULL);
if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) {
skipping("bzip2 is not fully supported on this platform");
archive_read_close(a);
return;
}
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@ -823,3 +878,41 @@ DEFINE_TEST(test_read_format_zip_ppmd8_crash_2)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_zip_lzma_alone_leak)
{
const char *refname = "test_read_format_zip_lzma_alone_leak.zipx";
struct archive *a;
struct archive_entry *ae;
char buf[64];
/* OSSFuzz #14470 sample file. */
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
if(ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading is not fully supported on this platform");
archive_read_close(a);
return;
}
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 37));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
/* Extraction of this file should fail, because the sample file is invalid.
* But it shouldn't crash. */
assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buf, sizeof(buf)));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
/* Extraction of this file should fail, because the sample file is invalid.
* But it shouldn't crash. */
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf)));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
/* This testcase shouldn't produce any memory leaks. When running test
* suite under Valgrind or ASan, the test runner won't return with
* exit code 0 in case if a memory leak. */
}

View file

@ -0,0 +1,102 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011 Michihiro NAKAJIMA
* Copyright (c) 2019 Mike Frysinger
* 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$");
#include <locale.h>
static void
verify(struct archive *a) {
struct archive_entry *ae;
const char *p;
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assert((p = archive_entry_pathname_utf8(ae)) != NULL);
assertEqualUTF8String(p, "File 1.txt");
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assert((p = archive_entry_pathname_utf8(ae)) != NULL);
#if defined(__APPLE__)
/* Compare NFD string. */
assertEqualUTF8String(p, "File 2 - o\xCC\x88.txt");
#else
/* Compare NFC string. */
assertEqualUTF8String(p, "File 2 - \xC3\xB6.txt");
#endif
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assert((p = archive_entry_pathname_utf8(ae)) != NULL);
#if defined(__APPLE__)
/* Compare NFD string. */
assertEqualUTF8String(p, "File 3 - a\xCC\x88.txt");
#else
/* Compare NFC string. */
assertEqualUTF8String(p, "File 3 - \xC3\xA4.txt");
#endif
/* The CRC of the filename fails, so fall back to CDE. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assert((p = archive_entry_pathname_utf8(ae)) != NULL);
assertEqualUTF8String(p, "File 4 - xx.txt");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
}
DEFINE_TEST(test_read_format_zip_utf8_paths)
{
const char *refname = "test_read_format_zip_7075_utf8_paths.zip";
struct archive *a;
char *p;
size_t s;
extract_reference_file(refname);
if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
skipping("en_US.UTF-8 locale not available on this system.");
return;
}
/* Verify with seeking reader. */
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));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
verify(a);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
p = slurpfile(&s, refname);
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));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
verify(a);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_free(a));
free(p);
}

View file

@ -0,0 +1,20 @@
begin 644 test_read_format_zip_7075_utf8_paths.zip
M4$L#!!0````(`,$^9D5BZ95P"P````D````*````1FEL92`Q+G1X=`M)+2Y1
M2,O,204`4$L#!!0````(`,$^9D5BZ95P"P````D````/`!@`1FEL92`R("T@
M>'@N='AT=7`4``$NSPQQ1FEL92`R("T@P[8N='AT"TDM+E%(R\Q)!0!02P,$
M%`````@`P3YF16+IE7`+````"0````\`&`!&:6QE(#,@+2!X>"YT>'1U<!0`
M`1"DSIY&:6QE(#,@+2##I"YT>'0+22TN44C+S$D%`%!+`P04````"`#!/F9%
M8NF5<`L````)````#P`8`$9I;&4@-"`M('AX+G1X='5P%``!G[AP'$9I;&4@
M-"`M(,.E+G1X=`M)+2Y12,O,204`4$L!`A\`%`````@`P3YF16+IE7`+````
M"0````H`)``````````@`````````$9I;&4@,2YT>'0*`"````````$`&``Q
M6UASCOG/`5^OQVV.^<\!7Z_';8[YSP%02P$"'P`4````"`#!/F9%8NF5<`L`
M```)````#@`\`````````"`````S````1FEL92`R("T@E"YT>'0*`"``````
M``$`&``Q6UASCOG/`2M.B72.^<\!*TZ)=([YSP%U<!0``2[/#'%&:6QE(#(@
M+2##MBYT>'102P$"'P`4````"`#!/F9%8NF5<`L````)````#@`\````````
M`"````"#````1FEL92`S("T@A"YT>'0*`"````````$`&``Q6UASCOG/`5<$
M&W>.^<\!5P0;=X[YSP%U<!0``1"DSIY&:6QE(#,@+2##I"YT>'102P$"'P`4
M````"`#!/F9%8NF5<`L````)````#@`\`````````"````#3````1FEL92`T
M("T@ABYT>'0*`"````````$`&``Q6UASCOG/`6#)ZG:.^<\!8,GJ=H[YSP%U
M<!0``9^X<!Q&:6QE(#0@+2##I2YT>'102P4&``````0`!`#$`0``(P$`````
`
end

View file

@ -0,0 +1,93 @@
/*-
* Copyright (c) 2003-2018 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"
/*
* Test archive verifies that we ignore padding in the extra field.
*
* APPNOTE.txt does not provide any provision for padding the extra
* field, so libarchive used to error when there were unconsumed
* bytes. Apparently, some Zip writers do routinely put zero padding
* in the extra field.
*
* The extra fields in this test (for both the local file header
* and the central directory entry) are formatted as follows:
*
* 0000 0000 - unrecognized field with type zero, zero bytes
* 5554 0900 03d258155cdb58155c - UX field with length 9
* 0000 0400 00000000 - unrecognized field with type zero, four bytes
* 000000 - three bytes padding
*
* The two valid type zero fields should be skipped and ignored, as
* should the three bytes padding (which is too short to be a valid
* extra data object). If there were no errors and we read the UX
* field correctly, then we've correctly handled all of the padding
* fields above.
*/
static void verify(struct archive *a) {
struct archive_entry *ae;
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("a", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae));
assertEqualInt(0x5c1558d2, archive_entry_mtime(ae));
assertEqualInt(0, archive_entry_ctime(ae));
assertEqualInt(0x5c1558db, archive_entry_atime(ae));
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
}
DEFINE_TEST(test_read_format_zip_extra_padding)
{
const char *refname = "test_read_format_zip_extra_padding.zip";
struct archive *a;
char *p;
size_t s;
extract_reference_file(refname);
/* Verify with seeking reader. */
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));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 7));
verify(a);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
p = slurpfile(&s, refname);
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));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 3));
verify(a);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
free(p);
}

View file

@ -0,0 +1,7 @@
begin 644 test_read_format_zip_extra_padding.zip
M4$L#!`H``````"-=CTW$\L?V`@````(````!`!P`80````!55`D``])8%5S;
M6!5<```$``````````!B"E!+`0(>`PH``````"-=CTW$\L?V`@````(````!
M`!@```````$```"D@0````!A`````%54"0`#TE@57-M8%5P```0``````$L%
3!@`````!``$`1P```#T`````````
`
end

View file

@ -0,0 +1,5 @@
begin 644 test_read_format_zip_lzma_alone_leak.zipx
M4$L#!"`@6B`.("`@("`@("`@%0```"`@("````4``0`!`"`@(`4``"``````
J(/\@("`@("`@("!02P,$("`@(`X@(/________\@("`@("`@(``````@
`
end

View file

@ -68,6 +68,14 @@ struct sparse {
static void create_sparse_file(const char *, const struct sparse *);
#if defined(__APPLE__)
/* On APFS holes need to be at least 4096x4097 bytes */
#define MIN_HOLE 16781312
#else
/* Elsewhere we work with 4096*10 bytes */
#define MIN_HOLE 409600
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <winioctl.h>
/*
@ -491,6 +499,7 @@ DEFINE_TEST(test_sparse_basic)
{
char *cwd;
struct archive *a;
const char *skip_sparse_tests;
/*
* The alignment of the hole of sparse files deeply depends
* on filesystem. In my experience, sparse_file2 test with
@ -501,42 +510,42 @@ DEFINE_TEST(test_sparse_basic)
*/
const struct sparse sparse_file0[] = {
// 0 // 1024
{ DATA, 1024 }, { HOLE, 2048000 },
{ DATA, 1024 }, { HOLE, MIN_HOLE + 1638400 },
// 2049024 // 2051072
{ DATA, 2048 }, { HOLE, 2048000 },
{ DATA, 2048 }, { HOLE, MIN_HOLE + 1638400 },
// 4099072 // 4103168
{ DATA, 4096 }, { HOLE, 20480000 },
{ DATA, 4096 }, { HOLE, MIN_HOLE + 20070400 },
// 24583168 // 24591360
{ DATA, 8192 }, { HOLE, 204800000 },
{ DATA, 8192 }, { HOLE, MIN_HOLE + 204390400 },
// 229391360 // 229391361
{ DATA, 1 }, { END, 0 }
};
const struct sparse sparse_file1[] = {
{ HOLE, 409600 }, { DATA, 1 },
{ HOLE, 409600 }, { DATA, 1 },
{ HOLE, 409600 }, { END, 0 }
{ HOLE, MIN_HOLE }, { DATA, 1 },
{ HOLE, MIN_HOLE }, { DATA, 1 },
{ HOLE, MIN_HOLE }, { END, 0 }
};
const struct sparse sparse_file2[] = {
{ HOLE, 409600 * 1 }, { DATA, 1024 },
{ HOLE, 409600 * 2 }, { DATA, 1024 },
{ HOLE, 409600 * 3 }, { DATA, 1024 },
{ HOLE, 409600 * 4 }, { DATA, 1024 },
{ HOLE, 409600 * 5 }, { DATA, 1024 },
{ HOLE, 409600 * 6 }, { DATA, 1024 },
{ HOLE, 409600 * 7 }, { DATA, 1024 },
{ HOLE, 409600 * 8 }, { DATA, 1024 },
{ HOLE, 409600 * 9 }, { DATA, 1024 },
{ HOLE, 409600 * 10}, { DATA, 1024 },/* 10 */
{ HOLE, 409600 * 1 }, { DATA, 1024 * 1 },
{ HOLE, 409600 * 2 }, { DATA, 1024 * 2 },
{ HOLE, 409600 * 3 }, { DATA, 1024 * 3 },
{ HOLE, 409600 * 4 }, { DATA, 1024 * 4 },
{ HOLE, 409600 * 5 }, { DATA, 1024 * 5 },
{ HOLE, 409600 * 6 }, { DATA, 1024 * 6 },
{ HOLE, 409600 * 7 }, { DATA, 1024 * 7 },
{ HOLE, 409600 * 8 }, { DATA, 1024 * 8 },
{ HOLE, 409600 * 9 }, { DATA, 1024 * 9 },
{ HOLE, 409600 * 10}, { DATA, 1024 * 10},/* 20 */
{ HOLE, MIN_HOLE }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 1 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 2 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 3 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 4 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 5 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 6 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 7 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 8 }, { DATA, 1024 },
{ HOLE, MIN_HOLE + 409600 * 9}, { DATA, 1024 },/* 10 */
{ HOLE, MIN_HOLE }, { DATA, 1024 * 1 },
{ HOLE, MIN_HOLE + 409600 * 1 }, { DATA, 1024 * 2 },
{ HOLE, MIN_HOLE + 409600 * 2 }, { DATA, 1024 * 3 },
{ HOLE, MIN_HOLE + 409600 * 3 }, { DATA, 1024 * 4 },
{ HOLE, MIN_HOLE + 409600 * 4 }, { DATA, 1024 * 5 },
{ HOLE, MIN_HOLE + 409600 * 5 }, { DATA, 1024 * 6 },
{ HOLE, MIN_HOLE + 409600 * 6 }, { DATA, 1024 * 7 },
{ HOLE, MIN_HOLE + 409600 * 7 }, { DATA, 1024 * 8 },
{ HOLE, MIN_HOLE + 409600 * 8 }, { DATA, 1024 * 9 },
{ HOLE, MIN_HOLE + 409600 * 9}, { DATA, 1024 * 10},/* 20 */
{ END, 0 }
};
const struct sparse sparse_file3[] = {
@ -553,6 +562,13 @@ DEFINE_TEST(test_sparse_basic)
*/
test_sparse_whole_file_data();
skip_sparse_tests = getenv("SKIP_TEST_SPARSE");
if (skip_sparse_tests != NULL) {
skipping("Skipping sparse tests due to SKIP_TEST_SPARSE "
"environment variable");
return;
}
/* Check if the filesystem where CWD on can
* report the number of the holes of a sparse file. */
#ifdef PATH_MAX
@ -599,10 +615,19 @@ DEFINE_TEST(test_fully_sparse_files)
{
char *cwd;
struct archive *a;
const char *skip_sparse_tests;
const struct sparse sparse_file[] = {
{ HOLE, 409600 }, { END, 0 }
{ HOLE, MIN_HOLE }, { END, 0 }
};
skip_sparse_tests = getenv("SKIP_TEST_SPARSE");
if (skip_sparse_tests != NULL) {
skipping("Skipping sparse tests due to SKIP_TEST_SPARSE "
"environment variable");
return;
}
/* Check if the filesystem where CWD on can
* report the number of the holes of a sparse file. */
#ifdef PATH_MAX

View file

@ -99,6 +99,139 @@ DEFINE_TEST(test_write_disk_symlink)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: dot -> . */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "dot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, ".");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: dotdot -> .. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "dotdot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "..");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: slash -> / */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "slash");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "/");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: sldot -> /. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "sldot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "/.");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: sldotdot -> /.. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "sldotdot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "/..");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Dir: d1 */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1");
archive_entry_set_mode(ae, AE_IFDIR | 0777);
archive_entry_unset_size(ae);
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1nosl -> d1 */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1nosl");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1slash -> d1/ */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1slash");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1/");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1sldot -> d1/. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1sldot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1/.");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1slddot -> d1/.. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1slddot");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1/..");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1dir -> d1 */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1dir");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
/* Symbolic link: d1file -> d1 */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "d1file");
archive_entry_set_mode(ae, AE_IFLNK | 0642);
archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_FILE);
archive_entry_unset_size(ae);
archive_entry_copy_symlink(ae, "d1");
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
if (r >= ARCHIVE_WARN)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
/* Test the entries on disk. */
@ -107,11 +240,30 @@ DEFINE_TEST(test_write_disk_symlink)
assertIsReg("link1a", -1);
assertFileSize("link1a", sizeof(data));
assertFileNLinks("link1a", 1);
assertIsSymlink("link1b", "link1a");
assertIsSymlink("link1b", "link1a", 0);
/* Test #2: Should produce identical results to test #1 */
assertIsReg("link2a", -1);
assertFileSize("link2a", sizeof(data));
assertFileNLinks("link2a", 1);
assertIsSymlink("link2b", "link2a");
assertIsSymlink("link2b", "link2a", 0);
/* Test #3: Special symlinks */
assertIsSymlink("dot", ".", 1);
assertIsSymlink("dotdot", "..", 1);
assertIsSymlink("slash", "/", 1);
assertIsSymlink("sldot", "/.", 1);
assertIsSymlink("sldotdot", "/..", 1);
/* Test #4: Directory symlink mixed with . and .. */
assertIsDir("d1", -1);
/* On Windows, d1nosl should be a file symlink */
assertIsSymlink("d1nosl", "d1", 0);
assertIsSymlink("d1slash", "d1/", 1);
assertIsSymlink("d1sldot", "d1/.", 1);
assertIsSymlink("d1slddot", "d1/..", 1);
/* Test #5: symlink_type is set */
assertIsSymlink("d1dir", "d1", 1);
assertIsSymlink("d1file", "d1", 0);
}

View file

@ -204,6 +204,18 @@ Do not process files or directories that match the
specified pattern.
Note that exclusions take precedence over patterns or filenames
specified on the command line.
.It Fl Fl exclude-vcs
Do not process files or directories internally used by the
version control systems
.Sq CVS ,
.Sq RCS ,
.Sq SCCS ,
.Sq SVN ,
.Sq Arch ,
.Sq Bazaar ,
.Sq Mercurial
and
.Sq Darcs .
.It Fl Fl fflags
(c, r, u, x modes only)
Archive or extract file flags. This is the reverse of
@ -386,8 +398,7 @@ and the default behavior in c, r, and u modes or if
.Nm
is run in x mode as root.
.It Fl n , Fl Fl norecurse , Fl Fl no-recursion
(c, r, u modes only)
Do not recursively archive the contents of directories.
Do not operate recursively on the content of directories.
.It Fl Fl newer Ar date
(c, r, u modes only)
Only include files and directories newer than the specified date.

View file

@ -129,6 +129,28 @@ static void version(void) __LA_DEAD;
(ARCHIVE_EXTRACT_SECURE_SYMLINKS \
| ARCHIVE_EXTRACT_SECURE_NODOTDOT)
static char const * const vcs_files[] = {
/* CVS */
"CVS", ".cvsignore",
/* RCS */
"RCS",
/* SCCS */
"SCCS",
/* SVN */
".svn",
/* git */
".git", ".gitignore", ".gitattributes", ".gitmodules",
/* Arch */
".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update",
/* Bazaar */
".bzr", ".bzrignore", ".bzrtags",
/* Mercurial */
".hg", ".hgignore", ".hgtags",
/* darcs */
"_darcs",
NULL
};
int
main(int argc, char **argv)
{
@ -318,6 +340,15 @@ main(int argc, char **argv)
lafe_errc(1, 0,
"Couldn't exclude %s\n", bsdtar->argument);
break;
case OPTION_EXCLUDE_VCS: /* GNU tar */
for(t=0; vcs_files[t]; t++) {
if (archive_match_exclude_pattern(
bsdtar->matching,
vcs_files[t]) != ARCHIVE_OK)
lafe_errc(1, 0, "Couldn't "
"exclude %s\n", vcs_files[t]);
}
break;
case OPTION_FFLAGS:
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS;
@ -808,8 +839,6 @@ main(int argc, char **argv)
break;
}
}
if (bsdtar->flags & OPTFLAG_NO_SUBDIRS)
only_mode(bsdtar, "-n", "cru");
if (bsdtar->flags & OPTFLAG_STDOUT)
only_mode(bsdtar, "-O", "xt");
if (bsdtar->flags & OPTFLAG_UNLINK_FIRST)
@ -859,6 +888,16 @@ main(int argc, char **argv)
only_mode(bsdtar, buff, "cru");
}
/*
* When creating an archive from a directory tree, the directory
* walking code will already avoid entering directories when
* recursive inclusion of directory content is disabled, therefore
* changing the matching behavior has no effect for creation modes.
* It is relevant for extraction or listing.
*/
archive_match_set_inclusion_recursion(bsdtar->matching,
!(bsdtar->flags & OPTFLAG_NO_SUBDIRS));
/* Filename "-" implies stdio. */
if (strcmp(bsdtar->filename, "-") == 0)
bsdtar->filename = NULL;

View file

@ -135,6 +135,7 @@ enum {
OPTION_CHROOT,
OPTION_CLEAR_NOCHANGE_FFLAGS,
OPTION_EXCLUDE,
OPTION_EXCLUDE_VCS,
OPTION_FFLAGS,
OPTION_FORMAT,
OPTION_GID,

View file

@ -85,6 +85,7 @@ static const struct bsdtar_option {
{ "disable-copyfile", 0, OPTION_NO_MAC_METADATA },
{ "exclude", 1, OPTION_EXCLUDE },
{ "exclude-from", 1, 'X' },
{ "exclude-vcs", 0, OPTION_EXCLUDE_VCS },
{ "extract", 0, 'x' },
{ "fast-read", 0, 'q' },
{ "fflags", 0, OPTION_FFLAGS },

View file

@ -42,7 +42,7 @@ make_files(void)
/* Symlink to above file. */
if (canSymlink())
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
/* Directory. */
assertMakeDir("dir", 0775);
@ -78,7 +78,7 @@ verify_files(const char *target)
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
/* dir */
failure("%s", target);

View file

@ -176,7 +176,7 @@ create_tree(void)
sprintf(buff, "s/%s", filenames[i]);
sprintf(buff2, "../f/%s", filenames[i]);
failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
assertMakeSymlink(buff, buff2);
assertMakeSymlink(buff, buff2, 0);
}
/* Create a dir named "d/abcdef...". */
buff[0] = 'd';
@ -222,7 +222,7 @@ verify_tree(size_t limit)
sprintf(name1, "s/%s", filenames[i]);
sprintf(name2, "../f/%s", filenames[i]);
if (strlen(name2) <= limit)
assertIsSymlink(name1, name2);
assertIsSymlink(name1, name2, 0);
}
/* Verify dir "d/abcdef...". */

View file

@ -36,6 +36,9 @@ DEFINE_TEST(test_option_C_mtree)
p0 = NULL;
char *content = "./foo type=file uname=root gname=root mode=0755\n";
char *filename = "output.tar";
#if defined(_WIN32) && !defined(CYGWIN)
char *p;
#endif
/* an absolute path to mtree file */
char *mtree_file = "/METALOG.mtree";
@ -48,9 +51,21 @@ DEFINE_TEST(test_option_C_mtree)
assertMakeDir("bar", 0775);
assertMakeFile("bar/foo", 0777, "abc");
r = systemf("%s -cf %s -C bar \"@%s\" >step1.out 2>step1.err", testprog, filename, absolute_path);
#if defined(_WIN32) && !defined(CYGWIN)
p = absolute_path;
while(*p != '\0') {
if (*p == '/')
*p = '\\';
p++;
}
r = systemf("%s -cf %s -C bar @%s >step1.out 2>step1.err", testprog, filename, absolute_path);
failure("Error invoking %s -cf %s -C bar @%s", testprog, filename, absolute_path);
#else
r = systemf("%s -cf %s -C bar \"@%s\" >step1.out 2>step1.err", testprog, filename, absolute_path);
failure("Error invoking %s -cf %s -C bar \"@%s\"", testprog, filename, absolute_path);
#endif
assertEqualInt(r, 0);
assertEmptyFile("step1.out");
assertEmptyFile("step1.err");
@ -68,6 +83,7 @@ DEFINE_TEST(test_option_C_mtree)
assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8);
done:
free(p0);
free(absolute_path);
}

View file

@ -39,13 +39,13 @@ DEFINE_TEST(test_option_H_upper)
assertMakeDir("in", 0755);
assertChdir("in");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 1: Without -H */
@ -55,11 +55,11 @@ DEFINE_TEST(test_option_H_upper)
assertChdir("test1");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsSymlink("ld1", "d1");
assertIsSymlink("d1/link1", "file1");
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("link2", "d1/file2");
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("ld1", "d1", 1);
assertIsSymlink("d1/link1", "file1", 0);
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsSymlink("link2", "d1/file2", 0);
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 2: With -H, no symlink on command line. */
@ -69,11 +69,11 @@ DEFINE_TEST(test_option_H_upper)
assertChdir("test2");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsSymlink("ld1", "d1");
assertIsSymlink("d1/link1", "file1");
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("link2", "d1/file2");
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("ld1", "d1", 1);
assertIsSymlink("d1/link1", "file1", 0);
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsSymlink("link2", "d1/file2", 0);
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 3: With -H, some symlinks on command line. */
@ -84,9 +84,9 @@ DEFINE_TEST(test_option_H_upper)
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("d1/link1", "file1");
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsSymlink("d1/link1", "file1", 0);
assertIsReg("link2", umasked(0644));
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
}

View file

@ -39,13 +39,13 @@ DEFINE_TEST(test_option_L_upper)
assertMakeDir("in", 0755);
assertChdir("in");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 1: Without -L */
@ -55,11 +55,11 @@ DEFINE_TEST(test_option_L_upper)
assertChdir("test1");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsSymlink("ld1", "d1");
assertIsSymlink("d1/link1", "file1");
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("link2", "d1/file2");
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("ld1", "d1", 1);
assertIsSymlink("d1/link1", "file1", 0);
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsSymlink("link2", "d1/file2", 0);
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 2: With -L, no symlink on command line. */
@ -71,9 +71,9 @@ DEFINE_TEST(test_option_L_upper)
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
assertIsReg("d1/link1", umasked(0644));
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsReg("link2", umasked(0644));
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 3: With -L, some symlinks on command line. */
@ -85,8 +85,8 @@ DEFINE_TEST(test_option_L_upper)
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
assertIsReg("d1/link1", umasked(0644));
assertIsSymlink("d1/linkX", "fileX");
assertIsSymlink("d1/linkX", "fileX", 0);
assertIsReg("link2", umasked(0644));
assertIsSymlink("linkY", "d1/fileY");
assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
}

View file

@ -79,10 +79,10 @@ DEFINE_TEST(test_option_U_upper)
assertMakeDir("test3", 0755);
assertChdir("test3");
assertMakeDir("realDir", 0755);
assertMakeSymlink("d1", "realDir");
assertMakeSymlink("d1", "realDir", 1);
r = systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog);
assert(r != 0);
assertIsSymlink("d1", "realDir");
assertIsSymlink("d1", "realDir", 1);
assertFileNotExists("d1/file1");
assertEmptyFile("test.out");
assertNonEmptyFile("test.err");
@ -92,7 +92,7 @@ DEFINE_TEST(test_option_U_upper)
assertMakeDir("test4", 0755);
assertChdir("test4");
assertMakeDir("realDir", 0755);
assertMakeSymlink("d1", "realDir");
assertMakeSymlink("d1", "realDir", 1);
assertEqualInt(0,
systemf("%s -xUf ../archive.tar >test.out 2>test.err", testprog));
assertIsDir("d1", -1);
@ -105,10 +105,10 @@ DEFINE_TEST(test_option_U_upper)
assertMakeDir("test5", 0755);
assertChdir("test5");
assertMakeDir("realDir", 0755);
assertMakeSymlink("d1", "realDir");
assertMakeSymlink("d1", "realDir", 1);
assertEqualInt(0,
systemf("%s -xPf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
assertIsSymlink("d1", "realDir");
assertIsSymlink("d1", "realDir", 1);
assertFileContents("d1/file1", 8, "d1/file1");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
@ -118,10 +118,10 @@ DEFINE_TEST(test_option_U_upper)
assertMakeDir("test6", 0755);
assertChdir("test6");
assertMakeDir("realDir", 0755);
assertMakeSymlink("d1", "realDir");
assertMakeSymlink("d1", "realDir", 1);
assertEqualInt(0,
systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
assertIsSymlink("d1", "realDir");
assertIsSymlink("d1", "realDir", 1);
assertFileContents("d1/file1", 8, "d1/file1");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
@ -132,7 +132,7 @@ DEFINE_TEST(test_option_U_upper)
assertChdir("test7");
assertMakeDir("d1", 0755);
assertMakeFile("d1/realfile1", 0644, "realfile1");
assertMakeSymlink("d1/file1", "d1/realfile1");
assertMakeSymlink("d1/file1", "d1/realfile1", 0);
assertEqualInt(0,
systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
assertIsReg("d1/file1", umasked(0644));
@ -147,7 +147,7 @@ DEFINE_TEST(test_option_U_upper)
assertChdir("test8");
assertMakeDir("d1", 0755);
assertMakeFile("d1/realfile1", 0644, "realfile1");
assertMakeSymlink("d1/file1", "d1/realfile1");
assertMakeSymlink("d1/file1", "d1/realfile1", 0);
assertEqualInt(0,
systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
assertIsReg("d1/file1", umasked(0644));

View file

@ -0,0 +1,230 @@
/*-
* Copyright (c) 2019 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$");
DEFINE_TEST(test_option_exclude_vcs)
{
assertMakeDir("in", 0755);
assertChdir("in");
assertMakeFile("file", 0644, "");
assertMakeDir("dir", 0755);
assertMakeDir("CVS", 0755);
assertMakeFile("CVS/fileattr", 0644, "");
assertMakeFile(".cvsignore", 0644, "");
assertMakeDir("RCS", 0755);
assertMakeFile("RCS/somefile", 0655, "");
assertMakeDir("SCCS", 0755);
assertMakeFile("SCCS/somefile", 0655, "");
assertMakeDir(".svn", 0755);
assertMakeFile(".svn/format", 0655, "");
assertMakeDir(".git", 0755);
assertMakeFile(".git/config", 0655, "");
assertMakeFile(".gitignore", 0644, "");
assertMakeFile(".gitattributes", 0644, "");
assertMakeFile(".gitmodules", 0644, "");
assertMakeDir(".arch-ids", 0755);
assertMakeFile(".arch-ids/somefile", 0644, "");
assertMakeDir("{arch}", 0755);
assertMakeFile("{arch}/somefile", 0644, "");
assertMakeFile("=RELEASE-ID", 0644, "");
assertMakeFile("=meta-update", 0644, "");
assertMakeFile("=update", 0644, "");
assertMakeDir(".bzr", 0755);
assertMakeDir(".bzr/checkout", 0755);
assertMakeFile(".bzrignore", 0644, "");
assertMakeFile(".bzrtags", 0644, "");
assertMakeDir(".hg", 0755);
assertMakeFile(".hg/dirstate", 0644, "");
assertMakeFile(".hgignore", 0644, "");
assertMakeFile(".hgtags", 0644, "");
assertMakeDir("_darcs", 0755);
assertMakeFile("_darcs/format", 0644, "");
assertChdir("..");
assertEqualInt(0, systemf("%s -c -C in -f included.tar .", testprog));
assertEqualInt(0,
systemf("%s -c --exclude-vcs -C in -f excluded.tar .", testprog));
/* No flags, archive with vcs files */
assertMakeDir("vcs-noexclude", 0755);
assertEqualInt(0, systemf("%s -x -C vcs-noexclude -f included.tar",
testprog));
assertChdir("vcs-noexclude");
assertFileExists("file");
assertIsDir("dir", 0755);
assertIsDir("CVS", 0755);
assertFileExists("CVS/fileattr");
assertFileExists(".cvsignore");
assertIsDir("RCS", 0755);
assertFileExists("RCS/somefile");
assertIsDir("SCCS", 0755);
assertFileExists("SCCS/somefile");
assertIsDir(".svn", 0755);
assertFileExists(".svn/format");
assertIsDir(".git", 0755);
assertFileExists(".git/config");
assertFileExists(".gitignore");
assertFileExists(".gitattributes");
assertFileExists(".gitmodules");
assertIsDir(".arch-ids", 0755);
assertFileExists(".arch-ids/somefile");
assertIsDir("{arch}", 0755);
assertFileExists("{arch}/somefile");
assertFileExists("=RELEASE-ID");
assertFileExists("=meta-update");
assertFileExists("=update");
assertIsDir(".bzr", 0755);
assertIsDir(".bzr/checkout", 0755);
assertFileExists(".bzrignore");
assertFileExists(".bzrtags");
assertIsDir(".hg", 0755);
assertFileExists(".hg/dirstate");
assertFileExists(".hgignore");
assertFileExists(".hgtags");
assertIsDir("_darcs", 0755);
assertFileExists("_darcs/format");
assertChdir("..");
/* --exclude-vcs, archive with vcs files */
assertMakeDir("vcs-exclude", 0755);
assertEqualInt(0,
systemf("%s -x --exclude-vcs -C vcs-exclude -f included.tar", testprog));
assertChdir("vcs-exclude");
assertFileExists("file");
assertIsDir("dir", 0755);
assertFileNotExists("CVS");
assertFileNotExists("CVS/fileattr");
assertFileNotExists(".cvsignore");
assertFileNotExists("RCS");
assertFileNotExists("RCS/somefile");
assertFileNotExists("SCCS");
assertFileNotExists("SCCS/somefile");
assertFileNotExists(".svn");
assertFileNotExists(".svn/format");
assertFileNotExists(".git");
assertFileNotExists(".git/config");
assertFileNotExists(".gitignore");
assertFileNotExists(".gitattributes");
assertFileNotExists(".gitmodules");
assertFileNotExists(".arch-ids");
assertFileNotExists(".arch-ids/somefile");
assertFileNotExists("{arch}");
assertFileNotExists("{arch}/somefile");
assertFileNotExists("=RELEASE-ID");
assertFileNotExists("=meta-update");
assertFileNotExists("=update");
assertFileNotExists(".bzr");
assertFileNotExists(".bzr/checkout");
assertFileNotExists(".bzrignore");
assertFileNotExists(".bzrtags");
assertFileNotExists(".hg");
assertFileNotExists(".hg/dirstate");
assertFileNotExists(".hgignore");
assertFileNotExists(".hgtags");
assertFileNotExists("_darcs");
assertFileNotExists("_darcs/format");
assertChdir("..");
/* --exclude-vcs, archive without vcs files */
assertMakeDir("novcs-exclude", 0755);
assertEqualInt(0,
systemf("%s -x --exclude-vcs -C novcs-exclude -f excluded.tar",
testprog));
assertChdir("novcs-exclude");
assertFileExists("file");
assertIsDir("dir", 0755);
assertFileNotExists("CVS");
assertFileNotExists("CVS/fileattr");
assertFileNotExists(".cvsignore");
assertFileNotExists("RCS");
assertFileNotExists("RCS/somefile");
assertFileNotExists("SCCS");
assertFileNotExists("SCCS/somefile");
assertFileNotExists(".svn");
assertFileNotExists(".svn/format");
assertFileNotExists(".git");
assertFileNotExists(".git/config");
assertFileNotExists(".gitignore");
assertFileNotExists(".gitattributes");
assertFileNotExists(".gitmodules");
assertFileNotExists(".arch-ids");
assertFileNotExists(".arch-ids/somefile");
assertFileNotExists("{arch}");
assertFileNotExists("{arch}/somefile");
assertFileNotExists("=RELEASE-ID");
assertFileNotExists("=meta-update");
assertFileNotExists("=update");
assertFileNotExists(".bzr");
assertFileNotExists(".bzr/checkout");
assertFileNotExists(".bzrignore");
assertFileNotExists(".bzrtags");
assertFileNotExists(".hg");
assertFileNotExists(".hg/dirstate");
assertFileNotExists(".hgignore");
assertFileNotExists(".hgtags");
assertFileNotExists("_darcs");
assertFileNotExists("_darcs/format");
assertChdir("..");
/* No flags, archive without vcs files */
assertMakeDir("novcs-noexclude", 0755);
assertEqualInt(0,
systemf("%s -x -C novcs-noexclude -f excluded.tar", testprog));
assertChdir("novcs-noexclude");
assertFileExists("file");
assertIsDir("dir", 0755);
assertFileNotExists("CVS");
assertFileNotExists("CVS/fileattr");
assertFileNotExists(".cvsignore");
assertFileNotExists("RCS");
assertFileNotExists("RCS/somefile");
assertFileNotExists("SCCS");
assertFileNotExists("SCCS/somefile");
assertFileNotExists(".svn");
assertFileNotExists(".svn/format");
assertFileNotExists(".git");
assertFileNotExists(".git/config");
assertFileNotExists(".gitignore");
assertFileNotExists(".gitattributes");
assertFileNotExists(".gitmodules");
assertFileNotExists(".arch-ids");
assertFileNotExists(".arch-ids/somefile");
assertFileNotExists("{arch}");
assertFileNotExists("{arch}/somefile");
assertFileNotExists("=RELEASE-ID");
assertFileNotExists("=meta-update");
assertFileNotExists("=update");
assertFileNotExists(".bzr");
assertFileNotExists(".bzr/checkout");
assertFileNotExists(".bzrignore");
assertFileNotExists(".bzrtags");
assertFileNotExists(".hg");
assertFileNotExists(".hg/dirstate");
assertFileNotExists(".hgignore");
assertFileNotExists(".hgtags");
assertFileNotExists("_darcs");
assertFileNotExists("_darcs/format");
}

View file

@ -25,8 +25,14 @@
#include "test.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
DEFINE_TEST(test_option_n)
{
int status;
assertMakeDir("d1", 0755);
assertMakeFile("d1/file1", 0644, "d1/file1");
@ -58,4 +64,79 @@ DEFINE_TEST(test_option_n)
assertIsDir("d1", umasked(0755));
assertFileNotExists("d1/file1");
assertChdir("..");
/*
* Create a test archive with the following content:
* d1/
* d1/file1
* d1/file2
* file3
* d2/file4
*
* Extracting uses the same code as listing and thus does not
* get tested separately. This also covers the
* archive_match_set_inclusion_recursion()
* API.
*/
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeFile("file3", 0644, "file3");
assertMakeDir("d2", 0755);
assertMakeFile("d2/file4", 0644, "d2/file4");
assertEqualInt(0,
systemf("%s -cnf partial-archive.tar d1 d1/file1 d1/file2 file3 "
"d2/file4 >c.out 2>c.err", testprog));
/* Test 3: -t without other options */
assertEqualInt(0,
systemf("%s -tf partial-archive.tar >test3.out 2>test3.err",
testprog));
assertEmptyFile("test3.err");
assertTextFileContents("d1/\n"
"d1/file1\n"
"d1/file2\n"
"file3\n"
"d2/file4\n",
"test3.out");
/* Test 4: -t without -n and some entries selected */
assertEqualInt(0,
systemf("%s -tf partial-archive.tar d1 file3 d2/file4 "
">test4.out 2>test4.err", testprog));
assertEmptyFile("test4.err");
assertTextFileContents("d1/\n"
"d1/file1\n"
"d1/file2\n"
"file3\n"
"d2/file4\n",
"test4.out");
/* Test 5: -t with -n and some entries selected */
assertEqualInt(0,
systemf("%s -tnf partial-archive.tar d1 file3 d2/file4 "
">test5.out 2>test5.err", testprog));
assertEmptyFile("test5.err");
assertTextFileContents("d1/\n"
"file3\n"
"d2/file4\n",
"test5.out");
/* Test 6: -t without -n and non-existant directory selected */
assertEqualInt(0,
systemf("%s -tf partial-archive.tar d2 >test6.out 2>test6.err",
testprog));
assertEmptyFile("test6.err");
assertTextFileContents("d2/file4\n",
"test6.out");
/* Test 7: -t with -n and non-existant directory selected */
status = systemf("%s -tnf partial-archive.tar d2 "
">test7.out 2>test7.err", testprog);
assert(status);
assert(status != -1);
#if !defined(_WIN32) || defined(__CYGWIN__)
assert(WIFEXITED(status));
assertEqualInt(1, WEXITSTATUS(status));
#endif
assertNonEmptyFile("test7.err");
assertEmptyFile("test7.out");
}

View file

@ -36,7 +36,7 @@ DEFINE_TEST(test_option_s)
assertMakeFile("in/d1/bar", 0644, "bar");
if (canSymlink()) {
assertMakeFile("in/d1/realfile", 0644, "realfile");
assertMakeSymlink("in/d1/symlink", "realfile");
assertMakeSymlink("in/d1/symlink", "realfile", 0);
}
assertMakeFile("in/d1/hardlink1", 0644, "hardlinkedfile");
assertMakeHardlink("in/d1/hardlink2", "in/d1/hardlink1");
@ -109,14 +109,14 @@ DEFINE_TEST(test_option_s)
testprog, testprog);
assertFileContents("realfile", 8, "test6a/in/d2/realfile");
assertFileContents("realfile", 8, "test6a/in/d2/symlink");
assertIsSymlink("test6a/in/d2/symlink", "realfile");
assertIsSymlink("test6a/in/d2/symlink", "realfile", 0);
/* At creation time. */
assertMakeDir("test6b", 0755);
systemf("%s -cf - -s /d1/d2/ in/d1 | %s -xf - -C test6b",
testprog, testprog);
assertFileContents("realfile", 8, "test6b/in/d2/realfile");
assertFileContents("realfile", 8, "test6b/in/d2/symlink");
assertIsSymlink("test6b/in/d2/symlink", "realfile");
assertIsSymlink("test6b/in/d2/symlink", "realfile", 0);
}
/*
@ -129,14 +129,14 @@ DEFINE_TEST(test_option_s)
testprog, testprog);
assertFileContents("realfile", 8, "test7a/in/d1/realfile-renamed");
assertFileContents("realfile", 8, "test7a/in/d1/symlink");
assertIsSymlink("test7a/in/d1/symlink", "realfile-renamed");
assertIsSymlink("test7a/in/d1/symlink", "realfile-renamed", 0);
/* At creation. */
assertMakeDir("test7b", 0755);
systemf("%s -cf - -s /realfile/realfile-renamed/ in/d1 | %s -xf - -C test7b",
testprog, testprog);
assertFileContents("realfile", 8, "test7b/in/d1/realfile-renamed");
assertFileContents("realfile", 8, "test7b/in/d1/symlink");
assertIsSymlink("test7b/in/d1/symlink", "realfile-renamed");
assertIsSymlink("test7b/in/d1/symlink", "realfile-renamed", 0);
}
/*
@ -192,7 +192,7 @@ DEFINE_TEST(test_option_s)
assertFileContents("realfile", 8, "test10a/in/d1/foo");
assertFileContents("foo", 3, "test10a/in/d1/realfile");
assertFileContents("foo", 3, "test10a/in/d1/symlink");
assertIsSymlink("test10a/in/d1/symlink", "realfile");
assertIsSymlink("test10a/in/d1/symlink", "realfile", 0);
/* At creation. */
assertMakeDir("test10b", 0755);
systemf("%s -cf - -s /realfile/foo/S -s /foo/realfile/ in/d1 | %s -xf - -C test10b",
@ -200,7 +200,7 @@ DEFINE_TEST(test_option_s)
assertFileContents("realfile", 8, "test10b/in/d1/foo");
assertFileContents("foo", 3, "test10b/in/d1/realfile");
assertFileContents("foo", 3, "test10b/in/d1/symlink");
assertIsSymlink("test10b/in/d1/symlink", "realfile");
assertIsSymlink("test10b/in/d1/symlink", "realfile", 0);
}
/*
@ -214,7 +214,7 @@ DEFINE_TEST(test_option_s)
assertFileContents("foo", 3, "test11a/in/d1/foo");
assertFileContents("realfile", 8, "test11a/in/d1/realfile");
assertFileContents("foo", 3, "test11a/in/d1/symlink");
assertIsSymlink("test11a/in/d1/symlink", "foo");
assertIsSymlink("test11a/in/d1/symlink", "foo", 0);
/* At creation. */
assertMakeDir("test11b", 0755);
systemf("%s -cf - -s /realfile/foo/R in/d1 | %s -xf - -C test11b",
@ -222,7 +222,7 @@ DEFINE_TEST(test_option_s)
assertFileContents("foo", 3, "test11b/in/d1/foo");
assertFileContents("realfile", 8, "test11b/in/d1/realfile");
assertFileContents("foo", 3, "test11b/in/d1/symlink");
assertIsSymlink("test11b/in/d1/symlink", "foo");
assertIsSymlink("test11b/in/d1/symlink", "foo", 0);
}
/*

View file

@ -36,8 +36,8 @@ DEFINE_TEST(test_strip_components)
assertMakeHardlink("l1", "d1/d2/f1");
assertMakeHardlink("d1/l2", "d1/d2/f1");
if (canSymlink()) {
assertMakeSymlink("s1", "d1/d2/f1");
assertMakeSymlink("d1/s2", "d2/f1");
assertMakeSymlink("s1", "d1/d2/f1", 0);
assertMakeSymlink("d1/s2", "d2/f1", 0);
}
assertChdir("..");
@ -64,9 +64,10 @@ DEFINE_TEST(test_strip_components)
failure("d0/d1/s2 is a symlink to something that won't be extracted");
/* If platform supports symlinks, target/s2 is a broken symlink. */
/* If platform does not support symlink, target/s2 doesn't exist. */
assertFileNotExists("target/s2");
if (canSymlink())
assertIsSymlink("target/s2", "d2/f1");
assertIsSymlink("target/s2", "d2/f1", 0);
else
assertFileNotExists("target/s2");
failure("d0/d1/d2 should be extracted");
assertIsDir("target/d2", -1);
@ -122,7 +123,7 @@ DEFINE_TEST(test_strip_components)
/* If platform supports symlinks, target/s2 is included. */
if (canSymlink()) {
failure("d0/d1/s2 is a symlink to something included in archive");
assertIsSymlink("target2/s2", "d2/f1");
assertIsSymlink("target2/s2", "d2/f1", 0);
}
failure("d0/d1/d2 should be archived");
assertIsDir("target2/d2", -1);

View file

@ -66,22 +66,22 @@ DEFINE_TEST(test_symlink_dir)
/* "dir" is a symlink to an existing "dest1/real_dir" */
assertMakeDir("dest1/real_dir", 0755);
if (canSymlink()) {
assertMakeSymlink("dest1/dir", "real_dir");
assertMakeSymlink("dest1/dir", "real_dir", 1);
/* "dir2" is a symlink to a non-existing "real_dir2" */
assertMakeSymlink("dest1/dir2", "real_dir2");
assertMakeSymlink("dest1/dir2", "real_dir2", 1);
} else {
skipping("Symlinks are not supported on this platform");
}
/* "dir3" is a symlink to an existing "non_dir3" */
assertMakeFile("dest1/non_dir3", 0755, "abcdef");
if (canSymlink())
assertMakeSymlink("dest1/dir3", "non_dir3");
assertMakeSymlink("dest1/dir3", "non_dir3", 1);
/* "file" is a symlink to existing "real_file" */
assertMakeFile("dest1/real_file", 0755, "abcdefg");
if (canSymlink()) {
assertMakeSymlink("dest1/file", "real_file");
assertMakeSymlink("dest1/file", "real_file", 0);
/* "file2" is a symlink to non-existing "real_file2" */
assertMakeSymlink("dest1/file2", "real_file2");
assertMakeSymlink("dest1/file2", "real_file2", 0);
}
assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog));
@ -108,32 +108,32 @@ DEFINE_TEST(test_symlink_dir)
/* "dir" is a symlink to existing "real_dir" */
assertMakeDir("dest2/real_dir", 0755);
if (canSymlink())
assertMakeSymlink("dest2/dir", "real_dir");
assertMakeSymlink("dest2/dir", "real_dir", 1);
/* "dir2" is a symlink to a non-existing "real_dir2" */
if (canSymlink())
assertMakeSymlink("dest2/dir2", "real_dir2");
assertMakeSymlink("dest2/dir2", "real_dir2", 1);
/* "dir3" is a symlink to an existing "non_dir3" */
assertMakeFile("dest2/non_dir3", 0755, "abcdefgh");
if (canSymlink())
assertMakeSymlink("dest2/dir3", "non_dir3");
assertMakeSymlink("dest2/dir3", "non_dir3", 1);
/* "file" is a symlink to existing "real_file" */
assertMakeFile("dest2/real_file", 0755, "abcdefghi");
if (canSymlink())
assertMakeSymlink("dest2/file", "real_file");
assertMakeSymlink("dest2/file", "real_file", 0);
/* "file2" is a symlink to non-existing "real_file2" */
if (canSymlink())
assertMakeSymlink("dest2/file2", "real_file2");
assertMakeSymlink("dest2/file2", "real_file2", 0);
assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
/* "dir4" is a symlink to existing "real_dir" */
if (canSymlink())
assertMakeSymlink("dest2/dir4", "real_dir");
assertMakeSymlink("dest2/dir4", "real_dir", 1);
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");
assertIsSymlink("dest2/dir", "real_dir", 1);
assertIsSymlink("dest2/dir4", "real_dir", 1);
assertIsDir("dest2/real_dir", -1);
}

View file

@ -83,7 +83,9 @@
#include <sys/richacl.h>
#endif
#ifdef HAVE_WINDOWS_H
#define NOCRYPT
#include <windows.h>
#include <winioctl.h>
#endif
/*
@ -218,8 +220,8 @@
assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
#define assertIsSymlink(pathname, contents) \
assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
#define assertIsSymlink(pathname, contents, isdir) \
assertion_is_symlink(__FILE__, __LINE__, pathname, contents, isdir)
/* Create a directory, report error if it fails. */
#define assertMakeDir(dirname, mode) \
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
@ -229,8 +231,8 @@
assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
#define assertMakeHardlink(newfile, oldfile) \
assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
#define assertMakeSymlink(newfile, linkto) \
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
#define assertMakeSymlink(newfile, linkto, targetIsDir) \
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto, targetIsDir)
#define assertSetNodump(path) \
assertion_set_nodump(__FILE__, __LINE__, path)
#define assertUmask(mask) \
@ -287,11 +289,11 @@ int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
int assertion_is_not_hardlink(const char *, int, const char *, const char *);
int assertion_is_reg(const char *, int, const char *, int);
int assertion_is_symlink(const char *, int, const char *, const char *);
int assertion_is_symlink(const char *, int, const char *, const char *, int);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, int, const void *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *, int);
int assertion_non_empty_file(const char *, int, const char *);
int assertion_set_nodump(const char *, int, const char *);
int assertion_text_file_contents(const char *, int, const char *buff, const char *f);

View file

@ -168,6 +168,32 @@ static int my_CreateHardLinkA(const char *, const char *);
static int my_GetFileInformationByName(const char *,
BY_HANDLE_FILE_INFORMATION *);
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
static void *
GetFunctionKernel32(const char *name)
{
@ -185,15 +211,101 @@ GetFunctionKernel32(const char *name)
}
static int
my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
my_CreateSymbolicLinkA(const char *linkname, const char *target,
int targetIsDir)
{
static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
DWORD attrs;
static int set;
int ret, tmpflags, llen, tlen;
int flags = 0;
char *src, *tgt, *p;
if (!set) {
set = 1;
f = GetFunctionKernel32("CreateSymbolicLinkA");
}
return f == NULL ? 0 : (*f)(linkname, target, flags);
if (f == NULL)
return (0);
tlen = strlen(target);
llen = strlen(linkname);
if (tlen == 0 || llen == 0)
return (0);
tgt = malloc((tlen + 1) * sizeof(char));
if (tgt == NULL)
return (0);
src = malloc((llen + 1) * sizeof(char));
if (src == NULL) {
free(tgt);
return (0);
}
/*
* Translate slashes to backslashes
*/
p = src;
while(*linkname != '\0') {
if (*linkname == '/')
*p = '\\';
else
*p = *linkname;
linkname++;
p++;
}
*p = '\0';
p = tgt;
while(*target != '\0') {
if (*target == '/')
*p = '\\';
else
*p = *target;
target++;
p++;
}
*p = '\0';
/*
* Each test has to specify if a file or a directory symlink
* should be created.
*/
if (targetIsDir) {
#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
#else
flags |= 0x1;
#endif
}
#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
tmpflags = flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
#else
tmpflags = flags | 0x2;
#endif
/*
* Windows won't overwrite existing links
*/
attrs = GetFileAttributesA(linkname);
if (attrs != INVALID_FILE_ATTRIBUTES) {
if (attrs & FILE_ATTRIBUTE_DIRECTORY)
RemoveDirectoryA(linkname);
else
DeleteFileA(linkname);
}
ret = (*f)(src, tgt, tmpflags);
/*
* Prior to Windows 10 the SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
* is not undestood
*/
if (!ret)
ret = (*f)(src, tgt, flags);
free(src);
free(tgt);
return (ret);
}
static int
@ -1599,26 +1711,146 @@ assertion_is_reg(const char *file, int line, const char *pathname, int mode)
return (1);
}
/* Check whether 'pathname' is a symbolic link. If 'contents' is
* non-NULL, verify that the symlink has those contents. */
/*
* Check whether 'pathname' is a symbolic link. If 'contents' is
* non-NULL, verify that the symlink has those contents.
*
* On platforms with directory symlinks, set isdir to 0 to test for a file
* symlink and to 1 to test for a directory symlink. On other platforms
* the variable is ignored.
*/
static int
is_symlink(const char *file, int line,
const char *pathname, const char *contents)
const char *pathname, const char *contents, int isdir)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)pathname; /* UNUSED */
(void)contents; /* UNUSED */
assertion_count(file, line);
/* Windows sort-of has real symlinks, but they're only usable
* by privileged users and are crippled even then, so there's
* really not much point in bothering with this. */
return (0);
HANDLE h;
DWORD inbytes;
REPARSE_DATA_BUFFER *buf;
BY_HANDLE_FILE_INFORMATION st;
size_t len, len2;
wchar_t *linknamew, *contentsw;
const char *p;
char *s, *pn;
int ret = 0;
BYTE *indata;
const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OPEN_REPARSE_POINT;
/* Replace slashes with backslashes in pathname */
pn = malloc((strlen(pathname) + 1) * sizeof(char));
p = pathname;
s = pn;
while(*p != '\0') {
if(*p == '/')
*s = '\\';
else
*s = *p;
p++;
s++;
}
*s = '\0';
h = CreateFileA(pn, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
flag, NULL);
free(pn);
if (h == INVALID_HANDLE_VALUE) {
failure_start(file, line, "Can't access %s\n", pathname);
failure_finish(NULL);
return (0);
}
ret = GetFileInformationByHandle(h, &st);
if (ret == 0) {
failure_start(file, line,
"Can't stat: %s", pathname);
failure_finish(NULL);
} else if ((st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
failure_start(file, line,
"Not a symlink: %s", pathname);
failure_finish(NULL);
ret = 0;
}
if (isdir && ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
failure_start(file, line,
"Not a directory symlink: %s", pathname);
failure_finish(NULL);
ret = 0;
}
if (!isdir &&
((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
failure_start(file, line,
"Not a file symlink: %s", pathname);
failure_finish(NULL);
ret = 0;
}
if (ret == 0) {
CloseHandle(h);
return (0);
}
indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
1024, &inbytes, NULL);
CloseHandle(h);
if (ret == 0) {
free(indata);
failure_start(file, line,
"Could not retrieve symlink target: %s", pathname);
failure_finish(NULL);
return (0);
}
buf = (REPARSE_DATA_BUFFER *) indata;
if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
free(indata);
/* File is not a symbolic link */
failure_start(file, line,
"Not a symlink: %s", pathname);
failure_finish(NULL);
return (0);
}
if (contents == NULL) {
free(indata);
return (1);
}
len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
linknamew = malloc(len + sizeof(wchar_t));
if (linknamew == NULL) {
free(indata);
return (0);
}
memcpy(linknamew, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer)
[buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len);
free(indata);
linknamew[len / sizeof(wchar_t)] = L'\0';
contentsw = malloc(len + sizeof(wchar_t));
if (contentsw == NULL) {
free(linknamew);
return (0);
}
len2 = mbsrtowcs(contentsw, &contents, (len + sizeof(wchar_t)
/ sizeof(wchar_t)), NULL);
if (len2 > 0 && wcscmp(linknamew, contentsw) != 0)
ret = 1;
free(linknamew);
free(contentsw);
return (ret);
#else
char buff[300];
struct stat st;
ssize_t linklen;
int r;
(void)isdir; /* UNUSED */
assertion_count(file, line);
r = lstat(pathname, &st);
if (r != 0) {
@ -1647,9 +1879,9 @@ is_symlink(const char *file, int line,
/* Assert that path is a symlink that (optionally) contains contents. */
int
assertion_is_symlink(const char *file, int line,
const char *path, const char *contents)
const char *path, const char *contents, int isdir)
{
if (is_symlink(file, line, path, contents))
if (is_symlink(file, line, path, contents, isdir))
return (1);
if (contents)
failure_start(file, line, "File %s is not a symlink to %s",
@ -1777,20 +2009,26 @@ assertion_make_hardlink(const char *file, int line,
return(0);
}
/* Create a symlink and report any failures. */
/*
* Create a symlink and report any failures.
*
* Windows symlinks need to know if the target is a directory.
*/
int
assertion_make_symlink(const char *file, int line,
const char *newpath, const char *linkto)
const char *newpath, const char *linkto, int targetIsDir)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
int targetIsDir = 0; /* TODO: Fix this */
assertion_count(file, line);
if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
return (1);
#elif HAVE_SYMLINK
(void)targetIsDir; /* UNUSED */
assertion_count(file, line);
if (0 == symlink(linkto, newpath))
return (1);
#else
(void)targetIsDir; /* UNUSED */
#endif
failure_start(file, line, "Could not create symlink");
logprintf(" New link: %s\n", newpath);
@ -2217,10 +2455,12 @@ canSymlink(void)
* use the Win32 CreateSymbolicLink() function. */
#if defined(_WIN32) && !defined(__CYGWIN__)
value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
&& is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
&& is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0",
0);
#elif HAVE_SYMLINK
value = (0 == symlink("canSymlink.0", "canSymlink.1"))
&& is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
&& is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0",
0);
#endif
return (value);
}

View file

@ -168,6 +168,7 @@ SRCS= archive_acl.c \
MAN= archive_entry.3 \
archive_entry_acl.3 \
archive_entry_linkify.3 \
archive_entry_misc.3 \
archive_entry_paths.3 \
archive_entry_perms.3 \
archive_entry_stat.3 \

View file

@ -169,6 +169,7 @@ TESTS_SRCS= \
test_read_format_tar_concatenated.c \
test_read_format_tar_empty_filename.c \
test_read_format_tar_empty_pax.c \
test_read_format_tar_empty_with_gnulabel.c \
test_read_format_tar_filename.c \
test_read_format_tbz.c \
test_read_format_tgz.c \
@ -179,10 +180,12 @@ TESTS_SRCS= \
test_read_format_warc.c \
test_read_format_xar.c \
test_read_format_zip.c \
test_read_format_zip_7075_utf8_paths.c \
test_read_format_zip_comment_stored.c \
test_read_format_zip_encryption_data.c \
test_read_format_zip_encryption_header.c \
test_read_format_zip_encryption_partially.c \
test_read_format_zip_extra_padding.c \
test_read_format_zip_filename.c \
test_read_format_zip_high_compression.c \
test_read_format_zip_jar.c \
@ -486,6 +489,7 @@ ${PACKAGE}FILES+= test_read_format_mtree_crash747.mtree.bz2.uu
${PACKAGE}FILES+= test_read_format_mtree_nomagic.mtree.uu
${PACKAGE}FILES+= test_read_format_mtree_nomagic2.mtree.uu
${PACKAGE}FILES+= test_read_format_mtree_nomagic3.mtree.uu
${PACKAGE}FILES+= test_read_format_mtree_noprint.mtree.uu
${PACKAGE}FILES+= test_read_format_rar.rar.uu
${PACKAGE}FILES+= test_read_format_rar_binary_data.rar.uu
${PACKAGE}FILES+= test_read_format_rar_compress_best.rar.uu
@ -501,6 +505,7 @@ ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0003.rar.uu
${PACKAGE}FILES+= test_read_format_rar_multivolume.part0004.rar.uu
${PACKAGE}FILES+= test_read_format_rar_noeof.rar.uu
${PACKAGE}FILES+= test_read_format_rar_ppmd_lzss_conversion.rar.uu
${PACKAGE}FILES+= test_read_format_rar_ppmd_use_after_free.rar.uu
${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
@ -508,6 +513,13 @@ ${PACKAGE}FILES+= test_read_format_rar_windows.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_arm.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_blake2.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_compressed.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_fileattr.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_hardlink.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_invalid_dict_reference.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_leftshift1.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_leftshift2.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiarchive.part01.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiarchive.part02.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiarchive.part03.rar.uu
@ -522,15 +534,22 @@ ${PACKAGE}FILES+= test_read_format_rar5_multiarchive_solid.part03.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiarchive_solid.part04.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiple_files.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiple_files_solid.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_nonempty_dir_stream.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_owner.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_readtables_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_solid.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_stored.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_stored_manyfiles.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_symlink.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_truncated_huff.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_win32.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.gz.uu
${PACKAGE}FILES+= test_read_format_raw.data.uu
${PACKAGE}FILES+= test_read_format_tar_concatenated.tar.uu
${PACKAGE}FILES+= test_read_format_tar_empty_filename.tar.uu
${PACKAGE}FILES+= test_read_format_tar_empty_with_gnulabel.tar.uu
${PACKAGE}FILES+= test_read_format_tar_empty_pax.tar.Z.uu
${PACKAGE}FILES+= test_read_format_tar_filename_koi8r.tar.Z.uu
${PACKAGE}FILES+= test_read_format_ustar_filename_cp866.tar.Z.uu
@ -546,6 +565,7 @@ ${PACKAGE}FILES+= test_read_format_zip_comment_stored_2.zip.uu
${PACKAGE}FILES+= test_read_format_zip_encryption_data.zip.uu
${PACKAGE}FILES+= test_read_format_zip_encryption_header.zip.uu
${PACKAGE}FILES+= test_read_format_zip_encryption_partially.zip.uu
${PACKAGE}FILES+= test_read_format_zip_extra_padding.zip.uu
${PACKAGE}FILES+= test_read_format_zip_filename_cp866.zip.uu
${PACKAGE}FILES+= test_read_format_zip_filename_cp932.zip.uu
${PACKAGE}FILES+= test_read_format_zip_filename_koi8r.zip.uu
@ -555,6 +575,8 @@ ${PACKAGE}FILES+= test_read_format_zip_filename_utf8_ru2.zip.uu
${PACKAGE}FILES+= test_read_format_zip_high_compression.zip.uu
${PACKAGE}FILES+= test_read_format_zip_jar.jar.uu
${PACKAGE}FILES+= test_read_format_zip_length_at_end.zip.uu
${PACKAGE}FILES+= test_read_format_zip_lzma_alone_leak.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_lzma_multi.zipx.uu
${PACKAGE}FILES+= test_read_format_zip_mac_metadata.zip.uu

View file

@ -53,6 +53,7 @@ TESTS_SRCS= \
test_option_b.c \
test_option_b64encode.c \
test_option_exclude.c \
test_option_exclude_vcs.c \
test_option_fflags.c \
test_option_gid_gname.c \
test_option_grzip.c \