MFV r299425:

Update libarchive to 3.2.0

New features:
- new bsdcat command-line utility
- LZ4 compression (in src only via external utility from ports)
- Warc format support
- 'Raw' format writer
- Zip: Support archives >4GB, entries >4GB
- Zip: Support encrypting and decrypting entries
- Zip: Support experimental streaming extension
- Identify encrypted entries in several formats
- New --clear-nochange-flags option to bsdtar tries to remove noschg and
  similar flags before deleting files
- New --ignore-zeros option to bsdtar to handle concatenated tar archives
- Use multi-threaded LZMA decompression if liblzma supports it
- Expose version info for libraries used by libarchive

Patched files (fixed compiler warnings):

contrib/libarchive/cat/bsdcat.c (vendor PR #702)
contrib/libarchive/cat/bsdcat.h (vendor PR #702)
contrib/libarchive/libarchive/archive_read_support_format_mtree.c (PR #701)
contrib/libarchive/libarchive_fe/err.c (vendor PR #703)

MFC after:	1 month
Relnotes:	yes
This commit is contained in:
Martin Matuska 2016-05-12 10:16:16 +00:00
commit cdf63a700c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=299529
401 changed files with 61548 additions and 4703 deletions

View File

@ -17,12 +17,11 @@ the actual statements in the files are controlling.
files for details:
libarchive/archive_entry.c
libarchive/archive_read_support_filter_compress.c
libarchive/archive_write_set_filter_compress.c
libarchive/archive_write_add_filter_compress.c
libarchive/mtree.5
tar/matching.c
* The following source files are in the public domain:
tar/getdate.c
libarchive/archive_getdate.c
* The build files---including Makefiles, configure scripts,
and auxiliary scripts used as part of the compile process---have

View File

@ -1,11 +1,15 @@
.git
.gitattributes
.gitignore
.travis.yml
CMakeLists.txt
CONTRIBUTING.md
CTestConfig.cmake
INSTALL
Makefile.am
build
cat/CMakeLists.txt
cat/test/CMakeLists.txt
configure.ac
contrib
cpio/CMakeLists.txt

View File

@ -4,13 +4,14 @@ libarchive
The source code is pulled with git:
git clone -b release git://github.com/libarchive/libarchive.git
git clone git://github.com/libarchive/libarchive.git
For the contrib directory files and directories were pruned by:
sh -c 'for F in `cat FREEBSD-Xlist | grep -v FreeBSD`; do rm -rf ./$F ; done'
You may check if there are any new files that we don't need.
You may check if there are any new files that we don't need and add them to
FREEBSD-Xlist.
The instructions for importing new release and merging to HEAD can be found
at FreeBSD wiki:

View File

@ -1,3 +1,35 @@
Apr 09, 2016: libarchive 3.1.901a released
Another test release in preparation for 3.2.0
Feb 13, 2016: libarchive 3.1.900a released
This is a test release in preparation for 3.2.0
Oct 21, 2015: Preliminary port to OSF
Apr 11, 2015: libarchive's issue tracker is now hosted at GitHub.
https://github.com/libarchive/libarchive/issues
Early 2015: Many fixes to crash and overflow bugs thanks to Hanno Boeck
Oct 13, 2014: Zip encryption and decryption support
Aug 13, 2014: Add support for lz4 compression.
Jun 10, 2014: Add warc format support
May 3, 2014: Add experimental Zip streaming extension
Apr 6, 2014: Add bsdcat command-line tool
Jan 12, 2014: Add Zip64 support
Dec 1, 2013: Rewrite Zip write logic
Jul 1, 2013: Add ability to detect encrypted entries for many formats
(This does not add the ability to *decrypt* those entries, however)
Feb 23, 2013: "raw" write support added
Feb 09, 2013: libarchive 3.1.2 released
Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org.

View File

@ -5,7 +5,7 @@ Questions? Issues?
libarchive development, including documentation, and
links to the libarchive mailing lists.
* To report an issue, use the issue tracker at
http://code.google.com/p/libarchive/issues/list
https://github.com/libarchive/libarchive/issues
* To submit an enhancement to libarchive, please submit
a pull request via GitHub.
https://github.com/libarchive/libarchive/pulls
@ -13,9 +13,11 @@ Questions? Issues?
This distribution bundle includes the following components:
* libarchive: a library for reading and writing streaming archives
* tar: the 'bsdtar' program is a full-featured 'tar'
replacement built on libarchive
implementation built on libarchive
* cpio: the 'bsdcpio' program is a different interface to
essentially the same functionality
* cat: the 'bsdcat' program is a simple replacement tool for
zcat, bzcat, xzcat, and such
* examples: Some small example programs that you may find useful.
* examples/minitar: a compact sample demonstrating use of libarchive.
* contrib: Various items sent to me by third parties;
@ -39,6 +41,7 @@ The following files in the top-level directory are used by the
Guide to Documentation installed by this system:
* bsdtar.1 explains the use of the bsdtar program
* bsdcpio.1 explains the use of the bsdcpio program
* bsdcat.1 explains the use of the bsdcat program
* libarchive.3 gives an overview of the library as a whole
* archive_read.3, archive_write.3, archive_write_disk.3, and
archive_read_disk.3 provide detailed calling sequences for the read
@ -84,6 +87,8 @@ The library also detects and handles any of the following before evaluating the
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
The library can create archives in any of the following formats:
* POSIX ustar
@ -91,6 +96,7 @@ The library can create archives in any of the following formats:
* "restricted" pax format, which will create ustar archives except for
entries that require pax extensions (for long filenames, ACLs, etc).
* Old GNU tar format
* Old V7 tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* shar archives
@ -107,6 +113,8 @@ When creating archives, the result can be filtered with any of the following:
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
Notes about the library architecture:
@ -123,12 +131,12 @@ Notes about the library architecture:
* I've attempted to minimize static link pollution. If you don't
explicitly invoke a particular feature (such as support for a
particular compression or format), it won't get pulled in.
In particular, if you don't explicitly enable a particular
compression or decompression support, you won't need to link
against the corresponding compression or decompression libraries.
This also reduces the size of statically-linked binaries in
environments where that matters.
particular compression or format), it won't get pulled in to
statically-linked programs. In particular, if you don't explicitly
enable a particular compression or decompression support, you won't
need to link against the corresponding compression or decompression
libraries. This also reduces the size of statically-linked
binaries in environments where that matters.
* On read, the library accepts whatever blocks you hand it.
Your read callback is free to pass the library a byte at a time

View File

@ -0,0 +1,62 @@
.\" Copyright (c) 2011-2014, Mike Kazantsev
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd March 1, 2014
.Dt BSDCAT 1
.Os
.Sh NAME
.Nm bsdcat
.Nd expand files to standard output
.Sh SYNOPSIS
.Nm
.Op options
.Op files
.Pp
.Sh DESCRIPTION
.Nm
expands files to standard output.
.Sh OPTIONS
.Nm
typically takes a filename as an argument or reads standard input when used in a
pipe. In both cases decompressed data it written to standard output.
.Sh EXAMPLES
.Pp
To decompress a file:
.Pp
.Dl bsdcat example.txt.gz > example.txt
.Pp
To decompress standard input in a pipe:
.Pp
.Dl cat example.txt.gz | bsdcat > example.txt
.Pp
Both examples achieve the same results - a decompressed file by redirecting
output.
.Sh SEE ALSO
.Xr uncompress 1 ,
.Xr zcat 1 ,
.Xr bzcat 1 ,
.Xr xzcat 1 ,
.Xr libarchive-formats 5 ,

View File

@ -0,0 +1,146 @@
/*-
* Copyright (c) 2011-2014, Mike Kazantsev
* 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 "bsdcat_platform.h"
__FBSDID("$FreeBSD$");
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "bsdcat.h"
#include "err.h"
#define BYTES_PER_BLOCK (20*512)
static struct archive *a;
static struct archive_entry *ae;
static const char *bsdcat_current_path;
static int exit_status = 0;
void
usage(FILE *stream, int eval)
{
const char *p;
p = lafe_getprogname();
fprintf(stream,
"Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p);
exit(eval);
}
static void
version(void)
{
printf("bsdcat %s - %s\n",
BSDCAT_VERSION_STRING,
archive_version_details());
exit(0);
}
void
bsdcat_next(void)
{
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_empty(a);
archive_read_support_format_raw(a);
}
void
bsdcat_print_error(void)
{
lafe_warnc(0, "%s: %s",
bsdcat_current_path, archive_error_string(a));
exit_status = 1;
}
void
bsdcat_read_to_stdout(const char* filename)
{
int r;
if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK)
!= ARCHIVE_OK)
bsdcat_print_error();
else if (r = archive_read_next_header(a, &ae),
r != ARCHIVE_OK && r != ARCHIVE_EOF)
bsdcat_print_error();
else if (r == ARCHIVE_EOF)
/* for empty payloads don't try and read data */
;
else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK)
bsdcat_print_error();
if (archive_read_free(a) != ARCHIVE_OK)
bsdcat_print_error();
}
int
main(int argc, char **argv)
{
struct bsdcat *bsdcat, bsdcat_storage;
int c;
bsdcat = &bsdcat_storage;
memset(bsdcat, 0, sizeof(*bsdcat));
lafe_setprogname(*argv, "bsdcat");
bsdcat->argv = argv;
bsdcat->argc = argc;
while ((c = bsdcat_getopt(bsdcat)) != -1) {
switch (c) {
case 'h':
usage(stdout, 0);
break;
case OPTION_VERSION:
version();
break;
default:
usage(stderr, 1);
}
}
bsdcat_next();
if (*bsdcat->argv == NULL) {
bsdcat_current_path = "<stdin>";
bsdcat_read_to_stdout(NULL);
} else
while (*bsdcat->argv) {
bsdcat_current_path = *bsdcat->argv++;
bsdcat_read_to_stdout(bsdcat_current_path);
bsdcat_next();
}
exit(exit_status);
}

View File

@ -0,0 +1,56 @@
/*-
* Copyright (c) 2014, Mike Kazantsev
* 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.
*/
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
#else
/* Not having a config.h of some sort is a serious problem. */
#include "config.h"
#endif
#include <archive.h>
#include <archive_entry.h>
struct bsdcat {
/* Option parser state */
int getopt_state;
char *getopt_word;
/* Miscellaneous state information */
int argc;
char **argv;
const char *argument;
};
enum {
OPTION_VERSION
};
int bsdcat_getopt(struct bsdcat *);
void usage(FILE *stream, int eval);
void bsdcat_next(void);
void bsdcat_print_error(void);
void bsdcat_read_to_stdout(const char* filename);

View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* This header is the first thing included in any of the bsdtar
* source files. As far as possible, platform-specific issues should
* be dealt with here and not within individual source files.
*/
#ifndef BSDCAT_PLATFORM_H_INCLUDED
#define BSDCAT_PLATFORM_H_INCLUDED
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
#else
/* Not having a config.h of some sort is a serious problem. */
#include "config.h"
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifdef HAVE_LIBARCHIVE
/* If we're using the platform libarchive, include system headers. */
#include <archive.h>
#include <archive_entry.h>
#else
/* Otherwise, include user headers. */
#include "archive.h"
#include "archive_entry.h"
#endif
/* How to mark functions that don't return. */
/* This facilitates use of some newer static code analysis tools. */
#undef __LA_DEAD
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
#define __LA_DEAD __attribute__((__noreturn__))
#else
#define __LA_DEAD
#endif
#endif /* !BSDCAT_PLATFORM_H_INCLUDED */

View File

@ -0,0 +1,283 @@
/*-
* Copyright (c) 2003-2008 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.
*/
/*
* Command line parser for tar.
*/
#include "bsdcat_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "bsdcat.h"
#include "err.h"
/*
* Short options for tar. Please keep this sorted.
*/
static const char *short_options = "h";
/*
* Long options for tar. Please keep this list sorted.
*
* The symbolic names for options that lack a short equivalent are
* defined in bsdcat.h. Also note that so far I've found no need
* to support optional arguments to long options. That would be
* a small change to the code below.
*/
static const struct bsdcat_option {
const char *name;
int required; /* 1 if this option requires an argument. */
int equivalent; /* Equivalent short option. */
} tar_longopts[] = {
{ "help", 0, 'h' },
{ "version", 0, OPTION_VERSION },
{ NULL, 0, 0 }
};
/*
* This getopt implementation has two key features that common
* getopt_long() implementations lack. Apart from those, it's a
* straightforward option parser, considerably simplified by not
* needing to support the wealth of exotic getopt_long() features. It
* has, of course, been shamelessly tailored for bsdcat. (If you're
* looking for a generic getopt_long() implementation for your
* project, I recommend Gregory Pietsch's public domain getopt_long()
* implementation.) The two additional features are:
*
* Old-style tar arguments: The original tar implementation treated
* the first argument word as a list of single-character option
* letters. All arguments follow as separate words. For example,
* tar xbf 32 /dev/tape
* Here, the "xbf" is three option letters, "32" is the argument for
* "b" and "/dev/tape" is the argument for "f". We support this usage
* if the first command-line argument does not begin with '-'. We
* also allow regular short and long options to follow, e.g.,
* tar xbf 32 /dev/tape -P --format=pax
*
* -W long options: There's an obscure GNU convention (only rarely
* supported even there) that allows "-W option=argument" as an
* alternative way to support long options. This was supported in
* early bsdcat as a way to access long options on platforms that did
* not support getopt_long() and is preserved here for backwards
* compatibility. (Of course, if I'd started with a custom
* command-line parser from the beginning, I would have had normal
* long option support on every platform so that hack wouldn't have
* been necessary. Oh, well. Some mistakes you just have to live
* with.)
*
* TODO: We should be able to use this to pull files and intermingled
* options (such as -C) from the command line in write mode. That
* will require a little rethinking of the argument handling in
* bsdcat.c.
*
* TODO: If we want to support arbitrary command-line options from -T
* input (as GNU tar does), we may need to extend this to handle option
* words from sources other than argv/argc. I'm not really sure if I
* like that feature of GNU tar, so it's certainly not a priority.
*/
int
bsdcat_getopt(struct bsdcat *bsdcat)
{
enum { state_start = 0, state_old_tar, state_next_word,
state_short, state_long };
const struct bsdcat_option *popt, *match = NULL, *match2 = NULL;
const char *p, *long_prefix = "--";
size_t optlength;
int opt = '?';
int required = 0;
bsdcat->argument = NULL;
/* First time through, initialize everything. */
if (bsdcat->getopt_state == state_start) {
/* Skip program name. */
++bsdcat->argv;
--bsdcat->argc;
if (*bsdcat->argv == NULL)
return (-1);
/* Decide between "new style" and "old style" arguments. */
bsdcat->getopt_state = state_next_word;
}
/*
* We're ready to look at the next word in argv.
*/
if (bsdcat->getopt_state == state_next_word) {
/* No more arguments, so no more options. */
if (bsdcat->argv[0] == NULL)
return (-1);
/* Doesn't start with '-', so no more options. */
if (bsdcat->argv[0][0] != '-')
return (-1);
/* "--" marks end of options; consume it and return. */
if (strcmp(bsdcat->argv[0], "--") == 0) {
++bsdcat->argv;
--bsdcat->argc;
return (-1);
}
/* Get next word for parsing. */
bsdcat->getopt_word = *bsdcat->argv++;
--bsdcat->argc;
if (bsdcat->getopt_word[1] == '-') {
/* Set up long option parser. */
bsdcat->getopt_state = state_long;
bsdcat->getopt_word += 2; /* Skip leading '--' */
} else {
/* Set up short option parser. */
bsdcat->getopt_state = state_short;
++bsdcat->getopt_word; /* Skip leading '-' */
}
}
/*
* We're parsing a group of POSIX-style single-character options.
*/
if (bsdcat->getopt_state == state_short) {
/* Peel next option off of a group of short options. */
opt = *bsdcat->getopt_word++;
if (opt == '\0') {
/* End of this group; recurse to get next option. */
bsdcat->getopt_state = state_next_word;
return bsdcat_getopt(bsdcat);
}
/* Does this option take an argument? */
p = strchr(short_options, opt);
if (p == NULL)
return ('?');
if (p[1] == ':')
required = 1;
/* If it takes an argument, parse that. */
if (required) {
/* If arg is run-in, bsdcat->getopt_word already points to it. */
if (bsdcat->getopt_word[0] == '\0') {
/* Otherwise, pick up the next word. */
bsdcat->getopt_word = *bsdcat->argv;
if (bsdcat->getopt_word == NULL) {
lafe_warnc(0,
"Option -%c requires an argument",
opt);
return ('?');
}
++bsdcat->argv;
--bsdcat->argc;
}
if (opt == 'W') {
bsdcat->getopt_state = state_long;
long_prefix = "-W "; /* For clearer errors. */
} else {
bsdcat->getopt_state = state_next_word;
bsdcat->argument = bsdcat->getopt_word;
}
}
}
/* We're reading a long option, including -W long=arg convention. */
if (bsdcat->getopt_state == state_long) {
/* After this long option, we'll be starting a new word. */
bsdcat->getopt_state = state_next_word;
/* Option name ends at '=' if there is one. */
p = strchr(bsdcat->getopt_word, '=');
if (p != NULL) {
optlength = (size_t)(p - bsdcat->getopt_word);
bsdcat->argument = (char *)(uintptr_t)(p + 1);
} else {
optlength = strlen(bsdcat->getopt_word);
}
/* Search the table for an unambiguous match. */
for (popt = tar_longopts; popt->name != NULL; popt++) {
/* Short-circuit if first chars don't match. */
if (popt->name[0] != bsdcat->getopt_word[0])
continue;
/* If option is a prefix of name in table, record it.*/
if (strncmp(bsdcat->getopt_word, popt->name, optlength) == 0) {
match2 = match; /* Record up to two matches. */
match = popt;
/* If it's an exact match, we're done. */
if (strlen(popt->name) == optlength) {
match2 = NULL; /* Forget the others. */
break;
}
}
}
/* Fail if there wasn't a unique match. */
if (match == NULL) {
lafe_warnc(0,
"Option %s%s is not supported",
long_prefix, bsdcat->getopt_word);
return ('?');
}
if (match2 != NULL) {
lafe_warnc(0,
"Ambiguous option %s%s (matches --%s and --%s)",
long_prefix, bsdcat->getopt_word, match->name, match2->name);
return ('?');
}
/* We've found a unique match; does it need an argument? */
if (match->required) {
/* Argument required: get next word if necessary. */
if (bsdcat->argument == NULL) {
bsdcat->argument = *bsdcat->argv;
if (bsdcat->argument == NULL) {
lafe_warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
return ('?');
}
++bsdcat->argv;
--bsdcat->argc;
}
} else {
/* Argument forbidden: fail if there is one. */
if (bsdcat->argument != NULL) {
lafe_warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
return ('?');
}
}
return (match->equivalent);
}
return (opt);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,344 @@
/*
* Copyright (c) 2003-2006 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/* Every test program should #include "test.h" as the first thing. */
/*
* The goal of this file (and the matching test.c) is to
* simplify the very repetitive test-*.c test programs.
*/
#if defined(HAVE_CONFIG_H)
/* Most POSIX platforms use the 'configure' script to build config.h */
#include "config.h"
#elif defined(__FreeBSD__)
/* Building as part of FreeBSD system requires a pre-built config.h. */
#include "config_freebsd.h"
#elif defined(_WIN32) && !defined(__CYGWIN__)
/* Win32 can't run the 'configure' script. */
#include "config_windows.h"
#else
/* Warn if the library hasn't been (automatically or manually) configured. */
#error Oops: No config.h and no pre-built configuration in test.h.
#endif
#include <sys/types.h> /* Windows requires this before sys/stat.h */
#include <sys/stat.h>
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#define dirent direct
#endif
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <wchar.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
/*
* System-specific tweaks. We really want to minimize these
* as much as possible, since they make it harder to understand
* the mainline code.
*/
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(__BORLANDC__)
#undef chdir
#define chdir _chdir
#define strdup _strdup
#endif
#endif
/* Visual Studio */
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
#if defined(__BORLANDC__)
#pragma warn -8068 /* Constant out of range in comparison. */
#endif
/* Haiku OS and QNX */
#if defined(__HAIKU__) || defined(__QNXNTO__)
/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
#include <stdint.h>
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
#undef DEFINE_TEST
#define DEFINE_TEST(name) void name(void); void name(void)
/* An implementation of the standard assert() macro */
#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
/* chdir() and error if it fails */
#define assertChdir(path) \
assertion_chdir(__FILE__, __LINE__, path)
/* Assert two integers are the same. Reports value of each one if not. */
#define assertEqualInt(v1,v2) \
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
#define assertEqualUTF8String(v1,v2) \
assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
/* Assert that memory is full of a specified byte */
#define assertMemoryFilledWith(v1, l, b) \
assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
/* Assert two files are the same. */
#define assertEqualFile(f1, f2) \
assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
/* Assert that a file is empty. */
#define assertEmptyFile(pathname) \
assertion_empty_file(__FILE__, __LINE__, (pathname))
/* Assert that a file is not empty. */
#define assertNonEmptyFile(pathname) \
assertion_non_empty_file(__FILE__, __LINE__, (pathname))
#define assertFileAtime(pathname, sec, nsec) \
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileAtimeRecent(pathname) \
assertion_file_atime_recent(__FILE__, __LINE__, pathname)
#define assertFileBirthtime(pathname, sec, nsec) \
assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileBirthtimeRecent(pathname) \
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
/* Assert that a file exists; supports printf-style arguments. */
#define assertFileExists(pathname) \
assertion_file_exists(__FILE__, __LINE__, pathname)
/* Assert that a file exists. */
#define assertFileNotExists(pathname) \
assertion_file_not_exists(__FILE__, __LINE__, pathname)
/* Assert that file contents match a string. */
#define assertFileContents(data, data_size, pathname) \
assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
#define assertFileNLinks(pathname, nlinks) \
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
#define assertTextFileContents(text, pathname) \
assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
#define assertFileContainsLinesAnyOrder(pathname, lines) \
assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
#define assertIsHardlink(path1, path2) \
assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsNotHardlink(path1, path2) \
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)
/* Create a directory, report error if it fails. */
#define assertMakeDir(dirname, mode) \
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
#define assertMakeFile(path, mode, contents) \
assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
#define assertMakeBinFile(path, mode, csize, contents) \
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 assertNodump(path) \
assertion_nodump(__FILE__, __LINE__, path)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
/*
* This would be simple with C99 variadic macros, but I don't want to
* require that. Instead, I insert a function call before each
* skipping() call to pass the file and line information down. Crude,
* but effective.
*/
#define skipping \
skipping_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
void failure(const char *fmt, ...);
int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *);
int assertion_empty_file(const char *, int, const char *);
int assertion_equal_file(const char *, int, const char *, const char *);
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int assertion_file_atime(const char *, int, const char *, long, long);
int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
int assertion_file_contents(const char *, int, const void *, int, const char *);
int assertion_file_exists(const char *, int, const char *);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, int, const char *);
int assertion_file_size(const char *, int, const char *, long);
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_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_nodump(const char *, int, const char *);
int assertion_non_empty_file(const char *, int, const char *);
int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
int assertion_umask(const char *, int, int);
int assertion_utimes(const char *, int, const char *, long, long, long, long );
void skipping_setup(const char *, int);
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
int systemf(const char * fmt, ...);
/* Delay until time() returns a value after this. */
void sleepUntilAfter(time_t);
/* Return true if this platform can create symlinks. */
int canSymlink(void);
/* Return true if this platform can run the "bzip2" program. */
int canBzip2(void);
/* Return true if this platform can run the "grzip" program. */
int canGrzip(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
/* Return true if this platform can run the specified command. */
int canRunCommand(const char *);
/* Return true if this platform can run the "lrzip" program. */
int canLrzip(void);
/* Return true if this platform can run the "lz4" program. */
int canLz4(void);
/* Return true if this platform can run the "lzip" program. */
int canLzip(void);
/* Return true if this platform can run the "lzma" program. */
int canLzma(void);
/* Return true if this platform can run the "lzop" program. */
int canLzop(void);
/* Return true if this platform can run the "xz" program. */
int canXz(void);
/* Return true if this filesystem can handle nodump flags. */
int canNodump(void);
/* Return true if the file has large i-node number(>0xffffffff). */
int is_LargeInode(const char *);
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
/* Dump block of bytes to a file. */
void dumpfile(const char *filename, void *, size_t);
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/* Copies named reference file to the current directory. */
void copy_reference_file(const char *);
/* Extracts a list of files to the current directory.
* List must be NULL terminated.
*/
void extract_reference_files(const char **);
/* Path to working directory for current test */
extern const char *testworkdir;
/*
* Special interfaces for program test harness.
*/
/* Pathname of exe to be tested. */
extern const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
extern const char *testprog;
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif

View File

@ -0,0 +1,67 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
/*
* This first test does basic sanity checks on the environment. For
* most of these, we just exit on failure.
*/
#if !defined(_WIN32) || defined(__CYGWIN__)
#define DEV_NULL "/dev/null"
#else
#define DEV_NULL "NUL"
#endif
DEFINE_TEST(test_0)
{
struct stat st;
failure("File %s does not exist?!", testprog);
if (!assertEqualInt(0, stat(testprogfile, &st))) {
fprintf(stderr,
"\nFile %s does not exist; aborting test.\n\n",
testprog);
exit(1);
}
failure("%s is not executable?!", testprog);
if (!assert((st.st_mode & 0111) != 0)) {
fprintf(stderr,
"\nFile %s not executable; aborting test.\n\n",
testprog);
exit(1);
}
/*
* Try to successfully run the program; this requires that
* we know some option that will succeed.
*/
if (0 != systemf("%s --version >" DEV_NULL, testprog)) {
failure("Unable to successfully run: %s --version\n", testprog, testprog);
assert(0);
}
/* TODO: Ensure that our reference files are available. */
}

View File

@ -0,0 +1,4 @@
begin 644 test_empty.gz
?'XL(""\MZE,``W1E<W1?96UP='D``P``````````````
`
end

View File

@ -0,0 +1,4 @@
begin 644 test_empty.lz4
/!")-&&1PN0`````%7<P"
`
end

View File

@ -0,0 +1,4 @@
begin 644 test_empty.xz
@_3=Z6%H```3FUK1&`````!S?1"$?MO-]`0`````$65H`
`
end

View File

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2014 Sebastian Freundt
* 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"
DEFINE_TEST(test_empty_gz)
{
const char *reffile = "test_empty.gz";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canGzip()) {
assertEqualInt(0, f);
assertEmptyFile("test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems gzip is not supported on this platform");
}
}

View File

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2014 Sebastian Freundt
* 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"
DEFINE_TEST(test_empty_lz4)
{
const char *reffile = "test_empty.lz4";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canLz4()) {
assertEqualInt(0, f);
assertEmptyFile("test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems lz4 is not supported on this platform");
}
}

View File

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2014 Sebastian Freundt
* 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"
DEFINE_TEST(test_empty_xz)
{
const char *reffile = "test_empty.xz";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canXz()) {
assertEqualInt(0, f);
assertEmptyFile("test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems xz is not supported on this platform");
}
}

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* 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"
DEFINE_TEST(test_error)
{
const char *reffile = "test_expand.error";
assertFileNotExists(reffile);
assert(0 != systemf("%s %s >test.out 2>test.err", testprog, reffile));
assertEmptyFile("test.out");
assertNonEmptyFile("test.err");
}

View File

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* 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"
DEFINE_TEST(test_error_mixed)
{
const char *reffile1 = "test_expand.plain";
const char *reffile2 = "test_expand.error";
const char *reffile3 = "test_expand.Z";
assertFileNotExists(reffile2);
extract_reference_file(reffile1);
extract_reference_file(reffile3);
assert(0 != systemf("%s %s %s %s >test.out 2>test.err",
testprog, reffile1, reffile2, reffile3));
assertTextFileContents(
"contents of test_expand.plain.\n"
"contents of test_expand.Z.\n", "test.out");
assertNonEmptyFile("test.err");
}

View File

@ -0,0 +1,3 @@
begin 664 test_expand.Z
@'YV08]ZXH5-FX!P0;\R`(#B'SI<R>."$<4/&A187"@`
end

View File

@ -0,0 +1,5 @@
begin 664 test_expand.bz2
M0EIH.3%!62936=[T@^L [__N000(!!(#!@\P+(, !@4 1 @$" (0 80$
M(!D0 " 5%)D::#( #0]0 9J%1Z@>H :!B:&33(!"X";"%C@I$+32H/(0MXG
J,EA1G51 WG-"6JV7JKA;/&]$X 6MNH 8'N@3[\XCA_%W)%.%"0WO2#ZP
end

View File

@ -0,0 +1,4 @@
begin 664 test_expand.gz
M'XL("-UD1%,``V%S9`!+SL\K2<TK*5;(3U,H22TNB4^M*$C,2]%+K]+C`@`Z
'PQU''```````
end

View File

@ -0,0 +1,5 @@
begin 644 test_expand.lz4
M!")-&&1PN1T``(!C;VYT96YT<R!O9B!T97-T7V5X<&%N9"YL>C0N"@`````Y
#!E9+
`
end

View File

@ -0,0 +1,3 @@
begin 664 test_expand.plain
?8V]N=&5N=',@;V8@=&5S=%]E>'!A;F0N<&QA:6XN"@
end

View File

@ -0,0 +1,4 @@
begin 664 test_expand.xz
M_3=Z6%H 3FUK1& @ A 18 !T+^6C 0 ;8V]N=&5N=',@;V8@=&5S=%]E
G>'!A;F0N>'HN"@!S;^LVAO^3[ !-!R3&JV/'[;S?0$ !%E:
end

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* 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"
DEFINE_TEST(test_expand_Z)
{
const char *reffile = "test_expand.Z";
extract_reference_file(reffile);
assertEqualInt(0, systemf("%s %s >test.out 2>test.err", testprog, reffile));
assertTextFileContents("contents of test_expand.Z.\n", "test.out");
assertEmptyFile("test.err");
}

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* Copyright (c) 2012 Michihiro NAKAJIMA
* 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"
DEFINE_TEST(test_expand_bz2)
{
const char *reffile = "test_expand.bz2";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canBzip2()) {
assertEqualInt(0, f);
assertTextFileContents("contents of test_expand.bz2.\n", "test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems bzip2 is not supported on this platform");
}
}

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* Copyright (c) 2012 Michihiro NAKAJIMA
* 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"
DEFINE_TEST(test_expand_gz)
{
const char *reffile = "test_expand.gz";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canGzip()) {
assertEqualInt(0, f);
assertTextFileContents("contents of test_expand.gz.\n", "test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems gzip is not supported on this platform");
}
}

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* Copyright (c) 2012, 2014 Michihiro NAKAJIMA
* 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"
DEFINE_TEST(test_expand_lz4)
{
const char *reffile = "test_expand.lz4";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canLz4()) {
assertEqualInt(0, f);
assertTextFileContents("contents of test_expand.lz4.\n", "test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems lz4 is not supported on this platform");
}
}

View File

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* 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"
DEFINE_TEST(test_expand_mixed)
{
const char *reffile1 = "test_expand.Z";
const char *reffile2 = "test_expand.plain";
extract_reference_file(reffile1);
extract_reference_file(reffile2);
assertEqualInt(0, systemf("%s %s %s >test.out 2>test.err",
testprog, reffile1, reffile2));
assertTextFileContents(
"contents of test_expand.Z.\n"
"contents of test_expand.plain.\n", "test.out");
assertEmptyFile("test.err");
}

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* 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"
DEFINE_TEST(test_expand_plain)
{
const char *reffile = "test_expand.plain";
extract_reference_file(reffile);
assertEqualInt(0, systemf("%s %s >test.out 2>test.err", testprog, reffile));
assertTextFileContents("contents of test_expand.plain.\n", "test.out");
assertEmptyFile("test.err");
}

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2014 Mike Kazantsev
* Copyright (c) 2012 Michihiro NAKAJIMA
* 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"
DEFINE_TEST(test_expand_xz)
{
const char *reffile = "test_expand.xz";
int f;
extract_reference_file(reffile);
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canXz()) {
assertEqualInt(0, f);
assertTextFileContents("contents of test_expand.xz.\n", "test.out");
assertEmptyFile("test.err");
} else {
skipping("It seems xz is not supported on this platform");
}
}

View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
/*
* Test that "--help", "-h", and "-W help" options all work and
* generate reasonable output.
*/
static int
in_first_line(const char *p, const char *substring)
{
size_t l = strlen(substring);
while (*p != '\0' && *p != '\n') {
if (memcmp(p, substring, l) == 0)
return (1);
++p;
}
return (0);
}
DEFINE_TEST(test_help)
{
int r;
char *p;
size_t plen;
/* Exercise --help option. */
r = systemf("%s --help >help.stdout 2>help.stderr", testprog);
assertEqualInt(r, 0);
failure("--help should generate nothing to stderr.");
assertEmptyFile("help.stderr");
/* Help message should start with name of program. */
p = slurpfile(&plen, "help.stdout");
failure("Help output should be long enough.");
assert(plen >= 6);
failure("First line of help output should contain 'bsdcat': %s", p);
assert(in_first_line(p, "bsdcat"));
/*
* TODO: Extend this check to further verify that --help output
* looks approximately right.
*/
free(p);
/* -h option should generate the same output. */
r = systemf("%s -h >h.stdout 2>h.stderr", testprog);
assertEqualInt(r, 0);
failure("-h should generate nothing to stderr.");
assertEmptyFile("h.stderr");
failure("stdout should be same for -h and --help");
assertEqualFile("h.stdout", "help.stdout");
}

View File

@ -0,0 +1,97 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
/*
* Test that --version option works and generates reasonable output.
*/
DEFINE_TEST(test_version)
{
int r;
char *p, *q;
size_t s;
r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
failure("Unable to run %s --version", testprog);
if (!assert(r == 0))
return;
/* --version should generate nothing to stdout. */
assertEmptyFile("version.stderr");
/* Verify format of version message. */
q = p = slurpfile(&s, "version.stdout");
/* Version message should start with name of program, then space. */
assert(s > 6);
failure("Version must start with 'bsdcat': ``%s''", p);
if (!assertEqualMem(q, "bsdcat ", 7))
return;
q += 7; s -= 7;
/* Version number is a series of digits and periods. */
while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
++q;
--s;
}
/* Version number terminated by space. */
failure("No space after bsdcat version: ``%s''", p);
assert(s > 1);
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
failure("No space after bsdcat version: ``%s''", p);
assert(*q == ' ');
++q; --s;
/* Separator. */
failure("No `-' between bsdcat and libarchive versions: ``%s''", p);
assertEqualMem(q, "- ", 2);
q += 2; s -= 2;
/* libarchive name and version number */
failure("Not long enough for libarchive version: ``%s''", p);
assert(s > 11);
failure("Libarchive version must start with `libarchive': ``%s''", p);
assertEqualMem(q, "libarchive ", 11);
q += 11; s -= 11;
/* Version number is a series of digits and periods. */
while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
++q;
--s;
}
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
/* Skip arbitrary third-party version numbers. */
while (s > 0 && (*q == ' ' || *q == '/' || *q == '.' || isalnum(*q))) {
++q;
--s;
}
/* All terminated by end-of-line. */
assert(s >= 1);
/* Skip an optional CR character (e.g., Windows) */
failure("Version output must end with \\n or \\r\\n");
if (*q == '\r') { ++q; --s; }
assertEqualMem(q, "\n", 1);
free(p);
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 7, 2012
.Dd September 16, 2014
.Dt CPIO 1
.Os
.Sh NAME
@ -32,17 +32,17 @@
.Nd copy files to and from archives
.Sh SYNOPSIS
.Nm
.Brq Fl i
.Fl i
.Op Ar options
.Op Ar pattern ...
.Op Ar < archive
.Nm
.Brq Fl o
.Fl o
.Op Ar options
.Ar < name-list
.Op Ar > archive
.Nm
.Brq Fl p
.Fl p
.Op Ar options
.Ar dest-dir
.Ar < name-list
@ -156,7 +156,8 @@ See above for description.
.It Fl Fl insecure
(i and p mode only)
Disable security checks during extraction or copying.
This allows extraction via symbolic links and path names containing
This allows extraction via symbolic links, absolute paths,
and path names containing
.Sq ..
in the name.
.It Fl J , Fl Fl xz
@ -181,6 +182,11 @@ instead of copying.
Compress the resulting archive with
.Xr lrzip 1 .
In input mode, this option is ignored.
.It Fl Fl lz4
(o mode only)
Compress the archive with lz4-compatible compression before writing it.
In input mode, this option is ignored; lz4 compression is recognized
automatically on input.
.It Fl Fl lzma
(o mode only)
Compress the file with lzma-compatible compression before writing it.
@ -191,6 +197,15 @@ automatically on input.
Compress the resulting archive with
.Xr lzop 1 .
In input mode, this option is ignored.
.It Fl Fl passphrase Ar passphrase
The
.Pa passphrase
is used to extract or create an encrypted archive.
Currently, zip is only a format that
.Nm
can handle encrypted archives.
You shouldn't use this option unless you realize how insecure
use of this option is.
.It Fl m , Fl Fl preserve-modification-time
(i and p modes)
Set file modification time on created files to match

View File

@ -73,6 +73,7 @@ static const struct option {
{ "link", 0, 'l' },
{ "list", 0, 't' },
{ "lrzip", 0, OPTION_LRZIP },
{ "lz4", 0, OPTION_LZ4 },
{ "lzma", 0, OPTION_LZMA },
{ "lzop", 0, OPTION_LZOP },
{ "make-directories", 0, 'd' },
@ -80,6 +81,7 @@ static const struct option {
{ "null", 0, '0' },
{ "numeric-uid-gid", 0, 'n' },
{ "owner", 1, 'R' },
{ "passphrase", 1, OPTION_PASSPHRASE },
{ "pass-through", 0, 'p' },
{ "preserve-modification-time", 0, 'm' },
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },

View File

@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include "cpio.h"
#include "err.h"
#include "line_reader.h"
#include "passphrase.h"
/* Fixed size of uname/gname caches. */
#define name_cache_size 101
@ -123,6 +124,8 @@ static int restore_time(struct cpio *, struct archive_entry *,
const char *, int fd);
static void usage(void);
static void version(void);
static const char * passphrase_callback(struct archive *, void *);
static void passphrase_free(char *);
int
main(int argc, char *argv[])
@ -149,20 +152,9 @@ main(int argc, char *argv[])
}
#endif
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
lafe_progname = "bsdcpio";
else {
#if defined(_WIN32) && !defined(__CYGWIN__)
lafe_progname = strrchr(*argv, '\\');
if (strrchr(*argv, '/') > lafe_progname)
#endif
lafe_progname = strrchr(*argv, '/');
if (lafe_progname != NULL)
lafe_progname++;
else
lafe_progname = *argv;
}
/* Set lafe_progname before calling lafe_warnc. */
lafe_setprogname(*argv, "bsdcpio");
#if HAVE_SETLOCALE
if (setlocale(LC_ALL, "") == NULL)
lafe_warnc(0, "Failed to set default locale");
@ -179,6 +171,7 @@ main(int argc, char *argv[])
cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
cpio->extract_flags |= ARCHIVE_EXTRACT_PERM;
cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
cpio->extract_flags |= ARCHIVE_EXTRACT_ACL;
@ -264,6 +257,7 @@ main(int argc, char *argv[])
case OPTION_INSECURE:
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
break;
case 'L': /* GNU cpio */
cpio->option_follow_links = 1;
@ -272,6 +266,7 @@ main(int argc, char *argv[])
cpio->option_link = 1;
break;
case OPTION_LRZIP:
case OPTION_LZ4:
case OPTION_LZMA: /* GNU tar, others */
case OPTION_LZOP: /* GNU tar, others */
cpio->compress = opt;
@ -301,6 +296,9 @@ main(int argc, char *argv[])
cpio->mode = opt;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
break;
case OPTION_PASSPHRASE:
cpio->passphrase = cpio->argument;
break;
case OPTION_PRESERVE_OWNER:
cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
break;
@ -429,6 +427,7 @@ main(int argc, char *argv[])
free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
free(cpio->destdir);
passphrase_free(cpio->ppbuff);
return (cpio->return_value);
}
@ -437,7 +436,7 @@ usage(void)
{
const char *p;
p = lafe_progname;
p = lafe_getprogname();
fprintf(stderr, "Brief Usage:\n");
fprintf(stderr, " List: %s -it < archive\n", p);
@ -475,7 +474,7 @@ long_help(void)
const char *prog;
const char *p;
prog = lafe_progname;
prog = lafe_getprogname();
fflush(stderr);
@ -500,7 +499,7 @@ version(void)
{
fprintf(stdout,"bsdcpio %s -- %s\n",
BSDCPIO_VERSION_STRING,
archive_version_string());
archive_version_details());
exit(0);
}
@ -537,6 +536,9 @@ mode_out(struct cpio *cpio)
case OPTION_LRZIP:
r = archive_write_add_filter_lrzip(cpio->archive);
break;
case OPTION_LZ4:
r = archive_write_add_filter_lz4(cpio->archive);
break;
case OPTION_LZMA:
r = archive_write_add_filter_lzma(cpio->archive);
break;
@ -578,6 +580,14 @@ mode_out(struct cpio *cpio)
cpio->linkresolver = archive_entry_linkresolver_new();
archive_entry_linkresolver_set_strategy(cpio->linkresolver,
archive_format(cpio->archive));
if (cpio->passphrase != NULL)
r = archive_write_set_passphrase(cpio->archive,
cpio->passphrase);
else
r = archive_write_set_passphrase_callback(cpio->archive, cpio,
&passphrase_callback);
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
/*
* The main loop: Copy each file into the output archive.
@ -944,6 +954,13 @@ mode_in(struct cpio *cpio)
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (cpio->passphrase != NULL)
r = archive_read_add_passphrase(a, cpio->passphrase);
else
r = archive_read_set_passphrase_callback(a, cpio,
&passphrase_callback);
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
if (archive_read_open_filename(a, cpio->filename,
cpio->bytes_per_block))
@ -1047,6 +1064,13 @@ mode_list(struct cpio *cpio)
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (cpio->passphrase != NULL)
r = archive_read_add_passphrase(a, cpio->passphrase);
else
r = archive_read_set_passphrase_callback(a, cpio,
&passphrase_callback);
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
if (archive_read_open_filename(a, cpio->filename,
cpio->bytes_per_block))
@ -1236,8 +1260,10 @@ cpio_rename(const char *name)
if (t == NULL)
return (name);
to = fopen("CONOUT$", "w");
if (to == NULL)
if (to == NULL) {
fclose(t);
return (name);
}
fprintf(to, "%s (Enter/./(new name))? ", name);
fclose(to);
#else
@ -1417,3 +1443,28 @@ cpio_i64toa(int64_t n0)
*--p = '-';
return p;
}
#define PPBUFF_SIZE 1024
static const char *
passphrase_callback(struct archive *a, void *_client_data)
{
struct cpio *cpio = (struct cpio *)_client_data;
(void)a; /* UNUSED */
if (cpio->ppbuff == NULL) {
cpio->ppbuff = malloc(PPBUFF_SIZE);
if (cpio->ppbuff == NULL)
lafe_errc(1, errno, "Out of memory");
}
return lafe_readpassphrase("Enter passphrase:",
cpio->ppbuff, PPBUFF_SIZE);
}
static void
passphrase_free(char *ppbuff)
{
if (ppbuff != NULL) {
memset(ppbuff, 0, PPBUFF_SIZE);
free(ppbuff);
}
}

View File

@ -71,6 +71,7 @@ struct cpio {
int gid_override;
char *gname_override;
int day_first; /* true if locale prefers day/mon */
const char *passphrase;
/* If >= 0, then close this when done. */
int fd;
@ -90,6 +91,7 @@ struct cpio {
struct archive *matching;
char *buff;
size_t buff_size;
char *ppbuff;
};
const char *owner_parse(const char *, int *, int *);
@ -101,8 +103,10 @@ enum {
OPTION_GRZIP,
OPTION_INSECURE,
OPTION_LRZIP,
OPTION_LZ4,
OPTION_LZMA,
OPTION_LZOP,
OPTION_PASSPHRASE,
OPTION_NO_PRESERVE_OWNER,
OPTION_PRESERVE_OWNER,
OPTION_QUIET,

View File

@ -42,6 +42,10 @@
#include "config.h"
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "cpio_windows.h"
#endif
/* Get a real definition for __FBSDID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
@ -70,8 +74,4 @@
#define __LA_DEAD
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "cpio_windows.h"
#endif
#endif /* !CPIO_PLATFORM_H_INCLUDED */

View File

@ -130,6 +130,16 @@ __FBSDID("$FreeBSD$");
# include <crtdbg.h>
#endif
/* Path to working directory for current test */
const char *testworkdir;
#ifdef PROGRAM
/* Pathname of exe to be tested. */
const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *);
static int my_CreateSymbolicLinkA(const char *, const char *, int);
@ -194,7 +204,7 @@ my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
}
#endif
#if defined(HAVE__CrtSetReportMode)
#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
static void
invalid_parameter_handler(const wchar_t * expression,
const wchar_t * function, const wchar_t * file,
@ -565,10 +575,10 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8)
while (*p != '\0') {
unsigned int c = 0xff & *p++;
switch (c) {
case '\a': printf("\a"); break;
case '\b': printf("\b"); break;
case '\n': printf("\n"); break;
case '\r': printf("\r"); break;
case '\a': logprintf("\\a"); break;
case '\b': logprintf("\\b"); break;
case '\n': logprintf("\\n"); break;
case '\r': logprintf("\\r"); break;
default:
if (c >= 32 && c < 127)
logprintf("%c", c);
@ -771,6 +781,34 @@ assertion_equal_mem(const char *file, int line,
return (0);
}
/* Verify that a block of memory is filled with the specified byte. */
int
assertion_memory_filled_with(const char *file, int line,
const void *_v1, const char *vd,
size_t l, const char *ld,
char b, const char *bd, void *extra)
{
const char *v1 = (const char *)_v1;
size_t c = 0;
size_t i;
(void)ld; /* UNUSED */
assertion_count(file, line);
for (i = 0; i < l; ++i) {
if (v1[i] == b) {
++c;
}
}
if (c == l)
return (1);
failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
logprintf(" Only %d bytes were correct\n", (int)c);
failure_finish(extra);
return (0);
}
/* Verify that the named file exists and is empty. */
int
assertion_empty_file(const char *filename, int line, const char *f1)
@ -1036,6 +1074,7 @@ assertion_file_contains_lines_any_order(const char *file, int line,
if (expected == NULL) {
failure_start(pathname, line, "Can't allocate memory");
failure_finish(NULL);
free(expected);
return (0);
}
for (i = 0; lines[i] != NULL; ++i) {
@ -1060,7 +1099,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
free(expected);
return (0);
}
for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
for (j = 0, p = buff; p < buff + buff_size;
p += 1 + strlen(p)) {
if (*p != '\0') {
actual[j] = p;
++j;
@ -1911,6 +1951,18 @@ canGzip(void)
/*
* Can this platform run the lrzip program?
*/
int
canRunCommand(const char *cmd)
{
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
if (systemf("%s %s", cmd, redirectArgs) == 0)
value = 1;
}
return (value);
}
int
canLrzip(void)
{
@ -1923,6 +1975,21 @@ canLrzip(void)
return (value);
}
/*
* Can this platform run the lz4 program?
*/
int
canLz4(void)
{
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
if (systemf("lz4 -V %s", redirectArgs) == 0)
value = 1;
}
return (value);
}
/*
* Can this platform run the lzip program?
*/
@ -2135,8 +2202,31 @@ slurpfile(size_t * sizep, const char *fmt, ...)
return (p);
}
/*
* Slurp a file into memory for ease of comparison and testing.
* Returns size of file in 'sizep' if non-NULL, null-terminates
* data in memory for ease of use.
*/
void
dumpfile(const char *filename, void *data, size_t len)
{
ssize_t bytes_written;
FILE *f;
f = fopen(filename, "wb");
if (f == NULL) {
logprintf("Can't open file %s for writing\n", filename);
return;
}
bytes_written = fwrite(data, 1, len, f);
if (bytes_written < (ssize_t)len)
logprintf("Can't write file %s\n", filename);
fclose(f);
}
/* Read a uuencoded file from the reference directory, decode, and
* write the result into the current directory. */
#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
void
extract_reference_file(const char *name)
@ -2160,7 +2250,6 @@ extract_reference_file(const char *name)
break;
}
/* Now, decode the rest and write it. */
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while (fgets(buff, sizeof(buff), in) != NULL) {
char *p = buff;
@ -2174,17 +2263,21 @@ extract_reference_file(const char *name)
int n = 0;
/* Write out 1-3 bytes from that. */
if (bytes > 0) {
assert(VALID_UUDECODE(p[0]));
assert(VALID_UUDECODE(p[1]));
n = UUDECODE(*p++) << 18;
n |= UUDECODE(*p++) << 12;
fputc(n >> 16, out);
--bytes;
}
if (bytes > 0) {
assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++) << 6;
fputc((n >> 8) & 0xFF, out);
--bytes;
}
if (bytes > 0) {
assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++);
fputc(n & 0xFF, out);
--bytes;
@ -2195,6 +2288,32 @@ extract_reference_file(const char *name)
fclose(in);
}
void
copy_reference_file(const char *name)
{
char buff[1024];
FILE *in, *out;
size_t rbytes;
sprintf(buff, "%s/%s", refdir, name);
in = fopen(buff, "rb");
failure("Couldn't open reference file %s", buff);
assert(in != NULL);
if (in == NULL)
return;
/* Now, decode the rest and write it. */
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
if (fwrite(buff, 1, rbytes, out) != rbytes) {
logprintf("Error: fwrite\n");
break;
}
}
fclose(out);
fclose(in);
}
int
is_LargeInode(const char *file)
{
@ -2216,6 +2335,14 @@ is_LargeInode(const char *file)
return (ino > 0xffffffff);
#endif
}
void
extract_reference_files(const char **names)
{
while (names && *names)
extract_reference_file(*names++);
}
/*
*
* TEST management
@ -2245,7 +2372,7 @@ struct test_list_t tests[] = {
* Summarize repeated failures in the just-completed test.
*/
static void
test_summarize(int failed)
test_summarize(int failed, int skips_num)
{
unsigned int i;
@ -2255,7 +2382,7 @@ test_summarize(int failed)
fflush(stdout);
break;
case VERBOSITY_PASSFAIL:
printf(failed ? "FAIL\n" : "ok\n");
printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n");
break;
}
@ -2280,13 +2407,14 @@ test_run(int i, const char *tmpdir)
char workdir[1024];
char logfilename[64];
int failures_before = failures;
int skips_before = skips;
int oldumask;
switch (verbosity) {
case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
break;
case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
printf("%3d: %-50s", i, tests[i].name);
printf("%3d: %-64s", i, tests[i].name);
fflush(stdout);
break;
default: /* Title of test, details will follow */
@ -2336,7 +2464,7 @@ test_run(int i, const char *tmpdir)
}
/* Report per-test summaries. */
tests[i].failures = failures - failures_before;
test_summarize(tests[i].failures);
test_summarize(tests[i].failures, skips - skips_before);
/* Close the per-test log file. */
fclose(logfile);
logfile = NULL;
@ -2479,6 +2607,7 @@ get_refdir(const char *d)
failure:
printf("Unable to locate known reference file %s\n", KNOWNREF);
printf(" Checked following directories:\n%s\n", tried);
printf("Use -r option to specify full path to reference directory\n");
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
@ -2515,7 +2644,7 @@ main(int argc, char **argv)
while (pwd[strlen(pwd) - 1] == '\n')
pwd[strlen(pwd) - 1] = '\0';
#if defined(HAVE__CrtSetReportMode)
#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
/* To stop to run the default invalid parameter handler. */
_set_invalid_parameter_handler(invalid_parameter_handler);
/* Disable annoying assertion message box. */
@ -2562,7 +2691,7 @@ main(int argc, char **argv)
exit(1);
}
memmove(testprogdir + strlen(pwd) + 1, testprogdir,
strlen(testprogdir));
strlen(testprogdir) + 1);
memcpy(testprogdir, pwd, strlen(pwd));
testprogdir[strlen(pwd)] = '/';
}

View File

@ -66,6 +66,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -84,12 +85,14 @@
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(__BORLANDC__)
#undef chdir
#define chdir _chdir
#define strdup _strdup
#endif
#endif
/* Visual Studio */
#ifdef _MSC_VER
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
@ -142,6 +145,9 @@
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
/* Assert that memory is full of a specified byte */
#define assertMemoryFilledWith(v1, l, b) \
assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
/* Assert two files are the same. */
#define assertEqualFile(f1, f2) \
assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
@ -225,6 +231,7 @@ int assertion_empty_file(const char *, int, const char *);
int assertion_equal_file(const char *, int, const char *, const char *);
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int assertion_file_atime(const char *, int, const char *, long, long);
@ -275,9 +282,15 @@ int canGrzip(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
/* Return true if this platform can run the specified command. */
int canRunCommand(const char *);
/* Return true if this platform can run the "lrzip" program. */
int canLrzip(void);
/* Return true if this platform can run the "lz4" program. */
int canLz4(void);
/* Return true if this platform can run the "lzip" program. */
int canLzip(void);
@ -300,21 +313,31 @@ int is_LargeInode(const char *);
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
/* Dump block of bytes to a file. */
void dumpfile(const char *filename, void *, size_t);
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/* Copies named reference file to the current directory. */
void copy_reference_file(const char *);
/* Extracts a list of files to the current directory.
* List must be NULL terminated.
*/
void extract_reference_files(const char **);
/* Path to working directory for current test */
const char *testworkdir;
extern const char *testworkdir;
/*
* Special interfaces for program test harness.
*/
/* Pathname of exe to be tested. */
const char *testprogfile;
extern const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
extern const char *testprog;
#ifdef USE_DMALLOC
#include <dmalloc.h>

View File

@ -72,7 +72,7 @@ basic_cpio(const char *target,
return;
/* Use the cpio program to create an archive. */
r = systemf("%s -o %s < filelist >%s/archive 2>%s/pack.err",
r = systemf("%s -R 1000:1000 -o %s < filelist >%s/archive 2>%s/pack.err",
testprog, pack_options, target, target);
failure("Error invoking %s -o %s", testprog, pack_options);
assertEqualInt(r, 0);

View File

@ -0,0 +1,7 @@
begin 644 test_extract.cpio.lz4
M!")-&&1PN9$````A,#<"`&`P-#`P,3`!`&`Q,3`P-C8/`#0W-3`&```)``$&
M`,$P,3(P,S(W-#`R,S01`!$V!@```@#Q!3(S9FEL93$`8V]N=&5N=',@;V8@
M$@`A+@IC``AE`!\R90`4$#2#``YE`!TR90`6,F4`#P(`#@+H``P"`"<Q,Q(`
=OU1204E,15(A(2$``0#'4````````````"BVD[$`
`
end

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2012,2014 Michihiro NAKAJIMA
* 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_extract_cpio_lz4)
{
const char *reffile = "test_extract.cpio.lz4";
int f;
extract_reference_file(reffile);
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canLz4()) {
assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
testprog, reffile));
assertFileExists("file1");
assertTextFileContents("contents of file1.\n", "file1");
assertFileExists("file2");
assertTextFileContents("contents of file2.\n", "file2");
assertEmptyFile("test.out");
assertTextFileContents("1 block\n", "test.err");
} else {
skipping("It seems lz4 is not supported on this platform");
}
}

View File

@ -27,7 +27,7 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_extract_cpio_lzo)
{
const char *reffile = "test_extract.cpio.lrz";
const char *reffile = "test_extract.cpio.lzo";
int f;
extract_reference_file(reffile);

View File

@ -65,18 +65,14 @@ DEFINE_TEST(test_option_c)
{
FILE *filelist;
int r;
int uid = -1;
int dev, ino, gid;
int uid = 1000;
int dev, ino, gid = 1000;
time_t t, now;
char *p, *e;
size_t s;
assertUmask(0);
#if !defined(_WIN32)
uid = getuid();
#endif
/*
* Create an assortment of files.
* TODO: Extend this to cover more filetypes.
@ -101,7 +97,7 @@ DEFINE_TEST(test_option_c)
/* Use the cpio program to create an archive. */
fclose(filelist);
r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog);
r = systemf("%s -R 1000:1000 -oc <filelist >basic.out 2>basic.err", testprog);
/* Verify that nothing went to stderr. */
assertTextFileContents("1 block\n", "basic.err");

View File

@ -0,0 +1,74 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* 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_lz4)
{
char *p;
int r;
size_t s;
/* Create a file. */
assertMakeFile("f", 0644, "a");
/* Archive it with lz4 compression. */
r = systemf("echo f | %s -o --lz4 >archive.out 2>archive.err",
testprog);
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without lz4 support");
return;
}
/* POSIX permits different handling of the spawnp
* system call used to launch the subsidiary
* program: */
/* Some systems fail immediately to spawn the new process. */
if (strstr(p, "Can't launch") != NULL && !canLz4()) {
skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
return;
}
/* Some systems successfully spawn the new process,
* but fail to exec a program within that process.
* This results in failure at the first attempt to
* write. */
if (strstr(p, "Can't write") != NULL && !canLz4()) {
skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
return;
}
failure("--lz4 option is broken: %s", p);
assertEqualInt(r, 0);
return;
}
/* Check that the archive file has an lz4 signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x04\x22\x4d\x18", 4);
}

View File

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* 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_passphrase)
{
const char *reffile = "test_option_passphrase.zip";
extract_reference_file(reffile);
assertEqualInt(0,
systemf("%s -i --passphrase pass1 < %s >test.out 2>test.err",
testprog, reffile));
assertFileExists("file1");
assertTextFileContents("contents of file1.\n", "file1");
assertFileExists("file2");
assertTextFileContents("contents of file2.\n", "file2");
assertEmptyFile("test.out");
assertTextFileContents("1 block\n", "test.err");
}

View File

@ -0,0 +1,12 @@
begin 644 test_option_passphrase.zip
M4$L#!`H`"0```#B91$7D$C4,'P```!,````%`!P`9FEL93%55`D``VS'+U0"
MQR]4=7@+``$$]0$```04````BHPD*"^*I04=XKI\_FQ*TE+#),TD7TTKSP/7
MR6R35%!+!PCD$C4,'P```!,```!02P,$"@`)````09E$1;VL<PX?````$P``
M``4`'`!F:6QE,E54"0`#><<O5`+'+U1U>`L``03U`0``!!0```!D#6Z\@CI8
MV1GIJO5TISQF^I:7.;Y3<-G3$YOCL(C_4$L'"+VL<PX?````$P```%!+`0(>
M`PH`"0```#B91$7D$C4,'P```!,````%`!@```````$```"D@0````!F:6QE
M,554!0`#;,<O5'5X"P`!!/4!```$%````%!+`0(>`PH`"0```$&91$6]K',.
M'P```!,````%`!@```````$```"D@6X```!F:6QE,E54!0`#><<O5'5X"P`!
@!/4!```$%````%!+!08``````@`"`)8```#<````````
`
end

View File

@ -74,6 +74,11 @@ verify(const char *p, size_t s)
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
/* Skip arbitrary third-party version numbers. */
while (s > 0 && (*q == ' ' || *q == '/' || *q == '.' || isalnum(*q))) {
++q;
--s;
}
/* All terminated by end-of-line: \r, \r\n, or \n */
assert(s >= 1);
failure("Version: %s", p);

View File

@ -28,9 +28,20 @@
#ifndef ARCHIVE_H_INCLUDED
#define ARCHIVE_H_INCLUDED
/*
* The version number is expressed as a single integer that makes it
* easy to compare versions at build time: for version a.b.c, the
* version number is printf("%d%03d%03d",a,b,c). For example, if you
* know your application requires version 2.12.108 or later, you can
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3002000
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
#include <stdio.h> /* For FILE * */
#include <time.h> /* For time_t */
/*
* Note: archive.h is for use outside of libarchive; the configuration
@ -41,29 +52,53 @@
*/
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
# include <stdint.h>
#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS)
#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__)
# include <inttypes.h>
#endif
/* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */
#if defined(_WIN32) && !defined(__CYGWIN__)
# define __LA_INT64_T __int64
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
# define __LA_SSIZE_T ssize_t
# elif defined(_WIN64)
# define __LA_SSIZE_T __int64
# else
# define __LA_SSIZE_T long
/* Get appropriate definitions of 64-bit integer */
#if !defined(__LA_INT64_T_DEFINED)
/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */
# if ARCHIVE_VERSION_NUMBER < 4000000
#define __LA_INT64_T la_int64_t
# endif
#else
#define __LA_INT64_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
typedef __int64 la_int64_t;
# else
# include <unistd.h> /* ssize_t */
# if defined(_SCO_DS)
# define __LA_INT64_T long long
# else
# define __LA_INT64_T int64_t
# if defined(_SCO_DS) || defined(__osf__)
typedef long long la_int64_t;
# else
typedef int64_t la_int64_t;
# endif
# endif
# define __LA_SSIZE_T ssize_t
#endif
/* The la_ssize_t should match the type used in 'struct stat' */
#if !defined(__LA_SSIZE_T_DEFINED)
/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
# if ARCHIVE_VERSION_NUMBER < 4000000
#define __LA_SSIZE_T la_ssize_t
# endif
#define __LA_SSIZE_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
typedef ssize_t la_ssize_t;
# elif defined(_WIN64)
typedef __int64 la_ssize_t;
# else
typedef long la_ssize_t;
# endif
# else
# include <unistd.h> /* ssize_t */
typedef ssize_t la_ssize_t;
# endif
#endif
/* Large file support for Android */
#ifdef __ANDROID__
#include "android_lf.h"
#endif
/*
@ -115,24 +150,34 @@ extern "C" {
* header and library are very different, you should expect some
* strangeness. Don't do that.
*/
/*
* The version number is expressed as a single integer that makes it
* easy to compare versions at build time: for version a.b.c, the
* version number is printf("%d%03d%03d",a,b,c). For example, if you
* know your application requires version 2.12.108 or later, you can
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3001002
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
#define ARCHIVE_VERSION_ONLY_STRING "3.2.0"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
/*
* Detailed textual name/version of the library and its dependencies.
* This has the form:
* "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..."
* the list of libraries described here will vary depending on how
* libarchive was compiled.
*/
__LA_DECL const char * archive_version_details(void);
/*
* Returns NULL if libarchive was compiled without the associated library.
* Otherwise, returns the version number that libarchive was compiled
* against.
*/
__LA_DECL const char * archive_zlib_version(void);
__LA_DECL const char * archive_liblzma_version(void);
__LA_DECL const char * archive_bzlib_version(void);
__LA_DECL const char * archive_liblz4_version(void);
/* Declare our basic types. */
struct archive;
struct archive_entry;
@ -173,7 +218,7 @@ struct archive_entry;
*/
/* Returns pointer and size of next block of data from archive. */
typedef __LA_SSIZE_T archive_read_callback(struct archive *,
typedef la_ssize_t archive_read_callback(struct archive *,
void *_client_data, const void **_buffer);
/* Skips at most request bytes from archive and returns the skipped amount.
@ -181,18 +226,18 @@ typedef __LA_SSIZE_T archive_read_callback(struct archive *,
* If you do skip fewer bytes than requested, libarchive will invoke your
* read callback and discard data as necessary to make up the full skip.
*/
typedef __LA_INT64_T archive_skip_callback(struct archive *,
void *_client_data, __LA_INT64_T request);
typedef la_int64_t archive_skip_callback(struct archive *,
void *_client_data, la_int64_t request);
/* Seeks to specified location in the file and returns the position.
* Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
* Return ARCHIVE_FATAL if the seek fails for any reason.
*/
typedef __LA_INT64_T archive_seek_callback(struct archive *,
void *_client_data, __LA_INT64_T offset, int whence);
typedef la_int64_t archive_seek_callback(struct archive *,
void *_client_data, la_int64_t offset, int whence);
/* Returns size actually written, zero on EOF, -1 on error. */
typedef __LA_SSIZE_T archive_write_callback(struct archive *,
typedef la_ssize_t archive_write_callback(struct archive *,
void *_client_data,
const void *_buffer, size_t _length);
@ -207,6 +252,13 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
typedef int archive_switch_callback(struct archive *, void *_client_data1,
void *_client_data2);
/*
* Returns a passphrase used for encryption or decryption, NULL on nothing
* to do and give it up.
*/
typedef const char *archive_passphrase_callback(struct archive *,
void *_client_data);
/*
* Codes to identify various stream filters.
*/
@ -223,6 +275,7 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
#define ARCHIVE_FILTER_LRZIP 10
#define ARCHIVE_FILTER_LZOP 11
#define ARCHIVE_FILTER_GRZIP 12
#define ARCHIVE_FILTER_LZ4 13
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@ -284,6 +337,31 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
#define ARCHIVE_FORMAT_CAB 0xC0000
#define ARCHIVE_FORMAT_RAR 0xD0000
#define ARCHIVE_FORMAT_7ZIP 0xE0000
#define ARCHIVE_FORMAT_WARC 0xF0000
/*
* Codes returned by archive_read_format_capabilities().
*
* This list can be extended with values between 0 and 0xffff.
* The original purpose of this list was to let different archive
* format readers expose their general capabilities in terms of
* encryption.
*/
#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */
/*
* Codes returned by archive_read_has_encrypted_entries().
*
* In case the archive does not support encryption detection at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
* for some other reason (e.g. not enough bytes read) cannot say if
* there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
* is returned.
*/
#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
/*-
* Basic outline for reading an archive:
@ -342,6 +420,7 @@ __LA_DECL int archive_read_support_filter_compress(struct archive *);
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
__LA_DECL int archive_read_support_filter_grzip(struct archive *);
__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
__LA_DECL int archive_read_support_filter_lz4(struct archive *);
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
__LA_DECL int archive_read_support_filter_lzop(struct archive *);
@ -369,8 +448,17 @@ __LA_DECL int archive_read_support_format_mtree(struct archive *);
__LA_DECL int archive_read_support_format_rar(struct archive *);
__LA_DECL int archive_read_support_format_raw(struct archive *);
__LA_DECL int archive_read_support_format_tar(struct archive *);
__LA_DECL int archive_read_support_format_warc(struct archive *);
__LA_DECL int archive_read_support_format_xar(struct archive *);
/* archive_read_support_format_zip() enables both streamable and seekable
* zip readers. */
__LA_DECL int archive_read_support_format_zip(struct archive *);
/* Reads Zip archives as stream from beginning to end. Doesn't
* correctly handle SFX ZIP files or ZIP archives that have been modified
* in-place. */
__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
/* Reads starting from central directory; requires seekable input. */
__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
/* Functions to manually set the format and filters to be used. This is
* useful to bypass the bidding process when the format and filters to use
@ -441,9 +529,9 @@ __LA_DECL int archive_read_open_file(struct archive *,
const char *_filename, size_t _block_size) __LA_DEPRECATED;
/* Read an archive that's stored in memory. */
__LA_DECL int archive_read_open_memory(struct archive *,
void * buff, size_t size);
const void * buff, size_t size);
/* A more involved version that is only used for internal testing. */
__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff,
size_t size, size_t read_size);
/* Read an archive that's already open, using the file descriptor. */
__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
@ -464,14 +552,40 @@ __LA_DECL int archive_read_next_header2(struct archive *,
* Retrieve the byte offset in UNCOMPRESSED data where last-read
* header started.
*/
__LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
__LA_DECL la_int64_t archive_read_header_position(struct archive *);
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
__LA_DECL int archive_read_has_encrypted_entries(struct archive *);
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
__LA_DECL int archive_read_format_capabilities(struct archive *);
/* Read data from the body of an entry. Similar to read(2). */
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
__LA_DECL la_ssize_t archive_read_data(struct archive *,
void *, size_t);
/* Seek within the body of an entry. Similar to lseek(2). */
__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int);
/*
* A zero-copy version of archive_read_data that also exposes the file offset
@ -480,7 +594,7 @@ __LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
* be strictly increasing and that returned blocks will not overlap.
*/
__LA_DECL int archive_read_data_block(struct archive *a,
const void **buff, size_t *size, __LA_INT64_T *offset);
const void **buff, size_t *size, la_int64_t *offset);
/*-
* Some convenience functions that are built on archive_read_data:
@ -510,6 +624,14 @@ __LA_DECL int archive_read_set_option(struct archive *_a,
__LA_DECL int archive_read_set_options(struct archive *_a,
const char *opts);
/*
* Add a decryption passphrase.
*/
__LA_DECL int archive_read_add_passphrase(struct archive *, const char *);
__LA_DECL int archive_read_set_passphrase_callback(struct archive *,
void *client_data, archive_passphrase_callback *);
/*-
* Convenience function to recreate the current entry (whose header
* has just been read) on disk.
@ -562,6 +684,10 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
/* Default: Do not use HFS+ compression if it was not compressed. */
/* This has no effect except on Mac OS v10.6 or later. */
#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
/* Default: Do not reject entries with absolute paths */
#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
/* Default: Do not clear no-change flags when unlinking object */
#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000)
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
@ -573,7 +699,7 @@ __LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
/* Record the dev/ino of a file that will not be written. This is
* generally set to the dev/ino of the archive being read. */
__LA_DECL void archive_read_extract_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
la_int64_t, la_int64_t);
/* Close the file and release most resources. */
__LA_DECL int archive_read_close(struct archive *);
@ -612,7 +738,7 @@ __LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
/* The dev/ino of a file that won't be archived. This is used
* to avoid recursively adding an archive to itself. */
__LA_DECL int archive_write_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
la_int64_t, la_int64_t);
#if ARCHIVE_VERSION_NUMBER < 4000000
__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
@ -643,6 +769,7 @@ __LA_DECL int archive_write_add_filter_compress(struct archive *);
__LA_DECL int archive_write_add_filter_grzip(struct archive *);
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
__LA_DECL int archive_write_add_filter_lz4(struct archive *);
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
__LA_DECL int archive_write_add_filter_lzop(struct archive *);
@ -670,12 +797,16 @@ __LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_raw(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *);
__LA_DECL int archive_write_set_format_v7tar(struct archive *);
__LA_DECL int archive_write_set_format_warc(struct archive *);
__LA_DECL int archive_write_set_format_xar(struct archive *);
__LA_DECL int archive_write_set_format_zip(struct archive *);
__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename);
__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
__LA_DECL int archive_write_open(struct archive *, void *,
@ -700,12 +831,12 @@ __LA_DECL int archive_write_open_memory(struct archive *,
*/
__LA_DECL int archive_write_header(struct archive *,
struct archive_entry *);
__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
__LA_DECL la_ssize_t archive_write_data(struct archive *,
const void *, size_t);
/* This interface is currently only available for archive_write_disk handles. */
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
const void *, size_t, __LA_INT64_T);
__LA_DECL la_ssize_t archive_write_data_block(struct archive *,
const void *, size_t, la_int64_t);
__LA_DECL int archive_write_finish_entry(struct archive *);
__LA_DECL int archive_write_close(struct archive *);
@ -740,6 +871,13 @@ __LA_DECL int archive_write_set_option(struct archive *_a,
__LA_DECL int archive_write_set_options(struct archive *_a,
const char *opts);
/*
* Set a encryption passphrase.
*/
__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p);
__LA_DECL int archive_write_set_passphrase_callback(struct archive *,
void *client_data, archive_passphrase_callback *);
/*-
* ARCHIVE_WRITE_DISK API
*
@ -759,7 +897,7 @@ __LA_DECL int archive_write_set_options(struct archive *_a,
__LA_DECL struct archive *archive_write_disk_new(void);
/* This file will not be overwritten. */
__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
la_int64_t, la_int64_t);
/* Set flags to control how the next item gets created.
* This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
__LA_DECL int archive_write_disk_set_options(struct archive *,
@ -789,14 +927,14 @@ __LA_DECL int archive_write_disk_set_standard_lookup(struct archive *);
*/
__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
void * /* private_data */,
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
la_int64_t (*)(void *, const char *, la_int64_t),
void (* /* cleanup */)(void *));
__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
void * /* private_data */,
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
la_int64_t (*)(void *, const char *, la_int64_t),
void (* /* cleanup */)(void *));
__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T);
__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T);
__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t);
__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t);
/*
* ARCHIVE_READ_DISK API
@ -817,19 +955,19 @@ __LA_DECL int archive_read_disk_entry_from_file(struct archive *,
struct archive_entry *, int /* fd */, const struct stat *);
/* Look up gname for gid or uname for uid. */
/* Default implementations are very, very stupid. */
__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T);
__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T);
__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t);
__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t);
/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
* results for performance. */
__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *);
/* You can install your own lookups if you like. */
__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *,
void * /* private_data */,
const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
const char *(* /* lookup_fn */)(void *, la_int64_t),
void (* /* cleanup_fn */)(void *));
__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *,
void * /* private_data */,
const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
const char *(* /* lookup_fn */)(void *, la_int64_t),
void (* /* cleanup_fn */)(void *));
/* Start traversal. */
__LA_DECL int archive_read_disk_open(struct archive *, const char *);
@ -859,8 +997,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
/* Default: Skip a mac resource fork file whose prefix is "._" because of
* using copyfile. */
#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004)
/* Default: Do not traverse mount points. */
/* Default: Traverse mount points. */
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
/* Default: Xattrs are read from disk. */
#define ARCHIVE_READDISK_NO_XATTR (0x0010)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
@ -879,6 +1019,10 @@ __LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
int (*_metadata_filter_func)(struct archive *, void *,
struct archive_entry *), void *_client_data);
/* Simplified cleanup interface;
* This calls archive_read_free() or archive_write_free() as needed. */
__LA_DECL int archive_free(struct archive *);
/*
* Accessor functions to read/set various information in
* the struct archive object:
@ -889,7 +1033,7 @@ __LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
* last filter, which is always the pseudo-filter that wraps the
* client callbacks. */
__LA_DECL int archive_filter_count(struct archive *);
__LA_DECL __LA_INT64_T archive_filter_bytes(struct archive *, int);
__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int);
__LA_DECL int archive_filter_code(struct archive *, int);
__LA_DECL const char * archive_filter_name(struct archive *, int);
@ -897,10 +1041,10 @@ __LA_DECL const char * archive_filter_name(struct archive *, int);
/* These don't properly handle multiple filters, so are deprecated and
* will eventually be removed. */
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *)
__LA_DECL la_int64_t archive_position_compressed(struct archive *)
__LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *)
__LA_DECL la_int64_t archive_position_uncompressed(struct archive *)
__LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
__LA_DECL const char *archive_compression_name(struct archive *)
@ -1016,8 +1160,8 @@ __LA_DECL int archive_match_exclude_entry(struct archive *,
__LA_DECL int archive_match_owner_excluded(struct archive *,
struct archive_entry *);
/* Add inclusion uid, gid, uname and gname. */
__LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T);
__LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T);
__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t);
__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t);
__LA_DECL int archive_match_include_uname(struct archive *, const char *);
__LA_DECL int archive_match_include_uname_w(struct archive *,
const wchar_t *);
@ -1025,6 +1169,10 @@ __LA_DECL int archive_match_include_gname(struct archive *, const char *);
__LA_DECL int archive_match_include_gname_w(struct archive *,
const wchar_t *);
/* Utility functions */
/* Convenience function to sort a NULL terminated list of strings */
__LA_DECL int archive_utility_string_sort(char **);
#ifdef __cplusplus
}
#endif
@ -1032,9 +1180,4 @@ __LA_DECL int archive_match_include_gname_w(struct archive *,
/* These are meaningless outside of this header. */
#undef __LA_DECL
/* These need to remain defined because they're used in the
* callback type definitions. XXX Fix this. This is ugly. XXX */
/* #undef __LA_INT64_T */
/* #undef __LA_SSIZE_T */
#endif /* !ARCHIVE_H_INCLUDED */

View File

@ -0,0 +1,448 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "archive.h"
#include "archive_cryptor_private.h"
/*
* On systems that do not support any recognized crypto libraries,
* this file will normally define no usable symbols.
*
* But some compilers and linkers choke on empty object files, so
* define a public symbol that will always exist. This could
* be removed someday if this file gains another always-present
* symbol definition.
*/
int __libarchive_cryptor_build_hack(void) {
return 0;
}
#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len)
{
CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
derived_key, derived_key_len);
return 0;
}
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
#ifdef _MSC_VER
#pragma comment(lib, "Bcrypt.lib")
#endif
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE hAlg;
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (!BCRYPT_SUCCESS(status))
return -1;
status = BCryptDeriveKeyPBKDF2(hAlg,
(PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
(PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
(PUCHAR)derived_key, (ULONG)derived_key_len, 0);
BCryptCloseAlgorithmProvider(hAlg, 0);
return (BCRYPT_SUCCESS(status)) ? 0: -1;
}
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len) {
pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
salt_len, salt, derived_key_len, derived_key);
return 0;
}
#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len) {
PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
derived_key_len, derived_key);
return 0;
}
#else
/* Stub */
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len) {
(void)pw; /* UNUSED */
(void)pw_len; /* UNUSED */
(void)salt; /* UNUSED */
(void)salt_len; /* UNUSED */
(void)rounds; /* UNUSED */
(void)derived_key; /* UNUSED */
(void)derived_key_len; /* UNUSED */
return -1; /* UNSUPPORTED */
}
#endif
#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
# define kCCAlgorithmAES kCCAlgorithmAES128
# endif
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
CCCryptorStatus r;
ctx->key_len = key_len;
memcpy(ctx->key, key, key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
ctx->encr_pos = AES_BLOCK_SIZE;
r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
return (r == kCCSuccess)? 0: -1;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
CCCryptorRef ref = ctx->ctx;
CCCryptorStatus r;
r = CCCryptorReset(ref, NULL);
if (r != kCCSuccess)
return -1;
r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
AES_BLOCK_SIZE, NULL);
return (r == kCCSuccess)? 0: -1;
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{
memset(ctx->key, 0, ctx->key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
return 0;
}
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_KEY_HANDLE hKey;
DWORD keyObj_len, aes_key_len;
PBYTE keyObj;
ULONG result;
NTSTATUS status;
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
ctx->hAlg = NULL;
ctx->hKey = NULL;
ctx->keyObj = NULL;
switch (key_len) {
case 16: aes_key_len = 128; break;
case 24: aes_key_len = 192; break;
case 32: aes_key_len = 256; break;
default: return -1;
}
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
MS_PRIMITIVE_PROVIDER, 0);
if (!BCRYPT_SUCCESS(status))
return -1;
status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
sizeof(key_lengths), &result, 0);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
if (key_lengths.dwMinLength > aes_key_len
|| key_lengths.dwMaxLength < aes_key_len) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
sizeof(keyObj_len), &result, 0);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
if (keyObj == NULL) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
(PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
HeapFree(GetProcessHeap(), 0, keyObj);
return -1;
}
status = BCryptGenerateSymmetricKey(hAlg, &hKey,
keyObj, keyObj_len,
(PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
HeapFree(GetProcessHeap(), 0, keyObj);
return -1;
}
ctx->hAlg = hAlg;
ctx->hKey = hKey;
ctx->keyObj = keyObj;
ctx->keyObj_len = keyObj_len;
ctx->encr_pos = AES_BLOCK_SIZE;
return 0;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
NTSTATUS status;
ULONG result;
status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
&result, 0);
return BCRYPT_SUCCESS(status) ? 0 : -1;
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{
if (ctx->hAlg != NULL) {
BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
ctx->hAlg = NULL;
BCryptDestroyKey(ctx->hKey);
ctx->hKey = NULL;
HeapFree(GetProcessHeap(), 0, ctx->keyObj);
ctx->keyObj = NULL;
}
memset(ctx, 0, sizeof(*ctx));
return 0;
}
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
ctx->key_len = key_len;
memcpy(ctx->key, key, key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
ctx->encr_pos = AES_BLOCK_SIZE;
memset(&ctx->ctx, 0, sizeof(ctx->ctx));
return 0;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
return 0;
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
return 0;
}
#elif defined(HAVE_LIBCRYPTO)
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
switch (key_len) {
case 16: ctx->type = EVP_aes_128_ecb(); break;
case 24: ctx->type = EVP_aes_192_ecb(); break;
case 32: ctx->type = EVP_aes_256_ecb(); break;
default: ctx->type = NULL; return -1;
}
ctx->key_len = key_len;
memcpy(ctx->key, key, key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
ctx->encr_pos = AES_BLOCK_SIZE;
EVP_CIPHER_CTX_init(&ctx->ctx);
return 0;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
int outl = 0;
int r;
r = EVP_EncryptInit_ex(&ctx->ctx, ctx->type, NULL, ctx->key, NULL);
if (r == 0)
return -1;
r = EVP_EncryptUpdate(&ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
AES_BLOCK_SIZE);
if (r == 0 || outl != AES_BLOCK_SIZE)
return -1;
return 0;
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{
EVP_CIPHER_CTX_cleanup(&ctx->ctx);
memset(ctx->key, 0, ctx->key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
return 0;
}
#else
#define ARCHIVE_CRYPTOR_STUB
/* Stub */
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
(void)ctx; /* UNUSED */
(void)key; /* UNUSED */
(void)key_len; /* UNUSED */
return -1;
}
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
(void)ctx; /* UNUSED */
return -1;
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{
(void)ctx; /* UNUSED */
return 0;
}
#endif
#ifdef ARCHIVE_CRYPTOR_STUB
static int
aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
size_t in_len, uint8_t * const out, size_t *out_len)
{
(void)ctx; /* UNUSED */
(void)in; /* UNUSED */
(void)in_len; /* UNUSED */
(void)out; /* UNUSED */
(void)out_len; /* UNUSED */
aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
return -1;
}
#else
static void
aes_ctr_increase_counter(archive_crypto_ctx *ctx)
{
uint8_t *const nonce = ctx->nonce;
int j;
for (j = 0; j < 8; j++) {
if (++nonce[j])
break;
}
}
static int
aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
size_t in_len, uint8_t * const out, size_t *out_len)
{
uint8_t *const ebuf = ctx->encr_buf;
unsigned pos = ctx->encr_pos;
unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
unsigned i;
for (i = 0; i < max; ) {
if (pos == AES_BLOCK_SIZE) {
aes_ctr_increase_counter(ctx);
if (aes_ctr_encrypt_counter(ctx) != 0)
return -1;
while (max -i >= AES_BLOCK_SIZE) {
for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
out[i+pos] = in[i+pos] ^ ebuf[pos];
i += AES_BLOCK_SIZE;
aes_ctr_increase_counter(ctx);
if (aes_ctr_encrypt_counter(ctx) != 0)
return -1;
}
pos = 0;
if (i >= max)
break;
}
out[i] = in[i] ^ ebuf[pos++];
i++;
}
ctx->encr_pos = pos;
*out_len = i;
return 0;
}
#endif /* ARCHIVE_CRYPTOR_STUB */
const struct archive_cryptor __archive_cryptor =
{
&pbkdf2_sha1,
&aes_ctr_init,
&aes_ctr_update,
&aes_ctr_release,
&aes_ctr_init,
&aes_ctr_update,
&aes_ctr_release,
};

View File

@ -0,0 +1,163 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* 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.
*/
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
/*
* On systems that do not support any recognized crypto libraries,
* the archive_cryptor.c file will normally define no usable symbols.
*
* But some compilers and linkers choke on empty object files, so
* define a public symbol that will always exist. This could
* be removed someday if this file gains another always-present
* symbol definition.
*/
int __libarchive_cryptor_build_hack(void);
#ifdef __APPLE__
# include <AvailabilityMacros.h>
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
# endif
#endif
#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonKeyDerivation.h>
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE kCCKeySizeAES256
typedef struct {
CCCryptorRef ctx;
uint8_t key[AES_MAX_KEY_SIZE];
unsigned key_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
} archive_crypto_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
#include <Bcrypt.h>
/* Common in other bcrypt implementations, but missing from VS2008. */
#ifndef BCRYPT_SUCCESS
#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
#endif
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
typedef struct {
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_KEY_HANDLE hKey;
PBYTE keyObj;
DWORD keyObj_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
} archive_crypto_ctx;
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
#if defined(HAVE_NETTLE_PBKDF2_H)
#include <nettle/pbkdf2.h>
#endif
#include <nettle/aes.h>
typedef struct {
struct aes_ctx ctx;
uint8_t key[AES_MAX_KEY_SIZE];
unsigned key_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
} archive_crypto_ctx;
#elif defined(HAVE_LIBCRYPTO)
#include <openssl/evp.h>
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE 32
typedef struct {
EVP_CIPHER_CTX ctx;
const EVP_CIPHER *type;
uint8_t key[AES_MAX_KEY_SIZE];
unsigned key_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
} archive_crypto_ctx;
#else
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE 32
typedef int archive_crypto_ctx;
#endif
/* defines */
#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\
__archive_cryptor.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)
#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \
__archive_cryptor.decrypto_aes_ctr_init(ctx, key, key_len)
#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
__archive_cryptor.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
#define archive_decrypto_aes_ctr_release(ctx) \
__archive_cryptor.decrypto_aes_ctr_release(ctx)
#define archive_encrypto_aes_ctr_init(ctx, key, key_len) \
__archive_cryptor.encrypto_aes_ctr_init(ctx, key, key_len)
#define archive_encrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \
__archive_cryptor.encrypto_aes_ctr_update(ctx, in, in_len, out, out_len)
#define archive_encrypto_aes_ctr_release(ctx) \
__archive_cryptor.encrypto_aes_ctr_release(ctx)
/* Minimal interface to cryptographic functionality for internal use in
* libarchive */
struct archive_cryptor
{
/* PKCS5 PBKDF2 HMAC-SHA1 */
int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt,
size_t salt_len, unsigned rounds, uint8_t *derived_key,
size_t derived_key_len);
/* AES CTR mode(little endian version) */
int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
size_t, uint8_t *, size_t *);
int (*decrypto_aes_ctr_release)(archive_crypto_ctx *);
int (*encrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t);
int (*encrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *,
size_t, uint8_t *, size_t *);
int (*encrypto_aes_ctr_release)(archive_crypto_ctx *);
};
extern const struct archive_cryptor __archive_cryptor;
#endif

View File

@ -28,7 +28,7 @@
#include "archive_platform.h"
#include "archive.h"
#include "archive_crypto_private.h"
#include "archive_digest_private.h"
/* In particular, force the configure probe to break if it tries
* to test a combination of OpenSSL and libmd. */
@ -1216,8 +1216,8 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
#endif
/* NOTE: Crypto functions are set based on availability and by the following
* order of preference.
/* NOTE: Message Digest functions are set based on availability and by the
* following order of preference.
* 1. libc
* 2. libc2
* 3. libc3
@ -1227,7 +1227,7 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
* 7. libmd
* 8. Windows API
*/
const struct archive_crypto __archive_crypto =
const struct archive_digest __archive_digest =
{
/* MD5 */
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
@ -1412,7 +1412,7 @@ const struct archive_crypto __archive_crypto =
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
&__archive_nettle_sha512init,
&__archive_nettle_sha512update,
&__archive_nettle_sha512final,
&__archive_nettle_sha512final
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
&__archive_openssl_sha512init,
&__archive_openssl_sha512update,

View File

@ -264,11 +264,11 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_MD5
#endif
#define archive_md5_init(ctx)\
__archive_crypto.md5init(ctx)
__archive_digest.md5init(ctx)
#define archive_md5_final(ctx, md)\
__archive_crypto.md5final(ctx, md)
__archive_digest.md5final(ctx, md)
#define archive_md5_update(ctx, buf, n)\
__archive_crypto.md5update(ctx, buf, n)
__archive_digest.md5update(ctx, buf, n)
#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\
defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\
@ -276,11 +276,11 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_RMD160
#endif
#define archive_rmd160_init(ctx)\
__archive_crypto.rmd160init(ctx)
__archive_digest.rmd160init(ctx)
#define archive_rmd160_final(ctx, md)\
__archive_crypto.rmd160final(ctx, md)
__archive_digest.rmd160final(ctx, md)
#define archive_rmd160_update(ctx, buf, n)\
__archive_crypto.rmd160update(ctx, buf, n)
__archive_digest.rmd160update(ctx, buf, n)
#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\
defined(ARCHIVE_CRYPTO_SHA1_LIBMD) || \
@ -291,11 +291,11 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_SHA1
#endif
#define archive_sha1_init(ctx)\
__archive_crypto.sha1init(ctx)
__archive_digest.sha1init(ctx)
#define archive_sha1_final(ctx, md)\
__archive_crypto.sha1final(ctx, md)
__archive_digest.sha1final(ctx, md)
#define archive_sha1_update(ctx, buf, n)\
__archive_crypto.sha1update(ctx, buf, n)
__archive_digest.sha1update(ctx, buf, n)
#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
@ -308,11 +308,11 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_SHA256
#endif
#define archive_sha256_init(ctx)\
__archive_crypto.sha256init(ctx)
__archive_digest.sha256init(ctx)
#define archive_sha256_final(ctx, md)\
__archive_crypto.sha256final(ctx, md)
__archive_digest.sha256final(ctx, md)
#define archive_sha256_update(ctx, buf, n)\
__archive_crypto.sha256update(ctx, buf, n)
__archive_digest.sha256update(ctx, buf, n)
#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
@ -324,11 +324,11 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_SHA384
#endif
#define archive_sha384_init(ctx)\
__archive_crypto.sha384init(ctx)
__archive_digest.sha384init(ctx)
#define archive_sha384_final(ctx, md)\
__archive_crypto.sha384final(ctx, md)
__archive_digest.sha384final(ctx, md)
#define archive_sha384_update(ctx, buf, n)\
__archive_crypto.sha384update(ctx, buf, n)
__archive_digest.sha384update(ctx, buf, n)
#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
@ -341,14 +341,14 @@ typedef unsigned char archive_sha512_ctx;
#define ARCHIVE_HAS_SHA512
#endif
#define archive_sha512_init(ctx)\
__archive_crypto.sha512init(ctx)
__archive_digest.sha512init(ctx)
#define archive_sha512_final(ctx, md)\
__archive_crypto.sha512final(ctx, md)
__archive_digest.sha512final(ctx, md)
#define archive_sha512_update(ctx, buf, n)\
__archive_crypto.sha512update(ctx, buf, n)
__archive_digest.sha512update(ctx, buf, n)
/* Minimal interface to crypto functionality for internal use in libarchive */
struct archive_crypto
/* Minimal interface to digest functionality for internal use in libarchive */
struct archive_digest
{
/* Message Digest */
int (*md5init)(archive_md5_ctx *ctx);
@ -371,6 +371,6 @@ struct archive_crypto
int (*sha512final)(archive_sha512_ctx *, void *);
};
extern const struct archive_crypto __archive_crypto;
extern const struct archive_digest __archive_digest;
#endif

View File

@ -44,10 +44,16 @@
* - Watcom C++ in C code. (For any version?)
* - SGI MIPSpro
* - Microsoft Visual C++ 6.0 (supposedly newer versions too)
* - IBM VisualAge 6 (XL v6)
* - Sun WorkShop C (SunPro) before 5.9
*/
#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
#define inline
#elif defined(_MSC_VER)
#elif defined(__IBMC__) && __IBMC__ < 700
#define inline
#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
#define inline
#elif defined(_MSC_VER) || defined(__osf__)
#define inline __inline
#endif
@ -58,7 +64,13 @@ archive_be16dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[0] << 8) | p[1]);
/* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p0 << 8) | p1);
}
static inline uint32_t
@ -66,7 +78,15 @@ archive_be32dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
/* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p3 = p[3];
unsigned int p2 = p[2];
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3);
}
static inline uint64_t
@ -82,7 +102,13 @@ archive_le16dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[1] << 8) | p[0]);
/* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p1 << 8) | p0);
}
static inline uint32_t
@ -90,7 +116,15 @@ archive_le32dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
/* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p3 = p[3];
unsigned int p2 = p[2];
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0);
}
static inline uint64_t

View File

@ -131,11 +131,11 @@ be discarded in favor of the new data.
.\" .Sh RETURN VALUES
.\" .Sh ERRORS
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry_acl 3 ,
.Xr archive_entry_paths 3 ,
.Xr archive_entry_perms 3 ,
.Xr archive_entry_time 3
.Xr libarchive 3 ,
.Sh HISTORY
The
.Nm libarchive

View File

@ -201,6 +201,9 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy encryption status */
entry2->encryption = entry->encryption;
/* Copy ACL data over. */
archive_acl_copy(&entry2->acl, &entry->acl);
@ -415,6 +418,18 @@ archive_entry_gname(struct archive_entry *entry)
return (NULL);
}
const char *
archive_entry_gname_utf8(struct archive_entry *entry)
{
const char *p;
if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
const wchar_t *
archive_entry_gname_w(struct archive_entry *entry)
{
@ -447,6 +462,20 @@ archive_entry_hardlink(struct archive_entry *entry)
return (NULL);
}
const char *
archive_entry_hardlink_utf8(struct archive_entry *entry)
{
const char *p;
if ((entry->ae_set & AE_SET_HARDLINK) == 0)
return (NULL);
if (archive_mstring_get_utf8(
entry->archive, &entry->ae_hardlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
const wchar_t *
archive_entry_hardlink_w(struct archive_entry *entry)
{
@ -533,6 +562,18 @@ archive_entry_pathname(struct archive_entry *entry)
return (NULL);
}
const char *
archive_entry_pathname_utf8(struct archive_entry *entry)
{
const char *p;
if (archive_mstring_get_utf8(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
const wchar_t *
archive_entry_pathname_w(struct archive_entry *entry)
{
@ -634,6 +675,20 @@ archive_entry_symlink(struct archive_entry *entry)
return (NULL);
}
const char *
archive_entry_symlink_utf8(struct archive_entry *entry)
{
const char *p;
if ((entry->ae_set & AE_SET_SYMLINK) == 0)
return (NULL);
if (archive_mstring_get_utf8(
entry->archive, &entry->ae_symlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
const wchar_t *
archive_entry_symlink_w(struct archive_entry *entry)
{
@ -677,6 +732,17 @@ archive_entry_uname(struct archive_entry *entry)
return (NULL);
}
const char *
archive_entry_uname_utf8(struct archive_entry *entry)
{
const char *p;
if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
const wchar_t *
archive_entry_uname_w(struct archive_entry *entry)
{
@ -695,6 +761,24 @@ _archive_entry_uname_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
}
int
archive_entry_is_data_encrypted(struct archive_entry *entry)
{
return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
}
int
archive_entry_is_metadata_encrypted(struct archive_entry *entry)
{
return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
}
int
archive_entry_is_encrypted(struct archive_entry *entry)
{
return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
}
/*
* Functions to set archive_entry properties.
*/
@ -747,6 +831,12 @@ archive_entry_set_gname(struct archive_entry *entry, const char *name)
archive_mstring_copy_mbs(&entry->ae_gname, name);
}
void
archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name)
{
archive_mstring_copy_utf8(&entry->ae_gname, name);
}
void
archive_entry_copy_gname(struct archive_entry *entry, const char *name)
{
@ -803,6 +893,16 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
entry->ae_set &= ~AE_SET_HARDLINK;
}
void
archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target)
{
archive_mstring_copy_utf8(&entry->ae_hardlink, target);
if (target != NULL)
entry->ae_set |= AE_SET_HARDLINK;
else
entry->ae_set &= ~AE_SET_HARDLINK;
}
void
archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
{
@ -941,6 +1041,15 @@ archive_entry_set_link(struct archive_entry *entry, const char *target)
archive_mstring_copy_mbs(&entry->ae_hardlink, target);
}
void
archive_entry_set_link_utf8(struct archive_entry *entry, const char *target)
{
if (entry->ae_set & AE_SET_SYMLINK)
archive_mstring_copy_utf8(&entry->ae_symlink, target);
else
archive_mstring_copy_utf8(&entry->ae_hardlink, target);
}
/* Set symlink if symlink is already set, else set hardlink. */
void
archive_entry_copy_link(struct archive_entry *entry, const char *target)
@ -1030,6 +1139,12 @@ archive_entry_set_pathname(struct archive_entry *entry, const char *name)
archive_mstring_copy_mbs(&entry->ae_pathname, name);
}
void
archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name)
{
archive_mstring_copy_utf8(&entry->ae_pathname, name);
}
void
archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
{
@ -1130,6 +1245,16 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
entry->ae_set &= ~AE_SET_SYMLINK;
}
void
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
{
archive_mstring_copy_utf8(&entry->ae_symlink, linkname);
if (linkname != NULL)
entry->ae_set |= AE_SET_SYMLINK;
else
entry->ae_set &= ~AE_SET_SYMLINK;
}
void
archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
{
@ -1193,6 +1318,12 @@ archive_entry_set_uname(struct archive_entry *entry, const char *name)
archive_mstring_copy_mbs(&entry->ae_uname, name);
}
void
archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name)
{
archive_mstring_copy_utf8(&entry->ae_uname, name);
}
void
archive_entry_copy_uname(struct archive_entry *entry, const char *name)
{
@ -1216,6 +1347,26 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
return (0);
}
void
archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
{
if (is_encrypted) {
entry->encryption |= AE_ENCRYPTION_DATA;
} else {
entry->encryption &= ~AE_ENCRYPTION_DATA;
}
}
void
archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
{
if (is_encrypted) {
entry->encryption |= AE_ENCRYPTION_METADATA;
} else {
entry->encryption &= ~AE_ENCRYPTION_METADATA;
}
}
int
_archive_entry_copy_uname_l(struct archive_entry *entry,
const char *name, size_t len, struct archive_string_conv *sc)
@ -1588,19 +1739,23 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
while (*start == '\t' || *start == ' ' || *start == ',')
start++;
while (*start != '\0') {
size_t length;
/* Locate end of token. */
end = start;
while (*end != '\0' && *end != '\t' &&
*end != ' ' && *end != ',')
end++;
length = end - start;
for (flag = flags; flag->name != NULL; flag++) {
if (memcmp(start, flag->name, end - start) == 0) {
size_t flag_length = strlen(flag->name);
if (length == flag_length
&& memcmp(start, flag->name, length) == 0) {
/* Matched "noXXXX", so reverse the sense. */
clear |= flag->set;
set |= flag->clear;
break;
} else if (memcmp(start, flag->name + 2, end - start)
== 0) {
} else if (length == flag_length - 2
&& memcmp(start, flag->name + 2, length) == 0) {
/* Matched "XXXX", so don't reverse. */
set |= flag->set;
clear |= flag->clear;
@ -1652,19 +1807,23 @@ ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
while (*start == L'\t' || *start == L' ' || *start == L',')
start++;
while (*start != L'\0') {
size_t length;
/* Locate end of token. */
end = start;
while (*end != L'\0' && *end != L'\t' &&
*end != L' ' && *end != L',')
end++;
length = end - start;
for (flag = flags; flag->wname != NULL; flag++) {
if (wmemcmp(start, flag->wname, end - start) == 0) {
size_t flag_length = wcslen(flag->wname);
if (length == flag_length
&& wmemcmp(start, flag->wname, length) == 0) {
/* Matched "noXXXX", so reverse the sense. */
clear |= flag->set;
set |= flag->clear;
break;
} else if (wmemcmp(start, flag->wname + 2, end - start)
== 0) {
} else if (length == flag_length - 2
&& wmemcmp(start, flag->wname + 2, length) == 0) {
/* Matched "XXXX", so don't reverse. */
set |= flag->set;
clear |= flag->clear;

View File

@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3001002
#define ARCHIVE_VERSION_NUMBER 3002000
/*
* Note: archive_entry.h is for use outside of libarchive; the
@ -48,14 +48,20 @@
#endif
/* Get a suitable 64-bit integer type. */
#if defined(_WIN32) && !defined(__CYGWIN__)
# define __LA_INT64_T __int64
#else
#include <unistd.h>
# if defined(_SCO_DS)
# define __LA_INT64_T long long
#if !defined(__LA_INT64_T_DEFINED)
# if ARCHIVE_VERSION_NUMBER < 4000000
#define __LA_INT64_T la_int64_t
# endif
#define __LA_INT64_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
typedef __int64 la_int64_t;
# else
# define __LA_INT64_T int64_t
#include <unistd.h>
# if defined(_SCO_DS) || defined(__osf__)
typedef long long la_int64_t;
# else
typedef int64_t la_int64_t;
# endif
# endif
#endif
@ -63,12 +69,17 @@
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
# define __LA_MODE_T int
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
# define __LA_MODE_T unsigned short
#else
# define __LA_MODE_T mode_t
#endif
/* Large file support for Android */
#ifdef __ANDROID__
#include "android_lf.h"
#endif
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
* .lib. The default here assumes you're building a DLL. Only
@ -206,13 +217,15 @@ __LA_DECL void archive_entry_fflags(struct archive_entry *,
unsigned long * /* set */,
unsigned long * /* clear */);
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_gid(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *);
__LA_DECL const char *archive_entry_gname(struct archive_entry *);
__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *);
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
@ -220,6 +233,7 @@ __LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
@ -227,14 +241,19 @@ __LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
__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 const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
/*
* Set fields in an archive_entry.
@ -266,18 +285,21 @@ __LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
const char *);
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
const wchar_t *);
__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
@ -286,6 +308,7 @@ __LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
@ -293,19 +316,23 @@ __LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
__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_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 *);
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
/*
* Routines to bulk copy fields to/from a platform-native "struct
* stat." Libarchive used to just store a struct stat inside of each
@ -514,7 +541,7 @@ __LA_DECL int archive_entry_xattr_next(struct archive_entry *,
__LA_DECL void archive_entry_sparse_clear(struct archive_entry *);
__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
__LA_INT64_T /* offset */, __LA_INT64_T /* length */);
la_int64_t /* offset */, la_int64_t /* length */);
/*
* To retrieve the xattr list, first "reset", then repeatedly ask for the
@ -524,7 +551,7 @@ __LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
__LA_DECL int archive_entry_sparse_count(struct archive_entry *);
__LA_DECL int archive_entry_sparse_reset(struct archive_entry *);
__LA_DECL int archive_entry_sparse_next(struct archive_entry *,
__LA_INT64_T * /* offset */, __LA_INT64_T * /* length */);
la_int64_t * /* offset */, la_int64_t * /* length */);
/*
* Utility to match up hardlinks.

View File

@ -226,8 +226,8 @@ The returned long string is valid until the next call to
or
.Fn archive_entry_acl_text_w .
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry 3
.Xr libarchive 3 ,
.Sh BUGS
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
and

View File

@ -44,6 +44,10 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_NSEC
archive_entry_set_atime(entry, st->st_atime, st->st_atime_nsec);
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_nsec);
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);

View File

@ -149,5 +149,5 @@ It doesn't have a corresponding get accessor function.
is an alias for
.Fn archive_entry_copy_XXX .
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry 3
.Xr libarchive 3 ,

View File

@ -194,11 +194,11 @@ every name that is recognized.
.Xr strtofflags 3 ,
which stops parsing at the first unrecognized name.)
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry 3 ,
.Xr archive_entry_acl 3 ,
.Xr archive_read_disk 3 ,
.Xr archive_write_disk 3
.Xr libarchive 3 ,
.Sh BUGS
The platform types
.Vt uid_t

View File

@ -154,6 +154,11 @@ struct archive_entry {
/* Not used within libarchive; useful for some clients. */
struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */
#define AE_ENCRYPTION_NONE 0
#define AE_ENCRYPTION_DATA 1
#define AE_ENCRYPTION_METADATA 2
char encryption;
void *mac_metadata;
size_t mac_metadata_size;

View File

@ -58,7 +58,7 @@ archive_entry_sparse_add_entry(struct archive_entry *entry,
if (offset < 0 || length < 0)
/* Invalid value */
return;
if (offset + length < 0 ||
if (offset > INT64_MAX - length ||
offset + length > archive_entry_size(entry))
/* A value of "length" parameter is too large. */
return;

View File

@ -226,7 +226,7 @@ and
are used by
.Xr archive_entry_linkify 3
to find hardlinks.
The pair of device and inode is suppossed to identify hardlinked files.
The pair of device and inode is supposed to identify hardlinked files.
.Pp
The device major and minor number can be obtained independently using
.Fn archive_entry_devmajor
@ -267,8 +267,8 @@ platforms.
Some archive formats use the combined form, while other formats use
the split form.
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry_acl 3 ,
.Xr archive_entry_perms 3 ,
.Xr archive_entry_time 3 ,
.Xr libarchive 3 ,
.Xr stat 2

View File

@ -113,8 +113,8 @@ The current state can be queried using
.Fn XXX_is_set .
Unset time fields have a second and nanosecond field of 0.
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry 3
.Xr libarchive 3 ,
.Sh HISTORY
The
.Nm libarchive

View File

@ -98,7 +98,10 @@ archive_entry_xattr_add_entry(struct archive_entry *entry,
/* XXX Error XXX */
return;
xp->name = strdup(name);
if ((xp->name = strdup(name)) == NULL)
/* XXX Error XXX */
return;
if ((xp->value = malloc(size)) != NULL) {
memcpy(xp->value, value, size);
xp->size = size;

View File

@ -38,8 +38,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <time.h>
/* This file defines a single public function. */
time_t __archive_get_date(time_t now, char *);
#define __LIBARCHIVE_BUILD 1
#include "archive_getdate.h"
/* Basic time units. */
#define EPOCH 1970
@ -782,7 +782,7 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
* Tokenizer.
*/
static int
nexttoken(char **in, time_t *value)
nexttoken(const char **in, time_t *value)
{
char c;
char buff[64];
@ -809,7 +809,7 @@ nexttoken(char **in, time_t *value)
/* Try the next token in the word table first. */
/* This allows us to match "2nd", for example. */
{
char *src = *in;
const char *src = *in;
const struct LEXICON *tp;
unsigned i = 0;
@ -894,7 +894,7 @@ difftm (struct tm *a, struct tm *b)
* TODO: tokens[] array should be dynamically sized.
*/
time_t
__archive_get_date(time_t now, char *p)
__archive_get_date(time_t now, const char *p)
{
struct token tokens[256];
struct gdstate _gds;

View File

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2003-2015 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef ARCHIVE_GETDATE_H_INCLUDED
#define ARCHIVE_GETDATE_H_INCLUDED
#include <time.h>
time_t __archive_get_date(time_t now, const char *);
#endif

View File

@ -0,0 +1,248 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "archive.h"
#include "archive_hmac_private.h"
/*
* On systems that do not support any recognized crypto libraries,
* the archive_hmac.c file is expected to define no usable symbols.
*
* But some compilers and linkers choke on empty object files, so
* define a public symbol that will always exist. This could
* be removed someday if this file gains another always-present
* symbol definition.
*/
int __libarchive_hmac_build_hack(void) {
return 0;
}
#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len);
return 0;
}
static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
CCHmacUpdate(ctx, data, data_len);
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
CCHmacFinal(ctx, out);
*out_len = 20;
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_HASH_HANDLE hHash;
DWORD hash_len;
PBYTE hash;
ULONG result;
NTSTATUS status;
ctx->hAlg = NULL;
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (!BCRYPT_SUCCESS(status))
return -1;
status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len,
sizeof(hash_len), &result, 0);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len);
if (hash == NULL) {
BCryptCloseAlgorithmProvider(hAlg, 0);
return -1;
}
status = BCryptCreateHash(hAlg, &hHash, NULL, 0,
(PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG);
if (!BCRYPT_SUCCESS(status)) {
BCryptCloseAlgorithmProvider(hAlg, 0);
HeapFree(GetProcessHeap(), 0, hash);
return -1;
}
ctx->hAlg = hAlg;
ctx->hHash = hHash;
ctx->hash_len = hash_len;
ctx->hash = hash;
return 0;
}
static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0);
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0);
if (ctx->hash_len == *out_len)
memcpy(out, ctx->hash, *out_len);
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
if (ctx->hAlg != NULL) {
BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
HeapFree(GetProcessHeap(), 0, ctx->hash);
ctx->hAlg = NULL;
}
}
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
hmac_sha1_set_key(ctx, key_len, key);
return 0;
}
static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
hmac_sha1_update(ctx, data_len, data);
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
hmac_sha1_digest(ctx, (unsigned)*out_len, out);
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
#elif defined(HAVE_LIBCRYPTO)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
HMAC_CTX_init(ctx);
HMAC_Init(ctx, key, key_len, EVP_sha1());
return 0;
}
static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
HMAC_Update(ctx, data, data_len);
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
unsigned int len = (unsigned int)*out_len;
HMAC_Final(ctx, out, &len);
*out_len = len;
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
HMAC_CTX_cleanup(ctx);
memset(ctx, 0, sizeof(*ctx));
}
#else
/* Stub */
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
(void)ctx;/* UNUSED */
(void)key;/* UNUSED */
(void)key_len;/* UNUSED */
return -1;
}
static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
(void)ctx;/* UNUSED */
(void)data;/* UNUSED */
(void)data_len;/* UNUSED */
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
(void)ctx;/* UNUSED */
(void)out;/* UNUSED */
(void)out_len;/* UNUSED */
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
(void)ctx;/* UNUSED */
}
#endif
const struct archive_hmac __archive_hmac = {
&__hmac_sha1_init,
&__hmac_sha1_update,
&__hmac_sha1_final,
&__hmac_sha1_cleanup,
};

View File

@ -0,0 +1,106 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* 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.
*/
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
/*
* On systems that do not support any recognized crypto libraries,
* the archive_hmac.c file is expected to define no usable symbols.
*
* But some compilers and linkers choke on empty object files, so
* define a public symbol that will always exist. This could
* be removed someday if this file gains another always-present
* symbol definition.
*/
int __libarchive_hmac_build_hack(void);
#ifdef __APPLE__
# include <AvailabilityMacros.h>
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
# define ARCHIVE_HMAC_USE_Apple_CommonCrypto
# endif
#endif
#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
#include <CommonCrypto/CommonHMAC.h>
typedef CCHmacContext archive_hmac_sha1_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
#include <bcrypt.h>
typedef struct {
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_HASH_HANDLE hHash;
DWORD hash_len;
PBYTE hash;
} archive_hmac_sha1_ctx;
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
#include <nettle/hmac.h>
typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
#elif defined(HAVE_LIBCRYPTO)
#include <openssl/hmac.h>
typedef HMAC_CTX archive_hmac_sha1_ctx;
#else
typedef int archive_hmac_sha1_ctx;
#endif
/* HMAC */
#define archive_hmac_sha1_init(ctx, key, key_len)\
__archive_hmac.__hmac_sha1_init(ctx, key, key_len)
#define archive_hmac_sha1_update(ctx, data, data_len)\
__archive_hmac.__hmac_sha1_update(ctx, data, data_len)
#define archive_hmac_sha1_final(ctx, out, out_len)\
__archive_hmac.__hmac_sha1_final(ctx, out, out_len)
#define archive_hmac_sha1_cleanup(ctx)\
__archive_hmac.__hmac_sha1_cleanup(ctx)
struct archive_hmac {
/* HMAC */
int (*__hmac_sha1_init)(archive_hmac_sha1_ctx *, const uint8_t *,
size_t);
void (*__hmac_sha1_update)(archive_hmac_sha1_ctx *, const uint8_t *,
size_t);
void (*__hmac_sha1_final)(archive_hmac_sha1_ctx *, uint8_t *, size_t *);
void (*__hmac_sha1_cleanup)(archive_hmac_sha1_ctx *);
};
extern const struct archive_hmac __archive_hmac;
#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
#include "archive_entry.h"
#include "archive_getdate.h"
#include "archive_pathmatch.h"
#include "archive_rb.h"
#include "archive_string.h"
@ -184,7 +185,6 @@ static int time_excluded(struct archive_match *,
struct archive_entry *);
static int validate_time_flag(struct archive *, int, const char *);
time_t __archive_get_date(time_t now, const char *);
#define get_date __archive_get_date
static const struct archive_rb_tree_ops rb_ops_mbs = {
@ -580,6 +580,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
return (ARCHIVE_FATAL);
}
r = archive_read_support_format_raw(ar);
r = archive_read_support_format_empty(ar);
if (r != ARCHIVE_OK) {
archive_copy_error(&(a->archive), ar);
archive_read_free(ar);
@ -596,9 +597,13 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
}
r = archive_read_next_header(ar, &ae);
if (r != ARCHIVE_OK) {
archive_copy_error(&(a->archive), ar);
archive_read_free(ar);
return (r);
if (r == ARCHIVE_EOF) {
return (ARCHIVE_OK);
} else {
archive_copy_error(&(a->archive), ar);
return (r);
}
}
archive_string_init(&as);
@ -1152,7 +1157,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
{
/* NOTE: stat() on Windows cannot handle nano seconds. */
HANDLE h;
WIN32_FIND_DATA d;
WIN32_FIND_DATAA d;
if (path == NULL || *path == '\0') {
archive_set_error(&(a->archive), EINVAL, "pathname is empty");

View File

@ -42,9 +42,9 @@ _archive_set_option(struct archive *a,
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
mp = m != NULL && m[0] == '\0' ? NULL : m;
op = o != NULL && o[0] == '\0' ? NULL : o;
vp = v != NULL && v[0] == '\0' ? NULL : v;
mp = (m != NULL && m[0] != '\0') ? m : NULL;
op = (o != NULL && o[0] != '\0') ? o : NULL;
vp = (v != NULL && v[0] != '\0') ? v : NULL;
if (op == NULL && vp == NULL)
return (ARCHIVE_OK);

View File

@ -0,0 +1,329 @@
/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#include "archive_platform.h"
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#if !defined(lint)
__RCSID("$NetBSD$");
#endif /* not lint */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "archive_pack_dev.h"
static pack_t pack_netbsd;
static pack_t pack_freebsd;
static pack_t pack_8_8;
static pack_t pack_12_20;
static pack_t pack_14_18;
static pack_t pack_8_24;
static pack_t pack_bsdos;
static int compare_format(const void *, const void *);
static const char iMajorError[] = "invalid major number";
static const char iMinorError[] = "invalid minor number";
static const char tooManyFields[] = "too many fields for format";
/* This is blatantly stolen from libarchive/archive_entry.c,
* in an attempt to get this to play nice on MinGW... */
#if !defined(HAVE_MAJOR) && !defined(major)
/* Replacement for major/minor/makedev. */
#define major(x) ((int)(0x00ff & ((x) >> 8)))
#define minor(x) ((int)(0xffff00ff & (x)))
#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
#endif
/* Play games to come up with a suitable makedev() definition. */
#ifdef __QNXNTO__
/* QNX. <sigh> */
#include <sys/netmgr.h>
#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
#elif defined makedev
/* There's a "makedev" macro. */
#define apd_makedev(maj, min) makedev((maj), (min))
#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
/* Windows. <sigh> */
#define apd_makedev(maj, min) mkdev((maj), (min))
#else
/* There's a "makedev" function. */
#define apd_makedev(maj, min) makedev((maj), (min))
#endif
/* exported */
dev_t
pack_native(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = apd_makedev(numbers[0], numbers[1]);
if ((unsigned long)major(dev) != numbers[0])
*error = iMajorError;
else if ((unsigned long)minor(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
static dev_t
pack_netbsd(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_netbsd(numbers[0], numbers[1]);
if ((unsigned long)major_netbsd(dev) != numbers[0])
*error = iMajorError;
else if ((unsigned long)minor_netbsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0xffff00ff)))
static dev_t
pack_freebsd(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_freebsd(numbers[0], numbers[1]);
if ((unsigned long)major_freebsd(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_freebsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0x000000ff)))
static dev_t
pack_8_8(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_8(numbers[0], numbers[1]);
if ((unsigned long)major_8_8(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_8_8(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 0) & 0x000fffff)))
static dev_t
pack_12_20(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((unsigned long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \
(((y) << 0) & 0x0003ffff)))
static dev_t
pack_14_18(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_14_18(numbers[0], numbers[1]);
if ((unsigned long)major_14_18(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_14_18(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \
(((y) << 0) & 0x00ffffff)))
static dev_t
pack_8_24(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_24(numbers[0], numbers[1]);
if ((unsigned long)major_8_24(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_8_24(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 8) & 0x000fff00) | \
(((z) << 0) & 0x000000ff)))
static dev_t
pack_bsdos(int n, unsigned long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((unsigned long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else if (n == 3) {
dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
if ((unsigned long)major_12_12_8(dev) != numbers[0])
*error = iMajorError;
if ((unsigned long)unit_12_12_8(dev) != numbers[1])
*error = "invalid unit number";
if ((unsigned long)subunit_12_12_8(dev) != numbers[2])
*error = "invalid subunit number";
} else
*error = tooManyFields;
return (dev);
}
/* list of formats and pack functions */
/* this list must be sorted lexically */
static struct format {
const char *name;
pack_t *pack;
} formats[] = {
{"386bsd", pack_8_8},
{"4bsd", pack_8_8},
{"bsdos", pack_bsdos},
{"freebsd", pack_freebsd},
{"hpux", pack_8_24},
{"isc", pack_8_8},
{"linux", pack_8_8},
{"native", pack_native},
{"netbsd", pack_netbsd},
{"osf1", pack_12_20},
{"sco", pack_8_8},
{"solaris", pack_14_18},
{"sunos", pack_8_8},
{"svr3", pack_8_8},
{"svr4", pack_14_18},
{"ultrix", pack_8_8},
};
static int
compare_format(const void *key, const void *element)
{
const char *name;
const struct format *format;
name = key;
format = element;
return (strcmp(name, format->name));
}
pack_t *
pack_find(const char *name)
{
struct format *format;
format = bsearch(name, formats,
sizeof(formats)/sizeof(formats[0]),
sizeof(formats[0]), compare_format);
if (format == 0)
return (NULL);
return (format->pack);
}

View File

@ -0,0 +1,49 @@
/* $NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#ifndef _PACK_DEV_H
#define _PACK_DEV_H
typedef dev_t pack_t(int, unsigned long [], const char **);
pack_t *pack_find(const char *);
pack_t pack_native;
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
(((x) & 0x000000ff) >> 0)))
#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
#endif /* _PACK_DEV_H */

View File

@ -394,8 +394,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
if (*p == '/' && *s != '/')
return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == '*' || *p == '/' || *p == '/') {
/* Certain patterns anchor implicitly. */
if (*p == '*' || *p == '/') {
while (*p == '/')
++p;
while (*s == '/')
@ -434,8 +434,8 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
if (*p == L'/' && *s != L'/')
return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == L'*' || *p == L'/' || *p == L'/') {
/* Certain patterns anchor implicitly. */
if (*p == L'*' || *p == L'/') {
while (*p == L'/')
++p;
while (*s == L'/')

View File

@ -66,15 +66,18 @@
* headers as required.
*/
/* Get a real definition for __FBSDID if we can */
/* Get a real definition for __FBSDID or __RCSID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
/* If not, define them so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifndef __RCSID
#define __RCSID(a) struct _undefined_hack
#endif
/* Try to get standard C99-style integer type definitions. */
#if HAVE_INTTYPES_H
@ -114,6 +117,12 @@
#if !HAVE_DECL_UINT32_MAX
#define UINT32_MAX (~(uint32_t)0)
#endif
#if !HAVE_DECL_INT32_MAX
#define INT32_MAX ((int32_t)(UINT32_MAX >> 1))
#endif
#if !HAVE_DECL_INT32_MIN
#define INT32_MIN ((int32_t)(~INT32_MAX))
#endif
#if !HAVE_DECL_UINT64_MAX
#define UINT64_MAX (~(uint64_t)0)
#endif
@ -123,6 +132,15 @@
#if !HAVE_DECL_INT64_MIN
#define INT64_MIN ((int64_t)(~INT64_MAX))
#endif
#if !HAVE_DECL_UINTMAX_MAX
#define UINTMAX_MAX (~(uintmax_t)0)
#endif
#if !HAVE_DECL_INTMAX_MAX
#define INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1))
#endif
#if !HAVE_DECL_INTMAX_MIN
#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
#endif
/*
* If this platform has <sys/acl.h>, acl_create(), acl_init(),

View File

@ -119,6 +119,23 @@ struct archive {
unsigned current_codepage; /* Current ACP(ANSI CodePage). */
unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
struct archive_string_conv *sconv;
/*
* Used by archive_read_data() to track blocks and copy
* data to client buffers, filling gaps with zero bytes.
*/
const char *read_data_block;
int64_t read_data_offset;
int64_t read_data_output_offset;
size_t read_data_remaining;
/*
* Used by formats/filters to determine the amount of data
* requested from a call to archive_read_data(). This is only
* useful when the format/filter has seek support.
*/
char read_data_is_posix_read;
size_t read_data_requested;
};
/* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */
@ -139,6 +156,8 @@ int __archive_mktemp(const char *tmpdir);
int __archive_clean(struct archive *);
void __archive_reset_read_data(struct archive *);
#define err_combine(a,b) ((a) < (b) ? (a) : (b))
#if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER <= 1300)

View File

@ -0,0 +1,269 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
#ifdef HAVE_FCNTL
#include <fcntl.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
static void arc4random_buf(void *, size_t);
#endif /* HAVE_ARC4RANDOM_BUF */
#include "archive.h"
#include "archive_random_private.h"
#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
#include <wincrypt.h>
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
/*
* Random number generator function.
* This simply calls arc4random_buf function if the platform provides it.
*/
int
archive_random(void *buf, size_t nbytes)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
HCRYPTPROV hProv;
BOOL success;
success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT);
if (!success && GetLastError() == NTE_BAD_KEYSET) {
success = CryptAcquireContext(&hProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
}
if (success) {
success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf);
CryptReleaseContext(hProv, 0);
if (success)
return ARCHIVE_OK;
}
/* TODO: Does this case really happen? */
return ARCHIVE_FAILED;
#else
arc4random_buf(buf, nbytes);
return ARCHIVE_OK;
#endif
}
#if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
/* $OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Arc4 random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* RC4 is a registered trademark of RSA Laboratories.
*/
#ifdef __GNUC__
#define inline __inline
#else /* !__GNUC__ */
#define inline
#endif /* !__GNUC__ */
struct arc4_stream {
uint8_t i;
uint8_t j;
uint8_t s[256];
};
#define RANDOMDEV "/dev/urandom"
#define KEYSIZE 128
#ifdef HAVE_PTHREAD_H
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx);
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx);
#else
#define _ARC4_LOCK()
#define _ARC4_UNLOCK()
#endif
static int rs_initialized;
static struct arc4_stream rs;
static pid_t arc4_stir_pid;
static int arc4_count;
static inline uint8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
arc4_init(void)
{
int n;
for (n = 0; n < 256; n++)
rs.s[n] = n;
rs.i = 0;
rs.j = 0;
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
uint8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si + dat[n % datlen]);
rs.s[rs.i] = rs.s[rs.j];
rs.s[rs.j] = si;
}
rs.j = rs.i;
}
static void
arc4_stir(void)
{
int done, fd, i;
struct {
struct timeval tv;
pid_t pid;
u_char rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
arc4_init();
rs_initialized = 1;
}
done = 0;
fd = open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
(void)close(fd);
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
/* We'll just take whatever was on the stack too... */
}
arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
*/
for (i = 0; i < 1024; i++)
(void)arc4_getbyte();
arc4_count = 1600000;
}
static void
arc4_stir_if_needed(void)
{
pid_t pid = getpid();
if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
arc4_stir_pid = pid;
arc4_stir();
}
}
static inline uint8_t
arc4_getbyte(void)
{
uint8_t si, sj;
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si);
sj = rs.s[rs.j];
rs.s[rs.i] = sj;
rs.s[rs.j] = si;
return (rs.s[(si + sj) & 0xff]);
}
static void
arc4random_buf(void *_buf, size_t n)
{
u_char *buf = (u_char *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {
if (--arc4_count <= 0)
arc4_stir();
buf[n] = arc4_getbyte();
}
_ARC4_UNLOCK();
}
#endif /* !HAVE_ARC4RANDOM_BUF */

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* 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.
*/
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
/* Random number generator. */
int archive_random(void *buf, size_t nbytes);
#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */

View File

@ -130,7 +130,7 @@ which provides a slightly more efficient interface.
You may prefer to use the higher-level
.Fn archive_read_data_skip ,
which reads and discards the data for this entry,
.Fn archive_read_data_to_file ,
.Fn archive_read_data_into_fd ,
which copies the data to the provided file descriptor, or
.Fn archive_read_extract ,
which recreates the specified entry on disk and copies data
@ -186,7 +186,7 @@ list_archive(const char *name)
free(mydata);
}
ssize_t
la_ssize_t
myread(struct archive *a, void *client_data, const void **buff)
{
struct mydata *mydata = client_data;

View File

@ -101,16 +101,17 @@ archive_read_new(void)
{
struct archive_read *a;
a = (struct archive_read *)malloc(sizeof(*a));
a = (struct archive_read *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_READ_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->entry = archive_entry_new2(&a->archive);
a->archive.vtable = archive_read_vtable();
a->passphrases.last = &a->passphrases.first;
return (&a->archive);
}
@ -194,10 +195,12 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
ask = skip_limit;
get = (self->archive->client.skipper)
(&self->archive->archive, self->data, ask);
if (get == 0)
return (total);
request -= get;
total += get;
if (get == 0 || get == request)
return (total);
if (get > request)
return ARCHIVE_FATAL;
request -= get;
}
} else if (self->archive->client.seeker != NULL
&& request > 64 * 1024) {
@ -230,8 +233,11 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
* other libarchive code that assumes a successful forward
* seek means it can also seek backwards.
*/
if (self->archive->client.seeker == NULL)
if (self->archive->client.seeker == NULL) {
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"Current client reader does not support seeking a device");
return (ARCHIVE_FAILED);
}
return (self->archive->client.seeker)(&self->archive->archive,
self->data, offset, whence);
}
@ -454,8 +460,7 @@ archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter, *tmp;
int slot;
int e = 0;
int slot, e = ARCHIVE_OK;
unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
@ -542,16 +547,20 @@ archive_read_open1(struct archive *_a)
* it wants to handle this stream. Repeat until we've finished
* building the pipeline.
*/
/* We won't build a filter pipeline with more stages than this. */
#define MAX_NUMBER_FILTERS 25
static int
choose_filters(struct archive_read *a)
{
int number_bidders, i, bid, best_bid, n;
int number_bidders, i, bid, best_bid, number_filters;
struct archive_read_filter_bidder *bidder, *best_bidder;
struct archive_read_filter *filter;
ssize_t avail;
int r;
for (n = 0; n < 25; ++n) {
for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
best_bid = 0;
@ -662,16 +671,14 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
break;
}
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
a->read_data_is_posix_read = 0;
a->read_data_requested = 0;
__archive_reset_read_data(&a->archive);
a->data_start_node = a->client.cursor;
/* EOF always wins; otherwise return the worst error. */
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
}
int
static int
_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
{
int ret;
@ -750,6 +757,59 @@ archive_read_header_position(struct archive *_a)
return (a->header_position);
}
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
int
archive_read_has_encrypted_entries(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
int format_supports_encryption = archive_read_format_capabilities(_a)
& (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
if (!_a || !format_supports_encryption) {
/* Format in general doesn't support encryption */
return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
}
/* A reader potentially has read enough data now. */
if (a->format && a->format->has_encrypted_entries) {
return (a->format->has_encrypted_entries)(a);
}
/* For any other reason we cannot say how many entries are there. */
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
int
archive_read_format_capabilities(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
if (a && a->format && a->format->format_capabilties) {
return (a->format->format_capabilties)(a);
}
return ARCHIVE_READ_FORMAT_CAPS_NONE;
}
/*
* Read data from an archive entry, using a read(2)-style interface.
* This is a convenience routine that just calls
@ -764,7 +824,7 @@ archive_read_header_position(struct archive *_a)
ssize_t
archive_read_data(struct archive *_a, void *buff, size_t s)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive *a = (struct archive *)_a;
char *dest;
const void *read_buf;
size_t bytes_read;
@ -779,7 +839,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
read_buf = a->read_data_block;
a->read_data_is_posix_read = 1;
a->read_data_requested = s;
r = _archive_read_data_block(&a->archive, &read_buf,
r = archive_read_data_block(a, &read_buf,
&a->read_data_remaining, &a->read_data_offset);
a->read_data_block = read_buf;
if (r == ARCHIVE_EOF)
@ -794,7 +854,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
}
if (a->read_data_offset < a->read_data_output_offset) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Encountered out-of-order sparse blocks");
return (ARCHIVE_RETRY);
}
@ -837,6 +897,21 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
return (bytes_read);
}
/*
* Reset the read_data_* variables, used for starting a new entry.
*/
void __archive_reset_read_data(struct archive * a)
{
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
a->read_data_is_posix_read = 0;
a->read_data_requested = 0;
/* extra resets, from rar.c */
a->read_data_block = NULL;
a->read_data_offset = 0;
}
/*
* Skip over all remaining data in this entry.
*/
@ -904,7 +979,7 @@ _archive_read_data_block(struct archive *_a,
if (a->format->read_data == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Internal error: "
"No format_read_data_block function registered");
"No format->read_data function registered");
return (ARCHIVE_FATAL);
}
@ -991,6 +1066,7 @@ static int
_archive_read_free(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_passphrase *p;
int i, n;
int slots;
int r = ARCHIVE_OK;
@ -1028,9 +1104,20 @@ _archive_read_free(struct archive *_a)
}
}
/* Release passphrase list. */
p = a->passphrases.first;
while (p != NULL) {
struct archive_read_passphrase *np = p->next;
/* A passphrase should be cleaned. */
memset(p->passphrase, 0, strlen(p->passphrase));
free(p->passphrase);
free(p);
p = np;
}
archive_string_free(&a->archive.error_string);
if (a->entry)
archive_entry_free(a->entry);
archive_entry_free(a->entry);
a->archive.magic = 0;
__archive_clean(&a->archive);
free(a->client.dataset);
@ -1074,7 +1161,7 @@ static const char *
_archive_filter_name(struct archive *_a, int n)
{
struct archive_read_filter *f = get_filter(_a, n);
return f == NULL ? NULL : f->name;
return f != NULL ? f->name : NULL;
}
static int64_t
@ -1098,7 +1185,9 @@ __archive_read_register_format(struct archive_read *a,
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *))
int (*cleanup)(struct archive_read *),
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *))
{
int i, number_slots;
@ -1121,6 +1210,8 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data;
a->formats[i].name = name;
a->formats[i].format_capabilties = format_capabilities;
a->formats[i].has_encrypted_entries = has_encrypted_entries;
return (ARCHIVE_OK);
}
}
@ -1563,10 +1654,9 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
client->dataset[++cursor].begin_position = r;
}
offset -= client->dataset[cursor].begin_position;
if (offset < 0)
offset = 0;
else if (offset > client->dataset[cursor].total_size - 1)
offset = client->dataset[cursor].total_size - 1;
if (offset < 0
|| offset > client->dataset[cursor].total_size)
return ARCHIVE_FATAL;
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
return r;
break;

View File

@ -0,0 +1,74 @@
.\" Copyright (c) 2014 Michihiro NAKAJIMA
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd September 14, 2014
.Dt ARCHIVE_READ_ADD_PASSPHRASE 3
.Os
.Sh NAME
.Nm archive_read_add_passphrase ,
.Nm archive_read_set_passphrase_callback
.Nd functions for reading encrypted archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
.Fo archive_read_add_passphrase
.Fa "struct archive *"
.Fa "const char *passphrase"
.Fc
.Ft int
.Fo archive_read_set_passphrase_callback
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "archive_passphrase_callback *"
.Fc
.Sh DESCRIPTION
.Bl -tag -width indent
.It Fn archive_read_add_passphrase
Register passphrases for reading an encryption archive.
If
.Ar passphrase
is
.Dv NULL
or empty, this function will do nothing and
.Cm ARCHIVE_FAILED
will be returned.
Otherwise,
.Cm ARCHIVE_OK
will be returned.
.It Fn archive_read_set_passphrase_callback
Register callback function that will be invoked to get a passphrase
for decrption after trying all passphrases registered by the
.Fn archive_read_add_passphrase
function failed.
.El
.\" .Sh ERRORS
.Sh SEE ALSO
.Xr tar 1 ,
.Xr libarchive 3 ,
.Xr archive_read 3 ,
.Xr archive_read_set_options 3

View File

@ -0,0 +1,186 @@
/*-
* Copyright (c) 2014 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive_read_private.h"
static void
add_passphrase_to_tail(struct archive_read *a,
struct archive_read_passphrase *p)
{
*a->passphrases.last = p;
a->passphrases.last = &p->next;
p->next = NULL;
}
static struct archive_read_passphrase *
remove_passphrases_from_head(struct archive_read *a)
{
struct archive_read_passphrase *p;
p = a->passphrases.first;
if (p != NULL)
a->passphrases.first = p->next;
return (p);
}
static void
insert_passphrase_to_head(struct archive_read *a,
struct archive_read_passphrase *p)
{
p->next = a->passphrases.first;
a->passphrases.first = p;
}
static struct archive_read_passphrase *
new_read_passphrase(struct archive_read *a, const char *passphrase)
{
struct archive_read_passphrase *p;
p = malloc(sizeof(*p));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
return (NULL);
}
p->passphrase = strdup(passphrase);
if (p->passphrase == NULL) {
free(p);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
return (NULL);
}
return (p);
}
int
archive_read_add_passphrase(struct archive *_a, const char *passphrase)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_passphrase *p;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_add_passphrase");
if (passphrase == NULL || passphrase[0] == '\0') {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Empty passphrase is unacceptable");
return (ARCHIVE_FAILED);
}
p = new_read_passphrase(a, passphrase);
if (p == NULL)
return (ARCHIVE_FATAL);
add_passphrase_to_tail(a, p);
return (ARCHIVE_OK);
}
int
archive_read_set_passphrase_callback(struct archive *_a, void *client_data,
archive_passphrase_callback *cb)
{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_set_passphrase_callback");
a->passphrases.callback = cb;
a->passphrases.client_data = client_data;
return (ARCHIVE_OK);
}
/*
* Call this in advance when you start to get a passphrase for decryption
* for a entry.
*/
void
__archive_read_reset_passphrase(struct archive_read *a)
{
a->passphrases.candiate = -1;
}
/*
* Get a passphrase for decryption.
*/
const char *
__archive_read_next_passphrase(struct archive_read *a)
{
struct archive_read_passphrase *p;
const char *passphrase;
if (a->passphrases.candiate < 0) {
/* Count out how many passphrases we have. */
int cnt = 0;
for (p = a->passphrases.first; p != NULL; p = p->next)
cnt++;
a->passphrases.candiate = cnt;
p = a->passphrases.first;
} else if (a->passphrases.candiate > 1) {
/* Rotate a passphrase list. */
a->passphrases.candiate--;
p = remove_passphrases_from_head(a);
add_passphrase_to_tail(a, p);
/* Pick a new passphrase candiate up. */
p = a->passphrases.first;
} else if (a->passphrases.candiate == 1) {
/* This case is that all cadiates failed to decryption. */
a->passphrases.candiate = 0;
if (a->passphrases.first->next != NULL) {
/* Rotate a passphrase list. */
p = remove_passphrases_from_head(a);
add_passphrase_to_tail(a, p);
}
p = NULL;
} else /* There is no passphrase candaite. */
p = NULL;
if (p != NULL)
passphrase = p->passphrase;
else if (a->passphrases.callback != NULL) {
/* Get a passphrase through a call-back function
* since we tried all passphrases out or we don't
* have it. */
passphrase = a->passphrases.callback(&a->archive,
a->passphrases.client_data);
if (passphrase != NULL) {
p = new_read_passphrase(a, passphrase);
if (p == NULL)
return (NULL);
insert_passphrase_to_head(a, p);
a->passphrases.candiate = 1;
}
} else
passphrase = NULL;
return (passphrase);
}

View File

@ -43,7 +43,7 @@ archive_read_append_filter(struct archive *_a, int code)
struct archive_read_filter *filter;
struct archive_read *a = (struct archive_read *)_a;
r1 = r2 = (ARCHIVE_OK);
r2 = (ARCHIVE_OK);
switch (code)
{
case ARCHIVE_FILTER_NONE:
@ -85,6 +85,10 @@ archive_read_append_filter(struct archive *_a, int code)
strcpy(str, "rpm");
r1 = archive_read_support_filter_rpm(_a);
break;
case ARCHIVE_FILTER_LZ4:
strcpy(str, "lz4");
r1 = archive_read_support_filter_lz4(_a);
break;
case ARCHIVE_FILTER_LZIP:
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);

View File

@ -37,7 +37,7 @@
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft ssize_t
.Ft la_ssize_t
.Fn archive_read_data "struct archive *" "void *buff" "size_t len"
.Ft int
.Fo archive_read_data_block

View File

@ -251,9 +251,11 @@ archive_read_disk_entry_from_file(struct archive *_a,
#endif /* HAVE_READLINK || HAVE_READLINKAT */
r = setup_acls(a, entry, &fd);
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
if (!a->suppress_xattr) {
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
}
if (a->enable_copyfile) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
@ -399,7 +401,7 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
#ifdef HAVE_POSIX_ACL
static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
@ -419,6 +421,7 @@ setup_acls(struct archive_read_disk *a,
archive_entry_acl_clear(entry);
#ifdef ACL_TYPE_NFS4
/* Try NFS4 ACL first. */
if (*fd >= 0)
acl = acl_get_fd(*fd);
@ -447,6 +450,7 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl);
return (ARCHIVE_OK);
}
#endif
/* Retrieve access ACL from file. */
if (*fd >= 0)
@ -492,6 +496,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#ifdef ACL_TYPE_NFS4
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@ -508,8 +513,10 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
};
#ifdef ACL_TYPE_NFS4
static struct {
int archive_inherit;
int platform_inherit;
@ -519,20 +526,24 @@ static struct {
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
};
#endif
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
#ifdef ACL_TYPE_NFS4
acl_entry_type_t acl_type;
acl_flagset_t acl_flagset;
int brand, r;
#endif
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int brand, i, r, entry_acl_type;
int i, entry_acl_type;
int s, ae_id, ae_tag, ae_perm;
const char *ae_name;
#ifdef ACL_TYPE_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
@ -559,6 +570,7 @@ translate_acl(struct archive_read_disk *a,
return ARCHIVE_FAILED;
break;
}
#endif
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
@ -591,9 +603,11 @@ translate_acl(struct archive_read_disk *a,
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
#ifdef ACL_TYPE_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
@ -604,6 +618,7 @@ translate_acl(struct archive_read_disk *a,
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
// non-NFSv4 ACLs
entry_acl_type = default_entry_acl_type;
#ifdef ACL_TYPE_NFS4
r = acl_get_entry_type_np(acl_entry, &acl_type);
if (r == 0) {
switch (acl_type) {
@ -633,9 +648,10 @@ translate_acl(struct archive_read_disk *a,
ae_perm |= acl_inherit_map[i].archive_inherit;
}
#endif
acl_get_permset(acl_entry, &acl_permset);
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.
@ -1029,7 +1045,7 @@ setup_sparse(struct archive_read_disk *a,
struct fiemap *fm;
struct fiemap_extent *fe;
int64_t size;
int count, do_fiemap;
int count, do_fiemap, iters;
int exit_sts = ARCHIVE_OK;
if (archive_entry_filetype(entry) != AE_IFREG
@ -1066,7 +1082,7 @@ setup_sparse(struct archive_read_disk *a,
fm->fm_extent_count = count;
do_fiemap = 1;
size = archive_entry_size(entry);
for (;;) {
for (iters = 0; ; ++iters) {
int i, r;
r = ioctl(*fd, FS_IOC_FIEMAP, fm);
@ -1076,8 +1092,13 @@ setup_sparse(struct archive_read_disk *a,
* version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
goto exit_setup_sparse;
}
if (fm->fm_mapped_extents == 0)
if (fm->fm_mapped_extents == 0) {
if (iters == 0) {
/* Fully sparse file; insert a zero-length "data" entry */
archive_entry_sparse_add_entry(entry, 0, 0);
}
break;
}
fe = fm->fm_extents;
for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
@ -1122,6 +1143,7 @@ setup_sparse(struct archive_read_disk *a,
off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
int exit_sts = ARCHIVE_OK;
int check_fully_sparse = 0;
if (archive_entry_filetype(entry) != AE_IFREG
|| archive_entry_size(entry) <= 0
@ -1174,8 +1196,14 @@ setup_sparse(struct archive_read_disk *a,
while (off_s < size) {
off_s = lseek(*fd, off_s, SEEK_DATA);
if (off_s == (off_t)-1) {
if (errno == ENXIO)
break;/* no more hole */
if (errno == ENXIO) {
/* no more hole */
if (archive_entry_sparse_count(entry) == 0) {
/* Potentially a fully-sparse file. */
check_fully_sparse = 1;
}
break;
}
archive_set_error(&a->archive, errno,
"lseek(SEEK_HOLE) failed");
exit_sts = ARCHIVE_FAILED;
@ -1199,6 +1227,14 @@ setup_sparse(struct archive_read_disk *a,
off_e - off_s);
off_s = off_e;
}
if (check_fully_sparse) {
if (lseek(*fd, 0, SEEK_HOLE) == 0 &&
lseek(*fd, 0, SEEK_END) == size) {
/* Fully sparse file; insert a zero-length "data" entry */
archive_entry_sparse_add_entry(entry, 0, 0);
}
}
exit_setup_sparse:
lseek(*fd, initial_off, SEEK_SET);
return (exit_sts);

View File

@ -356,6 +356,8 @@ static int _archive_read_free(struct archive *);
static int _archive_read_close(struct archive *);
static int _archive_read_data_block(struct archive *,
const void **, size_t *, int64_t *);
static int _archive_read_next_header(struct archive *,
struct archive_entry **);
static int _archive_read_next_header2(struct archive *,
struct archive_entry *);
static const char *trivial_lookup_gname(void *, int64_t gid);
@ -377,6 +379,7 @@ archive_read_disk_vtable(void)
av.archive_free = _archive_read_free;
av.archive_close = _archive_read_close;
av.archive_read_data_block = _archive_read_data_block;
av.archive_read_next_header = _archive_read_next_header;
av.archive_read_next_header2 = _archive_read_next_header2;
inited = 1;
}
@ -459,6 +462,7 @@ archive_read_disk_new(void)
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_read_disk_vtable();
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
a->enable_copyfile = 1;
@ -491,6 +495,7 @@ _archive_read_free(struct archive *_a)
if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
(a->cleanup_uname)(a->lookup_uname_data);
archive_string_free(&a->archive.error_string);
archive_entry_free(a->entry);
a->archive.magic = 0;
__archive_clean(&a->archive);
free(a);
@ -609,6 +614,10 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
a->traverse_mount_points = 0;
else
a->traverse_mount_points = 1;
if (flags & ARCHIVE_READDISK_NO_XATTR)
a->suppress_xattr = 1;
else
a->suppress_xattr = 0;
return (r);
}
@ -708,6 +717,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
int r;
ssize_t bytes;
size_t buffbytes;
int empty_sparse_region = 0;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
"archive_read_data_block");
@ -789,6 +799,9 @@ _archive_read_data_block(struct archive *_a, const void **buff,
if ((int64_t)buffbytes > t->current_sparse->length)
buffbytes = t->current_sparse->length;
if (t->current_sparse->length == 0)
empty_sparse_region = 1;
/*
* Skip hole.
* TODO: Should we consider t->current_filesystem->xfer_align?
@ -819,7 +832,11 @@ _archive_read_data_block(struct archive *_a, const void **buff,
}
} else
bytes = 0;
if (bytes == 0) {
/*
* Return an EOF unless we've read a leading empty sparse region, which
* is used to represent fully-sparse files.
*/
if (bytes == 0 && !empty_sparse_region) {
/* Get EOF */
t->entry_eof = 1;
r = ARCHIVE_EOF;
@ -1080,6 +1097,17 @@ next_entry(struct archive_read_disk *a, struct tree *t,
return (r);
}
static int
_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
{
int ret;
struct archive_read_disk *a = (struct archive_read_disk *)_a;
*entryp = NULL;
ret = _archive_read_next_header2(_a, a->entry);
*entryp = a->entry;
return ret;
}
static int
_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
{
@ -1148,6 +1176,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
break;
}
__archive_reset_read_data(&a->archive);
return (r);
}
@ -1555,6 +1584,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
t->current_filesystem->name_max = sfs.f_namemax;
#else
# if defined(_PC_NAME_MAX)
/* Mac OS X does not have f_namemax in struct statfs. */
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
@ -1564,6 +1594,9 @@ setup_current_filesystem(struct archive_read_disk *a)
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
# else
nm = -1;
# endif
if (nm == -1)
t->current_filesystem->name_max = NAME_MAX;
else
@ -1660,7 +1693,9 @@ setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
struct statfs sfs;
#if defined(HAVE_STATVFS)
struct statvfs svfs;
#endif
int r, vr = 0, xr = 0;
if (tree_current_is_symblic_link_target(t)) {
@ -1677,7 +1712,9 @@ setup_current_filesystem(struct archive_read_disk *a)
"openat failed");
return (ARCHIVE_FAILED);
}
#if defined(HAVE_FSTATVFS)
vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
#endif
r = fstatfs(fd, &sfs);
if (r == 0)
xr = get_xfer_size(t, fd, NULL);
@ -1687,14 +1724,18 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
#if defined(HAVE_STATVFS)
vr = statvfs(tree_current_access_path(t), &svfs);
#endif
r = statfs(tree_current_access_path(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
#endif
} else {
#ifdef HAVE_FSTATFS
#if defined(HAVE_FSTATVFS)
vr = fstatvfs(tree_current_dir_fd(t), &svfs);
#endif
r = fstatfs(tree_current_dir_fd(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
@ -1703,7 +1744,9 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
#if defined(HAVE_STATVFS)
vr = statvfs(".", &svfs);
#endif
r = statfs(".", &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, ".");
@ -1716,10 +1759,17 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
#if defined(HAVE_STATVFS)
t->current_filesystem->xfer_align = svfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
t->current_filesystem->min_xfer_size = svfs.f_bsize;
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
#else
t->current_filesystem->xfer_align = sfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
t->current_filesystem->min_xfer_size = sfs.f_bsize;
t->current_filesystem->incr_xfer_size = sfs.f_bsize;
#endif
}
switch (sfs.f_type) {
case AFS_SUPER_MAGIC:
@ -1744,7 +1794,11 @@ setup_current_filesystem(struct archive_read_disk *a)
}
#if defined(ST_NOATIME)
#if defined(HAVE_STATVFS)
if (svfs.f_flag & ST_NOATIME)
#else
if (sfs.f_flag & ST_NOATIME)
#endif
t->current_filesystem->noatime = 1;
else
#endif
@ -1973,7 +2027,7 @@ tree_dup(int fd)
static volatile int can_dupfd_cloexec = 1;
if (can_dupfd_cloexec) {
new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (new_fd != -1)
return (new_fd);
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,

View File

@ -39,6 +39,9 @@ struct archive_entry;
struct archive_read_disk {
struct archive archive;
/* Reused by archive_read_next_header() */
struct archive_entry *entry;
/*
* Symlink mode is one of 'L'ogical, 'P'hysical, or 'H'ybrid,
* following an old BSD convention. 'L' follows all symlinks,
@ -68,6 +71,8 @@ struct archive_read_disk {
int enable_copyfile;
/* Set 1 if users request to traverse mount points. */
int traverse_mount_points;
/* Set 1 if users want to suppress xattr information. */
int suppress_xattr;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);

View File

@ -83,7 +83,7 @@ static const char * lookup_uname_helper(struct name_cache *, id_t uid);
* a simple cache to accelerate such lookups---into the archive_read_disk
* object. This is in a separate file because getpwuid()/getgrgid()
* can pull in a LOT of library code (including NIS/LDAP functions, which
* pull in DNS resolveers, etc). This can easily top 500kB, which makes
* pull in DNS resolvers, etc). This can easily top 500kB, which makes
* it inappropriate for some space-constrained applications.
*
* Applications that are size-sensitive may want to just use the

View File

@ -26,158 +26,35 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_private.h"
#include "archive_write_disk_private.h"
struct extract {
struct archive *ad; /* archive_write_disk object */
/* Progress function invoked during extract. */
void (*extract_progress)(void *);
void *extract_progress_user_data;
};
static int archive_read_extract_cleanup(struct archive_read *);
static int copy_data(struct archive *ar, struct archive *aw);
static struct extract *get_extract(struct archive_read *);
static struct extract *
get_extract(struct archive_read *a)
{
/* If we haven't initialized, do it now. */
/* This also sets up a lot of global state. */
if (a->extract == NULL) {
a->extract = (struct extract *)malloc(sizeof(*a->extract));
if (a->extract == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (NULL);
}
memset(a->extract, 0, sizeof(*a->extract));
a->extract->ad = archive_write_disk_new();
if (a->extract->ad == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (NULL);
}
archive_write_disk_set_standard_lookup(a->extract->ad);
a->cleanup_archive_extract = archive_read_extract_cleanup;
}
return (a->extract);
}
int
archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
{
struct extract *extract;
struct archive_read_extract *extract;
struct archive_read * a = (struct archive_read *)_a;
extract = get_extract((struct archive_read *)_a);
extract = __archive_read_get_extract(a);
if (extract == NULL)
return (ARCHIVE_FATAL);
archive_write_disk_set_options(extract->ad, flags);
return (archive_read_extract2(_a, entry, extract->ad));
}
int
archive_read_extract2(struct archive *_a, struct archive_entry *entry,
struct archive *ad)
{
struct archive_read *a = (struct archive_read *)_a;
int r, r2;
/* Set up for this particular entry. */
if (a->skip_file_set)
archive_write_disk_set_skip_file(ad,
a->skip_file_dev, a->skip_file_ino);
r = archive_write_header(ad, entry);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK)
/* If _write_header failed, copy the error. */
archive_copy_error(&a->archive, ad);
else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
/* Otherwise, pour data into the entry. */
r = copy_data(_a, ad);
r2 = archive_write_finish_entry(ad);
if (r2 < ARCHIVE_WARN)
r2 = ARCHIVE_WARN;
/* Use the first message. */
if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
archive_copy_error(&a->archive, ad);
/* Use the worst error return. */
if (r2 < r)
r = r2;
return (r);
}
void
archive_read_extract_set_progress_callback(struct archive *_a,
void (*progress_func)(void *), void *user_data)
{
struct archive_read *a = (struct archive_read *)_a;
struct extract *extract = get_extract(a);
if (extract != NULL) {
extract->extract_progress = progress_func;
extract->extract_progress_user_data = user_data;
}
}
static int
copy_data(struct archive *ar, struct archive *aw)
{
int64_t offset;
const void *buff;
struct extract *extract;
size_t size;
int r;
extract = get_extract((struct archive_read *)ar);
if (extract == NULL)
return (ARCHIVE_FATAL);
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
r = (int)archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK) {
archive_set_error(ar, archive_errno(aw),
"%s", archive_error_string(aw));
return (r);
/* If we haven't initialized the archive_write_disk object, do it now. */
if (extract->ad == NULL) {
extract->ad = archive_write_disk_new();
if (extract->ad == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (ARCHIVE_FATAL);
}
if (extract->extract_progress)
(extract->extract_progress)
(extract->extract_progress_user_data);
archive_write_disk_set_standard_lookup(extract->ad);
}
}
/*
* Cleanup function for archive_extract.
*/
static int
archive_read_extract_cleanup(struct archive_read *a)
{
int ret = ARCHIVE_OK;
ret = archive_write_free(a->extract->ad);
free(a->extract);
a->extract = NULL;
return (ret);
archive_write_disk_set_options(extract->ad, flags);
return (archive_read_extract2(&a->archive, entry, extract->ad));
}

View File

@ -0,0 +1,156 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_private.h"
static int copy_data(struct archive *ar, struct archive *aw);
static int archive_read_extract_cleanup(struct archive_read *);
/* Retrieve an extract object without initialising the associated
* archive_write_disk object.
*/
struct archive_read_extract *
__archive_read_get_extract(struct archive_read *a)
{
if (a->extract == NULL) {
a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract));
if (a->extract == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (NULL);
}
memset(a->extract, 0, sizeof(*a->extract));
a->cleanup_archive_extract = archive_read_extract_cleanup;
}
return (a->extract);
}
/*
* Cleanup function for archive_extract.
*/
static int
archive_read_extract_cleanup(struct archive_read *a)
{
int ret = ARCHIVE_OK;
if (a->extract->ad != NULL) {
ret = archive_write_free(a->extract->ad);
}
free(a->extract);
a->extract = NULL;
return (ret);
}
int
archive_read_extract2(struct archive *_a, struct archive_entry *entry,
struct archive *ad)
{
struct archive_read *a = (struct archive_read *)_a;
int r, r2;
/* Set up for this particular entry. */
if (a->skip_file_set)
archive_write_disk_set_skip_file(ad,
a->skip_file_dev, a->skip_file_ino);
r = archive_write_header(ad, entry);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK)
/* If _write_header failed, copy the error. */
archive_copy_error(&a->archive, ad);
else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
/* Otherwise, pour data into the entry. */
r = copy_data(_a, ad);
r2 = archive_write_finish_entry(ad);
if (r2 < ARCHIVE_WARN)
r2 = ARCHIVE_WARN;
/* Use the first message. */
if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
archive_copy_error(&a->archive, ad);
/* Use the worst error return. */
if (r2 < r)
r = r2;
return (r);
}
void
archive_read_extract_set_progress_callback(struct archive *_a,
void (*progress_func)(void *), void *user_data)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_extract *extract = __archive_read_get_extract(a);
if (extract != NULL) {
extract->extract_progress = progress_func;
extract->extract_progress_user_data = user_data;
}
}
static int
copy_data(struct archive *ar, struct archive *aw)
{
int64_t offset;
const void *buff;
struct archive_read_extract *extract;
size_t size;
int r;
extract = __archive_read_get_extract((struct archive_read *)ar);
if (extract == NULL)
return (ARCHIVE_FATAL);
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
r = (int)archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r < ARCHIVE_OK) {
archive_set_error(ar, archive_errno(aw),
"%s", archive_error_string(aw));
return (r);
}
if (extract->extract_progress)
(extract->extract_progress)
(extract->extract_progress_user_data);
}
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 2, 2012
.Dd August 14, 2014
.Dt ARCHIVE_READ_FILTER 3
.Os
.Sh NAME
@ -32,8 +32,11 @@
.Nm archive_read_support_filter_bzip2 ,
.Nm archive_read_support_filter_compress ,
.Nm archive_read_support_filter_gzip ,
.Nm archive_read_support_filter_lz4 ,
.Nm archive_read_support_filter_lzma ,
.Nm archive_read_support_filter_none ,
.Nm archive_read_support_filter_rpm ,
.Nm archive_read_support_filter_uu ,
.Nm archive_read_support_filter_xz ,
.Nm archive_read_support_filter_program ,
.Nm archive_read_support_filter_program_signature
@ -50,12 +53,24 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_read_support_filter_compress "struct archive *"
.Ft int
.Fn archive_read_support_filter_grzip "struct archive *"
.Ft int
.Fn archive_read_support_filter_gzip "struct archive *"
.Ft int
.Fn archive_read_support_filter_lrzip "struct archive *"
.Ft int
.Fn archive_read_support_filter_lz4 "struct archive *"
.Ft int
.Fn archive_read_support_filter_lzma "struct archive *"
.Ft int
.Fn archive_read_support_filter_lzop "struct archive *"
.Ft int
.Fn archive_read_support_filter_none "struct archive *"
.Ft int
.Fn archive_read_support_filter_rpm "struct archive *"
.Ft int
.Fn archive_read_support_filter_uu "struct archive *"
.Ft int
.Fn archive_read_support_filter_xz "struct archive *"
.Ft int
.Fo archive_read_support_filter_program
@ -75,9 +90,15 @@ Streaming Archive Library (libarchive, -larchive)
.It Xo
.Fn archive_read_support_filter_bzip2 ,
.Fn archive_read_support_filter_compress ,
.Fn archive_read_support_filter_grzip ,
.Fn archive_read_support_filter_gzip ,
.Fn archive_read_support_filter_lrzip ,
.Fn archive_read_support_filter_lz4 ,
.Fn archive_read_support_filter_lzma ,
.Fn archive_read_support_filter_lzop ,
.Fn archive_read_support_filter_none ,
.Fn archive_read_support_filter_rpm ,
.Fn archive_read_support_filter_uu ,
.Fn archive_read_support_filter_xz
.Xc
Enables auto-detection code and decompression support for the

View File

@ -130,14 +130,14 @@ objects can be found in the overview manual page for
The callback functions must match the following prototypes:
.Bl -item -offset indent
.It
.Ft typedef ssize_t
.Ft typedef la_ssize_t
.Fo archive_read_callback
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "const void **buffer"
.Fc
.It
.Ft typedef off_t
.Ft typedef la_int64_t
.Fo archive_skip_callback
.Fa "struct archive *"
.Fa "void *client_data"

View File

@ -59,6 +59,7 @@ struct read_fd_data {
static int file_close(struct archive *, void *);
static ssize_t file_read(struct archive *, void *, const void **buff);
static int64_t file_seek(struct archive *, void *, int64_t request, int);
static int64_t file_skip(struct archive *, void *, int64_t request);
int
@ -102,6 +103,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
archive_read_set_read_callback(a, file_read);
archive_read_set_skip_callback(a, file_skip);
archive_read_set_seek_callback(a, file_seek);
archive_read_set_close_callback(a, file_close);
archive_read_set_callback_data(a, mine);
return (archive_read_open1(a));
@ -170,6 +172,33 @@ file_skip(struct archive *a, void *client_data, int64_t request)
return (-1);
}
/*
* TODO: Store the offset and use it in the read callback.
*/
static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
int64_t r;
/* We use off_t here because lseek() is declared that way. */
/* See above for notes about when off_t is less than 64 bits. */
r = lseek(mine->fd, request, whence);
if (r >= 0)
return r;
if (errno == ESPIPE) {
archive_set_error(a, errno,
"A file descriptor(%d) is not seekable(PIPE)", mine->fd);
return (ARCHIVE_FAILED);
} else {
/* If the input is corrupted or truncated, fail. */
archive_set_error(a, errno,
"Error seeking in a file descriptor(%d)", mine->fd);
return (ARCHIVE_FATAL);
}
}
static int
file_close(struct archive *a, void *client_data)
{

View File

@ -83,8 +83,9 @@ archive_read_open_FILE(struct archive *a, FILE *f)
mine->f = f;
/*
* If we can't fstat() the file, it may just be that it's not
* a file. (FILE * objects can wrap many kinds of I/O
* streams, some of which don't support fileno()).)
* a file. (On some platforms, FILE * objects can wrap I/O
* streams that don't support fileno()). As a result, fileno()
* should be used cautiously.)
*/
if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
@ -150,7 +151,10 @@ file_skip(struct archive *a, void *client_data, int64_t request)
skip = max_skip;
}
#if HAVE_FSEEKO
#ifdef __ANDROID__
/* fileno() isn't safe on all platforms ... see above. */
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
#elif HAVE_FSEEKO
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)

View File

@ -103,7 +103,9 @@ int
archive_read_open_filename(struct archive *a, const char *filename,
size_t block_size)
{
const char *filenames[2] = { filename, NULL };
const char *filenames[2];
filenames[0] = filename;
filenames[1] = NULL;
return archive_read_open_filenames(a, filenames, block_size);
}
@ -176,7 +178,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
#else
/*
* POSIX system does not support a wchar_t interface for
* open() system call, so we have to translate a whcar_t
* open() system call, so we have to translate a wchar_t
* filename to multi-byte one and use it.
*/
struct archive_string fn;

Some files were not shown because too many files have changed in this diff Show More